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_STANDARD; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 22 import static android.server.wm.ProtoExtractors.extract; 23 import static android.server.wm.StateLogger.log; 24 import static android.server.wm.StateLogger.logE; 25 import static android.view.Display.DEFAULT_DISPLAY; 26 27 import static androidx.test.InstrumentationRegistry.getInstrumentation; 28 29 import static org.junit.Assert.assertTrue; 30 import static org.junit.Assert.fail; 31 32 import android.content.res.Configuration; 33 import android.graphics.Rect; 34 import android.os.ParcelFileDescriptor; 35 import android.os.SystemClock; 36 import android.view.WindowManager; 37 import android.view.nano.DisplayInfoProto; 38 import android.view.nano.ViewProtoEnums; 39 40 import androidx.annotation.NonNull; 41 import androidx.annotation.Nullable; 42 43 import com.android.server.wm.nano.AppTransitionProto; 44 import com.android.server.wm.nano.AppWindowTokenProto; 45 import com.android.server.wm.nano.ConfigurationContainerProto; 46 import com.android.server.wm.nano.DisplayContentProto; 47 import com.android.server.wm.nano.DisplayFramesProto; 48 import com.android.server.wm.nano.IdentifierProto; 49 import com.android.server.wm.nano.PinnedStackControllerProto; 50 import com.android.server.wm.nano.StackProto; 51 import com.android.server.wm.nano.TaskProto; 52 import com.android.server.wm.nano.WindowContainerProto; 53 import com.android.server.wm.nano.WindowFramesProto; 54 import com.android.server.wm.nano.WindowManagerServiceDumpProto; 55 import com.android.server.wm.nano.WindowStateAnimatorProto; 56 import com.android.server.wm.nano.WindowStateProto; 57 import com.android.server.wm.nano.WindowSurfaceControllerProto; 58 import com.android.server.wm.nano.WindowTokenProto; 59 60 import com.google.protobuf.nano.InvalidProtocolBufferNanoException; 61 62 import java.io.ByteArrayOutputStream; 63 import java.io.FileInputStream; 64 import java.io.IOException; 65 import java.nio.charset.StandardCharsets; 66 import java.util.ArrayList; 67 import java.util.Arrays; 68 import java.util.HashMap; 69 import java.util.LinkedList; 70 import java.util.List; 71 import java.util.Map; 72 import java.util.function.Predicate; 73 import java.util.stream.Collectors; 74 import java.util.stream.Stream; 75 76 public class WindowManagerState { 77 public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN"; 78 public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE"; 79 public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN"; 80 public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE"; 81 82 public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN"; 83 public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE"; 84 public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN"; 85 public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE"; 86 87 public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY"; 88 public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 89 "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER"; 90 public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE"; 91 public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE"; 92 public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 93 "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN"; 94 public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 95 "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE"; 96 97 public static final String APP_STATE_IDLE = "APP_STATE_IDLE"; 98 99 private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto"; 100 101 private static final String STARTING_WINDOW_PREFIX = "Starting "; 102 private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: "; 103 104 /** @see WindowManager.LayoutParams */ 105 private static final int TYPE_NAVIGATION_BAR = 2019; 106 107 /** @see WindowManager.LayoutParams */ 108 private static final int TYPE_NAVIGATION_BAR_PANEL = 2024; 109 110 // Windows in z-order with the top most at the front of the list. 111 private List<WindowState> mWindowStates = new ArrayList(); 112 // Stacks in z-order with the top most at the front of the list, starting with primary display. 113 private final List<WindowStack> mStacks = new ArrayList(); 114 // Stacks on all attached displays, in z-order with the top most at the front of the list. 115 private final Map<Integer, List<WindowStack>> mDisplayStacks 116 = new HashMap<>(); 117 private List<Display> mDisplays = new ArrayList(); 118 private String mFocusedWindow = null; 119 private String mFocusedApp = null; 120 private String mInputMethodWindowAppToken = null; 121 private Rect mDefaultPinnedStackBounds = new Rect(); 122 private Rect mPinnedStackMovementBounds = new Rect(); 123 private final LinkedList<String> mSysDump = new LinkedList(); 124 private int mRotation; 125 private int mLastOrientation; 126 private boolean mDisplayFrozen; 127 private boolean mIsDockedStackMinimized; 128 computeState()129 public void computeState() { 130 // It is possible the system is in the middle of transition to the right state when we get 131 // the dump. We try a few times to get the information we need before giving up. 132 int retriesLeft = 3; 133 boolean retry = false; 134 byte[] dump = null; 135 136 log("=============================="); 137 log(" WindowManagerState "); 138 log("=============================="); 139 do { 140 if (retry) { 141 log("***Incomplete WM state. Retrying..."); 142 // Wait half a second between retries for window manager to finish transitioning... 143 SystemClock.sleep(500); 144 } 145 146 dump = executeShellCommand(DUMPSYS_WINDOW); 147 try { 148 parseSysDumpProto(dump); 149 } catch (InvalidProtocolBufferNanoException ex) { 150 throw new RuntimeException("Failed to parse dumpsys:\n" 151 + new String(dump, StandardCharsets.UTF_8), ex); 152 } 153 154 retry = mWindowStates.isEmpty() || mFocusedApp == null; 155 } while (retry && retriesLeft-- > 0); 156 157 if (mWindowStates.isEmpty()) { 158 logE("No Windows found..."); 159 } 160 if (mFocusedWindow == null) { 161 logE("No Focused Window..."); 162 } 163 if (mFocusedApp == null) { 164 logE("No Focused App..."); 165 } 166 } 167 executeShellCommand(String cmd)168 private byte[] executeShellCommand(String cmd) { 169 try { 170 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation() 171 .executeShellCommand(cmd); 172 byte[] buf = new byte[512]; 173 int bytesRead; 174 FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 175 ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 176 while ((bytesRead = fis.read(buf)) != -1) { 177 stdout.write(buf, 0, bytesRead); 178 } 179 fis.close(); 180 return stdout.toByteArray(); 181 } catch (IOException e) { 182 throw new RuntimeException(e); 183 } 184 } 185 186 parseSysDumpProto(byte[] sysDump)187 private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException { 188 reset(); 189 WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump); 190 List<WindowState> allWindows = new ArrayList<>(); 191 Map<String, WindowState> windowMap = new HashMap<>(); 192 if (state.focusedWindow != null) { 193 mFocusedWindow = state.focusedWindow.title; 194 } 195 mFocusedApp = state.focusedApp; 196 for (int i = 0; i < state.rootWindowContainer.displays.length; i++) { 197 DisplayContentProto displayProto = state.rootWindowContainer.displays[i]; 198 final Display display = new Display(displayProto); 199 mDisplays.add(display); 200 allWindows.addAll(display.getWindows()); 201 List<WindowStack> stacks = new ArrayList<>(); 202 for (int j = 0; j < displayProto.stacks.length; j++) { 203 StackProto stackProto = displayProto.stacks[j]; 204 final WindowStack stack = new WindowStack(stackProto); 205 mStacks.add(stack); 206 stacks.add(stack); 207 allWindows.addAll(stack.getWindows()); 208 } 209 mDisplayStacks.put(display.mDisplayId, stacks); 210 211 // use properties from the default display only 212 if (display.getDisplayId() == DEFAULT_DISPLAY) { 213 if (displayProto.dockedStackDividerController != null) { 214 mIsDockedStackMinimized = 215 displayProto.dockedStackDividerController.minimizedDock; 216 } 217 PinnedStackControllerProto pinnedStackProto = displayProto.pinnedStackController; 218 if (pinnedStackProto != null) { 219 mDefaultPinnedStackBounds = extract(pinnedStackProto.defaultBounds); 220 mPinnedStackMovementBounds = extract(pinnedStackProto.movementBounds); 221 } 222 } 223 } 224 for (WindowState w : allWindows) { 225 windowMap.put(w.getToken(), w); 226 } 227 for (int i = 0; i < state.rootWindowContainer.windows.length; i++) { 228 IdentifierProto identifierProto = state.rootWindowContainer.windows[i]; 229 String hash_code = Integer.toHexString(identifierProto.hashCode); 230 mWindowStates.add(windowMap.get(hash_code)); 231 } 232 if (state.inputMethodWindow != null) { 233 mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode); 234 } 235 mDisplayFrozen = state.displayFrozen; 236 mRotation = state.rotation; 237 mLastOrientation = state.lastOrientation; 238 } 239 appStateToString(int appState)240 static String appStateToString(int appState) { 241 switch (appState) { 242 case AppTransitionProto.APP_STATE_IDLE: 243 return "APP_STATE_IDLE"; 244 case AppTransitionProto.APP_STATE_READY: 245 return "APP_STATE_READY"; 246 case AppTransitionProto.APP_STATE_RUNNING: 247 return "APP_STATE_RUNNING"; 248 case AppTransitionProto.APP_STATE_TIMEOUT: 249 return "APP_STATE_TIMEOUT"; 250 default: 251 fail("Invalid AppTransitionState"); 252 return null; 253 } 254 } 255 appTransitionToString(int transition)256 static String appTransitionToString(int transition) { 257 switch (transition) { 258 case ViewProtoEnums.TRANSIT_UNSET: { 259 return "TRANSIT_UNSET"; 260 } 261 case ViewProtoEnums.TRANSIT_NONE: { 262 return "TRANSIT_NONE"; 263 } 264 case ViewProtoEnums.TRANSIT_ACTIVITY_OPEN: { 265 return TRANSIT_ACTIVITY_OPEN; 266 } 267 case ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE: { 268 return TRANSIT_ACTIVITY_CLOSE; 269 } 270 case ViewProtoEnums.TRANSIT_TASK_OPEN: { 271 return TRANSIT_TASK_OPEN; 272 } 273 case ViewProtoEnums.TRANSIT_TASK_CLOSE: { 274 return TRANSIT_TASK_CLOSE; 275 } 276 case ViewProtoEnums.TRANSIT_TASK_TO_FRONT: { 277 return "TRANSIT_TASK_TO_FRONT"; 278 } 279 case ViewProtoEnums.TRANSIT_TASK_TO_BACK: { 280 return "TRANSIT_TASK_TO_BACK"; 281 } 282 case ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE: { 283 return TRANSIT_WALLPAPER_CLOSE; 284 } 285 case ViewProtoEnums.TRANSIT_WALLPAPER_OPEN: { 286 return TRANSIT_WALLPAPER_OPEN; 287 } 288 case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN: { 289 return TRANSIT_WALLPAPER_INTRA_OPEN; 290 } 291 case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE: { 292 return TRANSIT_WALLPAPER_INTRA_CLOSE; 293 } 294 case ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND: { 295 return "TRANSIT_TASK_OPEN_BEHIND"; 296 } 297 case ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH: { 298 return "TRANSIT_ACTIVITY_RELAUNCH"; 299 } 300 case ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS: { 301 return "TRANSIT_DOCK_TASK_FROM_RECENTS"; 302 } 303 case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY: { 304 return TRANSIT_KEYGUARD_GOING_AWAY; 305 } 306 case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: { 307 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER; 308 } 309 case ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE: { 310 return TRANSIT_KEYGUARD_OCCLUDE; 311 } 312 case ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE: { 313 return TRANSIT_KEYGUARD_UNOCCLUDE; 314 } 315 case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: { 316 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN; 317 } 318 case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: { 319 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE; 320 } 321 case ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE: { 322 return "TRANSIT_CRASHING_ACTIVITY_CLOSE"; 323 } 324 default: { 325 fail("Invalid lastUsedAppTransition"); 326 return null; 327 } 328 } 329 } 330 getMatchingWindowType(int type)331 List<WindowState> getMatchingWindowType(int type) { 332 return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList()); 333 } 334 getMatchingWindowTokens(final String windowName)335 List<String> getMatchingWindowTokens(final String windowName) { 336 return getMatchingWindows(ws -> windowName.equals(ws.getName())) 337 .map(WindowState::getToken) 338 .collect(Collectors.toList()); 339 } 340 getAllNavigationBarStates()341 List<WindowState> getAllNavigationBarStates() { 342 return getMatchingWindows(WindowManagerState::isValidNavBarType) 343 .collect(Collectors.toList()); 344 } 345 getAndAssertSingleNavBarWindowOnDisplay(int displayId)346 WindowState getAndAssertSingleNavBarWindowOnDisplay(int displayId) { 347 List<WindowState> navWindow = getMatchingWindows(ws -> 348 isValidNavBarType(ws) && ws.getDisplayId() == displayId) 349 .collect(Collectors.toList()); 350 351 // We may need some time to wait for nav bar showing. 352 // It's Ok to get 0 nav bar here. 353 assertTrue("There should be at most one navigation bar on a display", 354 navWindow.size() <= 1); 355 356 return navWindow.isEmpty() ? null : navWindow.get(0); 357 } 358 isValidNavBarType(WindowState navState)359 private static boolean isValidNavBarType(WindowState navState) { 360 return TYPE_NAVIGATION_BAR == navState.getType(); 361 } 362 getMatchingVisibleWindowState(final String windowName)363 public List<WindowState> getMatchingVisibleWindowState(final String windowName) { 364 return getMatchingWindows(ws -> ws.isShown() && windowName.equals(ws.getName())) 365 .collect(Collectors.toList()); 366 } 367 getExitingWindows()368 List<WindowState> getExitingWindows() { 369 return getMatchingWindows(WindowState::isExitingWindow) 370 .collect(Collectors.toList()); 371 } 372 getMatchingWindows(Predicate<WindowState> condition)373 private Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) { 374 return mWindowStates.stream().filter(condition); 375 } 376 377 @Nullable getWindowByPackageName(String packageName, int windowType)378 public WindowState getWindowByPackageName(String packageName, int windowType) { 379 final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType); 380 return windowList.isEmpty() ? null : windowList.get(0); 381 } 382 getWindowsByPackageName(String packageName, int... restrictToTypes)383 public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) { 384 return getMatchingWindows(ws -> 385 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/")) 386 && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType())) 387 .collect(Collectors.toList()); 388 } 389 getWindowStateForAppToken(String appToken)390 WindowState getWindowStateForAppToken(String appToken) { 391 return getMatchingWindows(ws -> ws.getToken().equals(appToken)) 392 .findFirst() 393 .orElse(null); 394 } 395 getDisplay(int displayId)396 Display getDisplay(int displayId) { 397 for (Display display : mDisplays) { 398 if (displayId == display.getDisplayId()) { 399 return display; 400 } 401 } 402 return null; 403 } 404 getDisplays()405 List<Display> getDisplays() { 406 return mDisplays; 407 } 408 getFrontWindow()409 String getFrontWindow() { 410 if (mWindowStates == null || mWindowStates.isEmpty()) { 411 return null; 412 } 413 return mWindowStates.get(0).getName(); 414 } 415 getFocusedWindow()416 public String getFocusedWindow() { 417 return mFocusedWindow; 418 } 419 getFocusedApp()420 public String getFocusedApp() { 421 return mFocusedApp; 422 } 423 getDefaultDisplayLastTransition()424 String getDefaultDisplayLastTransition() { 425 return getDisplay(DEFAULT_DISPLAY).getLastTransition(); 426 } 427 getDefaultDisplayAppTransitionState()428 String getDefaultDisplayAppTransitionState() { 429 return getDisplay(DEFAULT_DISPLAY).getAppTransitionState(); 430 } 431 getFrontStackId(int displayId)432 int getFrontStackId(int displayId) { 433 return mDisplayStacks.get(displayId).get(0).mStackId; 434 } 435 getFrontStackActivityType(int displayId)436 int getFrontStackActivityType(int displayId) { 437 return mDisplayStacks.get(displayId).get(0).getActivityType(); 438 } 439 getRotation()440 public int getRotation() { 441 return mRotation; 442 } 443 getLastOrientation()444 int getLastOrientation() { 445 return mLastOrientation; 446 } 447 containsStack(int stackId)448 boolean containsStack(int stackId) { 449 for (WindowStack stack : mStacks) { 450 if (stackId == stack.mStackId) { 451 return true; 452 } 453 } 454 return false; 455 } 456 containsStack(int windowingMode, int activityType)457 boolean containsStack(int windowingMode, int activityType) { 458 for (WindowStack stack : mStacks) { 459 if (activityType != ACTIVITY_TYPE_UNDEFINED 460 && activityType != stack.getActivityType()) { 461 continue; 462 } 463 if (windowingMode != WINDOWING_MODE_UNDEFINED 464 && windowingMode != stack.getWindowingMode()) { 465 continue; 466 } 467 return true; 468 } 469 return false; 470 } 471 472 /** 473 * Check if there exists a window record with matching windowName. 474 */ containsWindow(String windowName)475 public boolean containsWindow(String windowName) { 476 for (WindowState window : mWindowStates) { 477 if (window.getName().equals(windowName)) { 478 return true; 479 } 480 } 481 return false; 482 } 483 484 /** 485 * Check if at least one window which matches provided window name is visible. 486 */ isWindowVisible(String windowName)487 boolean isWindowVisible(String windowName) { 488 for (WindowState window : mWindowStates) { 489 if (window.getName().equals(windowName)) { 490 if (window.isShown()) { 491 return true; 492 } 493 } 494 } 495 return false; 496 } 497 allWindowsVisible(String windowName)498 boolean allWindowsVisible(String windowName) { 499 boolean allVisible = false; 500 for (WindowState window : mWindowStates) { 501 if (window.getName().equals(windowName)) { 502 if (!window.isShown()) { 503 log("[VISIBLE] not visible" + windowName); 504 return false; 505 } 506 log("[VISIBLE] visible" + windowName); 507 allVisible = true; 508 } 509 } 510 return allVisible; 511 } 512 getStack(int stackId)513 WindowStack getStack(int stackId) { 514 for (WindowStack stack : mStacks) { 515 if (stackId == stack.mStackId) { 516 return stack; 517 } 518 } 519 return null; 520 } 521 getStandardStackByWindowingMode(int windowingMode)522 WindowStack getStandardStackByWindowingMode(int windowingMode) { 523 for (WindowStack stack : mStacks) { 524 if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) { 525 continue; 526 } 527 if (stack.getWindowingMode() == windowingMode) { 528 return stack; 529 } 530 } 531 return null; 532 } 533 534 /** Get the stack position on its display. */ getStackIndexByActivityType(int activityType)535 int getStackIndexByActivityType(int activityType) { 536 for (Integer displayId : mDisplayStacks.keySet()) { 537 List<WindowStack> stacks = mDisplayStacks.get(displayId); 538 for (int i = 0; i < stacks.size(); i++) { 539 if (activityType == stacks.get(i).getActivityType()) { 540 return i; 541 } 542 } 543 } 544 return -1; 545 } 546 getInputMethodWindowState()547 WindowState getInputMethodWindowState() { 548 return getWindowStateForAppToken(mInputMethodWindowAppToken); 549 } 550 getStableBounds()551 Rect getStableBounds() { 552 return getDisplay(DEFAULT_DISPLAY).mStableBounds; 553 } 554 getDefaultPinnedStackBounds()555 Rect getDefaultPinnedStackBounds() { 556 return new Rect(mDefaultPinnedStackBounds); 557 } 558 getPinnedStackMovementBounds()559 Rect getPinnedStackMovementBounds() { 560 return new Rect(mPinnedStackMovementBounds); 561 } 562 findFirstWindowWithType(int type)563 WindowState findFirstWindowWithType(int type) { 564 for (WindowState window : mWindowStates) { 565 if (window.getType() == type) { 566 return window; 567 } 568 } 569 return null; 570 } 571 isDisplayFrozen()572 public boolean isDisplayFrozen() { 573 return mDisplayFrozen; 574 } 575 isDockedStackMinimized()576 public boolean isDockedStackMinimized() { 577 return mIsDockedStackMinimized; 578 } 579 getZOrder(WindowState w)580 public int getZOrder(WindowState w) { 581 return mWindowStates.size() - mWindowStates.indexOf(w); 582 } 583 reset()584 private void reset() { 585 mSysDump.clear(); 586 mStacks.clear(); 587 mDisplays.clear(); 588 mWindowStates.clear(); 589 mDisplayStacks.clear(); 590 mFocusedWindow = null; 591 mFocusedApp = null; 592 mInputMethodWindowAppToken = null; 593 mIsDockedStackMinimized = false; 594 mDefaultPinnedStackBounds.setEmpty(); 595 mPinnedStackMovementBounds.setEmpty(); 596 mRotation = 0; 597 mLastOrientation = 0; 598 mDisplayFrozen = false; 599 } 600 601 static class WindowStack extends WindowContainer { 602 603 int mStackId; 604 ArrayList<WindowTask> mTasks = new ArrayList<>(); 605 boolean mWindowAnimationBackgroundSurfaceShowing; 606 boolean mAnimatingBounds; 607 WindowStack(StackProto proto)608 WindowStack(StackProto proto) { 609 super(proto.windowContainer); 610 mStackId = proto.id; 611 mFullscreen = proto.fillsParent; 612 mBounds = extract(proto.bounds); 613 for (int i = 0; i < proto.tasks.length; i++) { 614 TaskProto taskProto = proto.tasks[i]; 615 WindowTask task = new WindowTask(taskProto); 616 mTasks.add(task); 617 mSubWindows.addAll(task.getWindows()); 618 } 619 mWindowAnimationBackgroundSurfaceShowing = proto.animationBackgroundSurfaceIsDimming; 620 mAnimatingBounds = proto.animatingBounds; 621 } 622 getTask(int taskId)623 WindowTask getTask(int taskId) { 624 for (WindowTask task : mTasks) { 625 if (taskId == task.mTaskId) { 626 return task; 627 } 628 } 629 return null; 630 } 631 isWindowAnimationBackgroundSurfaceShowing()632 boolean isWindowAnimationBackgroundSurfaceShowing() { 633 return mWindowAnimationBackgroundSurfaceShowing; 634 } 635 } 636 637 static class WindowTask extends WindowContainer { 638 639 int mTaskId; 640 List<String> mAppTokens = new ArrayList<>(); 641 private int mSurfaceWidth; 642 private int mSurfaceHeight; 643 WindowTask(TaskProto proto)644 WindowTask(TaskProto proto) { 645 super(proto.windowContainer); 646 mTaskId = proto.id; 647 mFullscreen = proto.fillsParent; 648 mBounds = extract(proto.bounds); 649 for (int i = 0; i < proto.appWindowTokens.length; i++) { 650 AppWindowTokenProto appWindowTokenProto = proto.appWindowTokens[i]; 651 mAppTokens.add(appWindowTokenProto.name); 652 WindowTokenProto windowTokenProto = appWindowTokenProto.windowToken; 653 for (int j = 0; j < windowTokenProto.windows.length; j++) { 654 WindowStateProto windowProto = windowTokenProto.windows[j]; 655 WindowState window = new WindowState(windowProto); 656 mSubWindows.add(window); 657 mSubWindows.addAll(window.getWindows()); 658 } 659 } 660 mSurfaceWidth = proto.surfaceWidth; 661 mSurfaceHeight = proto.surfaceHeight; 662 } 663 getSurfaceWidth()664 int getSurfaceWidth() { 665 return mSurfaceWidth; 666 } 667 getSurfaceHeight()668 int getSurfaceHeight() { 669 return mSurfaceHeight; 670 } 671 } 672 673 static class ConfigurationContainer { 674 final Configuration mOverrideConfiguration = new Configuration(); 675 final Configuration mFullConfiguration = new Configuration(); 676 final Configuration mMergedOverrideConfiguration = new Configuration(); 677 ConfigurationContainer(ConfigurationContainerProto proto)678 ConfigurationContainer(ConfigurationContainerProto proto) { 679 if (proto == null) { 680 return; 681 } 682 mOverrideConfiguration.setTo(extract(proto.overrideConfiguration)); 683 mFullConfiguration.setTo(extract(proto.fullConfiguration)); 684 mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration)); 685 } 686 getWindowingMode()687 int getWindowingMode() { 688 if (mFullConfiguration == null) { 689 return WINDOWING_MODE_UNDEFINED; 690 } 691 return mFullConfiguration.windowConfiguration.getWindowingMode(); 692 } 693 getActivityType()694 int getActivityType() { 695 if (mFullConfiguration == null) { 696 return ACTIVITY_TYPE_UNDEFINED; 697 } 698 return mFullConfiguration.windowConfiguration.getActivityType(); 699 } 700 } 701 702 static abstract class WindowContainer extends ConfigurationContainer { 703 704 protected boolean mFullscreen; 705 protected Rect mBounds; 706 protected int mOrientation; 707 protected List<WindowState> mSubWindows = new ArrayList<>(); 708 WindowContainer(WindowContainerProto proto)709 WindowContainer(WindowContainerProto proto) { 710 super(proto.configurationContainer); 711 mOrientation = proto.orientation; 712 } 713 getBounds()714 Rect getBounds() { 715 return mBounds; 716 } 717 isFullscreen()718 boolean isFullscreen() { 719 return mFullscreen; 720 } 721 getWindows()722 List<WindowState> getWindows() { 723 return mSubWindows; 724 } 725 } 726 727 static class Display extends WindowContainer { 728 729 private final int mDisplayId; 730 private Rect mDisplayRect = new Rect(); 731 private Rect mAppRect = new Rect(); 732 private int mDpi; 733 private Rect mStableBounds; 734 private String mName; 735 private int mSurfaceSize; 736 private String mFocusedApp; 737 private String mLastTransition; 738 private String mAppTransitionState; 739 Display(DisplayContentProto proto)740 public Display(DisplayContentProto proto) { 741 super(proto.windowContainer); 742 mDisplayId = proto.id; 743 for (int i = 0; i < proto.aboveAppWindows.length; i++) { 744 addWindowsFromTokenProto(proto.aboveAppWindows[i]); 745 } 746 for (int i = 0; i < proto.belowAppWindows.length; i++) { 747 addWindowsFromTokenProto(proto.belowAppWindows[i]); 748 } 749 for (int i = 0; i < proto.imeWindows.length; i++) { 750 addWindowsFromTokenProto(proto.imeWindows[i]); 751 } 752 mDpi = proto.dpi; 753 DisplayInfoProto infoProto = proto.displayInfo; 754 if (infoProto != null) { 755 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight); 756 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight); 757 mName = infoProto.name; 758 } 759 final DisplayFramesProto displayFramesProto = proto.displayFrames; 760 if (displayFramesProto != null) { 761 mStableBounds = extract(displayFramesProto.stableBounds); 762 } 763 mSurfaceSize = proto.surfaceSize; 764 mFocusedApp = proto.focusedApp; 765 766 final AppTransitionProto appTransitionProto = proto.appTransition; 767 int appState = 0; 768 int lastTransition = 0; 769 if (appTransitionProto != null) { 770 appState = appTransitionProto.appTransitionState; 771 lastTransition = appTransitionProto.lastUsedAppTransition; 772 } 773 mAppTransitionState = appStateToString(appState); 774 mLastTransition = appTransitionToString(lastTransition); 775 } 776 addWindowsFromTokenProto(WindowTokenProto proto)777 private void addWindowsFromTokenProto(WindowTokenProto proto) { 778 for (int j = 0; j < proto.windows.length; j++) { 779 WindowStateProto windowProto = proto.windows[j]; 780 WindowState childWindow = new WindowState(windowProto); 781 mSubWindows.add(childWindow); 782 mSubWindows.addAll(childWindow.getWindows()); 783 } 784 } 785 getDisplayId()786 int getDisplayId() { 787 return mDisplayId; 788 } 789 getDpi()790 int getDpi() { 791 return mDpi; 792 } 793 getDisplayRect()794 Rect getDisplayRect() { 795 return mDisplayRect; 796 } 797 getAppRect()798 Rect getAppRect() { 799 return mAppRect; 800 } 801 getName()802 String getName() { 803 return mName; 804 } 805 getSurfaceSize()806 int getSurfaceSize() { 807 return mSurfaceSize; 808 } 809 getFocusedApp()810 String getFocusedApp() { 811 return mFocusedApp; 812 } 813 getLastTransition()814 String getLastTransition() { return mLastTransition; } 815 getAppTransitionState()816 String getAppTransitionState() { return mAppTransitionState; } 817 818 @Override toString()819 public String toString() { 820 return "Display #" + mDisplayId + ": name=" + mName + " mDisplayRect=" + mDisplayRect 821 + " mAppRect=" + mAppRect; 822 } 823 } 824 825 public static class WindowState extends WindowContainer { 826 827 private static final int WINDOW_TYPE_NORMAL = 0; 828 private static final int WINDOW_TYPE_STARTING = 1; 829 private static final int WINDOW_TYPE_EXITING = 2; 830 private static final int WINDOW_TYPE_DEBUGGER = 3; 831 832 private String mName; 833 private final String mAppToken; 834 private final int mWindowType; 835 private int mType = 0; 836 private int mDisplayId; 837 private int mStackId; 838 private int mLayer; 839 private boolean mShown; 840 private Rect mContainingFrame; 841 private Rect mParentFrame; 842 private Rect mContentFrame; 843 private Rect mFrame; 844 private Rect mSurfaceInsets = new Rect(); 845 private Rect mContentInsets = new Rect(); 846 private Rect mGivenContentInsets = new Rect(); 847 private Rect mCrop = new Rect(); 848 WindowState(WindowStateProto proto)849 WindowState(WindowStateProto proto) { 850 super(proto.windowContainer); 851 IdentifierProto identifierProto = proto.identifier; 852 mName = identifierProto.title; 853 mAppToken = Integer.toHexString(identifierProto.hashCode); 854 mDisplayId = proto.displayId; 855 mStackId = proto.stackId; 856 if (proto.attributes != null) { 857 mType = proto.attributes.type; 858 } 859 WindowStateAnimatorProto animatorProto = proto.animator; 860 if (animatorProto != null) { 861 if (animatorProto.surface != null) { 862 WindowSurfaceControllerProto surfaceProto = animatorProto.surface; 863 mShown = surfaceProto.shown; 864 mLayer = surfaceProto.layer; 865 } 866 mCrop = extract(animatorProto.lastClipRect); 867 } 868 mGivenContentInsets = extract(proto.givenContentInsets); 869 WindowFramesProto windowFramesProto = proto.windowFrames; 870 if (windowFramesProto != null) { 871 mFrame = extract(windowFramesProto.frame); 872 mContainingFrame = extract(windowFramesProto.containingFrame); 873 mParentFrame = extract(windowFramesProto.parentFrame); 874 mContentFrame = extract(windowFramesProto.contentFrame); 875 mContentInsets = extract(windowFramesProto.contentInsets); 876 } 877 mSurfaceInsets = extract(proto.surfaceInsets); 878 if (mName.startsWith(STARTING_WINDOW_PREFIX)) { 879 mWindowType = WINDOW_TYPE_STARTING; 880 // Existing code depends on the prefix being removed 881 mName = mName.substring(STARTING_WINDOW_PREFIX.length()); 882 } else if (proto.animatingExit) { 883 mWindowType = WINDOW_TYPE_EXITING; 884 } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) { 885 mWindowType = WINDOW_TYPE_STARTING; 886 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length()); 887 } else { 888 mWindowType = 0; 889 } 890 for (int i = 0; i < proto.childWindows.length; i++) { 891 WindowStateProto childProto = proto.childWindows[i]; 892 WindowState childWindow = new WindowState(childProto); 893 mSubWindows.add(childWindow); 894 mSubWindows.addAll(childWindow.getWindows()); 895 } 896 } 897 898 @NonNull getName()899 public String getName() { 900 return mName; 901 } 902 getToken()903 String getToken() { 904 return mAppToken; 905 } 906 isStartingWindow()907 boolean isStartingWindow() { 908 return mWindowType == WINDOW_TYPE_STARTING; 909 } 910 isExitingWindow()911 boolean isExitingWindow() { 912 return mWindowType == WINDOW_TYPE_EXITING; 913 } 914 isDebuggerWindow()915 boolean isDebuggerWindow() { 916 return mWindowType == WINDOW_TYPE_DEBUGGER; 917 } 918 getDisplayId()919 int getDisplayId() { 920 return mDisplayId; 921 } 922 getStackId()923 int getStackId() { 924 return mStackId; 925 } 926 getContainingFrame()927 Rect getContainingFrame() { 928 return mContainingFrame; 929 } 930 getFrame()931 public Rect getFrame() { 932 return mFrame; 933 } 934 getSurfaceInsets()935 Rect getSurfaceInsets() { 936 return mSurfaceInsets; 937 } 938 getContentInsets()939 Rect getContentInsets() { 940 return mContentInsets; 941 } 942 getGivenContentInsets()943 Rect getGivenContentInsets() { 944 return mGivenContentInsets; 945 } 946 getContentFrame()947 public Rect getContentFrame() { 948 return mContentFrame; 949 } 950 getParentFrame()951 Rect getParentFrame() { 952 return mParentFrame; 953 } 954 getCrop()955 Rect getCrop() { 956 return mCrop; 957 } 958 isShown()959 public boolean isShown() { 960 return mShown; 961 } 962 getType()963 public int getType() { 964 return mType; 965 } 966 getWindowTypeSuffix(int windowType)967 private String getWindowTypeSuffix(int windowType) { 968 switch (windowType) { 969 case WINDOW_TYPE_STARTING: 970 return " STARTING"; 971 case WINDOW_TYPE_EXITING: 972 return " EXITING"; 973 case WINDOW_TYPE_DEBUGGER: 974 return " DEBUGGER"; 975 default: 976 break; 977 } 978 return ""; 979 } 980 981 @Override toString()982 public String toString() { 983 return "WindowState: {" + mAppToken + " " + mName 984 + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType 985 + " cf=" + mContainingFrame + " pf=" + mParentFrame; 986 } 987 } 988 } 989