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