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