1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.server.wm; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 25 import static android.server.wm.ComponentNameUtils.getActivityName; 26 import static android.server.wm.ProtoExtractors.extract; 27 import static android.server.wm.StateLogger.log; 28 import static android.server.wm.StateLogger.logE; 29 import static android.server.wm.WindowManagerState.Task.INVALID_TASK_ID; 30 import static android.util.DisplayMetrics.DENSITY_DEFAULT; 31 import static android.view.Display.DEFAULT_DISPLAY; 32 import static android.window.DisplayAreaOrganizer.FEATURE_IME; 33 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; 34 35 import static androidx.test.InstrumentationRegistry.getInstrumentation; 36 37 import static com.google.common.truth.Truth.assertWithMessage; 38 39 import static org.junit.Assert.assertTrue; 40 import static org.junit.Assert.fail; 41 42 import android.app.ActivityTaskManager; 43 import android.app.UiAutomation; 44 import android.content.ComponentName; 45 import android.content.res.Configuration; 46 import android.graphics.Point; 47 import android.graphics.Rect; 48 import android.graphics.nano.RectProto; 49 import android.os.ParcelFileDescriptor; 50 import android.os.SystemClock; 51 import android.util.SparseArray; 52 import android.view.nano.DisplayInfoProto; 53 import android.view.nano.InsetsSourceProto; 54 import android.view.nano.ViewProtoEnums; 55 56 import androidx.annotation.NonNull; 57 import androidx.annotation.Nullable; 58 59 import com.android.server.wm.nano.ActivityRecordProto; 60 import com.android.server.wm.nano.AppTransitionProto; 61 import com.android.server.wm.nano.BackNavigationProto; 62 import com.android.server.wm.nano.ConfigurationContainerProto; 63 import com.android.server.wm.nano.DisplayAreaProto; 64 import com.android.server.wm.nano.DisplayContentProto; 65 import com.android.server.wm.nano.DisplayFramesProto; 66 import com.android.server.wm.nano.DisplayRotationProto; 67 import com.android.server.wm.nano.IdentifierProto; 68 import com.android.server.wm.nano.KeyguardControllerProto; 69 import com.android.server.wm.nano.KeyguardServiceDelegateProto; 70 import com.android.server.wm.nano.PinnedTaskControllerProto; 71 import com.android.server.wm.nano.RootWindowContainerProto; 72 import com.android.server.wm.nano.TaskFragmentProto; 73 import com.android.server.wm.nano.TaskProto; 74 import com.android.server.wm.nano.WindowContainerChildProto; 75 import com.android.server.wm.nano.WindowContainerProto; 76 import com.android.server.wm.nano.WindowFramesProto; 77 import com.android.server.wm.nano.WindowManagerServiceDumpProto; 78 import com.android.server.wm.nano.WindowStateAnimatorProto; 79 import com.android.server.wm.nano.WindowStateProto; 80 import com.android.server.wm.nano.WindowSurfaceControllerProto; 81 import com.android.server.wm.nano.WindowTokenProto; 82 83 import com.google.protobuf.nano.InvalidProtocolBufferNanoException; 84 85 import java.io.ByteArrayOutputStream; 86 import java.io.FileInputStream; 87 import java.io.IOException; 88 import java.nio.charset.StandardCharsets; 89 import java.util.ArrayList; 90 import java.util.Arrays; 91 import java.util.List; 92 import java.util.Objects; 93 import java.util.function.Consumer; 94 import java.util.function.Predicate; 95 import java.util.stream.Collectors; 96 import java.util.stream.Stream; 97 98 public class WindowManagerState { 99 100 public static final String STATE_INITIALIZING = "INITIALIZING"; 101 public static final String STATE_STARTED = "STARTED"; 102 public static final String STATE_RESUMED = "RESUMED"; 103 public static final String STATE_PAUSED = "PAUSED"; 104 public static final String STATE_STOPPED = "STOPPED"; 105 public static final String STATE_DESTROYED = "DESTROYED"; 106 public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN"; 107 public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE"; 108 public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN"; 109 public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE"; 110 public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN"; 111 public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE"; 112 public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN"; 113 public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE"; 114 public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY"; 115 public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 116 "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER"; 117 public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE"; 118 public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE"; 119 public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 120 "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN"; 121 public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 122 "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE"; 123 public static final String APP_STATE_IDLE = "APP_STATE_IDLE"; 124 public static final String APP_STATE_RUNNING = "APP_STATE_RUNNING"; 125 126 private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto"; 127 private static final String STARTING_WINDOW_PREFIX = "Starting "; 128 private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: "; 129 /** @see WindowManager.LayoutParams */ 130 private static final int TYPE_NAVIGATION_BAR = 2019; 131 /** @see WindowManager.LayoutParams */ 132 private static final int TYPE_NAVIGATION_BAR_PANEL = 2024; 133 /** @see WindowManager.LayoutParams */ 134 private static final int TYPE_NOTIFICATION_SHADE = 2040; 135 136 /** Whether accessibility services should be suppressed when taking the WindowManager dump. */ 137 private boolean mSuppressAccessibilityServices = true; 138 139 private RootWindowContainer mRoot = null; 140 // Displays in z-order with the top most at the front of the list, starting with primary. 141 private final List<DisplayContent> mDisplays = new ArrayList<>(); 142 /** 143 * Root tasks in z-order with the top most at the front of the list, starting with primary 144 * display. 145 */ 146 private final List<Task> mRootTasks = new ArrayList<>(); 147 // Windows in z-order with the top most at the front of the list. 148 private final List<WindowState> mWindowStates = new ArrayList<>(); 149 private KeyguardControllerState mKeyguardControllerState; 150 private KeyguardServiceDelegateState mKeyguardServiceDelegateState; 151 private final List<String> mPendingActivities = new ArrayList<>(); 152 private int mTopFocusedTaskId = -1; 153 private int mFocusedDisplayId = DEFAULT_DISPLAY; 154 private String mFocusedWindow = null; 155 private String mFocusedApp = null; 156 private Boolean mIsHomeRecentsComponent; 157 private String mTopResumedActivityRecord = null; 158 final List<String> mResumedActivitiesInRootTasks = new ArrayList<>(); 159 final List<String> mResumedActivitiesInDisplays = new ArrayList<>(); 160 private Rect mDefaultPinnedStackBounds = new Rect(); 161 private Rect mPinnedStackMovementBounds = new Rect(); 162 private String mInputMethodWindowAppToken = null; 163 private boolean mDisplayFrozen; 164 private boolean mSanityCheckFocusedWindow = true; 165 private boolean mWindowFramesValid; 166 private BackNavigationState mBackNavigationState; 167 appStateToString(int appState)168 static String appStateToString(int appState) { 169 switch (appState) { 170 case AppTransitionProto.APP_STATE_IDLE: 171 return "APP_STATE_IDLE"; 172 case AppTransitionProto.APP_STATE_READY: 173 return "APP_STATE_READY"; 174 case AppTransitionProto.APP_STATE_RUNNING: 175 return "APP_STATE_RUNNING"; 176 case AppTransitionProto.APP_STATE_TIMEOUT: 177 return "APP_STATE_TIMEOUT"; 178 default: 179 fail("Invalid AppTransitionState"); 180 return null; 181 } 182 } 183 appTransitionToString(int transition)184 static String appTransitionToString(int transition) { 185 switch (transition) { 186 case ViewProtoEnums.TRANSIT_UNSET: { 187 return "TRANSIT_UNSET"; 188 } 189 case ViewProtoEnums.TRANSIT_NONE: { 190 return "TRANSIT_NONE"; 191 } 192 case ViewProtoEnums.TRANSIT_ACTIVITY_OPEN: { 193 return TRANSIT_ACTIVITY_OPEN; 194 } 195 case ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE: { 196 return TRANSIT_ACTIVITY_CLOSE; 197 } 198 case ViewProtoEnums.TRANSIT_TASK_OPEN: { 199 return TRANSIT_TASK_OPEN; 200 } 201 case ViewProtoEnums.TRANSIT_TASK_CLOSE: { 202 return TRANSIT_TASK_CLOSE; 203 } 204 case ViewProtoEnums.TRANSIT_TASK_TO_FRONT: { 205 return "TRANSIT_TASK_TO_FRONT"; 206 } 207 case ViewProtoEnums.TRANSIT_TASK_TO_BACK: { 208 return "TRANSIT_TASK_TO_BACK"; 209 } 210 case ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE: { 211 return TRANSIT_WALLPAPER_CLOSE; 212 } 213 case ViewProtoEnums.TRANSIT_WALLPAPER_OPEN: { 214 return TRANSIT_WALLPAPER_OPEN; 215 } 216 case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN: { 217 return TRANSIT_WALLPAPER_INTRA_OPEN; 218 } 219 case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE: { 220 return TRANSIT_WALLPAPER_INTRA_CLOSE; 221 } 222 case ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND: { 223 return "TRANSIT_TASK_OPEN_BEHIND"; 224 } 225 case ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH: { 226 return "TRANSIT_ACTIVITY_RELAUNCH"; 227 } 228 case ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS: { 229 return "TRANSIT_DOCK_TASK_FROM_RECENTS"; 230 } 231 case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY: { 232 return TRANSIT_KEYGUARD_GOING_AWAY; 233 } 234 case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: { 235 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER; 236 } 237 case ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE: { 238 return TRANSIT_KEYGUARD_OCCLUDE; 239 } 240 case ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE: { 241 return TRANSIT_KEYGUARD_UNOCCLUDE; 242 } 243 case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: { 244 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN; 245 } 246 case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: { 247 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE; 248 } 249 case ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE: { 250 return "TRANSIT_CRASHING_ACTIVITY_CLOSE"; 251 } 252 default: { 253 fail("Invalid lastUsedAppTransition"); 254 return null; 255 } 256 } 257 } 258 isValidNavBarType(WindowState navState)259 static boolean isValidNavBarType(WindowState navState) { 260 return TYPE_NAVIGATION_BAR == navState.getType(); 261 } 262 263 /** 264 * For a given WindowContainer, traverse down the hierarchy and add all children of type 265 * {@code T} to {@code outChildren}. 266 */ collectDescendantsOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)267 private static <T extends WindowContainer> void collectDescendantsOfType(Class<T> clazz, 268 WindowContainer root, List<T> outChildren) { 269 collectDescendantsOfTypeIf(clazz, t -> true, root, outChildren); 270 } 271 272 /** 273 * For a given WindowContainer, traverse down the hierarchy and add all children of type 274 * {@code T} to {@code outChildren} if the child passes the test {@code predicate}. 275 */ collectDescendantsOfTypeIf(Class<T> clazz, Predicate<T> predicate, WindowContainer root, List<T> outChildren)276 private static <T extends WindowContainer> void collectDescendantsOfTypeIf(Class<T> clazz, 277 Predicate<T> predicate, WindowContainer root, List<T> outChildren) { 278 // Traverse top to bottom 279 for (int i = root.mChildren.size()-1; i >= 0; i--) { 280 final WindowContainer child = root.mChildren.get(i); 281 if (clazz.isInstance(child)) { 282 if(predicate.test(clazz.cast(child))) { 283 outChildren.add(clazz.cast(child)); 284 } 285 } 286 collectDescendantsOfTypeIf(clazz, predicate, child, outChildren); 287 } 288 } 289 290 /** 291 * For a given WindowContainer, traverse down the hierarchy and add all immediate children of 292 * type {@code T} to {@code outChildren}. 293 */ collectChildrenOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)294 private static <T extends WindowContainer> void collectChildrenOfType(Class<T> clazz, 295 WindowContainer root, List<T> outChildren) { 296 for (int i = root.mChildren.size()-1; i >= 0; i--) { 297 final WindowContainer child = root.mChildren.get(i); 298 if (clazz.isInstance(child)) { 299 outChildren.add(clazz.cast(child)); 300 } 301 } 302 } 303 304 /** Enable/disable the mFocusedWindow check during the computeState.*/ setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow)305 void setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow) { 306 mSanityCheckFocusedWindow = sanityCheckFocusedWindow; 307 } 308 computeState()309 public void computeState() { 310 // It is possible the system is in the middle of transition to the right state when we get 311 // the dump. We try a few times to get the information we need before giving up. 312 int retriesLeft = 3; 313 boolean retry = false; 314 byte[] dump = null; 315 316 log("=============================="); 317 log(" WindowManagerState "); 318 log("=============================="); 319 320 do { 321 if (retry) { 322 log("***Incomplete AM state. Retrying..."); 323 // Wait half a second between retries for activity manager to finish transitioning. 324 SystemClock.sleep(500); 325 } 326 327 dump = executeShellCommand(DUMPSYS_WINDOW); 328 try { 329 parseSysDumpProto(dump); 330 } catch (InvalidProtocolBufferNanoException ex) { 331 throw new RuntimeException("Failed to parse dumpsys:\n" 332 + new String(dump, StandardCharsets.UTF_8), ex); 333 } 334 335 retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty() 336 || mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null) 337 || !mWindowFramesValid 338 || (mTopResumedActivityRecord == null 339 || mResumedActivitiesInRootTasks.isEmpty()) 340 && !mKeyguardControllerState.keyguardShowing; 341 } while (retry && retriesLeft-- > 0); 342 343 if (mRootTasks.isEmpty()) { 344 logE("No root tasks found..."); 345 } 346 if (mTopFocusedTaskId == -1) { 347 logE("No focused task found..."); 348 } 349 if (mTopResumedActivityRecord == null) { 350 logE("No focused activity found..."); 351 } 352 if (mResumedActivitiesInRootTasks.isEmpty()) { 353 logE("No resumed activities found..."); 354 } 355 if (mWindowStates.isEmpty()) { 356 logE("No Windows found..."); 357 } 358 if (mFocusedWindow == null) { 359 logE("No Focused Window..."); 360 } 361 if (mFocusedApp == null) { 362 logE("No Focused App..."); 363 } 364 if (!mWindowFramesValid) { 365 logE("Window Frames Invalid..."); 366 } 367 } 368 setSuppressAccessibilityServices(boolean suppressAccessibilityServices)369 public void setSuppressAccessibilityServices(boolean suppressAccessibilityServices) { 370 mSuppressAccessibilityServices = suppressAccessibilityServices; 371 } 372 executeShellCommand(String cmd)373 private byte[] executeShellCommand(String cmd) { 374 try { 375 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation( 376 mSuppressAccessibilityServices ? 0 377 : UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) 378 .executeShellCommand(cmd); 379 byte[] buf = new byte[512]; 380 int bytesRead; 381 FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 382 ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 383 while ((bytesRead = fis.read(buf)) != -1) { 384 stdout.write(buf, 0, bytesRead); 385 } 386 fis.close(); 387 return stdout.toByteArray(); 388 } catch (IOException e) { 389 throw new RuntimeException(e); 390 } 391 } 392 393 /** Update WindowManagerState state for a newly added DisplayContent. */ updateForDisplayContent(DisplayContent display)394 private void updateForDisplayContent(DisplayContent display) { 395 if (display.mResumedActivity != null) { 396 mResumedActivitiesInDisplays.add(display.mResumedActivity); 397 } 398 399 for (int i = 0; i < display.mRootTasks.size(); i++) { 400 Task task = display.mRootTasks.get(i); 401 mRootTasks.add(task); 402 addResumedActivity(task); 403 } 404 405 if (display.mDefaultPinnedStackBounds != null) { 406 mDefaultPinnedStackBounds = display.mDefaultPinnedStackBounds; 407 mPinnedStackMovementBounds = display.mPinnedStackMovementBounds; 408 } 409 } 410 addResumedActivity(Task task)411 private void addResumedActivity(Task task) { 412 final int numChildTasks = task.mTasks.size(); 413 if (numChildTasks > 0) { 414 for (int i = numChildTasks - 1; i >=0; i--) { 415 addResumedActivity(task.mTasks.get(i)); 416 } 417 } else if (task.mResumedActivity != null) { 418 mResumedActivitiesInRootTasks.add(task.mResumedActivity); 419 } 420 } 421 parseSysDumpProto(byte[] sysDump)422 private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException { 423 reset(); 424 425 WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump); 426 final RootWindowContainerProto root = state.rootWindowContainer; 427 if (state.focusedWindow != null) { 428 mFocusedWindow = state.focusedWindow.title; 429 } 430 mRoot = new RootWindowContainer(root); 431 collectDescendantsOfType(DisplayContent.class, mRoot, mDisplays); 432 for (int i = 0; i < mDisplays.size(); i++) { 433 DisplayContent display = mDisplays.get(i); 434 updateForDisplayContent(display); 435 } 436 mKeyguardControllerState = new KeyguardControllerState(root.keyguardController); 437 mKeyguardServiceDelegateState = 438 new KeyguardServiceDelegateState(state.policy.keyguardDelegate); 439 mFocusedApp = state.focusedApp; 440 mFocusedDisplayId = state.focusedDisplayId; 441 final DisplayContent focusedDisplay = getDisplay(mFocusedDisplayId); 442 if (focusedDisplay != null) { 443 mTopFocusedTaskId = focusedDisplay.mFocusedRootTaskId; 444 mTopResumedActivityRecord = focusedDisplay.mResumedActivity; 445 } 446 mIsHomeRecentsComponent = new Boolean(root.isHomeRecentsComponent); 447 448 for (int i = 0; i < root.pendingActivities.length; i++) { 449 mPendingActivities.add(root.pendingActivities[i].title); 450 } 451 452 collectDescendantsOfType(WindowState.class, mRoot, mWindowStates); 453 454 if (state.inputMethodWindow != null) { 455 mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode); 456 } 457 mDisplayFrozen = state.displayFrozen; 458 mWindowFramesValid = state.windowFramesValid; 459 460 mBackNavigationState = new BackNavigationState(state.backNavigation); 461 } 462 reset()463 private void reset() { 464 mRoot = null; 465 mDisplays.clear(); 466 mRootTasks.clear(); 467 mWindowStates.clear(); 468 mTopFocusedTaskId = -1; 469 mFocusedDisplayId = DEFAULT_DISPLAY; 470 mFocusedWindow = null; 471 mFocusedApp = null; 472 mTopResumedActivityRecord = null; 473 mResumedActivitiesInRootTasks.clear(); 474 mResumedActivitiesInDisplays.clear(); 475 mKeyguardControllerState = null; 476 mKeyguardServiceDelegateState = null; 477 mIsHomeRecentsComponent = null; 478 mPendingActivities.clear(); 479 mDefaultPinnedStackBounds.setEmpty(); 480 mPinnedStackMovementBounds.setEmpty(); 481 mInputMethodWindowAppToken = null; 482 mDisplayFrozen = false; 483 mWindowFramesValid = false; 484 } 485 getFocusedApp()486 public String getFocusedApp() { 487 return mFocusedApp; 488 } 489 getFocusedWindow()490 public String getFocusedWindow() { 491 return mFocusedWindow; 492 } 493 494 /** @return Whether the home activity is the recents component. */ isHomeRecentsComponent()495 boolean isHomeRecentsComponent() { 496 if (mIsHomeRecentsComponent == null) { 497 computeState(); 498 } 499 return mIsHomeRecentsComponent; 500 } 501 getDisplay(int displayId)502 DisplayContent getDisplay(int displayId) { 503 for (DisplayContent display : mDisplays) { 504 if (display.mId == displayId) { 505 return display; 506 } 507 } 508 return null; 509 } 510 511 @Nullable getTaskDisplayArea(ComponentName activityName)512 DisplayArea getTaskDisplayArea(ComponentName activityName) { 513 final List<DisplayArea> result = new ArrayList<>(); 514 for (DisplayContent display : mDisplays) { 515 final DisplayArea tda = display.getTaskDisplayArea(activityName); 516 if (tda != null) { 517 result.add(tda); 518 } 519 } 520 assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.") 521 .that(result.size()).isAtMost(1); 522 523 return result.stream().findFirst().orElse(null); 524 } 525 getTaskDisplayAreaFeatureId(ComponentName activityName)526 public int getTaskDisplayAreaFeatureId(ComponentName activityName) { 527 final DisplayArea taskDisplayArea = getTaskDisplayArea(activityName); 528 if (taskDisplayArea != null) { 529 return taskDisplayArea.getFeatureId(); 530 } 531 532 return FEATURE_UNDEFINED; 533 } 534 535 @Nullable getDisplayArea(String windowName)536 DisplayArea getDisplayArea(String windowName) { 537 final List<DisplayArea> result = new ArrayList<>(); 538 for (DisplayContent display : mDisplays) { 539 final DisplayArea da = display.getDisplayArea(windowName); 540 if (da != null) { 541 result.add(da); 542 } 543 } 544 assertWithMessage("There must be exactly one window among all DisplayAreas.") 545 .that(result.size()).isAtMost(1); 546 547 return result.stream().findFirst().orElse(null); 548 } 549 550 @Nullable getImeContainer(int displayId)551 public DisplayArea getImeContainer(int displayId) { 552 final DisplayContent displayContent = getDisplay(displayId); 553 if (displayContent == null) { 554 return null; 555 } 556 return displayContent.getImeContainer(); 557 } 558 getFrontRootTaskId(int displayId)559 int getFrontRootTaskId(int displayId) { 560 return getDisplay(displayId).mRootTasks.get(0).mRootTaskId; 561 } 562 getFrontRootTaskActivityType(int displayId)563 public int getFrontRootTaskActivityType(int displayId) { 564 return getDisplay(displayId).mRootTasks.get(0).getActivityType(); 565 } 566 getFrontRootTaskWindowingMode(int displayId)567 public int getFrontRootTaskWindowingMode(int displayId) { 568 return getDisplay(displayId).mRootTasks.get(0).getWindowingMode(); 569 } 570 getTopActivityName(int displayId)571 public String getTopActivityName(int displayId) { 572 if (!getDisplay(displayId).mRootTasks.isEmpty()) { 573 final Task topRootTask = getDisplay(displayId).mRootTasks.get(0); 574 final Task topTask = topRootTask.getTopTask(); 575 if (!topTask.mActivities.isEmpty()) { 576 return topTask.mActivities.get(0).name; 577 } 578 } 579 return null; 580 } 581 getFocusedTaskId()582 int getFocusedTaskId() { 583 return mTopFocusedTaskId; 584 } 585 getFocusedRootTaskActivityType()586 public int getFocusedRootTaskActivityType() { 587 final Task rootTask = getRootTask(mTopFocusedTaskId); 588 return rootTask != null ? rootTask.getActivityType() : ACTIVITY_TYPE_UNDEFINED; 589 } 590 getFocusedRootTaskWindowingMode()591 public int getFocusedRootTaskWindowingMode() { 592 final Task rootTask = getRootTask(mTopFocusedTaskId); 593 return rootTask != null ? rootTask.getWindowingMode() : WINDOWING_MODE_UNDEFINED; 594 } 595 getFocusedActivity()596 public String getFocusedActivity() { 597 return mTopResumedActivityRecord; 598 } 599 getResumedActivitiesCount()600 public int getResumedActivitiesCount() { 601 return mResumedActivitiesInRootTasks.size(); 602 } 603 getResumedActivitiesCountInPackage(String packageName)604 public int getResumedActivitiesCountInPackage(String packageName) { 605 final String componentPrefix = packageName + "/"; 606 int count = 0; 607 for (int i = mDisplays.size() - 1; i >= 0; --i) { 608 final ArrayList<Task> rootTasks = mDisplays.get(i).getRootTasks(); 609 for (int j = rootTasks.size() - 1; j >= 0; --j) { 610 final String resumedActivity = rootTasks.get(j).mResumedActivity; 611 if (resumedActivity != null && resumedActivity.startsWith(componentPrefix)) { 612 count++; 613 } 614 } 615 } 616 return count; 617 } 618 getResumedActivityOnDisplay(int displayId)619 public String getResumedActivityOnDisplay(int displayId) { 620 return getDisplay(displayId).mResumedActivity; 621 } 622 getKeyguardControllerState()623 public KeyguardControllerState getKeyguardControllerState() { 624 return mKeyguardControllerState; 625 } 626 getKeyguardServiceDelegateState()627 public KeyguardServiceDelegateState getKeyguardServiceDelegateState() { 628 return mKeyguardServiceDelegateState; 629 } 630 getBackNavigationState()631 public BackNavigationState getBackNavigationState() { 632 return mBackNavigationState; 633 } 634 containsRootTasks(int windowingMode, int activityType)635 public boolean containsRootTasks(int windowingMode, int activityType) { 636 return countRootTasks(windowingMode, activityType) > 0; 637 } 638 countRootTasks(int windowingMode, int activityType)639 public int countRootTasks(int windowingMode, int activityType) { 640 int count = 0; 641 for (Task rootTask : mRootTasks) { 642 if (activityType != ACTIVITY_TYPE_UNDEFINED 643 && activityType != rootTask.getActivityType()) { 644 continue; 645 } 646 if (windowingMode != WINDOWING_MODE_UNDEFINED 647 && windowingMode != rootTask.getWindowingMode()) { 648 continue; 649 } 650 ++count; 651 } 652 return count; 653 } 654 getRootTask(int taskId)655 public Task getRootTask(int taskId) { 656 for (Task rootTask : mRootTasks) { 657 if (taskId == rootTask.mRootTaskId) { 658 return rootTask; 659 } 660 } 661 return null; 662 } 663 getRootTaskByActivityType(int activityType)664 public Task getRootTaskByActivityType(int activityType) { 665 for (Task rootTask : mRootTasks) { 666 if (activityType == rootTask.getActivityType()) { 667 return rootTask; 668 } 669 } 670 return null; 671 } 672 getStandardTaskCountByWindowingMode(int windowingMode)673 public int getStandardTaskCountByWindowingMode(int windowingMode) { 674 int count = 0; 675 for (Task rootTask : mRootTasks) { 676 if (rootTask.getActivityType() != ACTIVITY_TYPE_STANDARD) { 677 continue; 678 } 679 if (rootTask.getWindowingMode() == windowingMode) { 680 count += rootTask.mTasks.isEmpty() ? 1 : rootTask.mTasks.size(); 681 } 682 } 683 return count; 684 } 685 686 /** Gets the position of root task on its display with the given {@code activityType}. */ getRootTaskIndexByActivityType(int activityType)687 int getRootTaskIndexByActivityType(int activityType) { 688 for (DisplayContent display : mDisplays) { 689 for (int i = 0; i < display.mRootTasks.size(); i++) { 690 if (activityType == display.mRootTasks.get(i).getActivityType()) { 691 return i; 692 } 693 } 694 } 695 return -1; 696 } 697 698 /** Gets the root task on its display with the given {@code activityName}. */ 699 @Nullable getRootTaskByActivity(ComponentName activityName)700 Task getRootTaskByActivity(ComponentName activityName) { 701 for (DisplayContent display : mDisplays) { 702 for (int i = display.mRootTasks.size() - 1; i >= 0; --i) { 703 final Task rootTask = display.mRootTasks.get(i); 704 if (rootTask.containsActivity(activityName)) return rootTask; 705 } 706 } 707 return null; 708 } 709 710 /** Get display id by activity on it. */ getDisplayByActivity(ComponentName activityComponent)711 public int getDisplayByActivity(ComponentName activityComponent) { 712 final Task task = getTaskByActivity(activityComponent); 713 if (task == null) { 714 return -1; 715 } 716 return getRootTask(task.mRootTaskId).mDisplayId; 717 } 718 getDisplays()719 List<DisplayContent> getDisplays() { 720 return new ArrayList<>(mDisplays); 721 } 722 getRootTasks()723 public List<Task> getRootTasks() { 724 return new ArrayList<>(mRootTasks); 725 } 726 getRootTaskCount()727 public int getRootTaskCount() { 728 return mRootTasks.size(); 729 } 730 getDisplayCount()731 public int getDisplayCount() { 732 return mDisplays.size(); 733 } 734 containsActivity(ComponentName activityName)735 public boolean containsActivity(ComponentName activityName) { 736 for (Task rootTask : mRootTasks) { 737 if (rootTask.containsActivity(activityName)) return true; 738 } 739 return false; 740 } 741 containsNoneOf(Iterable<ComponentName> activityNames)742 public boolean containsNoneOf(Iterable<ComponentName> activityNames) { 743 for (ComponentName activityName : activityNames) { 744 for (Task rootTask : mRootTasks) { 745 if (rootTask.containsActivity(activityName)) return false; 746 } 747 } 748 return true; 749 } 750 containsActivityInWindowingMode(ComponentName activityName, int windowingMode)751 public boolean containsActivityInWindowingMode(ComponentName activityName, int windowingMode) { 752 for (Task rootTask : mRootTasks) { 753 final Activity activity = rootTask.getActivity(activityName); 754 if (activity != null && activity.getWindowingMode() == windowingMode) { 755 return true; 756 } 757 } 758 return false; 759 } 760 isActivityVisible(ComponentName activityName)761 public boolean isActivityVisible(ComponentName activityName) { 762 for (Task rootTask : mRootTasks) { 763 final Activity activity = rootTask.getActivity(activityName); 764 if (activity != null) return activity.visible; 765 } 766 return false; 767 } 768 isActivityTranslucent(ComponentName activityName)769 public boolean isActivityTranslucent(ComponentName activityName) { 770 for (Task rootTask : mRootTasks) { 771 final Activity activity = rootTask.getActivity(activityName); 772 if (activity != null) return activity.translucent; 773 } 774 return false; 775 } 776 isBehindOpaqueActivities(ComponentName activityName)777 public boolean isBehindOpaqueActivities(ComponentName activityName) { 778 final String fullName = getActivityName(activityName); 779 for (Task rootTask : mRootTasks) { 780 final Activity activity = 781 rootTask.getActivity((a) -> a.name.equals(fullName) || !a.translucent); 782 if (activity != null) { 783 if (activity.name.equals(fullName)) { 784 return false; 785 } 786 if (!activity.translucent) { 787 return true; 788 } 789 } 790 } 791 792 return false; 793 } 794 isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName)795 public boolean isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName) { 796 return getTaskDisplayArea(activityName).isIgnoringOrientationRequest(); 797 } 798 containsStartedActivities()799 public boolean containsStartedActivities() { 800 for (Task rootTask : mRootTasks) { 801 final Activity activity = rootTask.getActivity( 802 (a) -> !a.state.equals(STATE_STOPPED) && !a.state.equals(STATE_DESTROYED)); 803 if (activity != null) return true; 804 } 805 return false; 806 } 807 hasActivityState(ComponentName activityName, String activityState)808 boolean hasActivityState(ComponentName activityName, String activityState) { 809 for (Task rootTask : mRootTasks) { 810 final Activity activity = rootTask.getActivity(activityName); 811 if (activity != null) return activity.state.equals(activityState); 812 } 813 return false; 814 } 815 getActivityProcId(ComponentName activityName)816 int getActivityProcId(ComponentName activityName) { 817 for (Task rootTask : mRootTasks) { 818 final Activity activity = rootTask.getActivity(activityName); 819 if (activity != null) return activity.procId; 820 } 821 return -1; 822 } 823 isRecentsActivityVisible()824 boolean isRecentsActivityVisible() { 825 final Activity recentsActivity = getRecentsActivity(); 826 return recentsActivity != null && recentsActivity.visible; 827 } 828 getHomeActivityName()829 ComponentName getHomeActivityName() { 830 Activity activity = getHomeActivity(); 831 if (activity == null) { 832 return null; 833 } 834 return ComponentName.unflattenFromString(activity.name); 835 } 836 getDreamTask()837 Task getDreamTask() { 838 final Task dreamRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_DREAM); 839 if (dreamRootTask != null) { 840 return dreamRootTask.getTopTask(); 841 } 842 return null; 843 } 844 getHomeTask()845 Task getHomeTask() { 846 final Task homeRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_HOME); 847 if (homeRootTask != null) { 848 return homeRootTask.getTopTask(); 849 } 850 return null; 851 } 852 getRecentsTask()853 private Task getRecentsTask() { 854 final Task recentsRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_RECENTS); 855 if (recentsRootTask != null) { 856 return recentsRootTask.getTopTask(); 857 } 858 return null; 859 } 860 getHomeActivity()861 private Activity getHomeActivity() { 862 final Task homeTask = getHomeTask(); 863 return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null; 864 } 865 getRecentsActivity()866 private Activity getRecentsActivity() { 867 final Task recentsTask = getRecentsTask(); 868 return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1) 869 : null; 870 } 871 getRootTaskIdByActivity(ComponentName activityName)872 public int getRootTaskIdByActivity(ComponentName activityName) { 873 final Task rootTask = getRootTaskByActivity(activityName); 874 return (rootTask == null) ? INVALID_TASK_ID : rootTask.mTaskId; 875 } 876 getTaskByActivity(ComponentName activityName)877 public Task getTaskByActivity(ComponentName activityName) { 878 return getTaskByActivity( 879 activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID }); 880 } 881 getTaskByActivity(ComponentName activityName, int[] excludeTaskIds)882 public Task getTaskByActivity(ComponentName activityName, int[] excludeTaskIds) { 883 return getTaskByActivity(activityName, WINDOWING_MODE_UNDEFINED, excludeTaskIds); 884 } 885 getTaskByActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)886 private Task getTaskByActivity(ComponentName activityName, int windowingMode, 887 int[] excludeTaskIds) { 888 Activity activity = getActivity(activityName, windowingMode, excludeTaskIds); 889 return activity == null ? null : activity.getTask(); 890 } 891 892 @Nullable getTaskFragmentByActivity(ComponentName activityName)893 public TaskFragment getTaskFragmentByActivity(ComponentName activityName) { 894 return getActivity(activityName).getTaskFragment(); 895 } 896 getActivity(ComponentName activityName)897 public Activity getActivity(ComponentName activityName) { 898 return getActivity(activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID }); 899 } 900 getActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)901 private Activity getActivity(ComponentName activityName, int windowingMode, 902 int[] excludeTaskIds) { 903 for (Task rootTask : mRootTasks) { 904 if (windowingMode == WINDOWING_MODE_UNDEFINED 905 || windowingMode == rootTask.getWindowingMode()) { 906 Activity activity = rootTask.getActivity(activityName, excludeTaskIds); 907 if (activity != null) return activity; 908 } 909 } 910 return null; 911 } 912 913 /** 914 * Get the number of activities in the task, with the option to count only activities with 915 * specific name. 916 * @param taskId Id of the task where we're looking for the number of activities. 917 * @param activityName Optional name of the activity we're interested in. 918 * @return Number of all activities in the task if activityName is {@code null}, otherwise will 919 * report number of activities that have specified name. 920 */ getActivityCountInTask(int taskId, @Nullable ComponentName activityName)921 public int getActivityCountInTask(int taskId, @Nullable ComponentName activityName) { 922 // If activityName is null, count all activities in the task. 923 // Otherwise count activities that have specified name. 924 for (Task rootTask : mRootTasks) { 925 final Task task = rootTask.getTask(taskId); 926 if (task == null) continue; 927 928 if (activityName == null) { 929 return task.mActivities.size(); 930 } 931 final String fullName = getActivityName(activityName); 932 int count = 0; 933 for (Activity activity : task.mActivities) { 934 if (activity.name.equals(fullName)) { 935 count++; 936 } 937 } 938 return count; 939 } 940 return 0; 941 } 942 getRootTasksCount()943 public int getRootTasksCount() { 944 return mRootTasks.size(); 945 } 946 getRootTasksCount(int displayId)947 public int getRootTasksCount(int displayId) { 948 return getRootTasksCount(t -> t.mDisplayId == displayId); 949 } 950 951 /** 952 * Count root tasks filtered by the predicate passed as argument. 953 */ getRootTasksCount(Predicate<? super Task> predicate)954 public int getRootTasksCount(Predicate<? super Task> predicate) { 955 return (int) mRootTasks.stream().filter(predicate).count(); 956 } 957 pendingActivityContain(ComponentName activityName)958 boolean pendingActivityContain(ComponentName activityName) { 959 return mPendingActivities.contains(getActivityName(activityName)); 960 } 961 962 // Get the logical display size of the default display. getLogicalDisplaySize()963 public static Point getLogicalDisplaySize() { 964 WindowManagerState mWmState = new WindowManagerState(); 965 mWmState.computeState(); 966 Rect size = mWmState.getDisplay(DEFAULT_DISPLAY).getDisplayRect(); 967 return new Point(size.width(), size.height()); 968 } 969 getDefaultDisplayLastTransition()970 String getDefaultDisplayLastTransition() { 971 return getDisplay(DEFAULT_DISPLAY).getLastTransition(); 972 } 973 getDefaultDisplayAppTransitionState()974 String getDefaultDisplayAppTransitionState() { 975 return getDisplay(DEFAULT_DISPLAY).getAppTransitionState(); 976 } 977 getMatchingVisibleWindowState(final String windowName)978 public List<WindowState> getMatchingVisibleWindowState(final String windowName) { 979 return getMatchingWindows(ws -> ws.isSurfaceShown() && windowName.equals(ws.getName())) 980 .collect(Collectors.toList()); 981 } 982 getMatchingWindows(Predicate<WindowState> condition)983 public Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) { 984 return mWindowStates.stream().filter(condition); 985 } 986 987 @Nullable getWindowByPackageName(String packageName, int windowType)988 public WindowState getWindowByPackageName(String packageName, int windowType) { 989 final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType); 990 return windowList.isEmpty() ? null : windowList.get(0); 991 } 992 getWindowsByPackageName(String packageName, int... restrictToTypes)993 public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) { 994 return getMatchingWindows(ws -> 995 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/")) 996 && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType())) 997 .collect(Collectors.toList()); 998 } 999 allActivitiesResumed()1000 public boolean allActivitiesResumed() { 1001 for (Task rootTask : mRootTasks) { 1002 final Activity nonResumedActivity = 1003 rootTask.getActivity((a) -> !a.state.equals(STATE_RESUMED)); 1004 if (nonResumedActivity != null) return false; 1005 } 1006 return true; 1007 } 1008 hasNotificationShade()1009 public boolean hasNotificationShade() { 1010 computeState(); 1011 return !getMatchingWindowType(TYPE_NOTIFICATION_SHADE).isEmpty(); 1012 } 1013 getWindows()1014 List<WindowState> getWindows() { 1015 return new ArrayList<>(mWindowStates); 1016 } 1017 getMatchingWindowType(int type)1018 public List<WindowState> getMatchingWindowType(int type) { 1019 return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList()); 1020 } 1021 getAllNavigationBarStates()1022 List<WindowState> getAllNavigationBarStates() { 1023 return getMatchingWindows(WindowManagerState::isValidNavBarType) 1024 .collect(Collectors.toList()); 1025 } 1026 1027 @Nullable getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount)1028 List<WindowState> getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount) { 1029 List<WindowState> navWindows = getMatchingWindows(ws -> isValidNavBarType(ws) 1030 && ws.getDisplayId() == displayId) 1031 .filter(Objects::nonNull) 1032 .collect(Collectors.toList()); 1033 // We may need some time to wait for nav bar showing. 1034 // It's Ok to get less that expected nav bars here. 1035 assertTrue("There should be at most expectedNavBarCount navigation bar on a display", 1036 navWindows.size() <= expectedNavBarCount); 1037 1038 return navWindows.size() == expectedNavBarCount ? navWindows : null; 1039 } 1040 getWindowStateForAppToken(String appToken)1041 WindowState getWindowStateForAppToken(String appToken) { 1042 return getMatchingWindows(ws -> ws.getToken().equals(appToken)) 1043 .findFirst() 1044 .orElse(null); 1045 } 1046 getFrontWindow()1047 String getFrontWindow() { 1048 if (mWindowStates == null || mWindowStates.isEmpty()) { 1049 return null; 1050 } 1051 return mWindowStates.get(0).getName(); 1052 } 1053 1054 /** Check if there exists a window record with matching windowName. */ containsWindow(String windowName)1055 public boolean containsWindow(String windowName) { 1056 for (WindowState window : mWindowStates) { 1057 if (window.getName().equals(windowName)) { 1058 return true; 1059 } 1060 } 1061 return false; 1062 } 1063 1064 /** Check if at least one window which matches the specified name has shown it's surface. */ isWindowSurfaceShown(String windowName)1065 public boolean isWindowSurfaceShown(String windowName) { 1066 for (WindowState window : mWindowStates) { 1067 if (window.getName().equals(windowName)) { 1068 if (window.isSurfaceShown()) { 1069 return true; 1070 } 1071 } 1072 } 1073 return false; 1074 } 1075 1076 /** Check if at least one window which matches provided window name is visible. */ isWindowVisible(String windowName)1077 public boolean isWindowVisible(String windowName) { 1078 for (WindowState window : mWindowStates) { 1079 if (window.getName().equals(windowName)) { 1080 if (window.isVisible()) { 1081 return true; 1082 } 1083 } 1084 } 1085 return false; 1086 } 1087 allWindowSurfacesShown(String windowName)1088 public boolean allWindowSurfacesShown(String windowName) { 1089 boolean allShown = false; 1090 for (WindowState window : mWindowStates) { 1091 if (window.getName().equals(windowName)) { 1092 if (!window.isSurfaceShown()) { 1093 log("[VISIBLE] not visible" + windowName); 1094 return false; 1095 } 1096 log("[VISIBLE] visible" + windowName); 1097 allShown = true; 1098 } 1099 } 1100 return allShown; 1101 } 1102 1103 /** Checks whether the display contains the given activity. */ hasActivityInDisplay(int displayId, ComponentName activityName)1104 boolean hasActivityInDisplay(int displayId, ComponentName activityName) { 1105 for (Task rootTask : getDisplay(displayId).getRootTasks()) { 1106 if (rootTask.containsActivity(activityName)) { 1107 return true; 1108 } 1109 } 1110 return false; 1111 } 1112 findFirstWindowWithType(int type)1113 WindowState findFirstWindowWithType(int type) { 1114 for (WindowState window : mWindowStates) { 1115 if (window.getType() == type) { 1116 return window; 1117 } 1118 } 1119 return null; 1120 } 1121 getZOrder(WindowState w)1122 public int getZOrder(WindowState w) { 1123 return mWindowStates.size() - mWindowStates.indexOf(w); 1124 } 1125 getStandardRootTaskByWindowingMode(int windowingMode)1126 Task getStandardRootTaskByWindowingMode(int windowingMode) { 1127 for (Task task : mRootTasks) { 1128 if (task.getActivityType() != ACTIVITY_TYPE_STANDARD) { 1129 continue; 1130 } 1131 if (task.getWindowingMode() == windowingMode) { 1132 return task; 1133 } 1134 } 1135 return null; 1136 } 1137 getInputMethodWindowState()1138 WindowManagerState.WindowState getInputMethodWindowState() { 1139 return getWindowStateForAppToken(mInputMethodWindowAppToken); 1140 } 1141 isDisplayFrozen()1142 public boolean isDisplayFrozen() { 1143 return mDisplayFrozen; 1144 } 1145 getRotation()1146 public int getRotation() { 1147 return getDisplay(DEFAULT_DISPLAY).mRotation; 1148 } 1149 getLastOrientation()1150 public int getLastOrientation() { 1151 return getDisplay(DEFAULT_DISPLAY).mLastOrientation; 1152 } 1153 getFocusedDisplayId()1154 public int getFocusedDisplayId() { 1155 return mFocusedDisplayId; 1156 } 1157 isFixedToUserRotation()1158 public boolean isFixedToUserRotation() { 1159 return getDisplay(DEFAULT_DISPLAY).mIsFixedToUserRotation; 1160 } 1161 1162 public static class DisplayContent extends DisplayArea { 1163 public int mId; 1164 ArrayList<Task> mRootTasks = new ArrayList<>(); 1165 int mFocusedRootTaskId; 1166 String mResumedActivity; 1167 boolean mSingleTaskInstance; 1168 Rect mDefaultPinnedStackBounds = null; 1169 Rect mPinnedStackMovementBounds = null; 1170 int mMinSizeOfResizeableTaskDp; 1171 1172 private Rect mDisplayRect = new Rect(); 1173 private Rect mAppRect = new Rect(); 1174 private int mDpi; 1175 private int mFlags; 1176 private String mName; 1177 private int mSurfaceSize; 1178 private String mFocusedApp; 1179 private String mLastTransition; 1180 private String mAppTransitionState; 1181 private int mRotation; 1182 private boolean mFrozenToUserRotation; 1183 private int mUserRotation; 1184 private int mFixedToUserRotationMode; 1185 private int mLastOrientation; 1186 private boolean mIsFixedToUserRotation; 1187 private List<Rect> mKeepClearRects; 1188 DisplayContent(DisplayContentProto proto)1189 DisplayContent(DisplayContentProto proto) { 1190 super(proto.rootDisplayArea); 1191 mId = proto.id; 1192 mFocusedRootTaskId = proto.focusedRootTaskId; 1193 mSingleTaskInstance = proto.singleTaskInstance; 1194 if (proto.resumedActivity != null) { 1195 mResumedActivity = proto.resumedActivity.title; 1196 } 1197 addRootTasks(); 1198 1199 mDpi = proto.dpi; 1200 DisplayInfoProto infoProto = proto.displayInfo; 1201 if (infoProto != null) { 1202 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight); 1203 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight); 1204 mName = infoProto.name; 1205 mFlags = infoProto.flags; 1206 } 1207 final DisplayFramesProto displayFramesProto = proto.displayFrames; 1208 mSurfaceSize = proto.surfaceSize; 1209 mFocusedApp = proto.focusedApp; 1210 mMinSizeOfResizeableTaskDp = proto.minSizeOfResizeableTaskDp; 1211 1212 final AppTransitionProto appTransitionProto = proto.appTransition; 1213 int appState = 0; 1214 int lastTransition = 0; 1215 if (appTransitionProto != null) { 1216 appState = appTransitionProto.appTransitionState; 1217 lastTransition = appTransitionProto.lastUsedAppTransition; 1218 } 1219 mAppTransitionState = appStateToString(appState); 1220 mLastTransition = appTransitionToString(lastTransition); 1221 1222 PinnedTaskControllerProto pinnedTaskProto = proto.pinnedTaskController; 1223 if (pinnedTaskProto != null) { 1224 mDefaultPinnedStackBounds = extract(pinnedTaskProto.defaultBounds); 1225 mPinnedStackMovementBounds = extract(pinnedTaskProto.movementBounds); 1226 } 1227 1228 final DisplayRotationProto rotationProto = proto.displayRotation; 1229 if (rotationProto != null) { 1230 mRotation = rotationProto.rotation; 1231 mFrozenToUserRotation = rotationProto.frozenToUserRotation; 1232 mUserRotation = rotationProto.userRotation; 1233 mFixedToUserRotationMode = rotationProto.fixedToUserRotationMode; 1234 mLastOrientation = rotationProto.lastOrientation; 1235 mIsFixedToUserRotation = rotationProto.isFixedToUserRotation; 1236 } 1237 mKeepClearRects = new ArrayList(); 1238 for (RectProto r : proto.keepClearAreas) { 1239 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom)); 1240 } 1241 } 1242 getName()1243 public String getName() { 1244 return mName; 1245 } 1246 addRootTasks()1247 private void addRootTasks() { 1248 // TODO(b/149338177): figure out how CTS tests deal with organizer. For now, 1249 // don't treat them as regular root tasks 1250 collectDescendantsOfTypeIf(Task.class, t -> t.isRootTask(), this, 1251 mRootTasks); 1252 1253 ArrayList<Task> nonOrganizedRootTasks = new ArrayList<>(); 1254 for (int i = 0; i < mRootTasks.size(); i++) { 1255 final Task task = mRootTasks.get(i); 1256 if (task.mCreatedByOrganizer) { 1257 // Get all tasks inside the root-task created by an organizer 1258 List<Task> nonOrganizedDescendants = new ArrayList<>(); 1259 collectDescendantsOfTypeIf(Task.class, t -> !t.mCreatedByOrganizer, task, 1260 nonOrganizedDescendants); 1261 nonOrganizedRootTasks.addAll(nonOrganizedDescendants); 1262 } else { 1263 nonOrganizedRootTasks.add(task); 1264 } 1265 } 1266 1267 mRootTasks.clear(); 1268 mRootTasks.addAll(nonOrganizedRootTasks); 1269 } 1270 containsActivity(ComponentName activityName)1271 boolean containsActivity(ComponentName activityName) { 1272 for (Task task : mRootTasks) { 1273 if (task.containsActivity(activityName)) return true; 1274 } 1275 return false; 1276 } 1277 getAllTaskDisplayAreas()1278 List<DisplayArea> getAllTaskDisplayAreas() { 1279 final List<DisplayArea> taskDisplayAreas = new ArrayList<>(); 1280 collectDescendantsOfTypeIf(DisplayArea.class, DisplayArea::isTaskDisplayArea, this, 1281 taskDisplayAreas); 1282 return taskDisplayAreas; 1283 } 1284 1285 @Nullable getTaskDisplayArea(ComponentName activityName)1286 DisplayArea getTaskDisplayArea(ComponentName activityName) { 1287 final List<DisplayArea> taskDisplayAreas = getAllTaskDisplayAreas(); 1288 List<DisplayArea> result = taskDisplayAreas.stream().filter( 1289 tda -> tda.containsActivity(activityName)) 1290 .collect(Collectors.toList()); 1291 1292 assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.") 1293 .that(result.size()).isAtMost(1); 1294 1295 return result.stream().findFirst().orElse(null); 1296 } 1297 getAllChildDisplayAreas()1298 List<DisplayArea> getAllChildDisplayAreas() { 1299 final List<DisplayArea> displayAreas = new ArrayList<>(); 1300 collectDescendantsOfType(DisplayArea.class,this, displayAreas); 1301 return displayAreas; 1302 } 1303 1304 @Nullable getDisplayArea(String windowName)1305 DisplayArea getDisplayArea(String windowName) { 1306 List<DisplayArea> displayAreas = new ArrayList<>(); 1307 final Predicate<DisplayArea> p = da -> { 1308 final boolean containsChildWindowToken = !da.mChildren.isEmpty() 1309 && da.mChildren.get(0) instanceof WindowToken; 1310 return !da.isTaskDisplayArea() && containsChildWindowToken; 1311 }; 1312 collectDescendantsOfTypeIf(DisplayArea.class, p, this, displayAreas); 1313 List<DisplayArea> result = displayAreas.stream().filter( 1314 da -> da.containsWindow(windowName)) 1315 .collect(Collectors.toList()); 1316 1317 assertWithMessage("There must be exactly one window among all DisplayAreas.") 1318 .that(result.size()).isAtMost(1); 1319 1320 return result.stream().findFirst().orElse(null); 1321 } 1322 1323 @NonNull getImeContainer()1324 DisplayArea getImeContainer() { 1325 final List<DisplayArea> imeContainers = new ArrayList<>(); 1326 final Predicate<DisplayArea> p = da -> da.getFeatureId() == FEATURE_IME; 1327 collectDescendantsOfTypeIf(DisplayArea.class, p, this, imeContainers); 1328 1329 assertWithMessage("There must be exactly one ImeContainer per DisplayContent.") 1330 .that(imeContainers.size()).isEqualTo(1); 1331 1332 return imeContainers.get(0); 1333 } 1334 getRootTasks()1335 ArrayList<Task> getRootTasks() { 1336 return mRootTasks; 1337 } 1338 getDpi()1339 int getDpi() { 1340 return mDpi; 1341 } 1342 getDisplayRect()1343 Rect getDisplayRect() { 1344 return mDisplayRect; 1345 } 1346 getAppRect()1347 public Rect getAppRect() { 1348 return mAppRect; 1349 } 1350 getFlags()1351 int getFlags() { 1352 return mFlags; 1353 } 1354 getSurfaceSize()1355 int getSurfaceSize() { 1356 return mSurfaceSize; 1357 } 1358 getFocusedApp()1359 String getFocusedApp() { 1360 return mFocusedApp; 1361 } 1362 getLastTransition()1363 String getLastTransition() { return mLastTransition; } 1364 getAppTransitionState()1365 String getAppTransitionState() { return mAppTransitionState; } 1366 getKeepClearRects()1367 List<Rect> getKeepClearRects() { return mKeepClearRects; } 1368 1369 @Override toString()1370 public String toString() { 1371 return "Display #" + mId + ": name=" + mName + " mDisplayRect=" + mDisplayRect 1372 + " mAppRect=" + mAppRect + " mFlags=" + mFlags; 1373 } 1374 1375 @Override equals(Object o)1376 public boolean equals(Object o) { 1377 if (o == this) { 1378 return true; 1379 } 1380 if (o == null) { 1381 return false; 1382 } 1383 if (!(o instanceof DisplayContent)) { 1384 return false; 1385 } 1386 1387 DisplayContent dc = (DisplayContent) o; 1388 1389 return (dc.mDisplayRect == null ? mDisplayRect == null 1390 : dc.mDisplayRect.equals(mDisplayRect)) 1391 && (dc.mAppRect == null ? mAppRect == null : dc.mAppRect.equals(mAppRect)) 1392 && dc.mDpi == mDpi 1393 && dc.mFlags == mFlags 1394 && (dc.mName == null ? mName == null : dc.mName.equals(mName)) 1395 && dc.mSurfaceSize == mSurfaceSize 1396 && (dc.mAppTransitionState == null ? mAppTransitionState == null 1397 : dc.mAppTransitionState.equals(mAppTransitionState)) 1398 && dc.mRotation == mRotation 1399 && dc.mFrozenToUserRotation == mFrozenToUserRotation 1400 && dc.mUserRotation == mUserRotation 1401 && dc.mFixedToUserRotationMode == mFixedToUserRotationMode 1402 && dc.mLastOrientation == mLastOrientation 1403 && dc.mIsFixedToUserRotation == mIsFixedToUserRotation; 1404 } 1405 1406 @Override hashCode()1407 public int hashCode() { 1408 int result = 0; 1409 if (mDisplayRect != null) { 1410 result = 31 * result + mDisplayRect.hashCode(); 1411 } 1412 if (mAppRect != null) { 1413 result = 31 * result + mAppRect.hashCode(); 1414 } 1415 result = 31 * result + mDpi; 1416 result = 31 * result + mFlags; 1417 if (mName != null) { 1418 result = 31 * result + mName.hashCode(); 1419 } 1420 result = 31 * result + mSurfaceSize; 1421 if (mAppTransitionState != null) { 1422 result = 31 * result + mAppTransitionState.hashCode(); 1423 } 1424 result = 31 * result + mRotation; 1425 result = 31 * result + Boolean.hashCode(mFrozenToUserRotation); 1426 result = 31 * result + mUserRotation; 1427 result = 31 * result + mFixedToUserRotationMode; 1428 result = 31 * result + mLastOrientation; 1429 result = 31 * result + Boolean.hashCode(mIsFixedToUserRotation); 1430 return result; 1431 } 1432 } 1433 1434 public static class Task extends ActivityContainer { 1435 // TODO(b/292187837): Use the one in ActivityTaskManager instead. 1436 public static final int INVALID_TASK_ID = -1; 1437 int mTaskId; 1438 int mRootTaskId; 1439 public int mDisplayId; 1440 Rect mLastNonFullscreenBounds; 1441 String mRealActivity; 1442 String mOrigActivity; 1443 ArrayList<Task> mTasks = new ArrayList<>(); 1444 /** Contains TaskFragment but not Task children */ 1445 ArrayList<TaskFragment> mTaskFragments = new ArrayList<>(); 1446 ArrayList<Activity> mActivities = new ArrayList<>(); 1447 int mTaskType; 1448 private int mResizeMode; 1449 String mResumedActivity; 1450 boolean mAnimatingBounds; 1451 private int mSurfaceWidth; 1452 private int mSurfaceHeight; 1453 boolean mCreatedByOrganizer; 1454 String mAffinity; 1455 boolean mHasChildPipActivity; 1456 WindowContainer mParent; 1457 Task(TaskProto proto, WindowContainer parent)1458 Task(TaskProto proto, WindowContainer parent) { 1459 super(proto.taskFragment.windowContainer); 1460 mTaskId = proto.id; 1461 mRootTaskId = proto.rootTaskId; 1462 mParent = parent; 1463 mDisplayId = proto.taskFragment.displayId; 1464 mLastNonFullscreenBounds = extract(proto.lastNonFullscreenBounds); 1465 mRealActivity = proto.realActivity; 1466 mOrigActivity = proto.origActivity; 1467 mTaskType = proto.taskFragment.activityType; 1468 mResizeMode = proto.resizeMode; 1469 mFullscreen = proto.fillsParent; 1470 mBounds = extract(proto.bounds); 1471 mMinWidth = proto.taskFragment.minWidth; 1472 mMinHeight = proto.taskFragment.minHeight; 1473 mAnimatingBounds = proto.animatingBounds; 1474 mSurfaceWidth = proto.surfaceWidth; 1475 mSurfaceHeight = proto.surfaceHeight; 1476 mCreatedByOrganizer = proto.createdByOrganizer; 1477 mAffinity = proto.affinity; 1478 mHasChildPipActivity = proto.hasChildPipActivity; 1479 1480 if (proto.resumedActivity != null) { 1481 mResumedActivity = proto.resumedActivity.title; 1482 } 1483 1484 collectChildrenOfType(Task.class, this, mTasks); 1485 collectChildrenOfType(TaskFragment.class, this, mTaskFragments); 1486 collectChildrenOfType(Activity.class, this, mActivities); 1487 } 1488 isEmpty()1489 boolean isEmpty() { 1490 return mTasks.isEmpty() && mTaskFragments.isEmpty() && mActivities.isEmpty(); 1491 } 1492 1493 /** Gets the pure parent TaskFragment if exist. */ getParentTaskFragment()1494 public TaskFragment getParentTaskFragment() { 1495 if (mParent instanceof TaskFragment) { 1496 return (TaskFragment) mParent; 1497 } 1498 if (mParent instanceof Task) { 1499 return ((Task) mParent).getParentTaskFragment(); 1500 } 1501 // If the parent is a TaskDisplayArea, it means this Task doesn't have TaskFragment 1502 // parent. 1503 return null; 1504 } 1505 getResizeMode()1506 public int getResizeMode() { 1507 return mResizeMode; 1508 } 1509 getTaskId()1510 public int getTaskId() { 1511 return mTaskId; 1512 } isRootTask()1513 boolean isRootTask() { 1514 return mTaskId == mRootTaskId; 1515 } 1516 isLeafTask()1517 boolean isLeafTask() { 1518 return mTasks.size() == 0; 1519 } 1520 getRootTaskId()1521 public int getRootTaskId() { 1522 return mRootTaskId; 1523 } 1524 getSurfaceWidth()1525 int getSurfaceWidth() { 1526 return mSurfaceWidth; 1527 } 1528 getSurfaceHeight()1529 int getSurfaceHeight() { 1530 return mSurfaceHeight; 1531 } 1532 getAffinity()1533 public String getAffinity() { return mAffinity; } 1534 getActivities()1535 public ArrayList<Activity> getActivities() { 1536 return mActivities; 1537 } 1538 1539 /** @return the top task in the root task. */ getTopTask()1540 Task getTopTask() { 1541 // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom, 1542 // so the indices are inverted 1543 return getTask((t) -> true); 1544 } 1545 getResumedActivity()1546 public String getResumedActivity() { 1547 return mResumedActivity; 1548 } 1549 getTasks()1550 public List<Task> getTasks() { 1551 return new ArrayList<>(mTasks); 1552 } 1553 1554 /** Returns non-Task leaf {@link TaskFragment} list. */ getTaskFragments()1555 public List<TaskFragment> getTaskFragments() { 1556 return new ArrayList<>(mTaskFragments); 1557 } 1558 getTask(Predicate<Task> predicate)1559 Task getTask(Predicate<Task> predicate) { 1560 for (Task task : mTasks) { 1561 if (predicate.test(task)) return task; 1562 } 1563 return predicate.test(this) ? this : null; 1564 } 1565 getTask(int taskId)1566 Task getTask(int taskId) { 1567 return getTask((t) -> t.mTaskId == taskId); 1568 } 1569 forAllTasks(Consumer<Task> consumer)1570 void forAllTasks(Consumer<Task> consumer) { 1571 for (Task task : mTasks) { 1572 consumer.accept(task); 1573 } 1574 consumer.accept(this); 1575 } 1576 getActivity(Predicate<Activity> predicate)1577 Activity getActivity(Predicate<Activity> predicate) { 1578 for (Activity activity : mActivities) { 1579 if (predicate.test(activity)) return activity; 1580 } 1581 for (TaskFragment taskFragment : mTaskFragments) { 1582 final Activity activity = taskFragment.getActivity(predicate); 1583 if (activity != null) return activity; 1584 } 1585 for (Task task : mTasks) { 1586 final Activity activity = task.getActivity(predicate); 1587 if (activity != null) return activity; 1588 } 1589 return null; 1590 } 1591 getActivity(ComponentName activityName)1592 public Activity getActivity(ComponentName activityName) { 1593 final String fullName = getActivityName(activityName); 1594 return getActivity((activity) -> activity.name.equals(fullName)); 1595 } 1596 getActivity(ComponentName activityName, int[] excludeTaskIds)1597 public Activity getActivity(ComponentName activityName, int[] excludeTaskIds) { 1598 final String fullName = getActivityName(activityName); 1599 return getActivity((activity) -> { 1600 if (!activity.name.equals(fullName)) { 1601 return false; 1602 } 1603 for (int excludeTaskId : excludeTaskIds) { 1604 if (activity.getTask().mTaskId == excludeTaskId) { 1605 return false; 1606 } 1607 } 1608 return true; 1609 }); 1610 } 1611 containsActivity(ComponentName activityName)1612 boolean containsActivity(ComponentName activityName) { 1613 return getActivity(activityName) != null; 1614 } 1615 getActivityCount()1616 public int getActivityCount() { 1617 int count = mActivities.size(); 1618 for (TaskFragment taskFragment : mTaskFragments) { 1619 count += taskFragment.getActivityCount(); 1620 } 1621 for (Task task : mTasks) { 1622 count += task.getActivityCount(); 1623 } 1624 return count; 1625 } 1626 1627 @Override getActivityType()1628 int getActivityType() { 1629 return mTaskType; 1630 } 1631 1632 @Override toString()1633 public String toString() { 1634 return "Task[id=" + mTaskId + ", display=" + mDisplayId 1635 + ", mOrigActivity=" + mOrigActivity + ", realActivity=" + mRealActivity 1636 + ", activities=" + mActivities + "]"; 1637 } 1638 } 1639 1640 public static class TaskFragment extends ActivityContainer { 1641 public int mDisplayId; 1642 Task mParentTask; 1643 ArrayList<Activity> mActivities = new ArrayList<>(); 1644 int mTaskFragmentType; 1645 1646 TaskFragment(TaskFragmentProto proto, WindowContainer parent) { 1647 super(proto.windowContainer); 1648 mParentTask = (Task) parent; 1649 mDisplayId = proto.displayId; 1650 mTaskFragmentType = proto.activityType; 1651 mMinWidth = proto.minWidth; 1652 mMinHeight = proto.minHeight; 1653 1654 collectChildrenOfType(Activity.class, this, mActivities); 1655 } 1656 1657 public List<Activity> getActivities() { 1658 return mActivities; 1659 } 1660 1661 Activity getActivity(Predicate<Activity> predicate) { 1662 for (Activity activity : mActivities) { 1663 if (predicate.test(activity)) { 1664 return activity; 1665 } 1666 } 1667 return null; 1668 } 1669 1670 public int getActivityCount() { 1671 return mActivities.size(); 1672 } 1673 1674 @Override 1675 int getActivityType() { 1676 return mTaskFragmentType; 1677 } 1678 } 1679 1680 public static class Activity extends ActivityContainer { 1681 1682 String name; 1683 String state; 1684 boolean visible; 1685 boolean frontOfTask; 1686 boolean inSizeCompatMode; 1687 float minAspectRatio; 1688 boolean providesMaxBounds; 1689 int procId = -1; 1690 boolean isAnimating; 1691 public boolean translucent; 1692 private WindowContainer mParent; 1693 private boolean mEnableRecentsScreenshot; 1694 private int mLastDropInputMode; 1695 private boolean mShouldSendCompatFakeFocus; 1696 private int mOverrideOrientation; 1697 private boolean mShouldForceRotateForCameraCompat; 1698 private boolean mShouldRefreshActivityForCameraCompat; 1699 private boolean mShouldRefreshActivityViaPauseForCameraCompat; 1700 1701 Activity(ActivityRecordProto proto, WindowContainer parent) { 1702 super(proto.windowToken.windowContainer); 1703 name = proto.name; 1704 state = proto.state; 1705 visible = proto.visible; 1706 frontOfTask = proto.frontOfTask; 1707 inSizeCompatMode = proto.inSizeCompatMode; 1708 minAspectRatio = proto.minAspectRatio; 1709 providesMaxBounds = proto.providesMaxBounds; 1710 if (proto.procId != 0) { 1711 procId = proto.procId; 1712 } 1713 isAnimating = proto.isAnimating; 1714 translucent = proto.translucent; 1715 mEnableRecentsScreenshot = proto.enableRecentsScreenshot; 1716 mLastDropInputMode = proto.lastDropInputMode; 1717 mShouldSendCompatFakeFocus = proto.shouldSendCompatFakeFocus; 1718 mOverrideOrientation = proto.overrideOrientation; 1719 mParent = parent; 1720 mShouldForceRotateForCameraCompat = proto.shouldForceRotateForCameraCompat; 1721 mShouldRefreshActivityForCameraCompat = proto.shouldRefreshActivityForCameraCompat; 1722 mShouldRefreshActivityViaPauseForCameraCompat = 1723 proto.shouldRefreshActivityViaPauseForCameraCompat; 1724 } 1725 1726 @NonNull 1727 public Task getTask() { 1728 if (mParent instanceof Task) { 1729 return (Task) mParent; 1730 } 1731 return ((TaskFragment) mParent).mParentTask; 1732 } 1733 1734 @Nullable 1735 public TaskFragment getTaskFragment() { 1736 if (mParent instanceof TaskFragment) { 1737 return (TaskFragment) mParent; 1738 } 1739 return ((Task) mParent).getParentTaskFragment(); 1740 } 1741 1742 public String getName() { 1743 return name; 1744 } 1745 1746 public String getState() { 1747 return state; 1748 } 1749 1750 public boolean inSizeCompatMode() { 1751 return inSizeCompatMode; 1752 } 1753 1754 public boolean isAnimating() { 1755 return isAnimating; 1756 } 1757 1758 public float getMinAspectRatio() { 1759 return minAspectRatio; 1760 } 1761 1762 public boolean providesMaxBounds() { 1763 return providesMaxBounds; 1764 } 1765 1766 public boolean enableRecentsScreenshot() { 1767 return mEnableRecentsScreenshot; 1768 } 1769 1770 public int getLastDropInputMode() { 1771 return mLastDropInputMode; 1772 } 1773 1774 public boolean getShouldSendCompatFakeFocus() { 1775 return mShouldSendCompatFakeFocus; 1776 } 1777 1778 public int getUiMode() { 1779 return mFullConfiguration.uiMode; 1780 } 1781 1782 public int getOverrideOrientation() { 1783 return mOverrideOrientation; 1784 } 1785 1786 public boolean getShouldForceRotateForCameraCompat() { 1787 return mShouldForceRotateForCameraCompat; 1788 } 1789 1790 public boolean getShouldRefreshActivityForCameraCompat() { 1791 return mShouldRefreshActivityForCameraCompat; 1792 } 1793 1794 public boolean getShouldRefreshActivityViaPauseForCameraCompat() { 1795 return mShouldRefreshActivityViaPauseForCameraCompat; 1796 } 1797 1798 @Override 1799 public Rect getBounds() { 1800 if (mBounds == null) { 1801 return mFullConfiguration.windowConfiguration.getBounds(); 1802 } 1803 return mBounds; 1804 } 1805 1806 public Rect getMaxBounds() { 1807 return mFullConfiguration.windowConfiguration.getMaxBounds(); 1808 } 1809 1810 public Rect getAppBounds() { 1811 return mFullConfiguration.windowConfiguration.getAppBounds(); 1812 } 1813 1814 @Override 1815 public String toString() { 1816 return "Activity[name=" + name + ", state=" + state + ", visible=" + visible + "]"; 1817 } 1818 } 1819 1820 static abstract class ActivityContainer extends WindowContainer { 1821 protected boolean mFullscreen; 1822 protected Rect mBounds; 1823 protected int mMinWidth = -1; 1824 protected int mMinHeight = -1; 1825 1826 ActivityContainer(WindowContainerProto proto) { 1827 super(proto); 1828 } 1829 1830 public Rect getBounds() { 1831 return mBounds; 1832 } 1833 1834 boolean isFullscreen() { 1835 return mFullscreen; 1836 } 1837 1838 int getMinWidth() { 1839 return mMinWidth; 1840 } 1841 1842 int getMinHeight() { 1843 return mMinHeight; 1844 } 1845 } 1846 1847 static class KeyguardControllerState { 1848 1849 boolean aodShowing = false; 1850 boolean keyguardShowing = false; 1851 boolean mKeyguardGoingAway = false; 1852 SparseArray<Boolean> mKeyguardOccludedStates = new SparseArray<>(); 1853 1854 KeyguardControllerState(KeyguardControllerProto proto) { 1855 if (proto != null) { 1856 aodShowing = proto.aodShowing; 1857 keyguardShowing = proto.keyguardShowing; 1858 mKeyguardGoingAway = proto.keyguardGoingAway; 1859 for (int i = 0; i < proto.keyguardPerDisplay.length; i++) { 1860 mKeyguardOccludedStates.append(proto.keyguardPerDisplay[i].displayId, 1861 proto.keyguardPerDisplay[i].keyguardOccluded); 1862 } 1863 } 1864 } 1865 1866 boolean isKeyguardOccluded(int displayId) { 1867 if (mKeyguardOccludedStates.get(displayId) != null) { 1868 return mKeyguardOccludedStates.get(displayId); 1869 } 1870 return false; 1871 } 1872 } 1873 1874 static class KeyguardServiceDelegateState { 1875 1876 // copy from KeyguardServiceDelegate.java 1877 private static final int INTERACTIVE_STATE_SLEEP = 0; 1878 private static final int INTERACTIVE_STATE_WAKING = 1; 1879 private static final int INTERACTIVE_STATE_AWAKE = 2; 1880 private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 3; 1881 1882 private int mInteractiveState = -1; 1883 1884 KeyguardServiceDelegateState(KeyguardServiceDelegateProto proto) { 1885 if (proto != null) { 1886 mInteractiveState = proto.interactiveState; 1887 } 1888 } 1889 1890 boolean isKeyguardAwake() { 1891 return mInteractiveState == INTERACTIVE_STATE_AWAKE; 1892 } 1893 } 1894 1895 static class ConfigurationContainer { 1896 final Configuration mOverrideConfiguration = new Configuration(); 1897 final Configuration mFullConfiguration = new Configuration(); 1898 final Configuration mMergedOverrideConfiguration = new Configuration(); 1899 1900 ConfigurationContainer(ConfigurationContainerProto proto) { 1901 if (proto == null) { 1902 return; 1903 } 1904 mOverrideConfiguration.setTo(extract(proto.overrideConfiguration)); 1905 mFullConfiguration.setTo(extract(proto.fullConfiguration)); 1906 mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration)); 1907 } 1908 1909 boolean isWindowingModeCompatible(int requestedWindowingMode) { 1910 if (requestedWindowingMode == WINDOWING_MODE_UNDEFINED) { 1911 return true; 1912 } 1913 return getWindowingMode() == requestedWindowingMode; 1914 } 1915 1916 public int getWindowingMode() { 1917 if (mFullConfiguration == null) { 1918 return WINDOWING_MODE_UNDEFINED; 1919 } 1920 return mFullConfiguration.windowConfiguration.getWindowingMode(); 1921 } 1922 1923 int getActivityType() { 1924 if (mFullConfiguration == null) { 1925 return ACTIVITY_TYPE_UNDEFINED; 1926 } 1927 return mFullConfiguration.windowConfiguration.getActivityType(); 1928 } 1929 } 1930 1931 public static class RootWindowContainer extends WindowContainer { 1932 RootWindowContainer(RootWindowContainerProto proto) { 1933 super(proto.windowContainer); 1934 } 1935 } 1936 public static class DisplayArea extends WindowContainer { 1937 private final boolean mIsTaskDisplayArea; 1938 private final boolean mIsRootDisplayArea; 1939 private final int mFeatureId; 1940 private final boolean mIsOrganized; 1941 private final boolean mIsIgnoringOrientationRequest; 1942 private ArrayList<Activity> mActivities; 1943 private final ArrayList<WindowState> mWindows = new ArrayList<>(); 1944 1945 DisplayArea(DisplayAreaProto proto) { 1946 super(proto.windowContainer); 1947 mIsTaskDisplayArea = proto.isTaskDisplayArea; 1948 mIsRootDisplayArea = proto.isRootDisplayArea; 1949 mFeatureId = proto.featureId; 1950 mIsOrganized = proto.isOrganized; 1951 mIsIgnoringOrientationRequest = proto.isIgnoringOrientationRequest; 1952 if (mIsTaskDisplayArea) { 1953 mActivities = new ArrayList<>(); 1954 collectDescendantsOfType(Activity.class, this, mActivities); 1955 } 1956 collectDescendantsOfType(WindowState.class, this, mWindows); 1957 } 1958 1959 boolean isTaskDisplayArea() { 1960 return mIsTaskDisplayArea; 1961 } 1962 1963 boolean isRootDisplayArea() { 1964 return mIsRootDisplayArea; 1965 } 1966 1967 int getFeatureId() { 1968 return mFeatureId; 1969 } 1970 1971 public boolean isOrganized() { 1972 return mIsOrganized; 1973 } 1974 1975 public Rect getAppBounds() { 1976 return mFullConfiguration.windowConfiguration.getAppBounds(); 1977 } 1978 1979 public boolean isIgnoringOrientationRequest() { 1980 return mIsIgnoringOrientationRequest; 1981 } 1982 1983 @Override 1984 public Rect getBounds() { 1985 if (mBounds == null) { 1986 return mFullConfiguration.windowConfiguration.getBounds(); 1987 } 1988 return mBounds; 1989 } 1990 1991 boolean containsActivity(ComponentName activityName) { 1992 if (!mIsTaskDisplayArea) { 1993 return false; 1994 } 1995 1996 final String fullName = getActivityName(activityName); 1997 for (Activity a : mActivities) { 1998 if (a.name.equals(fullName)) { 1999 return true; 2000 } 2001 } 2002 return false; 2003 } 2004 2005 boolean containsWindow(String windowName) { 2006 for (WindowState w : mWindows) { 2007 if (w.mName.equals(windowName)) { 2008 return true; 2009 } 2010 } 2011 return false; 2012 } 2013 } 2014 public static class WindowToken extends WindowContainer { 2015 WindowToken(WindowTokenProto proto) { 2016 super(proto.windowContainer); 2017 } 2018 } 2019 2020 /** 2021 * Represents WindowContainer classes such as DisplayContent.WindowContainers and 2022 * DisplayContent.NonAppWindowContainers. This can be expanded into a specific class 2023 * if we need track and assert some state in the future. 2024 */ 2025 public static class GenericWindowContainer extends WindowContainer { 2026 GenericWindowContainer(WindowContainerProto proto) { 2027 super(proto); 2028 } 2029 } 2030 2031 static WindowContainer getWindowContainer(WindowContainerChildProto proto, 2032 WindowContainer parent) { 2033 if (proto.displayContent != null) { 2034 return new DisplayContent(proto.displayContent); 2035 } 2036 2037 if (proto.displayArea != null) { 2038 return new DisplayArea(proto.displayArea); 2039 } 2040 2041 if (proto.task != null) { 2042 return new Task(proto.task, parent); 2043 } 2044 2045 if (proto.taskFragment != null) { 2046 return new TaskFragment(proto.taskFragment, parent); 2047 } 2048 2049 if (proto.activity != null) { 2050 return new Activity(proto.activity, parent); 2051 } 2052 2053 if (proto.windowToken != null) { 2054 return new WindowToken(proto.windowToken); 2055 } 2056 2057 if (proto.window != null) { 2058 return new WindowState(proto.window); 2059 } 2060 2061 if (proto.windowContainer != null) { 2062 return new GenericWindowContainer(proto.windowContainer); 2063 } 2064 return null; 2065 } 2066 2067 static abstract class WindowContainer extends ConfigurationContainer { 2068 2069 protected String mName; 2070 protected final String mAppToken; 2071 protected boolean mFullscreen; 2072 protected Rect mBounds; 2073 protected int mOrientation; 2074 protected boolean mVisible; 2075 protected List<WindowState> mSubWindows = new ArrayList<>(); 2076 protected List<WindowContainer> mChildren = new ArrayList<>(); 2077 2078 WindowContainer(WindowContainerProto proto) { 2079 super(proto.configurationContainer); 2080 IdentifierProto identifierProto = proto.identifier; 2081 mName = identifierProto.title; 2082 mAppToken = Integer.toHexString(identifierProto.hashCode); 2083 mOrientation = proto.orientation; 2084 for (int i = 0; i < proto.children.length; i++) { 2085 final WindowContainer child = getWindowContainer(proto.children[i], this); 2086 if (child != null) { 2087 mChildren.add(child); 2088 } 2089 } 2090 mVisible = proto.visible; 2091 } 2092 2093 @NonNull 2094 public String getName() { 2095 return mName; 2096 } 2097 2098 @NonNull 2099 public String getPackageName() { 2100 int sep = mName.indexOf('/'); 2101 return sep == -1 ? mName : mName.substring(0, sep); 2102 } 2103 2104 String getToken() { 2105 return mAppToken; 2106 } 2107 2108 Rect getBounds() { 2109 return mBounds; 2110 } 2111 2112 boolean isFullscreen() { 2113 return mFullscreen; 2114 } 2115 2116 boolean isVisible() { 2117 return mVisible; 2118 } 2119 2120 List<WindowState> getWindows() { 2121 return mSubWindows; 2122 } 2123 } 2124 2125 public static class WindowState extends WindowContainer { 2126 2127 private static final int WINDOW_TYPE_NORMAL = 0; 2128 public static final int WINDOW_TYPE_STARTING = 1; 2129 private static final int WINDOW_TYPE_EXITING = 2; 2130 private static final int WINDOW_TYPE_DEBUGGER = 3; 2131 2132 private final int mWindowType; 2133 private int mType = 0; 2134 private int mDisplayId; 2135 private int mStackId; 2136 private int mLayer; 2137 private boolean mShown; 2138 private Rect mParentFrame; 2139 private Rect mFrame; 2140 private Rect mCompatFrame; 2141 private Rect mSurfaceInsets; 2142 private Rect mGivenContentInsets; 2143 private Rect mCrop = new Rect(); 2144 private boolean mHasCompatScale; 2145 private float mGlobalScale; 2146 private int mRequestedWidth; 2147 private int mRequestedHeight; 2148 private List<Rect> mKeepClearRects; 2149 private List<Rect> mUnrestrictedKeepClearRects; 2150 private List<InsetsSource> mMergedLocalInsetsSources; 2151 2152 WindowState(WindowStateProto proto) { 2153 super(proto.windowContainer); 2154 mDisplayId = proto.displayId; 2155 mStackId = proto.stackId; 2156 if (proto.attributes != null) { 2157 mType = proto.attributes.type; 2158 } 2159 WindowStateAnimatorProto animatorProto = proto.animator; 2160 if (animatorProto != null) { 2161 if (animatorProto.surface != null) { 2162 WindowSurfaceControllerProto surfaceProto = animatorProto.surface; 2163 mShown = surfaceProto.shown; 2164 mLayer = surfaceProto.layer; 2165 } 2166 mCrop = extract(animatorProto.lastClipRect); 2167 } 2168 mGivenContentInsets = extract(proto.givenContentInsets); 2169 WindowFramesProto windowFramesProto = proto.windowFrames; 2170 if (windowFramesProto != null) { 2171 mFrame = extract(windowFramesProto.frame); 2172 mParentFrame = extract(windowFramesProto.parentFrame); 2173 mCompatFrame = extract(windowFramesProto.compatFrame); 2174 } 2175 mSurfaceInsets = extract(proto.surfaceInsets); 2176 if (mName.startsWith(STARTING_WINDOW_PREFIX)) { 2177 mWindowType = WINDOW_TYPE_STARTING; 2178 // Existing code depends on the prefix being removed 2179 mName = mName.substring(STARTING_WINDOW_PREFIX.length()); 2180 } else if (proto.animatingExit) { 2181 mWindowType = WINDOW_TYPE_EXITING; 2182 } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) { 2183 mWindowType = WINDOW_TYPE_DEBUGGER; 2184 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length()); 2185 } else { 2186 mWindowType = 0; 2187 } 2188 collectDescendantsOfType(WindowState.class, this, mSubWindows); 2189 mHasCompatScale = proto.hasCompatScale; 2190 mGlobalScale = proto.globalScale; 2191 mRequestedWidth = proto.requestedWidth; 2192 mRequestedHeight = proto.requestedHeight; 2193 mKeepClearRects = new ArrayList(); 2194 for (RectProto r : proto.keepClearAreas) { 2195 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom)); 2196 } 2197 mUnrestrictedKeepClearRects = new ArrayList(); 2198 for (RectProto r : proto.unrestrictedKeepClearAreas) { 2199 mUnrestrictedKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom)); 2200 } 2201 mMergedLocalInsetsSources = new ArrayList(); 2202 for (InsetsSourceProto insets : proto.mergedLocalInsetsSources) { 2203 mMergedLocalInsetsSources.add(new InsetsSource(insets)); 2204 } 2205 } 2206 2207 boolean isStartingWindow() { 2208 return mWindowType == WINDOW_TYPE_STARTING; 2209 } 2210 2211 boolean isExitingWindow() { 2212 return mWindowType == WINDOW_TYPE_EXITING; 2213 } 2214 2215 boolean isDebuggerWindow() { 2216 return mWindowType == WINDOW_TYPE_DEBUGGER; 2217 } 2218 2219 int getDisplayId() { 2220 return mDisplayId; 2221 } 2222 2223 int getStackId() { 2224 return mStackId; 2225 } 2226 2227 public Rect getFrame() { 2228 return mFrame; 2229 } 2230 2231 Rect getSurfaceInsets() { 2232 return mSurfaceInsets; 2233 } 2234 2235 Rect getGivenContentInsets() { 2236 return mGivenContentInsets; 2237 } 2238 2239 Rect getParentFrame() { 2240 return mParentFrame; 2241 } 2242 2243 public Rect getCompatFrame() { 2244 return mCompatFrame; 2245 } 2246 2247 Rect getCrop() { 2248 return mCrop; 2249 } 2250 2251 public boolean isSurfaceShown() { 2252 return mShown; 2253 } 2254 2255 public int getType() { 2256 return mType; 2257 } 2258 2259 public boolean hasCompatScale() { 2260 return mHasCompatScale; 2261 } 2262 2263 public float getGlobalScale() { 2264 return mGlobalScale; 2265 } 2266 2267 public int getRequestedWidth() { 2268 return mRequestedWidth; 2269 } 2270 2271 public int getRequestedHeight() { 2272 return mRequestedHeight; 2273 } 2274 2275 public List<Rect> getKeepClearRects() { 2276 return mKeepClearRects; 2277 } 2278 2279 public List<Rect> getUnrestrictedKeepClearRects() { 2280 return mUnrestrictedKeepClearRects; 2281 } 2282 2283 List<InsetsSource> getMergedLocalInsetsSources() { 2284 return mMergedLocalInsetsSources; 2285 } 2286 2287 private String getWindowTypeSuffix(int windowType) { 2288 switch (windowType) { 2289 case WINDOW_TYPE_STARTING: 2290 return " STARTING"; 2291 case WINDOW_TYPE_EXITING: 2292 return " EXITING"; 2293 case WINDOW_TYPE_DEBUGGER: 2294 return " DEBUGGER"; 2295 default: 2296 break; 2297 } 2298 return ""; 2299 } 2300 2301 @Override 2302 public String toString() { 2303 return "WindowState: {" + mAppToken + " " + mName 2304 + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType 2305 + " pf=" + mParentFrame; 2306 } 2307 2308 public String toLongString() { 2309 return toString() + " f=" + mFrame + " crop=" + mCrop + " isSurfaceShown=" 2310 + isSurfaceShown(); 2311 } 2312 } 2313 2314 static class BackNavigationState { 2315 private boolean mAnimationInProgress; 2316 private int mLastBackType; 2317 private boolean mShowWallpaper; 2318 2319 BackNavigationState(BackNavigationProto proto) { 2320 if (proto != null) { 2321 mAnimationInProgress = proto.animationInProgress; 2322 mLastBackType = proto.lastBackType; 2323 mShowWallpaper = proto.showWallpaper; 2324 } 2325 } 2326 2327 boolean isAnimationInProgress() { 2328 return mAnimationInProgress; 2329 } 2330 2331 int getLastBackType() { 2332 return mLastBackType; 2333 } 2334 2335 boolean isShowWallpaper() { 2336 return mShowWallpaper; 2337 } 2338 } 2339 2340 static int dpToPx(float dp, int densityDpi) { 2341 return (int) (dp * densityDpi / DENSITY_DEFAULT + 0.5f); 2342 } 2343 2344 int defaultMinimalTaskSize(int displayId) { 2345 final DisplayContent dc = getDisplay(displayId); 2346 return dpToPx(dc.mMinSizeOfResizeableTaskDp, dc.getDpi()); 2347 } 2348 2349 int defaultMinimalDisplaySizeForSplitScreen(int displayId) { 2350 return dpToPx(ActivityTaskManager.DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP, 2351 getDisplay(displayId).getDpi()); 2352 } 2353 2354 static class InsetsSource { 2355 private String mType; 2356 private Rect mFrame; 2357 private Rect mVisibleFrame; 2358 private boolean mVisible; 2359 2360 InsetsSource(InsetsSourceProto proto) { 2361 mType = proto.type; 2362 mFrame = new Rect( 2363 proto.frame.left, proto.frame.top, proto.frame.right, proto.frame.bottom); 2364 if (proto.visibleFrame != null) { 2365 mVisibleFrame = new Rect(proto.visibleFrame.left, proto.visibleFrame.top, 2366 proto.visibleFrame.right, proto.visibleFrame.bottom); 2367 } 2368 mVisible = proto.visible; 2369 } 2370 2371 String getType() { 2372 return mType; 2373 } 2374 2375 Rect getFrame() { 2376 return mFrame; 2377 } 2378 2379 Rect getVisibleFrame() { 2380 return mVisibleFrame; 2381 } 2382 2383 boolean isVisible() { 2384 return mVisible; 2385 } 2386 2387 boolean isCaptionBar() { 2388 return mType.contains("captionBar"); 2389 } 2390 2391 void insetGivenFrame(Rect inOutFrame) { 2392 if (inOutFrame.left == mFrame.left && inOutFrame.right == mFrame.right) { 2393 if (inOutFrame.top == mFrame.top) { 2394 inOutFrame.top = mFrame.bottom; 2395 return; 2396 } 2397 if (inOutFrame.bottom == mFrame.bottom) { 2398 inOutFrame.bottom = mFrame.top; 2399 return; 2400 } 2401 } 2402 if (inOutFrame.top == mFrame.top && inOutFrame.bottom == mFrame.bottom) { 2403 if (inOutFrame.left == mFrame.left) { 2404 inOutFrame.left = mFrame.right; 2405 return; 2406 } 2407 if (inOutFrame.right == mFrame.right) { 2408 inOutFrame.right = mFrame.left; 2409 return; 2410 } 2411 } 2412 } 2413 2414 @Override 2415 public String toString() { 2416 return "InsetsSource: {type=" + mType 2417 + " frame=" + mFrame 2418 + " visibleFrame=" + mVisibleFrame 2419 + " visible=" + mVisible 2420 + "}"; 2421 } 2422 } 2423 } 2424