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.ActivityTaskManager.INVALID_STACK_ID;
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 
30 import static androidx.test.InstrumentationRegistry.getInstrumentation;
31 
32 import android.content.ComponentName;
33 import android.graphics.Rect;
34 import android.os.ParcelFileDescriptor;
35 import android.os.SystemClock;
36 import android.util.SparseArray;
37 
38 import androidx.annotation.Nullable;
39 
40 import com.android.server.am.nano.ActivityDisplayProto;
41 import com.android.server.am.nano.ActivityManagerServiceDumpActivitiesProto;
42 import com.android.server.am.nano.ActivityRecordProto;
43 import com.android.server.am.nano.ActivityStackProto;
44 import com.android.server.am.nano.ActivityStackSupervisorProto;
45 import com.android.server.am.nano.KeyguardControllerProto;
46 import com.android.server.am.nano.TaskRecordProto;
47 import com.android.server.wm.nano.ConfigurationContainerProto;
48 
49 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
50 
51 import java.io.ByteArrayOutputStream;
52 import java.io.FileInputStream;
53 import java.io.IOException;
54 import java.nio.charset.StandardCharsets;
55 import java.util.ArrayList;
56 import java.util.List;
57 
58 public class ActivityManagerState {
59 
60     public static final int DUMP_MODE_ACTIVITIES = 0;
61 
62     public static final String STATE_INITIALIZING = "INITIALIZING";
63     public static final String STATE_RESUMED = "RESUMED";
64     public static final String STATE_PAUSED = "PAUSED";
65     public static final String STATE_STOPPED = "STOPPED";
66     public static final String STATE_DESTROYED = "DESTROYED";
67 
68     private static final String DUMPSYS_ACTIVITY_ACTIVITIES = "dumpsys activity --proto activities";
69 
70     // Displays in z-order with the top most at the front of the list, starting with primary.
71     private final List<ActivityDisplay> mDisplays = new ArrayList<>();
72     // Stacks in z-order with the top most at the front of the list, starting with primary display.
73     private final List<ActivityStack> mStacks = new ArrayList<>();
74     private KeyguardControllerState mKeyguardControllerState;
75     private final List<String> mPendingActivities = new ArrayList<>();
76     private int mTopFocusedStackId = -1;
77     private Boolean mIsHomeRecentsComponent;
78     private String mTopResumedActivityRecord = null;
79     final List<String> mResumedActivitiesInStacks = new ArrayList<>();
80     final List<String> mResumedActivitiesInDisplays = new ArrayList<>();
81 
computeState()82     void computeState() {
83         computeState(DUMP_MODE_ACTIVITIES);
84     }
85 
computeState(int dumpMode)86     void computeState(int dumpMode) {
87         // It is possible the system is in the middle of transition to the right state when we get
88         // the dump. We try a few times to get the information we need before giving up.
89         int retriesLeft = 3;
90         boolean retry = false;
91         byte[] dump = null;
92 
93         log("==============================");
94         log("     ActivityManagerState     ");
95         log("==============================");
96 
97         do {
98             if (retry) {
99                 log("***Incomplete AM state. Retrying...");
100                 // Wait half a second between retries for activity manager to finish transitioning.
101                 SystemClock.sleep(500);
102             }
103 
104             String dumpsysCmd = "";
105             switch (dumpMode) {
106                 case DUMP_MODE_ACTIVITIES:
107                     dumpsysCmd = DUMPSYS_ACTIVITY_ACTIVITIES;
108                     break;
109             }
110 
111             dump = executeShellCommand(dumpsysCmd);
112             try {
113                 parseSysDumpProto(dump);
114             } catch (InvalidProtocolBufferNanoException ex) {
115                 throw new RuntimeException("Failed to parse dumpsys:\n"
116                         + new String(dump, StandardCharsets.UTF_8), ex);
117             }
118 
119             retry = mStacks.isEmpty() || mTopFocusedStackId == -1
120                     || (mTopResumedActivityRecord == null || mResumedActivitiesInStacks.isEmpty())
121                     && !mKeyguardControllerState.keyguardShowing;
122         } while (retry && retriesLeft-- > 0);
123 
124         if (mStacks.isEmpty()) {
125             logE("No stacks found...");
126         }
127         if (mTopFocusedStackId == -1) {
128             logE("No focused stack found...");
129         }
130         if (mTopResumedActivityRecord == null) {
131             logE("No focused activity found...");
132         }
133         if (mResumedActivitiesInStacks.isEmpty()) {
134             logE("No resumed activities found...");
135         }
136     }
137 
executeShellCommand(String cmd)138     private byte[] executeShellCommand(String cmd) {
139         try {
140             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
141                     .executeShellCommand(cmd);
142             byte[] buf = new byte[512];
143             int bytesRead;
144             FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
145             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
146             while ((bytesRead = fis.read(buf)) != -1) {
147                 stdout.write(buf, 0, bytesRead);
148             }
149             fis.close();
150             return stdout.toByteArray();
151         } catch (IOException e) {
152             throw new RuntimeException(e);
153         }
154     }
155 
parseSysDumpProto(byte[] sysDump)156     private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
157         reset();
158 
159         ActivityStackSupervisorProto state = ActivityManagerServiceDumpActivitiesProto.parseFrom(sysDump)
160                 .activityStackSupervisor;
161         for (int i = 0; i < state.displays.length; i++) {
162             ActivityDisplayProto activityDisplay = state.displays[i];
163             mDisplays.add(new ActivityDisplay(activityDisplay, this));
164         }
165         mKeyguardControllerState = new KeyguardControllerState(state.keyguardController);
166         mTopFocusedStackId = state.focusedStackId;
167         if (state.resumedActivity != null) {
168             mTopResumedActivityRecord = state.resumedActivity.title;
169         }
170         mIsHomeRecentsComponent = new Boolean(state.isHomeRecentsComponent);
171 
172         for (int i = 0; i < state.pendingActivities.length; i++) {
173             mPendingActivities.add(state.pendingActivities[i].title);
174         }
175     }
176 
reset()177     private void reset() {
178         mDisplays.clear();
179         mStacks.clear();
180         mTopFocusedStackId = -1;
181         mTopResumedActivityRecord = null;
182         mResumedActivitiesInStacks.clear();
183         mResumedActivitiesInDisplays.clear();
184         mKeyguardControllerState = null;
185         mIsHomeRecentsComponent = null;
186         mPendingActivities.clear();
187     }
188 
189     /**
190      * @return Whether the home activity is the recents component.
191      */
isHomeRecentsComponent()192     boolean isHomeRecentsComponent() {
193         if (mIsHomeRecentsComponent == null) {
194             computeState();
195         }
196         return mIsHomeRecentsComponent;
197     }
198 
getDisplay(int displayId)199     ActivityDisplay getDisplay(int displayId) {
200         for (ActivityDisplay display : mDisplays) {
201             if (display.mId == displayId) {
202                 return display;
203             }
204         }
205         return null;
206     }
207 
getFrontStackId(int displayId)208     int getFrontStackId(int displayId) {
209         return getDisplay(displayId).mStacks.get(0).mStackId;
210     }
211 
getFrontStackActivityType(int displayId)212     int getFrontStackActivityType(int displayId) {
213         return getDisplay(displayId).mStacks.get(0).getActivityType();
214     }
215 
getFrontStackWindowingMode(int displayId)216     int getFrontStackWindowingMode(int displayId) {
217         return getDisplay(displayId).mStacks.get(0).getWindowingMode();
218     }
219 
getTopActivityName(int displayId)220     public String getTopActivityName(int displayId) {
221         if (!getDisplay(displayId).mStacks.isEmpty()) {
222             final ActivityStack topStack = getDisplay(displayId).mStacks.get(0);
223             if (!topStack.mTasks.isEmpty()) {
224                 final ActivityTask topTask = topStack.mTasks.get(0);
225                 if (!topTask.mActivities.isEmpty()) {
226                     return topTask.mActivities.get(0).name;
227                 }
228             }
229         }
230         return null;
231     }
232 
getFocusedStackId()233     int getFocusedStackId() {
234         return mTopFocusedStackId;
235     }
236 
getFocusedStackActivityType()237     int getFocusedStackActivityType() {
238         final ActivityStack stack = getStackById(mTopFocusedStackId);
239         return stack != null ? stack.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
240     }
241 
getFocusedStackWindowingMode()242     int getFocusedStackWindowingMode() {
243         final ActivityStack stack = getStackById(mTopFocusedStackId);
244         return stack != null ? stack.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
245     }
246 
getFocusedActivity()247     String getFocusedActivity() {
248         return mTopResumedActivityRecord;
249     }
250 
getResumedActivitiesCount()251     int getResumedActivitiesCount() {
252         return mResumedActivitiesInStacks.size();
253     }
254 
getResumedActivitiesCountInPackage(String packageName)255     int getResumedActivitiesCountInPackage(String packageName) {
256         final String componentPrefix = packageName + "/";
257         int count = 0;
258         for (int i = mDisplays.size() - 1; i >= 0; --i) {
259             final ArrayList<ActivityStack> mStacks = mDisplays.get(i).getStacks();
260             for (int j = mStacks.size() - 1; j >= 0; --j) {
261                 final String resumedActivity = mStacks.get(j).mResumedActivity;
262                 if (resumedActivity != null && resumedActivity.startsWith(componentPrefix)) {
263                     count++;
264                 }
265             }
266         }
267         return count;
268     }
269 
getResumedActivityOnDisplay(int displayId)270     String getResumedActivityOnDisplay(int displayId) {
271         return getDisplay(displayId).mResumedActivity;
272     }
273 
getKeyguardControllerState()274     public KeyguardControllerState getKeyguardControllerState() {
275         return mKeyguardControllerState;
276     }
277 
containsStack(int stackId)278     boolean containsStack(int stackId) {
279         return getStackById(stackId) != null;
280     }
281 
containsStack(int windowingMode, int activityType)282     boolean containsStack(int windowingMode, int activityType) {
283         for (ActivityStack stack : mStacks) {
284             if (activityType != ACTIVITY_TYPE_UNDEFINED
285                     && activityType != stack.getActivityType()) {
286                 continue;
287             }
288             if (windowingMode != WINDOWING_MODE_UNDEFINED
289                     && windowingMode != stack.getWindowingMode()) {
290                 continue;
291             }
292             return true;
293         }
294         return false;
295     }
296 
getStackById(int stackId)297     ActivityStack getStackById(int stackId) {
298         for (ActivityStack stack : mStacks) {
299             if (stackId == stack.mStackId) {
300                 return stack;
301             }
302         }
303         return null;
304     }
305 
getStackByActivityType(int activityType)306     ActivityStack getStackByActivityType(int activityType) {
307         for (ActivityStack stack : mStacks) {
308             if (activityType == stack.getActivityType()) {
309                 return stack;
310             }
311         }
312         return null;
313     }
314 
getStandardStackByWindowingMode(int windowingMode)315     ActivityStack getStandardStackByWindowingMode(int windowingMode) {
316         for (ActivityStack stack : mStacks) {
317             if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
318                 continue;
319             }
320             if (stack.getWindowingMode() == windowingMode) {
321                 return stack;
322             }
323         }
324         return null;
325     }
326 
getStandardTaskCountByWindowingMode(int windowingMode)327     public int getStandardTaskCountByWindowingMode(int windowingMode) {
328         int count = 0;
329         for (ActivityStack stack : mStacks) {
330             if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
331                 continue;
332             }
333             if (stack.getWindowingMode() == windowingMode) {
334                 count += stack.mTasks.size();
335             }
336         }
337         return count;
338     }
339 
340     /** Get the stack position on its display. */
getStackIndexByActivityType(int activityType)341     int getStackIndexByActivityType(int activityType) {
342         for (ActivityDisplay display : mDisplays) {
343             for (int i = 0; i < display.mStacks.size(); i++) {
344                 if (activityType == display.mStacks.get(i).getActivityType()) {
345                     return i;
346                 }
347             }
348         }
349         return -1;
350     }
351 
352     /** Get the stack position on its display. */
getStackIndexByActivity(ComponentName activityName)353     int getStackIndexByActivity(ComponentName activityName) {
354         final String fullName = getActivityName(activityName);
355 
356         for (ActivityDisplay display : mDisplays) {
357             for (int i = display.mStacks.size() - 1; i >= 0; --i) {
358                 final ActivityStack stack = display.mStacks.get(i);
359                 for (ActivityTask task : stack.mTasks) {
360                     for (Activity activity : task.mActivities) {
361                         if (activity.name.equals(fullName)) {
362                             return i;
363                         }
364                     }
365                 }
366             }
367         }
368         return -1;
369     }
370 
371     /** Get display id by activity on it. */
getDisplayByActivity(ComponentName activityComponent)372     int getDisplayByActivity(ComponentName activityComponent) {
373         final ActivityManagerState.ActivityTask task = getTaskByActivity(activityComponent);
374         if (task == null) {
375             return -1;
376         }
377         return getStackById(task.mStackId).mDisplayId;
378     }
379 
getDisplays()380     List<ActivityDisplay> getDisplays() {
381         return new ArrayList<>(mDisplays);
382     }
383 
getStacks()384     public List<ActivityStack> getStacks() {
385         return new ArrayList<>(mStacks);
386     }
387 
getStackCount()388     int getStackCount() {
389         return mStacks.size();
390     }
391 
getDisplayCount()392     int getDisplayCount() {
393         return mDisplays.size();
394     }
395 
containsActivity(ComponentName activityName)396     public boolean containsActivity(ComponentName activityName) {
397         final String fullName = getActivityName(activityName);
398         for (ActivityStack stack : mStacks) {
399             for (ActivityTask task : stack.mTasks) {
400                 for (Activity activity : task.mActivities) {
401                     if (activity.name.equals(fullName)) {
402                         return true;
403                     }
404                 }
405             }
406         }
407         return false;
408     }
409 
containsNoneOf(Iterable<ComponentName> activityNames)410     public boolean containsNoneOf(Iterable<ComponentName> activityNames) {
411         for (ComponentName activityName : activityNames) {
412             String fullName = getActivityName(activityName);
413 
414             for (ActivityStack stack : mStacks) {
415                 for (ActivityTask task : stack.mTasks) {
416                     for (Activity activity : task.mActivities) {
417                         if (activity.name.equals(fullName)) {
418                             return false;
419                         }
420                     }
421                 }
422             }
423         }
424 
425         return true;
426     }
427 
containsActivityInWindowingMode(ComponentName activityName, int windowingMode)428     boolean containsActivityInWindowingMode(ComponentName activityName, int windowingMode) {
429         final String fullName = getActivityName(activityName);
430         for (ActivityStack stack : mStacks) {
431             for (ActivityTask task : stack.mTasks) {
432                 for (Activity activity : task.mActivities) {
433                     if (activity.name.equals(fullName)
434                             && activity.getWindowingMode() == windowingMode) {
435                         return true;
436                     }
437                 }
438             }
439         }
440         return false;
441     }
442 
isActivityVisible(ComponentName activityName)443     boolean isActivityVisible(ComponentName activityName) {
444         final String fullName = getActivityName(activityName);
445         for (ActivityStack stack : mStacks) {
446             for (ActivityTask task : stack.mTasks) {
447                 for (Activity activity : task.mActivities) {
448                     if (activity.name.equals(fullName)) {
449                         return activity.visible;
450                     }
451                 }
452             }
453         }
454         return false;
455     }
456 
isActivityTranslucent(ComponentName activityName)457     boolean isActivityTranslucent(ComponentName activityName) {
458         final String fullName = getActivityName(activityName);
459         for (ActivityStack stack : mStacks) {
460             for (ActivityTask task : stack.mTasks) {
461                 for (Activity activity : task.mActivities) {
462                     if (activity.name.equals(fullName)) {
463                         return activity.translucent;
464                     }
465                 }
466             }
467         }
468         return false;
469     }
470 
isBehindOpaqueActivities(ComponentName activityName)471     boolean isBehindOpaqueActivities(ComponentName activityName) {
472         final String fullName = getActivityName(activityName);
473         for (ActivityStack stack : mStacks) {
474             for (ActivityTask task : stack.mTasks) {
475                 for (Activity activity : task.mActivities) {
476                     if (activity.name.equals(fullName)) {
477                         return false;
478                     }
479                     if (!activity.translucent) {
480                         return true;
481                     }
482                 }
483             }
484         }
485 
486         return false;
487     }
488 
containsStartedActivities()489     boolean containsStartedActivities() {
490         for (ActivityStack stack : mStacks) {
491             for (ActivityTask task : stack.mTasks) {
492                 for (Activity activity : task.mActivities) {
493                     if (!activity.state.equals(STATE_STOPPED)
494                             && !activity.state.equals(STATE_DESTROYED)) {
495                         return true;
496                     }
497                 }
498             }
499         }
500         return false;
501     }
502 
hasActivityState(ComponentName activityName, String activityState)503     boolean hasActivityState(ComponentName activityName, String activityState) {
504         final String fullName = getActivityName(activityName);
505         for (ActivityStack stack : mStacks) {
506             for (ActivityTask task : stack.mTasks) {
507                 for (Activity activity : task.mActivities) {
508                     if (activity.name.equals(fullName)) {
509                         return activity.state.equals(activityState);
510                     }
511                 }
512             }
513         }
514         return false;
515     }
516 
getActivityProcId(ComponentName activityName)517     int getActivityProcId(ComponentName activityName) {
518         final String fullName = getActivityName(activityName);
519         for (ActivityStack stack : mStacks) {
520             for (ActivityTask task : stack.mTasks) {
521                 for (Activity activity : task.mActivities) {
522                     if (activity.name.equals(fullName)) {
523                         return activity.procId;
524                     }
525                 }
526             }
527         }
528         return -1;
529     }
530 
isHomeActivityVisible()531     boolean isHomeActivityVisible() {
532         final Activity homeActivity = getHomeActivity();
533         return homeActivity != null && homeActivity.visible;
534     }
535 
isRecentsActivityVisible()536     boolean isRecentsActivityVisible() {
537         final Activity recentsActivity = getRecentsActivity();
538         return recentsActivity != null && recentsActivity.visible;
539     }
540 
getHomeActivityName()541     ComponentName getHomeActivityName() {
542         Activity activity = getHomeActivity();
543         if (activity == null) {
544             return null;
545         }
546         return ComponentName.unflattenFromString(activity.name);
547     }
548 
getHomeTask()549     ActivityTask getHomeTask() {
550         final ActivityStack homeStack = getStackByActivityType(ACTIVITY_TYPE_HOME);
551         if (homeStack != null && !homeStack.mTasks.isEmpty()) {
552             return homeStack.mTasks.get(0);
553         }
554         return null;
555     }
556 
getRecentsTask()557     private ActivityTask getRecentsTask() {
558         final ActivityStack recentsStack = getStackByActivityType(ACTIVITY_TYPE_RECENTS);
559         if (recentsStack != null && !recentsStack.mTasks.isEmpty()) {
560             return recentsStack.mTasks.get(0);
561         }
562         return null;
563     }
564 
getHomeActivity()565     private Activity getHomeActivity() {
566         final ActivityTask homeTask = getHomeTask();
567         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
568     }
569 
getRecentsActivity()570     private Activity getRecentsActivity() {
571         final ActivityTask recentsTask = getRecentsTask();
572         return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
573                 : null;
574     }
575 
getStackIdByActivity(ComponentName activityName)576     public int getStackIdByActivity(ComponentName activityName) {
577         final ActivityTask task = getTaskByActivity(activityName);
578         return  (task == null) ? INVALID_STACK_ID : task.mStackId;
579     }
580 
getTaskByActivity(ComponentName activityName)581     public ActivityTask getTaskByActivity(ComponentName activityName) {
582         return getTaskByActivityInternal(getActivityName(activityName), WINDOWING_MODE_UNDEFINED);
583     }
584 
getTaskByActivity(ComponentName activityName, int windowingMode)585     ActivityTask getTaskByActivity(ComponentName activityName, int windowingMode) {
586         return getTaskByActivityInternal(getActivityName(activityName), windowingMode);
587     }
588 
getTaskByActivityInternal(String fullName, int windowingMode)589     private ActivityTask getTaskByActivityInternal(String fullName, int windowingMode) {
590         for (ActivityStack stack : mStacks) {
591             if (windowingMode == WINDOWING_MODE_UNDEFINED
592                     || windowingMode == stack.getWindowingMode()) {
593                 for (ActivityTask task : stack.mTasks) {
594                     for (Activity activity : task.mActivities) {
595                         if (activity.name.equals(fullName)) {
596                             return task;
597                         }
598                     }
599                 }
600             }
601         }
602         return null;
603     }
604 
605     /**
606      * Get the number of activities in the task, with the option to count only activities with
607      * specific name.
608      * @param taskId Id of the task where we're looking for the number of activities.
609      * @param activityName Optional name of the activity we're interested in.
610      * @return Number of all activities in the task if activityName is {@code null}, otherwise will
611      *         report number of activities that have specified name.
612      */
getActivityCountInTask(int taskId, @Nullable ComponentName activityName)613     public int getActivityCountInTask(int taskId, @Nullable ComponentName activityName) {
614         // If activityName is null, count all activities in the task.
615         // Otherwise count activities that have specified name.
616         for (ActivityStack stack : mStacks) {
617             for (ActivityTask task : stack.mTasks) {
618                 if (task.mTaskId == taskId) {
619                     if (activityName == null) {
620                         return task.mActivities.size();
621                     }
622                     final String fullName = getActivityName(activityName);
623                     int count = 0;
624                     for (Activity activity : task.mActivities) {
625                         if (activity.name.equals(fullName)) {
626                             count++;
627                         }
628                     }
629                     return count;
630                 }
631             }
632         }
633         return 0;
634     }
635 
getStackCounts()636     public int getStackCounts() {
637         return mStacks.size();
638     }
639 
pendingActivityContain(ComponentName activityName)640     boolean pendingActivityContain(ComponentName activityName) {
641         return mPendingActivities.contains(getActivityName(activityName));
642     }
643 
644     public static class ActivityDisplay extends ActivityContainer {
645 
646         public int mId;
647         ArrayList<ActivityStack> mStacks = new ArrayList<>();
648         int mFocusedStackId;
649         String mResumedActivity;
650         boolean mSingleTaskInstance;
651 
ActivityDisplay(ActivityDisplayProto proto, ActivityManagerState amState)652         ActivityDisplay(ActivityDisplayProto proto, ActivityManagerState amState) {
653             super(proto.configurationContainer);
654             mId = proto.id;
655             mFocusedStackId = proto.focusedStackId;
656             mSingleTaskInstance = proto.singleTaskInstance;
657             if (proto.resumedActivity != null) {
658                 mResumedActivity = proto.resumedActivity.title;
659                 amState.mResumedActivitiesInDisplays.add(mResumedActivity);
660             }
661             for (int i = 0; i < proto.stacks.length; i++) {
662                 ActivityStack activityStack = new ActivityStack(proto.stacks[i]);
663                 mStacks.add(activityStack);
664                 // Also update activity manager state
665                 amState.mStacks.add(activityStack);
666                 if (activityStack.mResumedActivity != null) {
667                     amState.mResumedActivitiesInStacks.add(activityStack.mResumedActivity);
668                 }
669             }
670         }
671 
containsActivity(ComponentName activityName)672         boolean containsActivity(ComponentName activityName) {
673             final String fullName = getActivityName(activityName);
674             for (ActivityStack stack : mStacks) {
675                 for (ActivityTask task : stack.mTasks) {
676                     for (Activity activity : task.mActivities) {
677                         if (activity.name.equals(fullName)) {
678                             return true;
679                         }
680                     }
681                 }
682             }
683             return false;
684         }
685 
getStacks()686         public ArrayList<ActivityStack> getStacks() {
687             return mStacks;
688         }
689     }
690 
691     public static class ActivityStack extends ActivityContainer {
692 
693         public int mDisplayId;
694         int mStackId;
695         String mResumedActivity;
696         ArrayList<ActivityTask> mTasks = new ArrayList<>();
697 
ActivityStack(ActivityStackProto proto)698         ActivityStack(ActivityStackProto proto) {
699             super(proto.configurationContainer);
700             mStackId = proto.id;
701             mDisplayId = proto.displayId;
702             mBounds = extract(proto.bounds);
703             mFullscreen = proto.fullscreen;
704             for (int i = 0; i < proto.tasks.length; i++) {
705                 mTasks.add(new ActivityTask(proto.tasks[i]));
706             }
707             if (proto.resumedActivity != null) {
708                 mResumedActivity = proto.resumedActivity.title;
709             }
710         }
711 
712         /**
713          * @return the bottom task in the stack.
714          */
getBottomTask()715         ActivityTask getBottomTask() {
716             if (!mTasks.isEmpty()) {
717                 // NOTE: Unlike the ActivityManager internals, we dump the state from top to bottom,
718                 //       so the indices are inverted
719                 return mTasks.get(mTasks.size() - 1);
720             }
721             return null;
722         }
723 
724         /**
725          * @return the top task in the stack.
726          */
getTopTask()727         ActivityTask getTopTask() {
728             if (!mTasks.isEmpty()) {
729                 // NOTE: Unlike the ActivityManager internals, we dump the state from top to bottom,
730                 //       so the indices are inverted
731                 return mTasks.get(0);
732             }
733             return null;
734         }
735 
getTasks()736         public List<ActivityTask> getTasks() {
737             return new ArrayList<>(mTasks);
738         }
739 
getTask(int taskId)740         ActivityTask getTask(int taskId) {
741             for (ActivityTask task : mTasks) {
742                 if (taskId == task.mTaskId) {
743                     return task;
744                 }
745             }
746             return null;
747         }
748 
getStackId()749         public int getStackId() {
750             return mStackId;
751         }
752 
getResumedActivity()753         public String getResumedActivity() {
754             return mResumedActivity;
755         }
756     }
757 
758     public static class ActivityTask extends ActivityContainer {
759 
760         int mTaskId;
761         int mStackId;
762         Rect mLastNonFullscreenBounds;
763         String mRealActivity;
764         String mOrigActivity;
765         ArrayList<Activity> mActivities = new ArrayList<>();
766         int mTaskType = -1;
767         private int mResizeMode;
768 
ActivityTask(TaskRecordProto proto)769         ActivityTask(TaskRecordProto proto) {
770             super(proto.configurationContainer);
771             mTaskId = proto.id;
772             mStackId = proto.stackId;
773             mLastNonFullscreenBounds = extract(proto.lastNonFullscreenBounds);
774             mRealActivity = proto.realActivity;
775             mOrigActivity = proto.origActivity;
776             mTaskType = proto.activityType;
777             mResizeMode = proto.resizeMode;
778             mFullscreen = proto.fullscreen;
779             mBounds = extract(proto.bounds);
780             mMinWidth = proto.minWidth;
781             mMinHeight = proto.minHeight;
782             for (int i = 0;  i < proto.activities.length; i++) {
783                 mActivities.add(new Activity(proto.activities[i]));
784             }
785         }
786 
getResizeMode()787         public int getResizeMode() {
788             return mResizeMode;
789         }
790 
getTaskId()791         public int getTaskId() {
792             return mTaskId;
793         }
794 
getActivities()795         public ArrayList<Activity> getActivities() {
796             return mActivities;
797         }
798     }
799 
800     public static class Activity extends ActivityContainer {
801 
802         String name;
803         String state;
804         boolean visible;
805         boolean frontOfTask;
806         int procId = -1;
807         public boolean translucent;
808 
Activity(ActivityRecordProto proto)809         Activity(ActivityRecordProto proto) {
810             super(proto.configurationContainer);
811             name = proto.identifier.title;
812             state = proto.state;
813             visible = proto.visible;
814             frontOfTask = proto.frontOfTask;
815             if (proto.procId != 0) {
816                 procId = proto.procId;
817             }
818             translucent = proto.translucent;
819         }
820 
getName()821         public String getName() {
822             return name;
823         }
824 
getState()825         public String getState() {
826             return state;
827         }
828     }
829 
830     static abstract class ActivityContainer extends WindowManagerState.ConfigurationContainer {
831         protected boolean mFullscreen;
832         protected Rect mBounds;
833         protected int mMinWidth = -1;
834         protected int mMinHeight = -1;
835 
ActivityContainer(ConfigurationContainerProto proto)836         ActivityContainer(ConfigurationContainerProto proto) {
837             super(proto);
838         }
839 
getBounds()840         public Rect getBounds() {
841             return mBounds;
842         }
843 
isFullscreen()844         boolean isFullscreen() {
845             return mFullscreen;
846         }
847 
getMinWidth()848         int getMinWidth() {
849             return mMinWidth;
850         }
851 
getMinHeight()852         int getMinHeight() {
853             return mMinHeight;
854         }
855     }
856 
857     static class KeyguardControllerState {
858 
859         boolean aodShowing = false;
860         boolean keyguardShowing = false;
861         SparseArray<Boolean> mKeyguardOccludedStates = new SparseArray<>();
862 
KeyguardControllerState(KeyguardControllerProto proto)863         KeyguardControllerState(KeyguardControllerProto proto) {
864             if (proto != null) {
865                 aodShowing = proto.aodShowing;
866                 keyguardShowing = proto.keyguardShowing;
867                 for (int i = 0;  i < proto.keyguardOccludedStates.length; i++) {
868                     mKeyguardOccludedStates.append(proto.keyguardOccludedStates[i].displayId,
869                             proto.keyguardOccludedStates[i].keyguardOccluded);
870                 }
871             }
872         }
873 
isKeyguardOccluded(int displayId)874         boolean isKeyguardOccluded(int displayId) {
875             if (mKeyguardOccludedStates.get(displayId) != null) {
876                 return mKeyguardOccludedStates.get(displayId);
877             }
878             return false;
879         }
880     }
881 }
882