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