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