Home | History | Annotate | Download | only in wm
      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 
     82     void computeState() {
     83         computeState(DUMP_MODE_ACTIVITIES);
     84     }
     85 
     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 
    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 
    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 
    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      */
    192     boolean isHomeRecentsComponent() {
    193         if (mIsHomeRecentsComponent == null) {
    194             computeState();
    195         }
    196         return mIsHomeRecentsComponent;
    197     }
    198 
    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 
    208     int getFrontStackId(int displayId) {
    209         return getDisplay(displayId).mStacks.get(0).mStackId;
    210     }
    211 
    212     int getFrontStackActivityType(int displayId) {
    213         return getDisplay(displayId).mStacks.get(0).getActivityType();
    214     }
    215 
    216     int getFrontStackWindowingMode(int displayId) {
    217         return getDisplay(displayId).mStacks.get(0).getWindowingMode();
    218     }
    219 
    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 
    233     int getFocusedStackId() {
    234         return mTopFocusedStackId;
    235     }
    236 
    237     int getFocusedStackActivityType() {
    238         final ActivityStack stack = getStackById(mTopFocusedStackId);
    239         return stack != null ? stack.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
    240     }
    241 
    242     int getFocusedStackWindowingMode() {
    243         final ActivityStack stack = getStackById(mTopFocusedStackId);
    244         return stack != null ? stack.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
    245     }
    246 
    247     String getFocusedActivity() {
    248         return mTopResumedActivityRecord;
    249     }
    250 
    251     int getResumedActivitiesCount() {
    252         return mResumedActivitiesInStacks.size();
    253     }
    254 
    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 
    270     String getResumedActivityOnDisplay(int displayId) {
    271         return getDisplay(displayId).mResumedActivity;
    272     }
    273 
    274     public KeyguardControllerState getKeyguardControllerState() {
    275         return mKeyguardControllerState;
    276     }
    277 
    278     boolean containsStack(int stackId) {
    279         return getStackById(stackId) != null;
    280     }
    281 
    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 
    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 
    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 
    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 
    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. */
    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. */
    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. */
    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 
    380     List<ActivityDisplay> getDisplays() {
    381         return new ArrayList<>(mDisplays);
    382     }
    383 
    384     public List<ActivityStack> getStacks() {
    385         return new ArrayList<>(mStacks);
    386     }
    387 
    388     int getStackCount() {
    389         return mStacks.size();
    390     }
    391 
    392     int getDisplayCount() {
    393         return mDisplays.size();
    394     }
    395 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    531     boolean isHomeActivityVisible() {
    532         final Activity homeActivity = getHomeActivity();
    533         return homeActivity != null && homeActivity.visible;
    534     }
    535 
    536     boolean isRecentsActivityVisible() {
    537         final Activity recentsActivity = getRecentsActivity();
    538         return recentsActivity != null && recentsActivity.visible;
    539     }
    540 
    541     ComponentName getHomeActivityName() {
    542         Activity activity = getHomeActivity();
    543         if (activity == null) {
    544             return null;
    545         }
    546         return ComponentName.unflattenFromString(activity.name);
    547     }
    548 
    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 
    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 
    565     private Activity getHomeActivity() {
    566         final ActivityTask homeTask = getHomeTask();
    567         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
    568     }
    569 
    570     private Activity getRecentsActivity() {
    571         final ActivityTask recentsTask = getRecentsTask();
    572         return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
    573                 : null;
    574     }
    575 
    576     public int getStackIdByActivity(ComponentName activityName) {
    577         final ActivityTask task = getTaskByActivity(activityName);
    578         return  (task == null) ? INVALID_STACK_ID : task.mStackId;
    579     }
    580 
    581     public ActivityTask getTaskByActivity(ComponentName activityName) {
    582         return getTaskByActivityInternal(getActivityName(activityName), WINDOWING_MODE_UNDEFINED);
    583     }
    584 
    585     ActivityTask getTaskByActivity(ComponentName activityName, int windowingMode) {
    586         return getTaskByActivityInternal(getActivityName(activityName), windowingMode);
    587     }
    588 
    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      */
    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 
    636     public int getStackCounts() {
    637         return mStacks.size();
    638     }
    639 
    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 
    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 
    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 
    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 
    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          */
    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          */
    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 
    736         public List<ActivityTask> getTasks() {
    737             return new ArrayList<>(mTasks);
    738         }
    739 
    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 
    749         public int getStackId() {
    750             return mStackId;
    751         }
    752 
    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 
    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 
    787         public int getResizeMode() {
    788             return mResizeMode;
    789         }
    790 
    791         public int getTaskId() {
    792             return mTaskId;
    793         }
    794 
    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 
    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 
    821         public String getName() {
    822             return name;
    823         }
    824 
    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 
    836         ActivityContainer(ConfigurationContainerProto proto) {
    837             super(proto);
    838         }
    839 
    840         public Rect getBounds() {
    841             return mBounds;
    842         }
    843 
    844         boolean isFullscreen() {
    845             return mFullscreen;
    846         }
    847 
    848         int getMinWidth() {
    849             return mMinWidth;
    850         }
    851 
    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 
    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 
    874         boolean isKeyguardOccluded(int displayId) {
    875             if (mKeyguardOccludedStates.get(displayId) != null) {
    876                 return mKeyguardOccludedStates.get(displayId);
    877             }
    878             return false;
    879         }
    880     }
    881 }
    882