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