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