• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.server.wm;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
25 import static android.server.wm.ComponentNameUtils.getActivityName;
26 import static android.server.wm.ProtoExtractors.extract;
27 import static android.server.wm.StateLogger.log;
28 import static android.server.wm.StateLogger.logE;
29 import static android.server.wm.TestTaskOrganizer.INVALID_TASK_ID;
30 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
31 import static android.view.Display.DEFAULT_DISPLAY;
32 import static android.window.DisplayAreaOrganizer.FEATURE_IME;
33 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
34 
35 import static androidx.test.InstrumentationRegistry.getInstrumentation;
36 
37 import static com.google.common.truth.Truth.assertWithMessage;
38 
39 import static org.junit.Assert.fail;
40 
41 import android.app.ActivityTaskManager;
42 import android.app.UiAutomation;
43 import android.content.ComponentName;
44 import android.content.res.Configuration;
45 import android.graphics.Point;
46 import android.graphics.Rect;
47 import android.os.ParcelFileDescriptor;
48 import android.os.SystemClock;
49 import android.util.SparseArray;
50 import android.view.WindowInsets;
51 
52 import androidx.annotation.NonNull;
53 import androidx.annotation.Nullable;
54 
55 import com.google.protobuf.ExtensionRegistryLite;
56 import com.google.protobuf.InvalidProtocolBufferException;
57 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
58 
59 import perfetto.protos.Displayinfo.DisplayInfoProto;
60 import perfetto.protos.Enums.TransitionTypeEnum;
61 import perfetto.protos.Insetssource.InsetsSourceProto;
62 import perfetto.protos.Rect.RectProto;
63 import perfetto.protos.TraceOuterClass.Trace;
64 import perfetto.protos.TracePacketOuterClass.TracePacket;
65 import perfetto.protos.Windowmanager.WindowManagerTraceEntry;
66 import perfetto.protos.Windowmanagerservice.ActivityRecordProto;
67 import perfetto.protos.Windowmanagerservice.AppTransitionProto;
68 import perfetto.protos.Windowmanagerservice.BackNavigationProto;
69 import perfetto.protos.Windowmanagerservice.ConfigurationContainerProto;
70 import perfetto.protos.Windowmanagerservice.DisplayAreaProto;
71 import perfetto.protos.Windowmanagerservice.DisplayContentProto;
72 import perfetto.protos.Windowmanagerservice.DisplayFramesProto;
73 import perfetto.protos.Windowmanagerservice.DisplayRotationProto;
74 import perfetto.protos.Windowmanagerservice.IdentifierProto;
75 import perfetto.protos.Windowmanagerservice.InsetsSourceProviderProto;
76 import perfetto.protos.Windowmanagerservice.KeyguardControllerProto;
77 import perfetto.protos.Windowmanagerservice.KeyguardServiceDelegateProto;
78 import perfetto.protos.Windowmanagerservice.PinnedTaskControllerProto;
79 import perfetto.protos.Windowmanagerservice.RootWindowContainerProto;
80 import perfetto.protos.Windowmanagerservice.TaskFragmentProto;
81 import perfetto.protos.Windowmanagerservice.TaskProto;
82 import perfetto.protos.Windowmanagerservice.WindowContainerChildProto;
83 import perfetto.protos.Windowmanagerservice.WindowContainerProto;
84 import perfetto.protos.Windowmanagerservice.WindowFramesProto;
85 import perfetto.protos.Windowmanagerservice.WindowManagerServiceDumpProto;
86 import perfetto.protos.Windowmanagerservice.WindowStateAnimatorProto;
87 import perfetto.protos.Windowmanagerservice.WindowStateProto;
88 import perfetto.protos.Windowmanagerservice.WindowSurfaceControllerProto;
89 import perfetto.protos.Windowmanagerservice.WindowTokenProto;
90 import perfetto.protos.WinscopeExtensionsImplOuterClass.WinscopeExtensionsImpl;
91 import perfetto.protos.WinscopeExtensionsOuterClass.WinscopeExtensions;
92 
93 import java.io.ByteArrayOutputStream;
94 import java.io.FileInputStream;
95 import java.io.IOException;
96 import java.nio.charset.StandardCharsets;
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.List;
100 import java.util.Objects;
101 import java.util.function.Consumer;
102 import java.util.function.Predicate;
103 import java.util.stream.Collectors;
104 import java.util.stream.Stream;
105 
106 public class WindowManagerState {
107 
108     public static final String STATE_INITIALIZING = "INITIALIZING";
109     public static final String STATE_STARTED = "STARTED";
110     public static final String STATE_RESUMED = "RESUMED";
111     public static final String STATE_PAUSING = "PAUSING";
112     public static final String STATE_PAUSED = "PAUSED";
113     public static final String STATE_STOPPING = "STOPPING";
114     public static final String STATE_STOPPED = "STOPPED";
115     public static final String STATE_DESTROYED = "DESTROYED";
116     public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
117     public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
118     public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
119     public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
120     public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN";
121     public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE";
122     public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN";
123     public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE";
124     public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY";
125     public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
126             "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
127     public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
128     public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
129     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN =
130             "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
131     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE =
132             "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
133     public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
134     public static final String APP_STATE_RUNNING = "APP_STATE_RUNNING";
135 
136     private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto";
137     private static final String STARTING_WINDOW_PREFIX = "Starting ";
138     private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: ";
139     /** @see WindowManager.LayoutParams */
140     private static final int TYPE_NAVIGATION_BAR = 2019;
141     /** @see WindowManager.LayoutParams */
142     private static final int TYPE_NAVIGATION_BAR_PANEL = 2024;
143     /** @see WindowManager.LayoutParams */
144     private static final int TYPE_NOTIFICATION_SHADE = 2040;
145 
146     /** Whether accessibility services should be suppressed when taking the WindowManager dump. */
147     private boolean mSuppressAccessibilityServices = true;
148 
149     private RootWindowContainer mRoot = null;
150     // Displays in z-order with the top most at the front of the list, starting with primary.
151     private final List<DisplayContent> mDisplays = new ArrayList<>();
152     /**
153      * Root tasks in z-order with the top most at the front of the list, starting with primary
154      * display.
155      */
156     private final List<Task> mRootTasks = new ArrayList<>();
157     // Windows in z-order with the top most at the front of the list.
158     private final List<WindowState> mWindowStates = new ArrayList<>();
159     private KeyguardControllerState mKeyguardControllerState;
160     private KeyguardServiceDelegateState mKeyguardServiceDelegateState;
161     private final List<String> mPendingActivities = new ArrayList<>();
162     private int mTopFocusedTaskId = -1;
163     private int mFocusedDisplayId = DEFAULT_DISPLAY;
164     private String mFocusedWindow = null;
165     private String mFocusedApp = null;
166     private Boolean mIsHomeRecentsComponent;
167     private String mTopResumedActivityRecord = null;
168     final SparseArray<ArrayList<String>> mResumedActivitiesInRootTasks = new SparseArray<>();
169     final List<String> mResumedActivitiesInDisplays = new ArrayList<>();
170     private Rect mDefaultPinnedStackBounds = new Rect();
171     private Rect mPinnedStackMovementBounds = new Rect();
172     private String mInputMethodWindowAppToken = null;
173     private boolean mDisplayFrozen;
174     private boolean mSanityCheckFocusedWindow = true;
175     private boolean mWindowFramesValid;
176     private BackNavigationState mBackNavigationState;
177 
appStateToString(int appState)178     static String appStateToString(int appState) {
179         switch (appState) {
180             case AppTransitionProto.AppState.APP_STATE_IDLE_VALUE:
181                 return "APP_STATE_IDLE";
182             case AppTransitionProto.AppState.APP_STATE_READY_VALUE:
183                 return "APP_STATE_READY";
184             case AppTransitionProto.AppState.APP_STATE_RUNNING_VALUE:
185                 return "APP_STATE_RUNNING";
186             case AppTransitionProto.AppState.APP_STATE_TIMEOUT_VALUE:
187                 return "APP_STATE_TIMEOUT";
188             default:
189                 fail("Invalid AppTransitionState");
190                 return null;
191         }
192     }
193 
appTransitionToString(int transition)194     static String appTransitionToString(int transition) {
195         switch (transition) {
196             case TransitionTypeEnum.TRANSIT_UNSET_VALUE: {
197                 return "TRANSIT_UNSET";
198             }
199             case TransitionTypeEnum.TRANSIT_NONE_VALUE: {
200                 return "TRANSIT_NONE";
201             }
202             case TransitionTypeEnum.TRANSIT_ACTIVITY_OPEN_VALUE: {
203                 return TRANSIT_ACTIVITY_OPEN;
204             }
205             case TransitionTypeEnum.TRANSIT_ACTIVITY_CLOSE_VALUE: {
206                 return TRANSIT_ACTIVITY_CLOSE;
207             }
208             case TransitionTypeEnum.TRANSIT_TASK_OPEN_VALUE: {
209                 return TRANSIT_TASK_OPEN;
210             }
211             case TransitionTypeEnum.TRANSIT_TASK_CLOSE_VALUE: {
212                 return TRANSIT_TASK_CLOSE;
213             }
214             case TransitionTypeEnum.TRANSIT_TASK_TO_FRONT_VALUE: {
215                 return "TRANSIT_TASK_TO_FRONT";
216             }
217             case TransitionTypeEnum.TRANSIT_TASK_TO_BACK_VALUE: {
218                 return "TRANSIT_TASK_TO_BACK";
219             }
220             case TransitionTypeEnum.TRANSIT_WALLPAPER_CLOSE_VALUE: {
221                 return TRANSIT_WALLPAPER_CLOSE;
222             }
223             case TransitionTypeEnum.TRANSIT_WALLPAPER_OPEN_VALUE: {
224                 return TRANSIT_WALLPAPER_OPEN;
225             }
226             case TransitionTypeEnum.TRANSIT_WALLPAPER_INTRA_OPEN_VALUE: {
227                 return TRANSIT_WALLPAPER_INTRA_OPEN;
228             }
229             case TransitionTypeEnum.TRANSIT_WALLPAPER_INTRA_CLOSE_VALUE: {
230                 return TRANSIT_WALLPAPER_INTRA_CLOSE;
231             }
232             case TransitionTypeEnum.TRANSIT_TASK_OPEN_BEHIND_VALUE: {
233                 return "TRANSIT_TASK_OPEN_BEHIND";
234             }
235             case TransitionTypeEnum.TRANSIT_ACTIVITY_RELAUNCH_VALUE: {
236                 return "TRANSIT_ACTIVITY_RELAUNCH";
237             }
238             case TransitionTypeEnum.TRANSIT_DOCK_TASK_FROM_RECENTS_VALUE: {
239                 return "TRANSIT_DOCK_TASK_FROM_RECENTS";
240             }
241             case TransitionTypeEnum.TRANSIT_KEYGUARD_GOING_AWAY_VALUE: {
242                 return TRANSIT_KEYGUARD_GOING_AWAY;
243             }
244             case TransitionTypeEnum.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER_VALUE: {
245                 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
246             }
247             case TransitionTypeEnum.TRANSIT_KEYGUARD_OCCLUDE_VALUE: {
248                 return TRANSIT_KEYGUARD_OCCLUDE;
249             }
250             case TransitionTypeEnum.TRANSIT_KEYGUARD_UNOCCLUDE_VALUE: {
251                 return TRANSIT_KEYGUARD_UNOCCLUDE;
252             }
253             case TransitionTypeEnum.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN_VALUE: {
254                 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
255             }
256             case TransitionTypeEnum.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE_VALUE: {
257                 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
258             }
259             case TransitionTypeEnum.TRANSIT_CRASHING_ACTIVITY_CLOSE_VALUE: {
260                 return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
261             }
262             default: {
263                 fail("Invalid lastUsedAppTransition");
264                 return null;
265             }
266         }
267     }
268 
269     /**
270      * For a given WindowContainer, traverse down the hierarchy and add all children of type
271      * {@code T} to {@code outChildren}.
272      */
collectDescendantsOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)273     private static <T extends WindowContainer> void collectDescendantsOfType(Class<T> clazz,
274             WindowContainer root, List<T> outChildren) {
275         collectDescendantsOfTypeIf(clazz, t -> true, root, outChildren);
276     }
277 
278     /**
279      * For a given WindowContainer, traverse down the hierarchy and add all children of type
280      * {@code T} to {@code outChildren} if the child passes the test {@code predicate}.
281      */
collectDescendantsOfTypeIf(Class<T> clazz, Predicate<T> predicate, WindowContainer root, List<T> outChildren)282     private static <T extends WindowContainer> void collectDescendantsOfTypeIf(Class<T> clazz,
283             Predicate<T> predicate, WindowContainer root, List<T> outChildren) {
284         // Traverse top to bottom
285         for (int i = root.mChildren.size()-1; i >= 0; i--) {
286             final WindowContainer child = root.mChildren.get(i);
287             if (clazz.isInstance(child)) {
288                 if(predicate.test(clazz.cast(child))) {
289                     outChildren.add(clazz.cast(child));
290                 }
291             }
292             collectDescendantsOfTypeIf(clazz, predicate, child, outChildren);
293         }
294     }
295 
296     /**
297      * For a given WindowContainer, traverse down the hierarchy and add all immediate children of
298      * type {@code T} to {@code outChildren}.
299      */
collectChildrenOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)300     private static <T extends WindowContainer> void collectChildrenOfType(Class<T> clazz,
301             WindowContainer root, List<T> outChildren) {
302         for (int i = root.mChildren.size()-1; i >= 0; i--) {
303             final WindowContainer child = root.mChildren.get(i);
304             if (clazz.isInstance(child)) {
305                 outChildren.add(clazz.cast(child));
306             }
307         }
308     }
309 
310     /** Enable/disable the mFocusedWindow check during the computeState. */
setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow)311     public void setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow) {
312         mSanityCheckFocusedWindow = sanityCheckFocusedWindow;
313     }
314 
computeState()315     public void computeState() {
316         // It is possible the system is in the middle of transition to the right state when we get
317         // the dump. We try a few times to get the information we need before giving up.
318         int retriesLeft = 3;
319         boolean retry = false;
320         byte[] dump = null;
321 
322         log("==============================");
323         log("     WindowManagerState     ");
324         log("==============================");
325 
326         do {
327             if (retry) {
328                 log("***Incomplete AM state. Retrying...");
329                 // Wait half a second between retries for activity manager to finish transitioning.
330                 SystemClock.sleep(500);
331             }
332 
333             if (isTracingFlagEnabled("perfettoWmDumpCts")) {
334                 dump = new WindowManagerTraceMonitor().captureDump();
335             } else {
336                 dump = executeShellCommand(DUMPSYS_WINDOW);
337             }
338 
339             try {
340                 reset();
341                 if (isTracingFlagEnabled("perfettoWmDumpCts")) {
342                     parseDump(dump);
343                 } else {
344                     parseDumpLegacy(dump);
345                 }
346             } catch (IOException ex) {
347                 final String dumpString = new String(dump, StandardCharsets.UTF_8);
348                 if (dumpString.contains("SERVICE \'window\' DUMP TIMEOUT")) {
349                     // retry and log when dump timeout
350                     logE(dumpString);
351                 } else {
352                     throw new RuntimeException("Failed to parse dumpsys:\n"
353                             + new String(dump, StandardCharsets.UTF_8), ex);
354                 }
355             }
356 
357             retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty()
358                     || mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null)
359                     || !mWindowFramesValid
360                     || (mTopResumedActivityRecord == null
361                     || mResumedActivitiesInRootTasks.size() == 0)
362                     && !mKeyguardControllerState.keyguardShowing;
363         } while (retry && retriesLeft-- > 0);
364 
365         if (mRootTasks.isEmpty()) {
366             logE("No root tasks found...");
367         }
368         if (mTopFocusedTaskId == -1) {
369             logE("No focused task found...");
370         }
371         if (mTopResumedActivityRecord == null) {
372             logE("No focused activity found...");
373         }
374         if (mResumedActivitiesInRootTasks.size() == 0) {
375             logE("No resumed activities found...");
376         }
377         if (mWindowStates.isEmpty()) {
378             logE("No Windows found...");
379         }
380         if (mFocusedWindow == null) {
381             logE("No Focused Window...");
382         }
383         if (mFocusedApp == null) {
384             logE("No Focused App...");
385         }
386         if (!mWindowFramesValid) {
387             logE("Window Frames Invalid...");
388         }
389     }
390 
setSuppressAccessibilityServices(boolean suppressAccessibilityServices)391     public void setSuppressAccessibilityServices(boolean suppressAccessibilityServices) {
392         mSuppressAccessibilityServices = suppressAccessibilityServices;
393     }
394 
executeShellCommand(String command)395     private byte[] executeShellCommand(String command) {
396         try {
397             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation(
398                             mSuppressAccessibilityServices ? 0
399                                     : UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES)
400                     .executeShellCommand(command);
401             byte[] buf = new byte[512];
402             int bytesRead;
403             FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
404             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
405             while ((bytesRead = fis.read(buf)) != -1) {
406                 stdout.write(buf, 0, bytesRead);
407             }
408             fis.close();
409             return stdout.toByteArray();
410         } catch (IOException e) {
411             throw new RuntimeException(e);
412         }
413     }
414 
isTracingFlagEnabled(String name)415     private boolean isTracingFlagEnabled(String name) {
416         // TODO(b/215373273): replace with normal flag check. This is a temporary workaround
417         //  to avoid runtime errors like "No static method perfettoWmDumpCts()Z"
418         try {
419             java.lang.reflect.Method flag = android.tracing.Flags.class.getMethod(name);
420             boolean value = (boolean) flag.invoke(null);
421             log("Read flag " + name + ": " + value);
422             return value;
423         } catch (Exception e) {
424             logE("Failed to read flag " + name + ". Assuming disabled.");
425         }
426         return false;
427     }
428 
429     /** Update WindowManagerState state for a newly added DisplayContent. */
updateForDisplayContent(DisplayContent display)430     private void updateForDisplayContent(DisplayContent display) {
431         if (display.mResumedActivity != null) {
432             mResumedActivitiesInDisplays.add(display.mResumedActivity);
433         }
434 
435         for (int i = 0; i < display.mRootTasks.size(); i++) {
436             Task task = display.mRootTasks.get(i);
437             mRootTasks.add(task);
438             addResumedActivity(task);
439         }
440 
441         if (display.mDefaultPinnedStackBounds != null) {
442             mDefaultPinnedStackBounds = display.mDefaultPinnedStackBounds;
443             mPinnedStackMovementBounds = display.mPinnedStackMovementBounds;
444         }
445     }
446 
addResumedActivity(Task task)447     private void addResumedActivity(Task task) {
448         final int numChildTasks = task.mTasks.size();
449         if (numChildTasks > 0) {
450             for (int i = numChildTasks - 1; i >=0; i--) {
451                 addResumedActivity(task.mTasks.get(i));
452             }
453         } else if (task.mResumedActivity != null) {
454             final ArrayList<String> resumedActivities =
455                     mResumedActivitiesInRootTasks.get(task.mDisplayId, new ArrayList<>());
456             resumedActivities.add(task.mResumedActivity);
457             mResumedActivitiesInRootTasks.put(task.mDisplayId, resumedActivities);
458         }
459     }
460 
parseDump(byte[] dump)461     private void parseDump(byte[] dump) throws InvalidProtocolBufferException {
462         reset();
463 
464         Trace trace = Trace.parseFrom(dump);
465 
466         for (int i = 0; i < trace.getPacketCount(); ++i) {
467             TracePacket packet = trace.getPacket(i);
468 
469             if (packet.hasWinscopeExtensions()) {
470                 ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
471                 registry.add(WinscopeExtensionsImpl.windowmanager);
472                 WinscopeExtensions extensions = WinscopeExtensions.parseFrom(
473                         packet.getWinscopeExtensions().toByteArray(), registry);
474                 if (extensions.hasExtension(WinscopeExtensionsImpl.windowmanager)) {
475                     WindowManagerTraceEntry entry =
476                             extensions.getExtension(WinscopeExtensionsImpl.windowmanager);
477                     parseWindowManagerServiceDumpProto(entry.getWindowManagerService());
478                     return;
479                 }
480             }
481         }
482 
483         throw new RuntimeException("Perfetto trace doesn't contain WM packets");
484     }
485 
parseWindowManagerServiceDumpProto(WindowManagerServiceDumpProto state)486     private void parseWindowManagerServiceDumpProto(WindowManagerServiceDumpProto state) {
487         final RootWindowContainerProto root = state.getRootWindowContainer();
488         if (state.hasFocusedWindow()) {
489             mFocusedWindow = state.getFocusedWindow().getTitle();
490         }
491         mRoot = new RootWindowContainer(root);
492         collectDescendantsOfType(DisplayContent.class, mRoot, mDisplays);
493         for (int i = 0; i < mDisplays.size(); i++) {
494             DisplayContent display = mDisplays.get(i);
495             updateForDisplayContent(display);
496         }
497         mKeyguardControllerState = new KeyguardControllerState(
498                 root.hasKeyguardController() ? root.getKeyguardController() : null);
499         mKeyguardServiceDelegateState = new KeyguardServiceDelegateState(
500                 state.getPolicy().hasKeyguardDelegate()
501                         ? state.getPolicy().getKeyguardDelegate()
502                         : null);
503         mFocusedApp = state.getFocusedApp();
504         mFocusedDisplayId = state.getFocusedDisplayId();
505         final DisplayContent focusedDisplay = getDisplay(mFocusedDisplayId);
506         if (focusedDisplay != null) {
507             mTopFocusedTaskId = focusedDisplay.mFocusedRootTaskId;
508             mTopResumedActivityRecord = focusedDisplay.mResumedActivity;
509         }
510         mIsHomeRecentsComponent = new Boolean(root.getIsHomeRecentsComponent());
511 
512         for (int i = 0; i < root.getPendingActivitiesCount(); i++) {
513             mPendingActivities.add(root.getPendingActivities(i).getTitle());
514         }
515 
516         collectDescendantsOfType(WindowState.class, mRoot, mWindowStates);
517 
518         if (state.hasInputMethodWindow()) {
519             mInputMethodWindowAppToken =
520                     Integer.toHexString(state.getInputMethodWindow().getHashCode());
521         }
522         mDisplayFrozen = state.getDisplayFrozen();
523         mWindowFramesValid = state.getWindowFramesValid();
524 
525         mBackNavigationState = new BackNavigationState(state.hasBackNavigation()
526                 ? state.getBackNavigation() : null);
527     }
528 
parseDumpLegacy(byte[] sysDump)529     private void parseDumpLegacy(byte[] sysDump) throws InvalidProtocolBufferNanoException {
530         com.android.server.wm.nano.WindowManagerServiceDumpProto state =
531                 com.android.server.wm.nano.WindowManagerServiceDumpProto.parseFrom(sysDump);
532         final com.android.server.wm.nano.RootWindowContainerProto root = state.rootWindowContainer;
533         if (state.focusedWindow != null) {
534             mFocusedWindow = state.focusedWindow.title;
535         }
536         mRoot = new RootWindowContainer(root);
537         collectDescendantsOfType(DisplayContent.class, mRoot, mDisplays);
538         for (int i = 0; i < mDisplays.size(); i++) {
539             DisplayContent display = mDisplays.get(i);
540             updateForDisplayContent(display);
541         }
542         mKeyguardControllerState = new KeyguardControllerState(root.keyguardController);
543         mKeyguardServiceDelegateState =
544                 new KeyguardServiceDelegateState(state.policy.keyguardDelegate);
545         mFocusedApp = state.focusedApp;
546         mFocusedDisplayId = state.focusedDisplayId;
547         final DisplayContent focusedDisplay = getDisplay(mFocusedDisplayId);
548         if (focusedDisplay != null) {
549             mTopFocusedTaskId = focusedDisplay.mFocusedRootTaskId;
550             mTopResumedActivityRecord = focusedDisplay.mResumedActivity;
551         }
552         mIsHomeRecentsComponent = new Boolean(root.isHomeRecentsComponent);
553 
554         for (int i = 0; i < root.pendingActivities.length; i++) {
555             mPendingActivities.add(root.pendingActivities[i].title);
556         }
557 
558         collectDescendantsOfType(WindowState.class, mRoot, mWindowStates);
559 
560         if (state.inputMethodWindow != null) {
561             mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
562         }
563         mDisplayFrozen = state.displayFrozen;
564         mWindowFramesValid = state.windowFramesValid;
565 
566         mBackNavigationState = new BackNavigationState(state.backNavigation);
567     }
568 
reset()569     private void reset() {
570         mRoot = null;
571         mDisplays.clear();
572         mRootTasks.clear();
573         mWindowStates.clear();
574         mTopFocusedTaskId = -1;
575         mFocusedDisplayId = DEFAULT_DISPLAY;
576         mFocusedWindow = null;
577         mFocusedApp = null;
578         mTopResumedActivityRecord = null;
579         mResumedActivitiesInRootTasks.clear();
580         mResumedActivitiesInDisplays.clear();
581         mKeyguardControllerState = null;
582         mKeyguardServiceDelegateState = null;
583         mIsHomeRecentsComponent = null;
584         mPendingActivities.clear();
585         mDefaultPinnedStackBounds.setEmpty();
586         mPinnedStackMovementBounds.setEmpty();
587         mInputMethodWindowAppToken = null;
588         mDisplayFrozen = false;
589         mWindowFramesValid = false;
590     }
591 
592     /** Returns the focused app on the provided display. */
getFocusedAppOnDisplay(int displayId)593     public String getFocusedAppOnDisplay(int displayId) {
594         return getDisplay(displayId).mFocusedApp;
595     }
596 
getFocusedApp()597     public String getFocusedApp() {
598         return mFocusedApp;
599     }
600 
getFocusedWindow()601     public String getFocusedWindow() {
602         return mFocusedWindow;
603     }
604 
605     /** @return Whether the home activity is the recents component. */
isHomeRecentsComponent()606     public boolean isHomeRecentsComponent() {
607         if (mIsHomeRecentsComponent == null) {
608             computeState();
609         }
610         return mIsHomeRecentsComponent;
611     }
612 
getDisplay(int displayId)613     public DisplayContent getDisplay(int displayId) {
614         for (DisplayContent display : mDisplays) {
615             if (display.mId == displayId) {
616                 return display;
617             }
618         }
619         return null;
620     }
621 
622     /**
623      * Returns the task display area feature id present on a display, or
624      * {@code DisplayAreaOrganizer.FEATURE_UNDEFINED} if task display area not found.
625      * Note: This is required since an activity can be present on more than one task display areas
626      * if there are visible background users.
627      */
getTaskDisplayAreaFeatureIdOnDisplay(ComponentName activityName, int displayId)628     public int getTaskDisplayAreaFeatureIdOnDisplay(ComponentName activityName, int displayId) {
629         final DisplayArea tda = getDisplay(displayId).getTaskDisplayArea(activityName);
630         if (tda != null) {
631             return tda.getFeatureId();
632         }
633         return FEATURE_UNDEFINED;
634     }
635 
636     @Nullable
getTaskDisplayArea(ComponentName activityName)637     public DisplayArea getTaskDisplayArea(ComponentName activityName) {
638         final List<DisplayArea> result = new ArrayList<>();
639         for (DisplayContent display : mDisplays) {
640             final DisplayArea tda = display.getTaskDisplayArea(activityName);
641             if (tda != null) {
642                 result.add(tda);
643             }
644         }
645         assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
646                 .that(result.size()).isAtMost(1);
647 
648         return result.stream().findFirst().orElse(null);
649     }
650 
getTaskDisplayAreaFeatureId(ComponentName activityName)651     public int getTaskDisplayAreaFeatureId(ComponentName activityName) {
652         final DisplayArea taskDisplayArea = getTaskDisplayArea(activityName);
653         if (taskDisplayArea != null) {
654             return taskDisplayArea.getFeatureId();
655         }
656 
657         return FEATURE_UNDEFINED;
658     }
659 
660     @Nullable
getDisplayArea(String windowName)661     public DisplayArea getDisplayArea(String windowName) {
662         final List<DisplayArea> result = new ArrayList<>();
663         for (DisplayContent display : mDisplays) {
664             final DisplayArea da = display.getDisplayArea(windowName);
665             if (da != null) {
666                 result.add(da);
667             }
668         }
669         assertWithMessage("There must be exactly one window among all DisplayAreas.")
670                 .that(result.size()).isAtMost(1);
671 
672         return result.stream().findFirst().orElse(null);
673     }
674 
675     @Nullable
getImeContainer(int displayId)676     public DisplayArea getImeContainer(int displayId) {
677         final DisplayContent displayContent = getDisplay(displayId);
678         if (displayContent == null) {
679             return null;
680         }
681         return displayContent.getImeContainer();
682     }
683 
getFrontRootTaskId(int displayId)684     public int getFrontRootTaskId(int displayId) {
685         return getDisplay(displayId).mRootTasks.get(0).mRootTaskId;
686     }
687 
getFrontRootTaskActivityType(int displayId)688     public int getFrontRootTaskActivityType(int displayId) {
689         return getDisplay(displayId).mRootTasks.get(0).getActivityType();
690     }
691 
getFrontRootTaskWindowingMode(int displayId)692     public int getFrontRootTaskWindowingMode(int displayId) {
693         return getDisplay(displayId).mRootTasks.get(0).getWindowingMode();
694     }
695 
getTopActivityName(int displayId)696     public String getTopActivityName(int displayId) {
697         if (!getDisplay(displayId).mRootTasks.isEmpty()) {
698             final Task topRootTask = getDisplay(displayId).mRootTasks.get(0);
699             final Task topTask = topRootTask.getTopTask();
700             if (!topTask.mActivities.isEmpty()) {
701                 return topTask.mActivities.get(0).name;
702             }
703         }
704         return null;
705     }
706 
getFocusedTaskIdOnDisplay(int displayId)707     int getFocusedTaskIdOnDisplay(int displayId) {
708         return getDisplay(displayId).mFocusedRootTaskId;
709     }
710 
getFocusedTaskId()711     public int getFocusedTaskId() {
712         return mTopFocusedTaskId;
713     }
714 
getFocusedRootTaskActivityType()715     public int getFocusedRootTaskActivityType() {
716         final Task rootTask = getRootTask(mTopFocusedTaskId);
717         return rootTask != null ? rootTask.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
718     }
719 
getFocusedRootTaskWindowingMode()720     public int getFocusedRootTaskWindowingMode() {
721         final Task rootTask = getRootTask(mTopFocusedTaskId);
722         return rootTask != null ? rootTask.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
723     }
724 
725     /** Returns the focused activity on the specified display. */
getFocusedActivityOnDisplay(int displayId)726     public String getFocusedActivityOnDisplay(int displayId) {
727         return getDisplay(displayId).mResumedActivity;
728     }
729 
getFocusedActivity()730     public String getFocusedActivity() {
731         return mTopResumedActivityRecord;
732     }
733 
getResumedActivitiesCount()734     public int getResumedActivitiesCount() {
735         int count = 0;
736         for (int i = 0; i < mResumedActivitiesInRootTasks.size(); i++) {
737             final ArrayList<String> resumedActivities = mResumedActivitiesInRootTasks.valueAt(i);
738             count += resumedActivities.size();
739         }
740         return count;
741     }
742 
getResumedActivitiesCountOnDisplay(int displayId)743     public int getResumedActivitiesCountOnDisplay(int displayId) {
744         final ArrayList<String> resumedActivitiesOnDisplay =
745                 mResumedActivitiesInRootTasks.get(displayId, new ArrayList<>());
746         return resumedActivitiesOnDisplay.size();
747     }
748 
getResumedActivitiesCountInPackage(String packageName)749     public int getResumedActivitiesCountInPackage(String packageName) {
750         final String componentPrefix = packageName + "/";
751         int count = 0;
752         for (int i = mDisplays.size() - 1; i >= 0; --i) {
753             final ArrayList<Task> rootTasks = mDisplays.get(i).getRootTasks();
754             for (int j = rootTasks.size() - 1; j >= 0; --j) {
755                 final String resumedActivity = rootTasks.get(j).mResumedActivity;
756                 if (resumedActivity != null && resumedActivity.startsWith(componentPrefix)) {
757                     count++;
758                 }
759             }
760         }
761         return count;
762     }
763 
getResumedActivityOnDisplay(int displayId)764     public String getResumedActivityOnDisplay(int displayId) {
765         return getDisplay(displayId).mResumedActivity;
766     }
767 
getKeyguardControllerState()768     public KeyguardControllerState getKeyguardControllerState() {
769         return mKeyguardControllerState;
770     }
771 
getKeyguardServiceDelegateState()772     public KeyguardServiceDelegateState getKeyguardServiceDelegateState() {
773         return mKeyguardServiceDelegateState;
774     }
775 
getBackNavigationState()776     public BackNavigationState getBackNavigationState() {
777         return mBackNavigationState;
778     }
779 
containsRootTasks(int windowingMode, int activityType)780     public boolean containsRootTasks(int windowingMode, int activityType) {
781         return countRootTasks(windowingMode, activityType) > 0;
782     }
783 
countRootTasks(int windowingMode, int activityType)784     public int countRootTasks(int windowingMode, int activityType) {
785         int count = 0;
786         for (Task rootTask : mRootTasks) {
787             if (activityType != ACTIVITY_TYPE_UNDEFINED
788                     && activityType != rootTask.getActivityType()) {
789                 continue;
790             }
791             if (windowingMode != WINDOWING_MODE_UNDEFINED
792                     && windowingMode != rootTask.getWindowingMode()) {
793                 continue;
794             }
795             ++count;
796         }
797         return count;
798     }
799 
getRootTask(int taskId)800     public Task getRootTask(int taskId) {
801         for (Task rootTask : mRootTasks) {
802             if (taskId == rootTask.mRootTaskId) {
803                 return rootTask;
804             }
805         }
806         return null;
807     }
808 
getRootTaskByActivityType(int activityType)809     public Task getRootTaskByActivityType(int activityType) {
810         for (Task rootTask : mRootTasks) {
811             if (activityType == rootTask.getActivityType()) {
812                 return rootTask;
813             }
814         }
815         return null;
816     }
817 
818     /** Gets the top root task with the {@code windowingMode}. **/
getTopRootTaskByWindowingMode(int windowingMode)819     public Task getTopRootTaskByWindowingMode(int windowingMode) {
820         for (Task rootTask : mRootTasks) {
821             if (windowingMode == rootTask.getWindowingMode()) {
822                 return rootTask;
823             }
824         }
825         return null;
826     }
827 
getStandardTaskCountByWindowingMode(int windowingMode)828     public int getStandardTaskCountByWindowingMode(int windowingMode) {
829         int count = 0;
830         for (Task rootTask : mRootTasks) {
831             if (rootTask.getActivityType() != ACTIVITY_TYPE_STANDARD) {
832                 continue;
833             }
834             if (rootTask.getWindowingMode() == windowingMode) {
835                 count += rootTask.mTasks.isEmpty() ? 1 : rootTask.mTasks.size();
836             }
837         }
838         return count;
839     }
840 
841     /** Gets the position of root task on its display with the given {@code activityType}. */
getRootTaskIndexByActivityType(int activityType)842     int getRootTaskIndexByActivityType(int activityType) {
843         for (DisplayContent display : mDisplays) {
844             for (int i = 0; i < display.mRootTasks.size(); i++) {
845                 if (activityType == display.mRootTasks.get(i).getActivityType()) {
846                     return i;
847                 }
848             }
849         }
850         return -1;
851     }
852 
853     /** Gets the root task on its display with the given {@code activityName}. */
854     @Nullable
getRootTaskByActivity(ComponentName activityName)855     public Task getRootTaskByActivity(ComponentName activityName) {
856         for (DisplayContent display : mDisplays) {
857             for (int i = display.mRootTasks.size() - 1; i >= 0; --i) {
858                 final Task rootTask = display.mRootTasks.get(i);
859                 if (rootTask.containsActivity(activityName)) return rootTask;
860             }
861         }
862         return null;
863     }
864 
865     /** Get display id by activity on it. */
getDisplayByActivity(ComponentName activityComponent)866     public int getDisplayByActivity(ComponentName activityComponent) {
867         final Task task = getTaskByActivity(activityComponent);
868         if (task == null) {
869             return -1;
870         }
871         return getRootTask(task.mRootTaskId).mDisplayId;
872     }
873 
getDisplays()874     public List<DisplayContent> getDisplays() {
875         return new ArrayList<>(mDisplays);
876     }
877 
getRootTasks()878     public List<Task> getRootTasks() {
879         return new ArrayList<>(mRootTasks);
880     }
881 
getRootTaskCount()882     public int getRootTaskCount() {
883         return mRootTasks.size();
884     }
885 
getDisplayCount()886     public int getDisplayCount() {
887         return mDisplays.size();
888     }
889 
containsActivity(ComponentName activityName)890     public boolean containsActivity(ComponentName activityName) {
891         for (Task rootTask : mRootTasks) {
892             if (rootTask.containsActivity(activityName)) return true;
893         }
894         return false;
895     }
896 
containsNoneOf(Iterable<ComponentName> activityNames)897     public boolean containsNoneOf(Iterable<ComponentName> activityNames) {
898         for (ComponentName activityName : activityNames) {
899             for (Task rootTask : mRootTasks) {
900                 if (rootTask.containsActivity(activityName)) return false;
901             }
902         }
903         return true;
904     }
905 
containsActivityInWindowingMode(ComponentName activityName, int windowingMode)906     public boolean containsActivityInWindowingMode(ComponentName activityName, int windowingMode) {
907         for (Task rootTask : mRootTasks) {
908             final Activity activity = rootTask.getActivity(activityName);
909             if (activity != null && activity.getWindowingMode() == windowingMode) {
910                 return true;
911             }
912         }
913         return false;
914     }
915 
isActivityVisible(ComponentName activityName)916     public boolean isActivityVisible(ComponentName activityName) {
917         for (Task rootTask : mRootTasks) {
918             final Activity activity = rootTask.getActivity(activityName);
919             if (activity != null) return activity.visible;
920         }
921         return false;
922     }
923 
isActivityTranslucent(ComponentName activityName)924     public boolean isActivityTranslucent(ComponentName activityName) {
925         for (Task rootTask : mRootTasks) {
926             final Activity activity = rootTask.getActivity(activityName);
927             if (activity != null) return activity.translucent;
928         }
929         return false;
930     }
931 
isBehindOpaqueActivities(ComponentName activityName)932     public boolean isBehindOpaqueActivities(ComponentName activityName) {
933         final String fullName = getActivityName(activityName);
934         for (Task rootTask : mRootTasks) {
935             final Activity activity =
936                     rootTask.getActivity((a) -> a.name.equals(fullName) || !a.translucent);
937             if (activity != null) {
938                 if (activity.name.equals(fullName)) {
939                     return false;
940                 }
941                 if (!activity.translucent) {
942                     return true;
943                 }
944             }
945         }
946 
947         return false;
948     }
949 
isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName)950     public boolean isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName) {
951         return getTaskDisplayArea(activityName).isIgnoringOrientationRequest();
952     }
953 
hasActivityState(ComponentName activityName, String activityState)954     public boolean hasActivityState(ComponentName activityName, String activityState) {
955         for (Task rootTask : mRootTasks) {
956             final Activity activity = rootTask.getActivity(activityName);
957             if (activity != null) return activity.state.equals(activityState);
958         }
959         return false;
960     }
961 
getActivityProcId(ComponentName activityName)962     int getActivityProcId(ComponentName activityName) {
963         for (Task rootTask : mRootTasks) {
964             final Activity activity = rootTask.getActivity(activityName);
965             if (activity != null) return activity.procId;
966         }
967         return -1;
968     }
969 
isRecentsActivityVisible()970     boolean isRecentsActivityVisible() {
971         final Activity recentsActivity = getRecentsActivity();
972         return recentsActivity != null && recentsActivity.visible;
973     }
974 
getHomeActivityName()975     public ComponentName getHomeActivityName() {
976         Activity activity = getHomeActivity();
977         if (activity == null) {
978             return null;
979         }
980         return ComponentName.unflattenFromString(activity.name);
981     }
982 
getDreamTask()983     Task getDreamTask() {
984         final Task dreamRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_DREAM);
985         if (dreamRootTask != null) {
986             return dreamRootTask.getTopTask();
987         }
988         return null;
989     }
990 
getHomeTask()991     public Task getHomeTask() {
992         final Task homeRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_HOME);
993         if (homeRootTask != null) {
994             return homeRootTask.getTopTask();
995         }
996         return null;
997     }
998 
getRecentsTask()999     private Task getRecentsTask() {
1000         final Task recentsRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_RECENTS);
1001         if (recentsRootTask != null) {
1002             return recentsRootTask.getTopTask();
1003         }
1004         return null;
1005     }
1006 
getHomeActivity()1007     private Activity getHomeActivity() {
1008         final Task homeTask = getHomeTask();
1009         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
1010     }
1011 
getRecentsActivity()1012     private Activity getRecentsActivity() {
1013         final Task recentsTask = getRecentsTask();
1014         return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
1015                 : null;
1016     }
1017 
getRootTaskIdByActivity(ComponentName activityName)1018     public int getRootTaskIdByActivity(ComponentName activityName) {
1019         final Task rootTask = getRootTaskByActivity(activityName);
1020         return  (rootTask == null) ? INVALID_TASK_ID : rootTask.mRootTaskId;
1021     }
1022 
getTaskByActivity(ComponentName activityName)1023     public Task getTaskByActivity(ComponentName activityName) {
1024         return getTaskByActivity(
1025                 activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
1026     }
1027 
getTaskByActivity(ComponentName activityName, int[] excludeTaskIds)1028     public Task getTaskByActivity(ComponentName activityName, int[] excludeTaskIds) {
1029         return getTaskByActivity(activityName, WINDOWING_MODE_UNDEFINED, excludeTaskIds);
1030     }
1031 
getTaskByActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)1032     private Task getTaskByActivity(ComponentName activityName, int windowingMode,
1033             int[] excludeTaskIds) {
1034         Activity activity = getActivity(activityName, windowingMode, excludeTaskIds);
1035         return activity == null ? null : activity.getTask();
1036     }
1037 
1038     @Nullable
getTaskFragmentByActivity(ComponentName activityName)1039     public TaskFragment getTaskFragmentByActivity(ComponentName activityName) {
1040         return getActivity(activityName).getTaskFragment();
1041     }
1042 
getActivity(ComponentName activityName)1043     public Activity getActivity(ComponentName activityName) {
1044         return getActivity(activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
1045     }
1046 
getActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)1047     private Activity getActivity(ComponentName activityName, int windowingMode,
1048             int[] excludeTaskIds) {
1049         for (Task rootTask : mRootTasks) {
1050             if (windowingMode == WINDOWING_MODE_UNDEFINED
1051                     || windowingMode == rootTask.getWindowingMode()) {
1052                 Activity activity = rootTask.getActivity(activityName, excludeTaskIds);
1053                 if (activity != null) return activity;
1054             }
1055         }
1056         return null;
1057     }
1058 
1059     /**
1060      * Get the number of activities in the task, with the option to count only activities with
1061      * specific name.
1062      * @param taskId Id of the task where we're looking for the number of activities.
1063      * @param activityName Optional name of the activity we're interested in.
1064      * @return Number of all activities in the task if activityName is {@code null}, otherwise will
1065      *         report number of activities that have specified name.
1066      */
getActivityCountInTask(int taskId, @Nullable ComponentName activityName)1067     public int getActivityCountInTask(int taskId, @Nullable ComponentName activityName) {
1068         // If activityName is null, count all activities in the task.
1069         // Otherwise count activities that have specified name.
1070         for (Task rootTask : mRootTasks) {
1071             final Task task = rootTask.getTask(taskId);
1072             if (task == null) continue;
1073 
1074             if (activityName == null) {
1075                 return task.mActivities.size();
1076             }
1077             final String fullName = getActivityName(activityName);
1078             int count = 0;
1079             for (Activity activity : task.mActivities) {
1080                 if (activity.name.equals(fullName)) {
1081                     count++;
1082                 }
1083             }
1084             return count;
1085         }
1086         return 0;
1087     }
1088 
getRootTasksCount()1089     public int getRootTasksCount() {
1090         return mRootTasks.size();
1091     }
1092 
getRootTasksCount(int displayId)1093     public int getRootTasksCount(int displayId) {
1094         return getRootTasksCount(t -> t.mDisplayId == displayId);
1095     }
1096 
1097     /**
1098      * Count root tasks with a specific activity type.
1099      */
getRootTaskCountWithActivityType(int activityType)1100     public int getRootTaskCountWithActivityType(int activityType) {
1101         return getRootTasksCount(t -> t.getActivityType() == activityType);
1102     }
1103 
1104     /**
1105      * Count root tasks filtered by the predicate passed as argument.
1106      */
getRootTasksCount(Predicate<? super Task> predicate)1107     public int getRootTasksCount(Predicate<? super Task> predicate) {
1108         return (int) mRootTasks.stream().filter(predicate).count();
1109     }
1110 
pendingActivityContain(ComponentName activityName)1111     boolean pendingActivityContain(ComponentName activityName) {
1112         return mPendingActivities.contains(getActivityName(activityName));
1113     }
1114 
1115     // Get the logical display size of the default display.
getLogicalDisplaySize()1116     public static Point getLogicalDisplaySize() {
1117         WindowManagerState mWmState = new WindowManagerState();
1118         mWmState.computeState();
1119         Rect size = mWmState.getDisplay(DEFAULT_DISPLAY).getDisplayRect();
1120         return new Point(size.width(), size.height());
1121     }
1122 
getDefaultDisplayLastTransition()1123     public String getDefaultDisplayLastTransition() {
1124         return getDisplay(DEFAULT_DISPLAY).getLastTransition();
1125     }
1126 
getDefaultDisplayAppTransitionState()1127     String getDefaultDisplayAppTransitionState() {
1128         return getDisplay(DEFAULT_DISPLAY).getAppTransitionState();
1129     }
1130 
getMatchingVisibleWindowState(final String windowName)1131     public List<WindowState> getMatchingVisibleWindowState(final String windowName) {
1132         return getMatchingWindows(ws -> ws.isSurfaceShown() && windowName.equals(ws.getName()))
1133                 .collect(Collectors.toList());
1134     }
1135 
getMatchingWindows(Predicate<WindowState> condition)1136     public Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) {
1137         return mWindowStates.stream().filter(condition);
1138     }
1139 
1140     @Nullable
getWindowByPackageName(String packageName, int windowType)1141     public WindowState getWindowByPackageName(String packageName, int windowType) {
1142         final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType);
1143         return windowList.isEmpty() ? null : windowList.get(0);
1144     }
1145 
getWindowsByPackageName(String packageName, int... restrictToTypes)1146     public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) {
1147         return getMatchingWindows(ws ->
1148                 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/"))
1149                         && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType()))
1150                 .collect(Collectors.toList());
1151     }
1152 
allActivitiesResumed()1153     public boolean allActivitiesResumed() {
1154         for (Task rootTask : mRootTasks) {
1155             final Activity nonResumedActivity =
1156                     rootTask.getActivity((a) -> !a.state.equals(STATE_RESUMED));
1157             if (nonResumedActivity != null) return false;
1158         }
1159         return true;
1160     }
1161 
hasNotificationShade()1162     public boolean hasNotificationShade() {
1163         computeState();
1164         return !getMatchingWindowType(TYPE_NOTIFICATION_SHADE).isEmpty();
1165     }
1166 
getWindows()1167     public List<WindowState> getWindows() {
1168         return new ArrayList<>(mWindowStates);
1169     }
1170 
getMatchingWindowType(int type)1171     public List<WindowState> getMatchingWindowType(int type) {
1172         return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList());
1173     }
1174 
getAllNavigationBarStates()1175     public List<WindowState> getAllNavigationBarStates() {
1176         return mDisplays.stream()
1177                 .filter(dc -> dc.mProviders != null)
1178                 .flatMap(dc -> dc.mProviders.stream())
1179                 .filter(provider -> (provider.mSource.is(WindowInsets.Type.navigationBars())))
1180                 .map(provider -> getWindowStateForAppToken(provider.mIdentifier.mAppToken))
1181                 .filter(Objects::nonNull)
1182                 .collect(Collectors.toList());
1183     }
1184 
1185     @NonNull
getNavBarWindowsOnDisplay(int displayId)1186     List<WindowState> getNavBarWindowsOnDisplay(int displayId) {
1187         return mDisplays.stream()
1188                 .filter(dc -> dc.mId == displayId)
1189                 .filter(dc -> dc.mProviders != null)
1190                 .flatMap(dc -> dc.mProviders.stream())
1191                 .filter(
1192                         provider ->
1193                                 (provider.mSource.is(WindowInsets.Type.navigationBars())))
1194                 .map(provider -> getWindowStateForAppToken(provider.mIdentifier.mAppToken))
1195                 .filter(Objects::nonNull)
1196                 .collect(Collectors.toList());
1197     }
1198 
getWindowStateForAppToken(String appToken)1199     WindowState getWindowStateForAppToken(String appToken) {
1200         return getMatchingWindows(ws -> ws.getToken().equals(appToken))
1201                 .findFirst()
1202                 .orElse(null);
1203     }
1204 
getFrontWindow()1205     String getFrontWindow() {
1206         if (mWindowStates == null || mWindowStates.isEmpty()) {
1207             return null;
1208         }
1209         return mWindowStates.get(0).getName();
1210     }
1211 
1212     /** Check if there exists a window record with matching windowName. */
containsWindow(String windowName)1213     public boolean containsWindow(String windowName) {
1214         for (WindowState window : mWindowStates) {
1215             if (window.getName().equals(windowName)) {
1216                 return true;
1217             }
1218         }
1219         return false;
1220     }
1221 
1222     /**
1223      * Check if at least one window on {@code displayId}. which matches the specified name has shown
1224      * it's surface.
1225      */
isWindowSurfaceShownOnDisplay(String windowName, int displayId)1226     public boolean isWindowSurfaceShownOnDisplay(String windowName, int displayId) {
1227         for (WindowState window : mWindowStates) {
1228             if (window.getName().equals(windowName) && window.getDisplayId() == displayId) {
1229                 if (window.isSurfaceShown()) {
1230                     return true;
1231                 }
1232             }
1233         }
1234         return false;
1235     }
1236 
1237     /** Check if at least one window which matches the specified name has shown it's surface. */
isWindowSurfaceShown(String windowName)1238     public boolean isWindowSurfaceShown(String windowName) {
1239         for (WindowState window : mWindowStates) {
1240             if (window.getName().equals(windowName)) {
1241                 if (window.isSurfaceShown()) {
1242                     return true;
1243                 }
1244             }
1245         }
1246         return false;
1247     }
1248 
1249     /** Check if at least one window which matches provided window name is visible. */
isWindowVisible(String windowName)1250     public boolean isWindowVisible(String windowName) {
1251         for (WindowState window : mWindowStates) {
1252             if (window.getName().equals(windowName)) {
1253                 if (window.isVisible()) {
1254                     return true;
1255                 }
1256             }
1257         }
1258         return false;
1259     }
1260 
allWindowSurfacesShown(String windowName)1261     public boolean allWindowSurfacesShown(String windowName) {
1262         boolean allShown = false;
1263         for (WindowState window : mWindowStates) {
1264             if (window.getName().equals(windowName)) {
1265                 if (!window.isSurfaceShown()) {
1266                     log("[VISIBLE] not visible" + windowName);
1267                     return false;
1268                 }
1269                 log("[VISIBLE] visible" + windowName);
1270                 allShown = true;
1271             }
1272         }
1273         return allShown;
1274     }
1275 
1276     /** Checks whether the display contains the given activity. */
hasActivityInDisplay(int displayId, ComponentName activityName)1277     public boolean hasActivityInDisplay(int displayId, ComponentName activityName) {
1278         for (Task rootTask : getDisplay(displayId).getRootTasks()) {
1279             if (rootTask.containsActivity(activityName)) {
1280                 return true;
1281             }
1282         }
1283         return false;
1284     }
1285 
findFirstWindowWithType(int type)1286     public WindowState findFirstWindowWithType(int type) {
1287         for (WindowState window : mWindowStates) {
1288             if (window.getType() == type) {
1289                 return window;
1290             }
1291         }
1292         return null;
1293     }
1294 
getZOrder(WindowState w)1295     public int getZOrder(WindowState w) {
1296         return mWindowStates.size() - mWindowStates.indexOf(w);
1297     }
1298 
getStandardRootTaskByWindowingMode(int windowingMode)1299     public Task getStandardRootTaskByWindowingMode(int windowingMode) {
1300         for (Task task : mRootTasks) {
1301             if (task.getActivityType() != ACTIVITY_TYPE_STANDARD) {
1302                 continue;
1303             }
1304             if (task.getWindowingMode() == windowingMode) {
1305                 return task;
1306             }
1307         }
1308         return null;
1309     }
1310 
getInputMethodWindowState()1311     public WindowManagerState.WindowState getInputMethodWindowState() {
1312         return getWindowStateForAppToken(mInputMethodWindowAppToken);
1313     }
1314 
isDisplayFrozen()1315     public boolean isDisplayFrozen() {
1316         return mDisplayFrozen;
1317     }
1318 
getRotation()1319     public int getRotation() {
1320         return getDisplay(DEFAULT_DISPLAY).mRotation;
1321     }
1322 
getLastOrientation()1323     public int getLastOrientation() {
1324         return getDisplay(DEFAULT_DISPLAY).mLastOrientation;
1325     }
1326 
getFocusedDisplayId()1327     public int getFocusedDisplayId() {
1328         return mFocusedDisplayId;
1329     }
1330 
isFixedToUserRotation()1331     public boolean isFixedToUserRotation() {
1332         return getDisplay(DEFAULT_DISPLAY).mIsFixedToUserRotation;
1333     }
1334 
1335     public static class DisplayContent extends DisplayArea {
1336         public int mId;
1337         ArrayList<Task> mRootTasks = new ArrayList<>();
1338         int mFocusedRootTaskId;
1339         String mResumedActivity;
1340         boolean mSingleTaskInstance;
1341         Rect mDefaultPinnedStackBounds = null;
1342         Rect mPinnedStackMovementBounds = null;
1343         int mMinSizeOfResizeableTaskDp;
1344 
1345         private Rect mDisplayRect = new Rect();
1346         private Rect mAppRect = new Rect();
1347         private int mDpi;
1348         private int mFlags;
1349         private String mName;
1350         private int mSurfaceSize;
1351         private String mFocusedApp;
1352         private String mLastTransition;
1353         private String mAppTransitionState;
1354         private int mRotation;
1355         private boolean mFrozenToUserRotation;
1356         private int mUserRotation;
1357         private int mFixedToUserRotationMode;
1358         private int mLastOrientation;
1359         private boolean mIsFixedToUserRotation;
1360         private List<Rect> mKeepClearRects;
1361         private List<InsetsSourceProvider> mProviders;
1362 
DisplayContent(DisplayContentProto proto)1363         DisplayContent(DisplayContentProto proto) {
1364             super(proto.getRootDisplayArea());
1365             mId = proto.getId();
1366             mFocusedRootTaskId = proto.getFocusedRootTaskId();
1367             mSingleTaskInstance = proto.getSingleTaskInstance();
1368             if (proto.hasResumedActivity()) {
1369                 mResumedActivity = proto.getResumedActivity().getTitle();
1370             }
1371             addRootTasks();
1372 
1373             mDpi = proto.getDpi();
1374             if (proto.hasDisplayInfo()) {
1375                 DisplayInfoProto infoProto = proto.getDisplayInfo();
1376                 mDisplayRect.set(0, 0, infoProto.getLogicalWidth(), infoProto.getLogicalHeight());
1377                 mAppRect.set(0, 0, infoProto.getAppWidth(), infoProto.getAppHeight());
1378                 mName = infoProto.getName();
1379                 mFlags = infoProto.getFlags();
1380             }
1381             final DisplayFramesProto displayFramesProto = proto.getDisplayFrames();
1382             mSurfaceSize = proto.getSurfaceSize();
1383             mFocusedApp = proto.getFocusedApp();
1384             mMinSizeOfResizeableTaskDp = proto.getMinSizeOfResizeableTaskDp();
1385             int appState = 0;
1386             int lastTransition = 0;
1387             if (proto.hasAppTransition()) {
1388                 final AppTransitionProto appTransitionProto = proto.getAppTransition();
1389                 appState = appTransitionProto.getAppTransitionState().getNumber();
1390                 lastTransition = appTransitionProto.getLastUsedAppTransition().getNumber();
1391             }
1392             mAppTransitionState = appStateToString(appState);
1393             mLastTransition = appTransitionToString(lastTransition);
1394 
1395             if (proto.hasPinnedTaskController()) {
1396                 PinnedTaskControllerProto pinnedTaskProto = proto.getPinnedTaskController();
1397                 mDefaultPinnedStackBounds = extract(pinnedTaskProto.getDefaultBounds());
1398                 mPinnedStackMovementBounds = extract(pinnedTaskProto.getMovementBounds());
1399             }
1400 
1401             if (proto.hasDisplayRotation()) {
1402                 final DisplayRotationProto rotationProto = proto.getDisplayRotation();
1403                 mRotation = rotationProto.getRotation();
1404                 mFrozenToUserRotation = rotationProto.getFrozenToUserRotation();
1405                 mUserRotation = rotationProto.getUserRotation();
1406                 mFixedToUserRotationMode = rotationProto.getFixedToUserRotationMode();
1407                 mLastOrientation = rotationProto.getLastOrientation();
1408                 mIsFixedToUserRotation = rotationProto.getIsFixedToUserRotation();
1409             }
1410             mKeepClearRects = new ArrayList();
1411             for (int i = 0; i < proto.getKeepClearAreasCount(); ++i) {
1412                 RectProto r = proto.getKeepClearAreas(i);
1413                 mKeepClearRects.add(new Rect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom()));
1414             }
1415             mProviders = new ArrayList<>();
1416             for (int i = 0; i < proto.getInsetsSourceProvidersCount(); ++i) {
1417                 InsetsSourceProviderProto provider = proto.getInsetsSourceProviders(i);
1418                 mProviders.add(new InsetsSourceProvider(provider));
1419             }
1420         }
1421 
DisplayContent(com.android.server.wm.nano.DisplayContentProto proto)1422         DisplayContent(com.android.server.wm.nano.DisplayContentProto proto) {
1423             super(proto.rootDisplayArea);
1424             mId = proto.id;
1425             mFocusedRootTaskId = proto.focusedRootTaskId;
1426             mSingleTaskInstance = proto.singleTaskInstance;
1427             if (proto.resumedActivity != null) {
1428                 mResumedActivity = proto.resumedActivity.title;
1429             }
1430             addRootTasks();
1431 
1432             mDpi = proto.dpi;
1433             android.view.nano.DisplayInfoProto infoProto = proto.displayInfo;
1434             if (infoProto != null) {
1435                 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
1436                 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
1437                 mName = infoProto.name;
1438                 mFlags = infoProto.flags;
1439             }
1440             final com.android.server.wm.nano.DisplayFramesProto displayFramesProto =
1441                     proto.displayFrames;
1442             mSurfaceSize = proto.surfaceSize;
1443             mFocusedApp = proto.focusedApp;
1444             mMinSizeOfResizeableTaskDp = proto.minSizeOfResizeableTaskDp;
1445 
1446             final com.android.server.wm.nano.AppTransitionProto appTransitionProto =
1447                     proto.appTransition;
1448             int appState = 0;
1449             int lastTransition = 0;
1450             if (appTransitionProto != null) {
1451                 appState = appTransitionProto.appTransitionState;
1452                 lastTransition = appTransitionProto.lastUsedAppTransition;
1453             }
1454             mAppTransitionState = appStateToString(appState);
1455             mLastTransition = appTransitionToString(lastTransition);
1456 
1457             com.android.server.wm.nano.PinnedTaskControllerProto pinnedTaskProto =
1458                     proto.pinnedTaskController;
1459             if (pinnedTaskProto != null) {
1460                 mDefaultPinnedStackBounds = extract(pinnedTaskProto.defaultBounds);
1461                 mPinnedStackMovementBounds = extract(pinnedTaskProto.movementBounds);
1462             }
1463 
1464             final com.android.server.wm.nano.DisplayRotationProto rotationProto =
1465                     proto.displayRotation;
1466             if (rotationProto != null) {
1467                 mRotation = rotationProto.rotation;
1468                 mFrozenToUserRotation = rotationProto.frozenToUserRotation;
1469                 mUserRotation = rotationProto.userRotation;
1470                 mFixedToUserRotationMode = rotationProto.fixedToUserRotationMode;
1471                 mLastOrientation = rotationProto.lastOrientation;
1472                 mIsFixedToUserRotation = rotationProto.isFixedToUserRotation;
1473             }
1474             mKeepClearRects = new ArrayList();
1475             for (android.graphics.nano.RectProto r : proto.keepClearAreas) {
1476                 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
1477             }
1478             mProviders = new ArrayList<>();
1479             for (com.android.server.wm.nano.InsetsSourceProviderProto provider :
1480                     proto.insetsSourceProviders) {
1481                 mProviders.add(new InsetsSourceProvider(provider));
1482             }
1483         }
1484 
getName()1485         public String getName() {
1486             return mName;
1487         }
1488 
getMinSizeOfResizeableTaskDp()1489         public int getMinSizeOfResizeableTaskDp() {
1490             return mMinSizeOfResizeableTaskDp;
1491         }
1492 
addRootTasks()1493         private void addRootTasks() {
1494             // TODO(b/149338177): figure out how CTS tests deal with organizer. For now,
1495             //                    don't treat them as regular root tasks
1496             collectDescendantsOfTypeIf(Task.class, t -> t.isRootTask(), this,
1497                     mRootTasks);
1498 
1499             ArrayList<Task> nonOrganizedRootTasks = new ArrayList<>();
1500             for (int i = 0; i < mRootTasks.size(); i++) {
1501                 final Task task = mRootTasks.get(i);
1502                 if (task.mCreatedByOrganizer) {
1503                     // Get all tasks inside the root-task created by an organizer
1504                     List<Task> nonOrganizedDescendants = new ArrayList<>();
1505                     collectDescendantsOfTypeIf(Task.class, t -> !t.mCreatedByOrganizer, task,
1506                             nonOrganizedDescendants);
1507                     nonOrganizedRootTasks.addAll(nonOrganizedDescendants);
1508                 } else {
1509                     nonOrganizedRootTasks.add(task);
1510                 }
1511             }
1512 
1513             mRootTasks.clear();
1514             mRootTasks.addAll(nonOrganizedRootTasks);
1515         }
1516 
containsActivity(ComponentName activityName)1517         boolean containsActivity(ComponentName activityName) {
1518             for (Task task : mRootTasks) {
1519                 if (task.containsActivity(activityName)) return true;
1520             }
1521             return false;
1522         }
1523 
getAllTaskDisplayAreas()1524         public List<DisplayArea> getAllTaskDisplayAreas() {
1525             final List<DisplayArea> taskDisplayAreas = new ArrayList<>();
1526             collectDescendantsOfTypeIf(DisplayArea.class, DisplayArea::isTaskDisplayArea, this,
1527                     taskDisplayAreas);
1528             return taskDisplayAreas;
1529         }
1530 
1531         @Nullable
getTaskDisplayArea(ComponentName activityName)1532         DisplayArea getTaskDisplayArea(ComponentName activityName) {
1533             final List<DisplayArea> taskDisplayAreas = getAllTaskDisplayAreas();
1534             List<DisplayArea> result = taskDisplayAreas.stream().filter(
1535                     tda -> tda.containsActivity(activityName))
1536                     .collect(Collectors.toList());
1537 
1538             assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
1539                     .that(result.size()).isAtMost(1);
1540 
1541             return result.stream().findFirst().orElse(null);
1542         }
1543 
getAllChildDisplayAreas()1544         public List<DisplayArea> getAllChildDisplayAreas() {
1545             final List<DisplayArea> displayAreas = new ArrayList<>();
1546             collectDescendantsOfType(DisplayArea.class,this, displayAreas);
1547             return displayAreas;
1548         }
1549 
1550         @Nullable
getDisplayArea(String windowName)1551         DisplayArea getDisplayArea(String windowName) {
1552             List<DisplayArea> displayAreas = new ArrayList<>();
1553             final Predicate<DisplayArea> p = da -> {
1554                 final boolean containsChildWindowToken = !da.mChildren.isEmpty()
1555                         && da.mChildren.get(0) instanceof WindowToken;
1556                 return !da.isTaskDisplayArea() && containsChildWindowToken;
1557             };
1558             collectDescendantsOfTypeIf(DisplayArea.class, p, this, displayAreas);
1559             List<DisplayArea> result = displayAreas.stream().filter(
1560                     da -> da.containsWindow(windowName))
1561                     .collect(Collectors.toList());
1562 
1563             assertWithMessage("There must be exactly one window among all DisplayAreas.")
1564                     .that(result.size()).isAtMost(1);
1565 
1566             return result.stream().findFirst().orElse(null);
1567         }
1568 
1569         @NonNull
getImeContainer()1570         public DisplayArea getImeContainer() {
1571             final List<DisplayArea> imeContainers = new ArrayList<>();
1572             final Predicate<DisplayArea> p = da -> da.getFeatureId() == FEATURE_IME;
1573             collectDescendantsOfTypeIf(DisplayArea.class, p, this, imeContainers);
1574 
1575             assertWithMessage("There must be exactly one ImeContainer per DisplayContent.")
1576                     .that(imeContainers.size()).isEqualTo(1);
1577 
1578             return imeContainers.get(0);
1579         }
1580 
getRootTasks()1581         public ArrayList<Task> getRootTasks() {
1582             return mRootTasks;
1583         }
1584 
getDpi()1585         public int getDpi() {
1586             return mDpi;
1587         }
1588 
getDisplayRect()1589         public Rect getDisplayRect() {
1590             return mDisplayRect;
1591         }
1592 
getAppRect()1593         public Rect getAppRect() {
1594             return mAppRect;
1595         }
1596 
getFlags()1597         public int getFlags() {
1598             return mFlags;
1599         }
1600 
getSurfaceSize()1601         public int getSurfaceSize() {
1602             return mSurfaceSize;
1603         }
1604 
getFocusedApp()1605         String getFocusedApp() {
1606             return mFocusedApp;
1607         }
1608 
getLastTransition()1609         public String getLastTransition() {
1610             return mLastTransition;
1611         }
1612 
getAppTransitionState()1613         public String getAppTransitionState() {
1614             return mAppTransitionState;
1615         }
1616 
getKeepClearRects()1617         public List<Rect> getKeepClearRects() {
1618             return mKeepClearRects;
1619         }
1620 
1621         @Override
toString()1622         public String toString() {
1623             return "Display #" + mId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
1624                     + " mAppRect=" + mAppRect + " mFlags=" + mFlags;
1625         }
1626 
1627         @Override
equals(Object o)1628         public boolean equals(Object o) {
1629             if (o == this) {
1630                 return true;
1631             }
1632             if (o == null) {
1633                 return false;
1634             }
1635             if (!(o instanceof DisplayContent)) {
1636                 return false;
1637             }
1638 
1639             DisplayContent dc = (DisplayContent) o;
1640 
1641             return (dc.mDisplayRect == null ? mDisplayRect == null
1642                     : dc.mDisplayRect.equals(mDisplayRect))
1643                 && (dc.mAppRect == null ? mAppRect == null : dc.mAppRect.equals(mAppRect))
1644                 && dc.mDpi == mDpi
1645                 && dc.mFlags == mFlags
1646                 && (dc.mName == null ? mName == null : dc.mName.equals(mName))
1647                 && dc.mSurfaceSize == mSurfaceSize
1648                 && (dc.mAppTransitionState == null ? mAppTransitionState == null
1649                     : dc.mAppTransitionState.equals(mAppTransitionState))
1650                 && dc.mRotation == mRotation
1651                 && dc.mFrozenToUserRotation == mFrozenToUserRotation
1652                 && dc.mUserRotation == mUserRotation
1653                 && dc.mFixedToUserRotationMode == mFixedToUserRotationMode
1654                 && dc.mLastOrientation == mLastOrientation
1655                 && dc.mIsFixedToUserRotation == mIsFixedToUserRotation;
1656         }
1657 
1658         @Override
hashCode()1659         public int hashCode() {
1660             int result = 0;
1661             if (mDisplayRect != null) {
1662                 result = 31 * result + mDisplayRect.hashCode();
1663             }
1664             if (mAppRect != null) {
1665                 result = 31 * result + mAppRect.hashCode();
1666             }
1667             result = 31 * result + mDpi;
1668             result = 31 * result + mFlags;
1669             if (mName != null) {
1670                 result = 31 * result + mName.hashCode();
1671             }
1672             result = 31 * result + mSurfaceSize;
1673             if (mAppTransitionState != null) {
1674                 result = 31 * result + mAppTransitionState.hashCode();
1675             }
1676             result = 31 * result + mRotation;
1677             result = 31 * result + Boolean.hashCode(mFrozenToUserRotation);
1678             result = 31 * result + mUserRotation;
1679             result = 31 * result + mFixedToUserRotationMode;
1680             result = 31 * result + mLastOrientation;
1681             result = 31 * result + Boolean.hashCode(mIsFixedToUserRotation);
1682             return result;
1683         }
1684     }
1685 
1686     public static class Task extends ActivityContainer {
1687         int mTaskId;
1688         int mRootTaskId;
1689         public int mDisplayId;
1690         Rect mLastNonFullscreenBounds;
1691         String mRealActivity;
1692         String mOrigActivity;
1693         ArrayList<Task> mTasks = new ArrayList<>();
1694         /** Contains TaskFragment but not Task children */
1695         ArrayList<TaskFragment> mTaskFragments = new ArrayList<>();
1696         ArrayList<Activity> mActivities = new ArrayList<>();
1697         int mTaskType;
1698         private int mResizeMode;
1699         String mResumedActivity;
1700         boolean mAnimatingBounds;
1701         private int mSurfaceWidth;
1702         private int mSurfaceHeight;
1703         boolean mCreatedByOrganizer;
1704         String mAffinity;
1705         boolean mHasChildPipActivity;
1706         WindowContainer mParent;
1707 
Task(TaskProto proto, WindowContainer parent)1708         Task(TaskProto proto, WindowContainer parent) {
1709             super(proto.getTaskFragment().getWindowContainer());
1710             mTaskId = proto.getId();
1711             mRootTaskId = proto.getRootTaskId();
1712             mParent = parent;
1713             mDisplayId = proto.getTaskFragment().getDisplayId();
1714             mLastNonFullscreenBounds = extract(proto.getLastNonFullscreenBounds());
1715             mRealActivity = proto.getRealActivity();
1716             mOrigActivity = proto.getOrigActivity();
1717             mTaskType = proto.getTaskFragment().getActivityType();
1718             mResizeMode = proto.getResizeMode();
1719             mFullscreen = proto.getFillsParent();
1720             mBounds = extract(proto.getBounds());
1721             mMinWidth = proto.getTaskFragment().getMinWidth();
1722             mMinHeight = proto.getTaskFragment().getMinHeight();
1723             mAnimatingBounds = proto.getAnimatingBounds();
1724             mSurfaceWidth = proto.getSurfaceWidth();
1725             mSurfaceHeight = proto.getSurfaceHeight();
1726             mCreatedByOrganizer = proto.getCreatedByOrganizer();
1727             mAffinity = proto.getAffinity();
1728             mHasChildPipActivity = proto.getHasChildPipActivity();
1729 
1730             if (proto.hasResumedActivity()) {
1731                 mResumedActivity = proto.getResumedActivity().getTitle();
1732             }
1733 
1734             collectChildrenOfType(Task.class, this, mTasks);
1735             collectChildrenOfType(TaskFragment.class, this, mTaskFragments);
1736             collectChildrenOfType(Activity.class, this, mActivities);
1737         }
1738 
Task(com.android.server.wm.nano.TaskProto proto, WindowContainer parent)1739         Task(com.android.server.wm.nano.TaskProto proto, WindowContainer parent) {
1740             super(proto.taskFragment.windowContainer);
1741             mTaskId = proto.id;
1742             mRootTaskId = proto.rootTaskId;
1743             mParent = parent;
1744             mDisplayId = proto.taskFragment.displayId;
1745             mLastNonFullscreenBounds = extract(proto.lastNonFullscreenBounds);
1746             mRealActivity = proto.realActivity;
1747             mOrigActivity = proto.origActivity;
1748             mTaskType = proto.taskFragment.activityType;
1749             mResizeMode = proto.resizeMode;
1750             mFullscreen = proto.fillsParent;
1751             mBounds = extract(proto.bounds);
1752             mMinWidth = proto.taskFragment.minWidth;
1753             mMinHeight = proto.taskFragment.minHeight;
1754             mAnimatingBounds = proto.animatingBounds;
1755             mSurfaceWidth = proto.surfaceWidth;
1756             mSurfaceHeight = proto.surfaceHeight;
1757             mCreatedByOrganizer = proto.createdByOrganizer;
1758             mAffinity = proto.affinity;
1759             mHasChildPipActivity = proto.hasChildPipActivity;
1760 
1761             if (proto.resumedActivity != null) {
1762                 mResumedActivity = proto.resumedActivity.title;
1763             }
1764 
1765             collectChildrenOfType(Task.class, this, mTasks);
1766             collectChildrenOfType(TaskFragment.class, this, mTaskFragments);
1767             collectChildrenOfType(Activity.class, this, mActivities);
1768         }
1769 
isEmpty()1770         boolean isEmpty() {
1771             return mTasks.isEmpty() && mTaskFragments.isEmpty() && mActivities.isEmpty();
1772         }
1773 
getRealActivity()1774         public String getRealActivity() {
1775             return mRealActivity;
1776         }
1777 
hasChildPipActivity()1778         public boolean hasChildPipActivity() {
1779             return mHasChildPipActivity;
1780         }
1781 
1782         /** Gets the pure parent TaskFragment if exist. */
getParentTaskFragment()1783         public TaskFragment getParentTaskFragment() {
1784             if (mParent instanceof TaskFragment) {
1785                 return (TaskFragment) mParent;
1786             }
1787             if (mParent instanceof Task) {
1788                 return ((Task) mParent).getParentTaskFragment();
1789             }
1790             // If the parent is a TaskDisplayArea, it means this Task doesn't have TaskFragment
1791             // parent.
1792             return null;
1793         }
1794 
getResizeMode()1795         public int getResizeMode() {
1796             return mResizeMode;
1797         }
1798 
getTaskId()1799         public int getTaskId() {
1800             return mTaskId;
1801         }
isRootTask()1802         boolean isRootTask() {
1803             return mTaskId == mRootTaskId;
1804         }
1805 
isLeafTask()1806         boolean isLeafTask() {
1807             return mTasks.size() == 0;
1808         }
1809 
getRootTaskId()1810         public int getRootTaskId() {
1811             return mRootTaskId;
1812         }
1813 
getSurfaceWidth()1814         public int getSurfaceWidth() {
1815             return mSurfaceWidth;
1816         }
1817 
getSurfaceHeight()1818         public int getSurfaceHeight() {
1819             return mSurfaceHeight;
1820         }
1821 
getAffinity()1822         public String getAffinity() {
1823             return mAffinity;
1824         }
1825 
getActivities()1826         public ArrayList<Activity> getActivities() {
1827             return mActivities;
1828         }
1829 
1830         /** @return the top task in the root task. */
getTopTask()1831         public Task getTopTask() {
1832             // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom,
1833             //       so the indices are inverted
1834             return getTask((t) -> true);
1835         }
1836 
getResumedActivity()1837         public String getResumedActivity() {
1838             return mResumedActivity;
1839         }
1840 
getTasks()1841         public List<Task> getTasks() {
1842             return new ArrayList<>(mTasks);
1843         }
1844 
1845         /** Returns non-Task leaf {@link TaskFragment} list. */
getTaskFragments()1846         public List<TaskFragment> getTaskFragments() {
1847             return new ArrayList<>(mTaskFragments);
1848         }
1849 
getTask(Predicate<Task> predicate)1850         Task getTask(Predicate<Task> predicate) {
1851             for (Task task : mTasks) {
1852                 if (predicate.test(task)) return task;
1853             }
1854             return predicate.test(this) ? this : null;
1855         }
1856 
getTask(int taskId)1857         Task getTask(int taskId) {
1858             return getTask((t) -> t.mTaskId == taskId);
1859         }
1860 
forAllTasks(Consumer<Task> consumer)1861         void forAllTasks(Consumer<Task> consumer) {
1862             for (Task task : mTasks) {
1863                 consumer.accept(task);
1864             }
1865             consumer.accept(this);
1866         }
1867 
getActivity(Predicate<Activity> predicate)1868         Activity getActivity(Predicate<Activity> predicate) {
1869             for (Activity activity : mActivities) {
1870                 if (predicate.test(activity)) return activity;
1871             }
1872             for (TaskFragment taskFragment : mTaskFragments) {
1873                 final Activity activity = taskFragment.getActivity(predicate);
1874                 if (activity != null) return activity;
1875             }
1876             for (Task task : mTasks) {
1877                 final Activity activity = task.getActivity(predicate);
1878                 if (activity != null) return activity;
1879             }
1880             return null;
1881         }
1882 
getActivity(ComponentName activityName)1883         public Activity getActivity(ComponentName activityName) {
1884             final String fullName = getActivityName(activityName);
1885             return getActivity((activity) -> activity.name.equals(fullName));
1886         }
1887 
getActivity(ComponentName activityName, int[] excludeTaskIds)1888         public Activity getActivity(ComponentName activityName, int[] excludeTaskIds) {
1889             final String fullName = getActivityName(activityName);
1890             return getActivity((activity) -> {
1891                 if (!activity.name.equals(fullName)) {
1892                     return false;
1893                 }
1894                 for (int excludeTaskId : excludeTaskIds) {
1895                     if (activity.getTask().mTaskId == excludeTaskId) {
1896                         return false;
1897                     }
1898                 }
1899                 return true;
1900             });
1901         }
1902 
containsActivity(ComponentName activityName)1903         public boolean containsActivity(ComponentName activityName) {
1904             return getActivity(activityName) != null;
1905         }
1906 
getActivityCount()1907         public int getActivityCount() {
1908             int count = mActivities.size();
1909             for (TaskFragment taskFragment : mTaskFragments) {
1910                 count += taskFragment.getActivityCount();
1911             }
1912             for (Task task : mTasks) {
1913                 count += task.getActivityCount();
1914             }
1915             return count;
1916         }
1917 
1918         @Override
getActivityType()1919         int getActivityType() {
1920             return mTaskType;
1921         }
1922 
1923         @Override
toString()1924         public String toString() {
1925             return "Task[id=" + mTaskId + ", display=" + mDisplayId
1926                     + ", mOrigActivity=" + mOrigActivity + ", realActivity=" + mRealActivity
1927                     + ", activities=" + mActivities + "]";
1928         }
1929     }
1930 
1931     public static class TaskFragment extends ActivityContainer {
1932         public int mDisplayId;
1933         Task mParentTask;
1934         ArrayList<Activity> mActivities = new ArrayList<>();
1935         int mTaskFragmentType;
1936 
1937         TaskFragment(TaskFragmentProto proto, WindowContainer parent) {
1938             super(proto.getWindowContainer());
1939             mParentTask = (Task) parent;
1940             mDisplayId = proto.getDisplayId();
1941             mTaskFragmentType = proto.getActivityType();
1942             mMinWidth = proto.getMinWidth();
1943             mMinHeight = proto.getMinHeight();
1944 
1945             collectChildrenOfType(Activity.class, this, mActivities);
1946         }
1947 
1948         TaskFragment(com.android.server.wm.nano.TaskFragmentProto proto, WindowContainer parent) {
1949             super(proto.windowContainer);
1950             mParentTask = (Task) parent;
1951             mDisplayId = proto.displayId;
1952             mTaskFragmentType = proto.activityType;
1953             mMinWidth = proto.minWidth;
1954             mMinHeight = proto.minHeight;
1955 
1956             collectChildrenOfType(Activity.class, this, mActivities);
1957         }
1958 
1959         public List<Activity> getActivities() {
1960             return mActivities;
1961         }
1962 
1963         Activity getActivity(Predicate<Activity> predicate) {
1964             for (Activity activity : mActivities) {
1965                 if (predicate.test(activity)) {
1966                     return activity;
1967                 }
1968             }
1969             return null;
1970         }
1971 
1972         public int getActivityCount() {
1973             return mActivities.size();
1974         }
1975 
1976         @Override
1977         int getActivityType() {
1978             return mTaskFragmentType;
1979         }
1980     }
1981 
1982     public static class Activity extends ActivityContainer {
1983 
1984         String name;
1985         String state;
1986         boolean visible;
1987         boolean frontOfTask;
1988         boolean inSizeCompatMode;
1989         float minAspectRatio;
1990         boolean providesMaxBounds;
1991         int procId = -1;
1992         boolean isAnimating;
1993         public boolean translucent;
1994         private WindowContainer mParent;
1995         private boolean mEnableRecentsScreenshot;
1996         private int mLastDropInputMode;
1997         private boolean mShouldSendCompatFakeFocus;
1998         private int mOverrideOrientation;
1999         private boolean mShouldForceRotateForCameraCompat;
2000         private boolean mShouldRefreshActivityForCameraCompat;
2001         private boolean mShouldRefreshActivityViaPauseForCameraCompat;
2002         private boolean mShouldOverrideMinAspectRatio;
2003         private boolean mShouldIgnoreOrientationRequestLoop;
2004         private boolean mShouldOverrideForceResizeApp;
2005         private boolean mShouldEnableUserAspectRatioSettings;
2006         private boolean mIsUserFullscreenOverrideEnabled;
2007         private long mRequestOpenInBrowserEducationTimestamp;
2008 
2009         Activity(ActivityRecordProto proto, WindowContainer parent) {
2010             super(proto.getWindowToken().getWindowContainer());
2011             name = proto.getName();
2012             state = proto.getState();
2013             visible = proto.getVisible();
2014             frontOfTask = proto.getFrontOfTask();
2015             inSizeCompatMode = proto.getInSizeCompatMode();
2016             minAspectRatio = proto.getMinAspectRatio();
2017             providesMaxBounds = proto.getProvidesMaxBounds();
2018             if (proto.hasProcId()) {
2019                 procId = proto.getProcId();
2020             }
2021             isAnimating = proto.getIsAnimating();
2022             translucent = proto.getTranslucent();
2023             mEnableRecentsScreenshot = proto.getEnableRecentsScreenshot();
2024             mLastDropInputMode = proto.getLastDropInputMode();
2025             mShouldSendCompatFakeFocus = proto.getShouldSendCompatFakeFocus();
2026             mOverrideOrientation = proto.getOverrideOrientation();
2027             mParent = parent;
2028             mShouldForceRotateForCameraCompat = proto.getShouldForceRotateForCameraCompat();
2029             mShouldRefreshActivityForCameraCompat = proto.getShouldRefreshActivityForCameraCompat();
2030             mShouldRefreshActivityViaPauseForCameraCompat =
2031                     proto.getShouldRefreshActivityViaPauseForCameraCompat();
2032             mShouldOverrideMinAspectRatio = proto.getShouldOverrideMinAspectRatio();
2033             mShouldIgnoreOrientationRequestLoop = proto.getShouldIgnoreOrientationRequestLoop();
2034             mShouldOverrideForceResizeApp = proto.getShouldOverrideForceResizeApp();
2035             mShouldEnableUserAspectRatioSettings = proto.getShouldEnableUserAspectRatioSettings();
2036             mIsUserFullscreenOverrideEnabled = proto.getIsUserFullscreenOverrideEnabled();
2037         }
2038 
2039         Activity(com.android.server.wm.nano.ActivityRecordProto proto, WindowContainer parent) {
2040             super(proto.windowToken.windowContainer);
2041             name = proto.name;
2042             state = proto.state;
2043             visible = proto.visible;
2044             frontOfTask = proto.frontOfTask;
2045             inSizeCompatMode = proto.inSizeCompatMode;
2046             minAspectRatio = proto.minAspectRatio;
2047             providesMaxBounds = proto.providesMaxBounds;
2048             if (proto.procId != 0) {
2049                 procId = proto.procId;
2050             }
2051             isAnimating = proto.isAnimating;
2052             translucent = proto.translucent;
2053             mEnableRecentsScreenshot = proto.enableRecentsScreenshot;
2054             mLastDropInputMode = proto.lastDropInputMode;
2055             mShouldSendCompatFakeFocus = proto.shouldSendCompatFakeFocus;
2056             mOverrideOrientation = proto.overrideOrientation;
2057             mParent = parent;
2058             mShouldForceRotateForCameraCompat = proto.shouldForceRotateForCameraCompat;
2059             mShouldRefreshActivityForCameraCompat = proto.shouldRefreshActivityForCameraCompat;
2060             mShouldRefreshActivityViaPauseForCameraCompat =
2061                     proto.shouldRefreshActivityViaPauseForCameraCompat;
2062             mShouldOverrideMinAspectRatio = proto.shouldOverrideMinAspectRatio;
2063             mShouldIgnoreOrientationRequestLoop = proto.shouldIgnoreOrientationRequestLoop;
2064             mShouldOverrideForceResizeApp = proto.shouldOverrideForceResizeApp;
2065             mShouldEnableUserAspectRatioSettings = proto.shouldEnableUserAspectRatioSettings;
2066             mIsUserFullscreenOverrideEnabled = proto.isUserFullscreenOverrideEnabled;
2067             mRequestOpenInBrowserEducationTimestamp = proto.requestOpenInBrowserEducationTimestamp;
2068         }
2069 
2070         @NonNull
2071         public Task getTask() {
2072             if (mParent instanceof Task) {
2073                 return (Task) mParent;
2074             }
2075             return ((TaskFragment) mParent).mParentTask;
2076         }
2077 
2078         @Nullable
2079         public TaskFragment getTaskFragment() {
2080             if (mParent instanceof TaskFragment) {
2081                 return (TaskFragment) mParent;
2082             }
2083             return ((Task) mParent).getParentTaskFragment();
2084         }
2085 
2086         public String getName() {
2087             return name;
2088         }
2089 
2090         public String getState() {
2091             return state;
2092         }
2093 
2094         public boolean inSizeCompatMode() {
2095             return inSizeCompatMode;
2096         }
2097 
2098         public boolean isAnimating() {
2099             return isAnimating;
2100         }
2101 
2102         public float getMinAspectRatio() {
2103             return minAspectRatio;
2104         }
2105 
2106         public boolean providesMaxBounds() {
2107             return providesMaxBounds;
2108         }
2109 
2110         public boolean enableRecentsScreenshot() {
2111             return mEnableRecentsScreenshot;
2112         }
2113 
2114         public int getLastDropInputMode() {
2115             return mLastDropInputMode;
2116         }
2117 
2118         public boolean getShouldSendCompatFakeFocus() {
2119             return mShouldSendCompatFakeFocus;
2120         }
2121 
2122         public int getUiMode() {
2123             return mFullConfiguration.uiMode;
2124         }
2125 
2126         public int getOverrideOrientation() {
2127             return mOverrideOrientation;
2128         }
2129 
2130         public boolean getShouldForceRotateForCameraCompat() {
2131             return mShouldForceRotateForCameraCompat;
2132         }
2133 
2134         public boolean getShouldRefreshActivityForCameraCompat() {
2135             return mShouldRefreshActivityForCameraCompat;
2136         }
2137 
2138         public boolean getShouldRefreshActivityViaPauseForCameraCompat() {
2139             return mShouldRefreshActivityViaPauseForCameraCompat;
2140         }
2141 
2142         public boolean getShouldOverrideMinAspectRatio() {
2143             return mShouldOverrideMinAspectRatio;
2144         }
2145 
2146         public boolean getShouldIgnoreOrientationRequestLoop() {
2147             return mShouldIgnoreOrientationRequestLoop;
2148         }
2149 
2150         public boolean getShouldOverrideForceResizeApp() {
2151             return mShouldOverrideForceResizeApp;
2152         }
2153 
2154         public boolean getShouldEnableUserAspectRatioSettings() {
2155             return mShouldEnableUserAspectRatioSettings;
2156         }
2157 
2158         public boolean getIsUserFullscreenOverrideEnabled() {
2159             return mIsUserFullscreenOverrideEnabled;
2160         }
2161 
2162         public long getRequestOpenInBrowserEducationTimestamp() {
2163             return mRequestOpenInBrowserEducationTimestamp;
2164         }
2165 
2166         @Override
2167         public Rect getBounds() {
2168             if (mBounds == null) {
2169                 return mFullConfiguration.windowConfiguration.getBounds();
2170             }
2171             return mBounds;
2172         }
2173 
2174         public Rect getMaxBounds() {
2175             return mFullConfiguration.windowConfiguration.getMaxBounds();
2176         }
2177 
2178         public Rect getAppBounds() {
2179             return mFullConfiguration.windowConfiguration.getAppBounds();
2180         }
2181 
2182         @Override
2183         public String toString() {
2184             return "Activity[name=" + name + ", state=" + state + ", visible=" + visible + "]";
2185         }
2186     }
2187 
2188     static abstract class ActivityContainer extends WindowContainer {
2189         protected boolean mFullscreen;
2190         protected Rect mBounds;
2191         protected int mMinWidth = -1;
2192         protected int mMinHeight = -1;
2193 
2194         ActivityContainer(WindowContainerProto proto) {
2195             super(proto);
2196         }
2197 
2198         ActivityContainer(com.android.server.wm.nano.WindowContainerProto proto) {
2199             super(proto);
2200         }
2201 
2202         public Rect getBounds() {
2203             return mBounds;
2204         }
2205 
2206         public boolean isFullscreen() {
2207             return mFullscreen;
2208         }
2209 
2210         int getMinWidth() {
2211             return mMinWidth;
2212         }
2213 
2214         int getMinHeight() {
2215             return mMinHeight;
2216         }
2217     }
2218 
2219     public static class KeyguardControllerState {
2220 
2221         boolean aodShowing = false;
2222         boolean keyguardShowing = false;
2223         boolean mKeyguardGoingAway = false;
2224         SparseArray<Boolean> mKeyguardOccludedStates = new SparseArray<>();
2225 
2226         public boolean isKeyguardShowing() {
2227             return keyguardShowing;
2228         }
2229 
2230         public boolean isKeyguardGoingAway() {
2231             return mKeyguardGoingAway;
2232         }
2233 
2234         public boolean isAodShowing() {
2235             return aodShowing;
2236         }
2237 
2238         public SparseArray<Boolean> getKeyguardOccludedStates() {
2239             return mKeyguardOccludedStates;
2240         }
2241 
2242         KeyguardControllerState(KeyguardControllerProto proto) {
2243             if (proto != null) {
2244                 aodShowing = proto.getAodShowing();
2245                 keyguardShowing = proto.getKeyguardShowing();
2246                 mKeyguardGoingAway = proto.getKeyguardGoingAway();
2247                 for (int i = 0;  i < proto.getKeyguardPerDisplayCount(); i++) {
2248                     mKeyguardOccludedStates.append(proto.getKeyguardPerDisplay(i).getDisplayId(),
2249                             proto.getKeyguardPerDisplay(i).getKeyguardOccluded());
2250                 }
2251             }
2252         }
2253 
2254         KeyguardControllerState(com.android.server.wm.nano.KeyguardControllerProto proto) {
2255             if (proto != null) {
2256                 aodShowing = proto.aodShowing;
2257                 keyguardShowing = proto.keyguardShowing;
2258                 mKeyguardGoingAway = proto.keyguardGoingAway;
2259                 for (int i = 0;  i < proto.keyguardPerDisplay.length; i++) {
2260                     mKeyguardOccludedStates.append(proto.keyguardPerDisplay[i].displayId,
2261                             proto.keyguardPerDisplay[i].keyguardOccluded);
2262                 }
2263             }
2264         }
2265 
2266         boolean isKeyguardOccluded(int displayId) {
2267             if (mKeyguardOccludedStates.get(displayId) != null) {
2268                 return mKeyguardOccludedStates.get(displayId);
2269             }
2270             return false;
2271         }
2272     }
2273 
2274     static class KeyguardServiceDelegateState {
2275 
2276         // copy from KeyguardServiceDelegate.java
2277         private static final int INTERACTIVE_STATE_SLEEP = 0;
2278         private static final int INTERACTIVE_STATE_WAKING = 1;
2279         private static final int INTERACTIVE_STATE_AWAKE = 2;
2280         private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 3;
2281 
2282         private int mInteractiveState = -1;
2283 
2284         KeyguardServiceDelegateState(KeyguardServiceDelegateProto proto) {
2285             if (proto != null) {
2286                 mInteractiveState = proto.getInteractiveState().getNumber();
2287             }
2288         }
2289 
2290         KeyguardServiceDelegateState(
2291                 com.android.server.wm.nano.KeyguardServiceDelegateProto proto) {
2292             if (proto != null) {
2293                 mInteractiveState = proto.interactiveState;
2294             }
2295         }
2296 
2297         boolean isKeyguardAwake() {
2298             return mInteractiveState == INTERACTIVE_STATE_AWAKE;
2299         }
2300     }
2301 
2302     public static class ConfigurationContainer {
2303         final Configuration mOverrideConfiguration = new Configuration();
2304         final Configuration mFullConfiguration = new Configuration();
2305         final Configuration mMergedOverrideConfiguration = new Configuration();
2306 
2307         ConfigurationContainer(ConfigurationContainerProto proto) {
2308             if (proto == null) {
2309                 return;
2310             }
2311             mOverrideConfiguration.setTo(extract(proto.getOverrideConfiguration()));
2312             mFullConfiguration.setTo(extract(proto.getFullConfiguration()));
2313             mMergedOverrideConfiguration.setTo(extract(proto.getMergedOverrideConfiguration()));
2314         }
2315 
2316         ConfigurationContainer(com.android.server.wm.nano.ConfigurationContainerProto proto) {
2317             if (proto == null) {
2318                 return;
2319             }
2320             mOverrideConfiguration.setTo(extract(proto.overrideConfiguration));
2321             mFullConfiguration.setTo(extract(proto.fullConfiguration));
2322             mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration));
2323         }
2324 
2325         public Configuration getOverrideConfiguration() {
2326             return mOverrideConfiguration;
2327         }
2328 
2329         public Configuration getFullConfiguration() {
2330             return mFullConfiguration;
2331         }
2332 
2333         public Configuration getMergedOverrideConfiguration() {
2334             return mMergedOverrideConfiguration;
2335         }
2336 
2337         boolean isWindowingModeCompatible(int requestedWindowingMode) {
2338             if (requestedWindowingMode == WINDOWING_MODE_UNDEFINED) {
2339                 return true;
2340             }
2341             return getWindowingMode() == requestedWindowingMode;
2342         }
2343 
2344         public int getWindowingMode() {
2345             if (mFullConfiguration == null) {
2346                 return WINDOWING_MODE_UNDEFINED;
2347             }
2348             return mFullConfiguration.windowConfiguration.getWindowingMode();
2349         }
2350 
2351         int getActivityType() {
2352             if (mFullConfiguration == null) {
2353                 return ACTIVITY_TYPE_UNDEFINED;
2354             }
2355             return mFullConfiguration.windowConfiguration.getActivityType();
2356         }
2357     }
2358 
2359     public static class RootWindowContainer extends WindowContainer {
2360         RootWindowContainer(RootWindowContainerProto proto) {
2361             super(proto.getWindowContainer());
2362         }
2363 
2364         RootWindowContainer(com.android.server.wm.nano.RootWindowContainerProto proto) {
2365             super(proto.windowContainer);
2366         }
2367     }
2368     public static class DisplayArea extends WindowContainer {
2369         private final boolean mIsTaskDisplayArea;
2370         private final boolean mIsRootDisplayArea;
2371         private final int mFeatureId;
2372         private final boolean mIsOrganized;
2373         private final boolean mIsIgnoringOrientationRequest;
2374         private ArrayList<Activity> mActivities;
2375         private final ArrayList<WindowState> mWindows = new ArrayList<>();
2376 
2377         DisplayArea(DisplayAreaProto proto) {
2378             super(proto.getWindowContainer());
2379             mIsTaskDisplayArea = proto.getIsTaskDisplayArea();
2380             mIsRootDisplayArea = proto.getIsRootDisplayArea();
2381             mFeatureId = proto.getFeatureId();
2382             mIsOrganized = proto.getIsOrganized();
2383             mIsIgnoringOrientationRequest = proto.getIsIgnoringOrientationRequest();
2384             if (mIsTaskDisplayArea) {
2385                 mActivities = new ArrayList<>();
2386                 collectDescendantsOfType(Activity.class, this, mActivities);
2387             }
2388             collectDescendantsOfType(WindowState.class, this, mWindows);
2389         }
2390 
2391         DisplayArea(com.android.server.wm.nano.DisplayAreaProto proto) {
2392             super(proto.windowContainer);
2393             mIsTaskDisplayArea = proto.isTaskDisplayArea;
2394             mIsRootDisplayArea = proto.isRootDisplayArea;
2395             mFeatureId = proto.featureId;
2396             mIsOrganized = proto.isOrganized;
2397             mIsIgnoringOrientationRequest = proto.isIgnoringOrientationRequest;
2398             if (mIsTaskDisplayArea) {
2399                 mActivities = new ArrayList<>();
2400                 collectDescendantsOfType(Activity.class, this, mActivities);
2401             }
2402             collectDescendantsOfType(WindowState.class, this, mWindows);
2403         }
2404 
2405         public boolean isTaskDisplayArea() {
2406             return mIsTaskDisplayArea;
2407         }
2408 
2409         public boolean isRootDisplayArea() {
2410             return mIsRootDisplayArea;
2411         }
2412 
2413         public int getFeatureId() {
2414             return mFeatureId;
2415         }
2416 
2417         public boolean isOrganized() {
2418             return mIsOrganized;
2419         }
2420 
2421         public Rect getAppBounds() {
2422             return mFullConfiguration.windowConfiguration.getAppBounds();
2423         }
2424 
2425         public boolean isIgnoringOrientationRequest() {
2426             return mIsIgnoringOrientationRequest;
2427         }
2428 
2429         @Override
2430         public Rect getBounds() {
2431             if (mBounds == null) {
2432                 return mFullConfiguration.windowConfiguration.getBounds();
2433             }
2434             return mBounds;
2435         }
2436 
2437         boolean containsActivity(ComponentName activityName) {
2438             if (!mIsTaskDisplayArea) {
2439                 return false;
2440             }
2441 
2442             final String fullName = getActivityName(activityName);
2443             for (Activity a : mActivities) {
2444                 if (a.name.equals(fullName)) {
2445                     return true;
2446                 }
2447             }
2448             return false;
2449         }
2450 
2451         boolean containsWindow(String windowName) {
2452             for (WindowState w : mWindows) {
2453                 if (w.mName.equals(windowName)) {
2454                     return true;
2455                 }
2456             }
2457             return false;
2458         }
2459     }
2460     public static class WindowToken extends WindowContainer {
2461         WindowToken(WindowTokenProto proto) {
2462             super(proto.getWindowContainer());
2463         }
2464 
2465         WindowToken(com.android.server.wm.nano.WindowTokenProto proto) {
2466             super(proto.windowContainer);
2467         }
2468     }
2469 
2470     /**
2471      * Represents WindowContainer classes such as DisplayContent.WindowContainers and
2472      * DisplayContent.NonAppWindowContainers. This can be expanded into a specific class
2473      * if we need track and assert some state in the future.
2474      */
2475     public static class GenericWindowContainer extends WindowContainer {
2476         GenericWindowContainer(WindowContainerProto proto) {
2477             super(proto);
2478         }
2479 
2480         GenericWindowContainer(com.android.server.wm.nano.WindowContainerProto proto) {
2481             super(proto);
2482         }
2483     }
2484 
2485     static WindowContainer getWindowContainer(WindowContainerChildProto proto,
2486             WindowContainer parent) {
2487         if (proto.hasDisplayContent()) {
2488             return new DisplayContent(proto.getDisplayContent());
2489         }
2490 
2491         if (proto.hasDisplayArea()) {
2492             return new DisplayArea(proto.getDisplayArea());
2493         }
2494 
2495         if (proto.hasTask()) {
2496             return new Task(proto.getTask(), parent);
2497         }
2498 
2499         if (proto.hasTaskFragment()) {
2500             return new TaskFragment(proto.getTaskFragment(), parent);
2501         }
2502 
2503         if (proto.hasActivity()) {
2504             return new Activity(proto.getActivity(), parent);
2505         }
2506 
2507         if (proto.hasWindowToken()) {
2508             return new WindowToken(proto.getWindowToken());
2509         }
2510 
2511         if (proto.hasWindow()) {
2512             return new WindowState(proto.getWindow());
2513         }
2514 
2515         if (proto.hasWindowContainer()) {
2516             return new GenericWindowContainer(proto.getWindowContainer());
2517         }
2518         return null;
2519     }
2520 
2521     static WindowContainer getWindowContainer(
2522             com.android.server.wm.nano.WindowContainerChildProto proto,
2523             WindowContainer parent) {
2524         if (proto.displayContent != null) {
2525             return new DisplayContent(proto.displayContent);
2526         }
2527 
2528         if (proto.displayArea != null) {
2529             return new DisplayArea(proto.displayArea);
2530         }
2531 
2532         if (proto.task != null) {
2533             return new Task(proto.task, parent);
2534         }
2535 
2536         if (proto.taskFragment != null) {
2537             return new TaskFragment(proto.taskFragment, parent);
2538         }
2539 
2540         if (proto.activity != null) {
2541             return new Activity(proto.activity, parent);
2542         }
2543 
2544         if (proto.windowToken != null) {
2545             return new WindowToken(proto.windowToken);
2546         }
2547 
2548         if (proto.window != null) {
2549             return new WindowState(proto.window);
2550         }
2551 
2552         if (proto.windowContainer != null) {
2553             return new GenericWindowContainer(proto.windowContainer);
2554         }
2555         return null;
2556     }
2557 
2558     public abstract static class WindowContainer extends ConfigurationContainer {
2559 
2560         protected String mName;
2561         protected final String mAppToken;
2562         protected boolean mFullscreen;
2563         protected Rect mBounds;
2564         protected int mOrientation;
2565         protected boolean mVisible;
2566         protected List<WindowState> mSubWindows = new ArrayList<>();
2567         protected List<WindowContainer> mChildren = new ArrayList<>();
2568 
2569         WindowContainer(WindowContainerProto proto) {
2570             super(proto.hasConfigurationContainer() ? proto.getConfigurationContainer() : null);
2571             IdentifierProto identifierProto = proto.getIdentifier();
2572             mName = identifierProto.getTitle();
2573             mAppToken = Integer.toHexString(identifierProto.getHashCode());
2574             mOrientation = proto.getOrientation();
2575             for (int i = 0; i < proto.getChildrenCount(); i++) {
2576                 final WindowContainer child = getWindowContainer(proto.getChildren(i), this);
2577                 if (child != null) {
2578                     mChildren.add(child);
2579                 }
2580             }
2581             mVisible = proto.getVisible();
2582         }
2583 
2584         WindowContainer(com.android.server.wm.nano.WindowContainerProto proto) {
2585             super(proto.configurationContainer);
2586             com.android.server.wm.nano.IdentifierProto identifierProto = proto.identifier;
2587             mName = identifierProto.title;
2588             mAppToken = Integer.toHexString(identifierProto.hashCode);
2589             mOrientation = proto.orientation;
2590             for (int i = 0; i < proto.children.length; i++) {
2591                 final WindowContainer child = getWindowContainer(proto.children[i], this);
2592                 if (child != null) {
2593                     mChildren.add(child);
2594                 }
2595             }
2596             mVisible = proto.visible;
2597         }
2598 
2599         @NonNull
2600         public String getName() {
2601             return mName;
2602         }
2603 
2604         @NonNull
2605         public String getPackageName() {
2606             int sep = mName.indexOf('/');
2607             return sep == -1 ? mName : mName.substring(0, sep);
2608         }
2609 
2610         public List<WindowContainer> getChildren() {
2611             return mChildren;
2612         }
2613 
2614         public String getToken() {
2615             return mAppToken;
2616         }
2617 
2618         public Rect getBounds() {
2619             return mBounds;
2620         }
2621 
2622         boolean isFullscreen() {
2623             return mFullscreen;
2624         }
2625 
2626         public boolean isVisible() {
2627             return mVisible;
2628         }
2629 
2630         List<WindowState> getWindows() {
2631             return mSubWindows;
2632         }
2633     }
2634 
2635     public static class WindowState extends WindowContainer {
2636 
2637         private static final int WINDOW_TYPE_NORMAL = 0;
2638         public static final int WINDOW_TYPE_STARTING = 1;
2639         private static final int WINDOW_TYPE_EXITING = 2;
2640         private static final int WINDOW_TYPE_DEBUGGER = 3;
2641 
2642         private final int mWindowType;
2643         private int mType = 0;
2644         private int mDisplayId;
2645         private int mStackId;
2646         private int mLayer;
2647         private boolean mShown;
2648         private Rect mParentFrame;
2649         private Rect mFrame;
2650         private Rect mCompatFrame;
2651         private Rect mSurfaceInsets;
2652         private Rect mGivenContentInsets;
2653         private Rect mCrop = new Rect();
2654         private boolean mHasCompatScale;
2655         private float mGlobalScale;
2656         private int mRequestedWidth;
2657         private int mRequestedHeight;
2658         private List<Rect> mKeepClearRects;
2659         private List<Rect> mUnrestrictedKeepClearRects;
2660         private List<InsetsSource> mMergedLocalInsetsSources;
2661         private int mFlags;
2662         private Rect mDimBounds;
2663 
2664         WindowState(WindowStateProto proto) {
2665             super(proto.getWindowContainer());
2666             mDisplayId = proto.getDisplayId();
2667             mStackId = proto.getStackId();
2668             if (proto.hasAttributes()) {
2669                 mType = proto.getAttributes().getType();
2670                 mFlags = proto.getAttributes().getFlags();
2671             }
2672             if (proto.hasAnimator()) {
2673                 WindowStateAnimatorProto animatorProto = proto.getAnimator();
2674                 if (animatorProto.hasSurface()) {
2675                     WindowSurfaceControllerProto surfaceProto = animatorProto.getSurface();
2676                     mShown = surfaceProto.getShown();
2677                     mLayer = surfaceProto.getLayer();
2678                 }
2679                 mCrop = extract(animatorProto.getLastClipRect());
2680             }
2681             mGivenContentInsets = extract(proto.getGivenContentInsets());
2682             if (proto.hasWindowFrames()) {
2683                 WindowFramesProto windowFramesProto = proto.getWindowFrames();
2684                 mFrame = extract(windowFramesProto.getFrame());
2685                 mParentFrame = extract(windowFramesProto.getParentFrame());
2686                 mCompatFrame = extract(windowFramesProto.getCompatFrame());
2687             }
2688             mSurfaceInsets = extract(proto.getSurfaceInsets());
2689             if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
2690                 mWindowType = WINDOW_TYPE_STARTING;
2691                 // Existing code depends on the prefix being removed
2692                 mName = mName.substring(STARTING_WINDOW_PREFIX.length());
2693             } else if (proto.getAnimatingExit()) {
2694                 mWindowType = WINDOW_TYPE_EXITING;
2695             } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
2696                 mWindowType = WINDOW_TYPE_DEBUGGER;
2697                 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
2698             } else {
2699                 mWindowType = 0;
2700             }
2701             collectDescendantsOfType(WindowState.class, this, mSubWindows);
2702             mHasCompatScale = proto.getHasCompatScale();
2703             mGlobalScale = proto.getGlobalScale();
2704             mRequestedWidth = proto.getRequestedWidth();
2705             mRequestedHeight = proto.getRequestedHeight();
2706             mKeepClearRects = new ArrayList();
2707             for (int i = 0; i < proto.getKeepClearAreasCount(); ++i) {
2708                 RectProto r = proto.getKeepClearAreas(i);
2709                 mKeepClearRects.add(new Rect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom()));
2710             }
2711             mUnrestrictedKeepClearRects = new ArrayList();
2712             for (int i = 0; i < proto.getUnrestrictedKeepClearAreasCount(); ++i) {
2713                 RectProto r = proto.getUnrestrictedKeepClearAreas(i);
2714                 mUnrestrictedKeepClearRects.add(
2715                         new Rect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom()));
2716             }
2717             mMergedLocalInsetsSources = new ArrayList();
2718             for (int i = 0; i < proto.getMergedLocalInsetsSourcesCount(); ++i) {
2719                 InsetsSourceProto insets = proto.getMergedLocalInsetsSources(i);
2720                 mMergedLocalInsetsSources.add(new InsetsSource(insets));
2721             }
2722             final RectProto r = proto.getDimBounds();
2723             mDimBounds = new Rect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom());
2724         }
2725 
2726         WindowState(com.android.server.wm.nano.WindowStateProto proto) {
2727             super(proto.windowContainer);
2728             mDisplayId = proto.displayId;
2729             mStackId = proto.stackId;
2730             if (proto.attributes != null) {
2731                 mType = proto.attributes.type;
2732                 mFlags = proto.attributes.flags;
2733             }
2734             com.android.server.wm.nano.WindowStateAnimatorProto animatorProto = proto.animator;
2735             if (animatorProto != null) {
2736                 if (animatorProto.surface != null) {
2737                     com.android.server.wm.nano.WindowSurfaceControllerProto surfaceProto =
2738                             animatorProto.surface;
2739                     mShown = surfaceProto.shown;
2740                     mLayer = surfaceProto.layer;
2741                 }
2742                 mCrop = extract(animatorProto.lastClipRect);
2743             }
2744             mGivenContentInsets = extract(proto.givenContentInsets);
2745             com.android.server.wm.nano.WindowFramesProto windowFramesProto = proto.windowFrames;
2746             if (windowFramesProto != null) {
2747                 mFrame = extract(windowFramesProto.frame);
2748                 mParentFrame = extract(windowFramesProto.parentFrame);
2749                 mCompatFrame = extract(windowFramesProto.compatFrame);
2750             }
2751             mSurfaceInsets = extract(proto.surfaceInsets);
2752             if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
2753                 mWindowType = WINDOW_TYPE_STARTING;
2754                 // Existing code depends on the prefix being removed
2755                 mName = mName.substring(STARTING_WINDOW_PREFIX.length());
2756             } else if (proto.animatingExit) {
2757                 mWindowType = WINDOW_TYPE_EXITING;
2758             } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
2759                 mWindowType = WINDOW_TYPE_DEBUGGER;
2760                 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
2761             } else {
2762                 mWindowType = 0;
2763             }
2764             collectDescendantsOfType(WindowState.class, this, mSubWindows);
2765             mHasCompatScale = proto.hasCompatScale;
2766             mGlobalScale = proto.globalScale;
2767             mRequestedWidth = proto.requestedWidth;
2768             mRequestedHeight = proto.requestedHeight;
2769             mKeepClearRects = new ArrayList();
2770             for (android.graphics.nano.RectProto r : proto.keepClearAreas) {
2771                 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
2772             }
2773             mUnrestrictedKeepClearRects = new ArrayList();
2774             for (android.graphics.nano.RectProto r : proto.unrestrictedKeepClearAreas) {
2775                 mUnrestrictedKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
2776             }
2777             mMergedLocalInsetsSources = new ArrayList();
2778             for (android.view.nano.InsetsSourceProto insets : proto.mergedLocalInsetsSources) {
2779                 mMergedLocalInsetsSources.add(new InsetsSource(insets));
2780             }
2781             mDimBounds = extract(proto.dimBounds);
2782         }
2783 
2784         boolean isStartingWindow() {
2785             return mWindowType == WINDOW_TYPE_STARTING;
2786         }
2787 
2788         boolean isExitingWindow() {
2789             return mWindowType == WINDOW_TYPE_EXITING;
2790         }
2791 
2792         boolean isDebuggerWindow() {
2793             return mWindowType == WINDOW_TYPE_DEBUGGER;
2794         }
2795 
2796         public int getDisplayId() {
2797             return mDisplayId;
2798         }
2799 
2800         public int getStackId() {
2801             return mStackId;
2802         }
2803 
2804         public Rect getFrame() {
2805             return mFrame;
2806         }
2807 
2808         Rect getSurfaceInsets() {
2809             return mSurfaceInsets;
2810         }
2811 
2812         Rect getGivenContentInsets() {
2813             return mGivenContentInsets;
2814         }
2815 
2816         public Rect getParentFrame() {
2817             return mParentFrame;
2818         }
2819 
2820         public Rect getCompatFrame() {
2821             return mCompatFrame;
2822         }
2823 
2824         Rect getCrop() {
2825             return mCrop;
2826         }
2827 
2828         public boolean isSurfaceShown() {
2829             return mShown;
2830         }
2831 
2832         public int getType() {
2833             return mType;
2834         }
2835 
2836         public boolean hasCompatScale() {
2837             return mHasCompatScale;
2838         }
2839 
2840         public float getGlobalScale() {
2841             return mGlobalScale;
2842         }
2843 
2844         public int getRequestedWidth() {
2845             return mRequestedWidth;
2846         }
2847 
2848         public int getRequestedHeight() {
2849             return mRequestedHeight;
2850         }
2851 
2852         public List<Rect> getKeepClearRects() {
2853             return mKeepClearRects;
2854         }
2855 
2856         public List<Rect> getUnrestrictedKeepClearRects() {
2857             return mUnrestrictedKeepClearRects;
2858         }
2859 
2860         public List<InsetsSource> getMergedLocalInsetsSources() {
2861             return mMergedLocalInsetsSources;
2862         }
2863 
2864         public int getFlags() {
2865             return mFlags;
2866         }
2867 
2868         @Nullable
2869         public Rect getDimBounds() {
2870             return mDimBounds;
2871         }
2872 
2873         private String getWindowTypeSuffix(int windowType) {
2874             switch (windowType) {
2875                 case WINDOW_TYPE_STARTING:
2876                     return " STARTING";
2877                 case WINDOW_TYPE_EXITING:
2878                     return " EXITING";
2879                 case WINDOW_TYPE_DEBUGGER:
2880                     return " DEBUGGER";
2881                 default:
2882                     break;
2883             }
2884             return "";
2885         }
2886 
2887         @Override
2888         public String toString() {
2889             return "WindowState: {" + mAppToken + " " + mName
2890                     + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
2891                     + " pf=" + mParentFrame;
2892         }
2893 
2894         public String toLongString() {
2895             return toString() + " f=" + mFrame + " crop=" + mCrop + " isSurfaceShown="
2896                     + isSurfaceShown();
2897         }
2898     }
2899 
2900     public static class BackNavigationState {
2901         private boolean mAnimationInProgress;
2902         private int mLastBackType;
2903         private boolean mShowWallpaper;
2904 
2905         BackNavigationState(BackNavigationProto proto) {
2906             if (proto != null) {
2907                 mAnimationInProgress = proto.getAnimationInProgress();
2908                 mLastBackType = proto.getLastBackType();
2909                 mShowWallpaper = proto.getShowWallpaper();
2910             }
2911         }
2912 
2913         BackNavigationState(com.android.server.wm.nano.BackNavigationProto proto) {
2914             if (proto != null) {
2915                 mAnimationInProgress = proto.animationInProgress;
2916                 mLastBackType = proto.lastBackType;
2917                 mShowWallpaper = proto.showWallpaper;
2918             }
2919         }
2920 
2921         boolean isAnimationInProgress() {
2922             return mAnimationInProgress;
2923         }
2924 
2925         public int getLastBackType() {
2926             return mLastBackType;
2927         }
2928 
2929         boolean isShowWallpaper() {
2930             return mShowWallpaper;
2931         }
2932     }
2933 
2934     public static int dpToPx(float dp, int densityDpi) {
2935         return (int) (dp * densityDpi / DENSITY_DEFAULT + 0.5f);
2936     }
2937 
2938     int defaultMinimalTaskSize(int displayId) {
2939         final DisplayContent dc = getDisplay(displayId);
2940         return dpToPx(dc.mMinSizeOfResizeableTaskDp, dc.getDpi());
2941     }
2942 
2943     int defaultMinimalDisplaySizeForSplitScreen(int displayId) {
2944         return dpToPx(ActivityTaskManager.DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP,
2945                 getDisplay(displayId).getDpi());
2946     }
2947 
2948     public static class InsetsSource {
2949         private int mType;
2950         private Rect mFrame;
2951         private Rect mVisibleFrame;
2952         private boolean mVisible;
2953 
2954         InsetsSource(InsetsSourceProto proto) {
2955             mType = proto.getTypeNumber();
2956             if (proto.hasFrame()) {
2957                 mFrame = new Rect(
2958                         proto.getFrame().getLeft(), proto.getFrame().getTop(),
2959                         proto.getFrame().getRight(), proto.getFrame().getBottom());
2960             }
2961             if (proto.hasVisibleFrame()) {
2962                 mVisibleFrame = new Rect(
2963                         proto.getVisibleFrame().getLeft(), proto.getVisibleFrame().getTop(),
2964                         proto.getVisibleFrame().getRight(), proto.getVisibleFrame().getBottom());
2965             }
2966             mVisible = proto.getVisible();
2967         }
2968 
2969         InsetsSource(android.view.nano.InsetsSourceProto proto) {
2970             mType = proto.typeNumber;
2971             if (proto.frame != null) {
2972                 mFrame = new Rect(
2973                         proto.frame.left, proto.frame.top, proto.frame.right, proto.frame.bottom);
2974             }
2975             if (proto.visibleFrame != null) {
2976                 mVisibleFrame = new Rect(proto.visibleFrame.left, proto.visibleFrame.top,
2977                         proto.visibleFrame.right, proto.visibleFrame.bottom);
2978             }
2979             mVisible = proto.visible;
2980         }
2981 
2982         int getType() {
2983             return mType;
2984         }
2985 
2986         Rect getFrame() {
2987             return mFrame;
2988         }
2989 
2990         Rect getVisibleFrame() {
2991             return mVisibleFrame;
2992         }
2993 
2994         boolean isVisible() {
2995             return mVisible;
2996         }
2997 
2998         /**
2999          * Check whether this InsetsSource is with given type.
3000          * @param type The type to which check against.
3001          * @return {@code true} if this insets source is with the given type.
3002          */
3003         public boolean is(int type) {
3004             return (mType & type) != 0;
3005         }
3006 
3007         public void insetGivenFrame(Rect inOutFrame) {
3008             if (inOutFrame.left == mFrame.left && inOutFrame.right == mFrame.right) {
3009                 if (inOutFrame.top == mFrame.top) {
3010                     inOutFrame.top = mFrame.bottom;
3011                     return;
3012                 }
3013                 if (inOutFrame.bottom == mFrame.bottom) {
3014                     inOutFrame.bottom = mFrame.top;
3015                     return;
3016                 }
3017             }
3018             if (inOutFrame.top == mFrame.top && inOutFrame.bottom == mFrame.bottom) {
3019                 if (inOutFrame.left == mFrame.left) {
3020                     inOutFrame.left = mFrame.right;
3021                     return;
3022                 }
3023                 if (inOutFrame.right == mFrame.right) {
3024                     inOutFrame.right = mFrame.left;
3025                     return;
3026                 }
3027             }
3028         }
3029 
3030         @Override
3031         public String toString() {
3032             return "InsetsSource: {type=" + WindowInsets.Type.toString(mType)
3033                     + " frame=" + mFrame
3034                     + " visibleFrame=" + mVisibleFrame
3035                     + " visible=" + mVisible
3036                     + "}";
3037         }
3038     }
3039 
3040     public static class InsetsSourceProvider {
3041         private Identifier mIdentifier;
3042         private InsetsSource mSource;
3043         private WindowState mWindowState;
3044 
3045         InsetsSourceProvider(InsetsSourceProviderProto proto) {
3046             if (proto.hasSource()) {
3047                 mSource = new InsetsSource(proto.getSource());
3048             }
3049             if (proto.hasSourceWindowState()) {
3050                 mWindowState = new WindowState(proto.getSourceWindowState());
3051             }
3052             if (proto.hasSourceWindowStateIdentifier()) {
3053                 mIdentifier = new Identifier(proto.getSourceWindowStateIdentifier());
3054             }
3055         }
3056 
3057         InsetsSourceProvider(com.android.server.wm.nano.InsetsSourceProviderProto proto) {
3058             if (proto.source != null) {
3059                 mSource = new InsetsSource(proto.source);
3060             }
3061             if (proto.sourceWindowState != null) {
3062                 mWindowState = new WindowState(proto.sourceWindowState);
3063             }
3064             if (proto.sourceWindowStateIdentifier != null) {
3065                 mIdentifier = new Identifier(proto.sourceWindowStateIdentifier);
3066             }
3067         }
3068 
3069         int getType() {
3070             return mSource.getType();
3071         }
3072 
3073         WindowState getWindowState() {
3074             return mWindowState;
3075         }
3076 
3077         @Override
3078         public String toString() {
3079             return "InsetsSourceProvider: mSource=" + mSource + " mWindowState=" + mWindowState;
3080         }
3081 
3082     }
3083 
3084     public static class Identifier {
3085         protected final String mName;
3086         protected final String mAppToken;
3087 
3088         Identifier(IdentifierProto proto) {
3089             mName = proto.getTitle();
3090             mAppToken = Integer.toHexString(proto.getHashCode());
3091         }
3092 
3093         Identifier(com.android.server.wm.nano.IdentifierProto proto) {
3094             mName = proto.title;
3095             mAppToken = Integer.toHexString(proto.hashCode);
3096         }
3097     }
3098 }
3099