• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 com.android.server.wm;
18 
19 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
21 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
22 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
23 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
24 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
25 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
28 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
29 
30 import android.app.ActivityManager.StackId;
31 import android.graphics.Matrix;
32 import android.graphics.Rect;
33 import android.graphics.RectF;
34 import android.graphics.Region;
35 import android.graphics.Region.Op;
36 import android.util.DisplayMetrics;
37 import android.util.Slog;
38 import android.view.Display;
39 import android.view.DisplayInfo;
40 import android.view.Surface;
41 import android.view.animation.Animation;
42 
43 import java.io.PrintWriter;
44 import java.util.ArrayList;
45 
46 class DisplayContentList extends ArrayList<DisplayContent> {
47 }
48 
49 /**
50  * Utility class for keeping track of the WindowStates and other pertinent contents of a
51  * particular Display.
52  *
53  * IMPORTANT: No method from this class should ever be used without holding
54  * WindowManagerService.mWindowMap.
55  */
56 class DisplayContent {
57 
58     /** Unique identifier of this stack. */
59     private final int mDisplayId;
60 
61     /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
62      * from mDisplayWindows; */
63     private final WindowList mWindows = new WindowList();
64 
65     int mInitialDisplayWidth = 0;
66     int mInitialDisplayHeight = 0;
67     int mInitialDisplayDensity = 0;
68     int mBaseDisplayWidth = 0;
69     int mBaseDisplayHeight = 0;
70     int mBaseDisplayDensity = 0;
71     boolean mDisplayScalingDisabled;
72     private final DisplayInfo mDisplayInfo = new DisplayInfo();
73     private final Display mDisplay;
74     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
75 
76     Rect mBaseDisplayRect = new Rect();
77     Rect mContentRect = new Rect();
78 
79     // Accessed directly by all users.
80     boolean layoutNeeded;
81     int pendingLayoutChanges;
82     final boolean isDefaultDisplay;
83 
84     /** Window tokens that are in the process of exiting, but still on screen for animations. */
85     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
86 
87     /** Array containing all TaskStacks on this display.  Array
88      * is stored in display order with the current bottom stack at 0. */
89     private final ArrayList<TaskStack> mStacks = new ArrayList<>();
90 
91     /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
92      * (except a future lockscreen TaskStack) moves to the top. */
93     private TaskStack mHomeStack = null;
94 
95     /** Detect user tapping outside of current focused task bounds .*/
96     TaskTapPointerEventListener mTapDetector;
97 
98     /** Detect user tapping outside of current focused stack bounds .*/
99     Region mTouchExcludeRegion = new Region();
100 
101     /** Detect user tapping in a non-resizeable task in docked or fullscreen stack .*/
102     Region mNonResizeableRegion = new Region();
103 
104     /** Save allocating when calculating rects */
105     private final Rect mTmpRect = new Rect();
106     private final Rect mTmpRect2 = new Rect();
107     private final RectF mTmpRectF = new RectF();
108     private final Matrix mTmpMatrix = new Matrix();
109     private final Region mTmpRegion = new Region();
110 
111     /** For gathering Task objects in order. */
112     final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
113 
114     final WindowManagerService mService;
115 
116     /** Remove this display when animation on it has completed. */
117     boolean mDeferredRemoval;
118 
119     final DockedStackDividerController mDividerControllerLocked;
120 
121     final DimLayerController mDimLayerController;
122 
123     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
124 
125     /**
126      * @param display May not be null.
127      * @param service You know.
128      */
DisplayContent(Display display, WindowManagerService service)129     DisplayContent(Display display, WindowManagerService service) {
130         mDisplay = display;
131         mDisplayId = display.getDisplayId();
132         display.getDisplayInfo(mDisplayInfo);
133         display.getMetrics(mDisplayMetrics);
134         isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
135         mService = service;
136         initializeDisplayBaseInfo();
137         mDividerControllerLocked = new DockedStackDividerController(service, this);
138         mDimLayerController = new DimLayerController(this);
139     }
140 
getDisplayId()141     int getDisplayId() {
142         return mDisplayId;
143     }
144 
getWindowList()145     WindowList getWindowList() {
146         return mWindows;
147     }
148 
getDisplay()149     Display getDisplay() {
150         return mDisplay;
151     }
152 
getDisplayInfo()153     DisplayInfo getDisplayInfo() {
154         return mDisplayInfo;
155     }
156 
getDisplayMetrics()157     DisplayMetrics getDisplayMetrics() {
158         return mDisplayMetrics;
159     }
160 
getDockedDividerController()161     DockedStackDividerController getDockedDividerController() {
162         return mDividerControllerLocked;
163     }
164 
165     /**
166      * Returns true if the specified UID has access to this display.
167      */
hasAccess(int uid)168     public boolean hasAccess(int uid) {
169         return mDisplay.hasAccess(uid);
170     }
171 
isPrivate()172     public boolean isPrivate() {
173         return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
174     }
175 
getStacks()176     ArrayList<TaskStack> getStacks() {
177         return mStacks;
178     }
179 
180     /**
181      * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
182      * @return All the Tasks, in order, on this display.
183      */
getTasks()184     ArrayList<Task> getTasks() {
185         mTmpTaskHistory.clear();
186         final int numStacks = mStacks.size();
187         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
188             mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks());
189         }
190         return mTmpTaskHistory;
191     }
192 
getHomeStack()193     TaskStack getHomeStack() {
194         if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) {
195             Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
196         }
197         return mHomeStack;
198     }
199 
getStackById(int stackId)200     TaskStack getStackById(int stackId) {
201         for (int i = mStacks.size() - 1; i >= 0; --i) {
202             final TaskStack stack = mStacks.get(i);
203             if (stack.mStackId == stackId) {
204                 return stack;
205             }
206         }
207         return null;
208     }
209 
updateDisplayInfo()210     void updateDisplayInfo() {
211         mDisplay.getDisplayInfo(mDisplayInfo);
212         mDisplay.getMetrics(mDisplayMetrics);
213         for (int i = mStacks.size() - 1; i >= 0; --i) {
214             mStacks.get(i).updateDisplayInfo(null);
215         }
216     }
217 
initializeDisplayBaseInfo()218     void initializeDisplayBaseInfo() {
219         // Bootstrap the default logical display from the display manager.
220         final DisplayInfo newDisplayInfo =
221                 mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId);
222         if (newDisplayInfo != null) {
223             mDisplayInfo.copyFrom(newDisplayInfo);
224         }
225         mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
226         mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
227         mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
228         mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
229     }
230 
getLogicalDisplayRect(Rect out)231     void getLogicalDisplayRect(Rect out) {
232         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
233         final int orientation = mDisplayInfo.rotation;
234         boolean rotated = (orientation == Surface.ROTATION_90
235                 || orientation == Surface.ROTATION_270);
236         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
237         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
238         int width = mDisplayInfo.logicalWidth;
239         int left = (physWidth - width) / 2;
240         int height = mDisplayInfo.logicalHeight;
241         int top = (physHeight - height) / 2;
242         out.set(left, top, left + width, top + height);
243     }
244 
getLogicalDisplayRect(Rect out, int orientation)245     private void getLogicalDisplayRect(Rect out, int orientation) {
246         getLogicalDisplayRect(out);
247 
248         // Rotate the Rect if needed.
249         final int currentRotation = mDisplayInfo.rotation;
250         final int rotationDelta = deltaRotation(currentRotation, orientation);
251         if (rotationDelta == Surface.ROTATION_90 || rotationDelta == Surface.ROTATION_270) {
252             createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
253             mTmpRectF.set(out);
254             mTmpMatrix.mapRect(mTmpRectF);
255             mTmpRectF.round(out);
256         }
257     }
258 
getContentRect(Rect out)259     void getContentRect(Rect out) {
260         out.set(mContentRect);
261     }
262 
263     /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
attachStack(TaskStack stack, boolean onTop)264     void attachStack(TaskStack stack, boolean onTop) {
265         if (stack.mStackId == HOME_STACK_ID) {
266             if (mHomeStack != null) {
267                 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
268             }
269             mHomeStack = stack;
270         }
271         if (onTop) {
272             mStacks.add(stack);
273         } else {
274             mStacks.add(0, stack);
275         }
276         layoutNeeded = true;
277     }
278 
moveStack(TaskStack stack, boolean toTop)279     void moveStack(TaskStack stack, boolean toTop) {
280         if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
281             // This stack is always-on-top silly...
282             Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
283             return;
284         }
285 
286         if (!mStacks.remove(stack)) {
287             Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
288         }
289 
290         int addIndex = toTop ? mStacks.size() : 0;
291 
292         if (toTop
293                 && mService.isStackVisibleLocked(PINNED_STACK_ID)
294                 && stack.mStackId != PINNED_STACK_ID) {
295             // The pinned stack is always the top most stack (always-on-top) when it is visible.
296             // So, stack is moved just below the pinned stack.
297             addIndex--;
298             TaskStack topStack = mStacks.get(addIndex);
299             if (topStack.mStackId != PINNED_STACK_ID) {
300                 throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks);
301             }
302         }
303         mStacks.add(addIndex, stack);
304     }
305 
detachStack(TaskStack stack)306     void detachStack(TaskStack stack) {
307         mDimLayerController.removeDimLayerUser(stack);
308         mStacks.remove(stack);
309     }
310 
311     /**
312      * Propagate the new bounds to all child stacks.
313      * @param contentRect The bounds to apply at the top level.
314      */
resize(Rect contentRect)315     void resize(Rect contentRect) {
316         mContentRect.set(contentRect);
317     }
318 
taskIdFromPoint(int x, int y)319     int taskIdFromPoint(int x, int y) {
320         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
321             TaskStack stack = mStacks.get(stackNdx);
322             stack.getBounds(mTmpRect);
323             if (!mTmpRect.contains(x, y) || stack.isAdjustedForMinimizedDockedStack()) {
324                 continue;
325             }
326             final ArrayList<Task> tasks = stack.getTasks();
327             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
328                 final Task task = tasks.get(taskNdx);
329                 final WindowState win = task.getTopVisibleAppMainWindow();
330                 if (win == null) {
331                     continue;
332                 }
333                 // We need to use the task's dim bounds (which is derived from the visible
334                 // bounds of its apps windows) for any touch-related tests. Can't use
335                 // the task's original bounds because it might be adjusted to fit the
336                 // content frame. For example, the presence of the IME adjusting the
337                 // windows frames when the app window is the IME target.
338                 task.getDimBounds(mTmpRect);
339                 if (mTmpRect.contains(x, y)) {
340                     return task.mTaskId;
341                 }
342             }
343         }
344         return -1;
345     }
346 
347     /**
348      * Find the task whose outside touch area (for resizing) (x, y) falls within.
349      * Returns null if the touch doesn't fall into a resizing area.
350      */
findTaskForControlPoint(int x, int y)351     Task findTaskForControlPoint(int x, int y) {
352         final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
353         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
354             TaskStack stack = mStacks.get(stackNdx);
355             if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
356                 break;
357             }
358             final ArrayList<Task> tasks = stack.getTasks();
359             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
360                 final Task task = tasks.get(taskNdx);
361                 if (task.isFullscreen()) {
362                     return null;
363                 }
364 
365                 // We need to use the task's dim bounds (which is derived from the visible
366                 // bounds of its apps windows) for any touch-related tests. Can't use
367                 // the task's original bounds because it might be adjusted to fit the
368                 // content frame. One example is when the task is put to top-left quadrant,
369                 // the actual visible area would not start at (0,0) after it's adjusted
370                 // for the status bar.
371                 task.getDimBounds(mTmpRect);
372                 mTmpRect.inset(-delta, -delta);
373                 if (mTmpRect.contains(x, y)) {
374                     mTmpRect.inset(delta, delta);
375                     if (!mTmpRect.contains(x, y)) {
376                         return task;
377                     }
378                     // User touched inside the task. No need to look further,
379                     // focus transfer will be handled in ACTION_UP.
380                     return null;
381                 }
382             }
383         }
384         return null;
385     }
386 
setTouchExcludeRegion(Task focusedTask)387     void setTouchExcludeRegion(Task focusedTask) {
388         mTouchExcludeRegion.set(mBaseDisplayRect);
389         final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
390         boolean addBackFocusedTask = false;
391         mNonResizeableRegion.setEmpty();
392         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
393             TaskStack stack = mStacks.get(stackNdx);
394             final ArrayList<Task> tasks = stack.getTasks();
395             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
396                 final Task task = tasks.get(taskNdx);
397                 AppWindowToken token = task.getTopVisibleAppToken();
398                 if (token == null || !token.isVisible()) {
399                     continue;
400                 }
401 
402                 /**
403                  * Exclusion region is the region that TapDetector doesn't care about.
404                  * Here we want to remove all non-focused tasks from the exclusion region.
405                  * We also remove the outside touch area for resizing for all freeform
406                  * tasks (including the focused).
407                  *
408                  * We save the focused task region once we find it, and add it back at the end.
409                  */
410 
411                 task.getDimBounds(mTmpRect);
412 
413                 if (task == focusedTask) {
414                     addBackFocusedTask = true;
415                     mTmpRect2.set(mTmpRect);
416                 }
417 
418                 final boolean isFreeformed = task.inFreeformWorkspace();
419                 if (task != focusedTask || isFreeformed) {
420                     if (isFreeformed) {
421                         // If the task is freeformed, enlarge the area to account for outside
422                         // touch area for resize.
423                         mTmpRect.inset(-delta, -delta);
424                         // Intersect with display content rect. If we have system decor (status bar/
425                         // navigation bar), we want to exclude that from the tap detection.
426                         // Otherwise, if the app is partially placed under some system button (eg.
427                         // Recents, Home), pressing that button would cause a full series of
428                         // unwanted transfer focus/resume/pause, before we could go home.
429                         mTmpRect.intersect(mContentRect);
430                     }
431                     mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
432                 }
433                 if (task.isTwoFingerScrollMode()) {
434                     stack.getBounds(mTmpRect);
435                     mNonResizeableRegion.op(mTmpRect, Region.Op.UNION);
436                     break;
437                 }
438             }
439         }
440         // If we removed the focused task above, add it back and only leave its
441         // outside touch area in the exclusion. TapDectector is not interested in
442         // any touch inside the focused task itself.
443         if (addBackFocusedTask) {
444             mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
445         }
446         final WindowState inputMethod = mService.mInputMethodWindow;
447         if (inputMethod != null && inputMethod.isVisibleLw()) {
448             // If the input method is visible and the user is typing, we don't want these touch
449             // events to be intercepted and used to change focus. This would likely cause a
450             // disappearance of the input method.
451             inputMethod.getTouchableRegion(mTmpRegion);
452             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
453         }
454         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
455             WindowState win = mTapExcludedWindows.get(i);
456             win.getTouchableRegion(mTmpRegion);
457             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
458         }
459         if (getDockedStackVisibleForUserLocked() != null) {
460             mDividerControllerLocked.getTouchRegion(mTmpRect);
461             mTmpRegion.set(mTmpRect);
462             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
463         }
464         if (mTapDetector != null) {
465             mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion, mNonResizeableRegion);
466         }
467     }
468 
switchUserStacks()469     void switchUserStacks() {
470         final WindowList windows = getWindowList();
471         for (int i = 0; i < windows.size(); i++) {
472             final WindowState win = windows.get(i);
473             if (win.isHiddenFromUserLocked()) {
474                 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
475                         + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
476                 win.hideLw(false);
477             }
478         }
479 
480         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
481             mStacks.get(stackNdx).switchUser();
482         }
483     }
484 
resetAnimationBackgroundAnimator()485     void resetAnimationBackgroundAnimator() {
486         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
487             mStacks.get(stackNdx).resetAnimationBackgroundAnimator();
488         }
489     }
490 
animateDimLayers()491     boolean animateDimLayers() {
492         return mDimLayerController.animateDimLayers();
493     }
494 
resetDimming()495     void resetDimming() {
496         mDimLayerController.resetDimming();
497     }
498 
isDimming()499     boolean isDimming() {
500         return mDimLayerController.isDimming();
501     }
502 
stopDimmingIfNeeded()503     void stopDimmingIfNeeded() {
504         mDimLayerController.stopDimmingIfNeeded();
505     }
506 
close()507     void close() {
508         mDimLayerController.close();
509         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
510             mStacks.get(stackNdx).close();
511         }
512     }
513 
isAnimating()514     boolean isAnimating() {
515         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
516             final TaskStack stack = mStacks.get(stackNdx);
517             if (stack.isAnimating()) {
518                 return true;
519             }
520         }
521         return false;
522     }
523 
checkForDeferredActions()524     void checkForDeferredActions() {
525         boolean animating = false;
526         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
527             final TaskStack stack = mStacks.get(stackNdx);
528             if (stack.isAnimating()) {
529                 animating = true;
530             } else {
531                 if (stack.mDeferDetach) {
532                     mService.detachStackLocked(this, stack);
533                 }
534                 final ArrayList<Task> tasks = stack.getTasks();
535                 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
536                     final Task task = tasks.get(taskNdx);
537                     AppTokenList tokens = task.mAppTokens;
538                     for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
539                         AppWindowToken wtoken = tokens.get(tokenNdx);
540                         if (wtoken.mIsExiting) {
541                             wtoken.removeAppFromTaskLocked();
542                         }
543                     }
544                 }
545             }
546         }
547         if (!animating && mDeferredRemoval) {
548             mService.onDisplayRemoved(mDisplayId);
549         }
550     }
551 
rotateBounds(int oldRotation, int newRotation, Rect bounds)552     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
553         getLogicalDisplayRect(mTmpRect, newRotation);
554 
555         // Compute a transform matrix to undo the coordinate space transformation,
556         // and present the window at the same physical position it previously occupied.
557         final int deltaRotation = deltaRotation(newRotation, oldRotation);
558         createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
559 
560         mTmpRectF.set(bounds);
561         mTmpMatrix.mapRect(mTmpRectF);
562         mTmpRectF.round(bounds);
563     }
564 
deltaRotation(int oldRotation, int newRotation)565     static int deltaRotation(int oldRotation, int newRotation) {
566         int delta = newRotation - oldRotation;
567         if (delta < 0) delta += 4;
568         return delta;
569     }
570 
createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)571     static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
572             Matrix outMatrix) {
573         // For rotations without Z-ordering we don't need the target rectangle's position.
574         createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
575                 displayHeight, outMatrix);
576     }
577 
createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)578     static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
579             float displayWidth, float displayHeight, Matrix outMatrix) {
580         switch (rotation) {
581             case Surface.ROTATION_0:
582                 outMatrix.reset();
583                 break;
584             case Surface.ROTATION_270:
585                 outMatrix.setRotate(270, 0, 0);
586                 outMatrix.postTranslate(0, displayHeight);
587                 outMatrix.postTranslate(rectTop, 0);
588                 break;
589             case Surface.ROTATION_180:
590                 outMatrix.reset();
591                 break;
592             case Surface.ROTATION_90:
593                 outMatrix.setRotate(90, 0, 0);
594                 outMatrix.postTranslate(displayWidth, 0);
595                 outMatrix.postTranslate(-rectTop, rectLeft);
596                 break;
597         }
598     }
599 
dump(String prefix, PrintWriter pw)600     public void dump(String prefix, PrintWriter pw) {
601         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
602         final String subPrefix = "  " + prefix;
603         pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
604             pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
605             pw.print("dpi");
606             if (mInitialDisplayWidth != mBaseDisplayWidth
607                     || mInitialDisplayHeight != mBaseDisplayHeight
608                     || mInitialDisplayDensity != mBaseDisplayDensity) {
609                 pw.print(" base=");
610                 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
611                 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
612             }
613             if (mDisplayScalingDisabled) {
614                 pw.println(" noscale");
615             }
616             pw.print(" cur=");
617             pw.print(mDisplayInfo.logicalWidth);
618             pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
619             pw.print(" app=");
620             pw.print(mDisplayInfo.appWidth);
621             pw.print("x"); pw.print(mDisplayInfo.appHeight);
622             pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
623             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
624             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
625             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
626             pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval);
627                 pw.print(" layoutNeeded="); pw.println(layoutNeeded);
628 
629         pw.println();
630         pw.println("  Application tokens in top down Z order:");
631         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
632             final TaskStack stack = mStacks.get(stackNdx);
633             stack.dump(prefix + "  ", pw);
634         }
635 
636         pw.println();
637         if (!mExitingTokens.isEmpty()) {
638             pw.println();
639             pw.println("  Exiting tokens:");
640             for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
641                 WindowToken token = mExitingTokens.get(i);
642                 pw.print("  Exiting #"); pw.print(i);
643                 pw.print(' '); pw.print(token);
644                 pw.println(':');
645                 token.dump(pw, "    ");
646             }
647         }
648         pw.println();
649         mDimLayerController.dump(prefix + "  ", pw);
650         pw.println();
651         mDividerControllerLocked.dump(prefix + "  ", pw);
652     }
653 
654     @Override
toString()655     public String toString() {
656         return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
657     }
658 
659     /**
660      * @return The docked stack, but only if it is visible, and {@code null} otherwise.
661      */
getDockedStackLocked()662     TaskStack getDockedStackLocked() {
663         final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
664         return (stack != null && stack.isVisibleLocked()) ? stack : null;
665     }
666 
667     /**
668      * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
669      * visible, as long as it's not hidden because the current user doesn't have any tasks there.
670      */
getDockedStackVisibleForUserLocked()671     TaskStack getDockedStackVisibleForUserLocked() {
672         final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
673         return (stack != null && stack.isVisibleLocked(true /* ignoreKeyguard */)) ? stack : null;
674     }
675 
676     /**
677      * Find the visible, touch-deliverable window under the given point
678      */
getTouchableWinAtPointLocked(float xf, float yf)679     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
680         WindowState touchedWin = null;
681         final int x = (int) xf;
682         final int y = (int) yf;
683 
684         for (int i = mWindows.size() - 1; i >= 0; i--) {
685             WindowState window = mWindows.get(i);
686             final int flags = window.mAttrs.flags;
687             if (!window.isVisibleLw()) {
688                 continue;
689             }
690             if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
691                 continue;
692             }
693 
694             window.getVisibleBounds(mTmpRect);
695             if (!mTmpRect.contains(x, y)) {
696                 continue;
697             }
698 
699             window.getTouchableRegion(mTmpRegion);
700 
701             final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
702             if (mTmpRegion.contains(x, y) || touchFlags == 0) {
703                 touchedWin = window;
704                 break;
705             }
706         }
707 
708         return touchedWin;
709     }
710 
711     /**
712      * See {@link WindowManagerService#overridePlayingAppAnimationsLw}.
713      */
overridePlayingAppAnimationsLw(Animation a)714     void overridePlayingAppAnimationsLw(Animation a) {
715         for (int i = mStacks.size() - 1; i >= 0; i--) {
716             mStacks.get(i).overridePlayingAppAnimations(a);
717         }
718     }
719 
canAddToastWindowForUid(int uid)720     boolean canAddToastWindowForUid(int uid) {
721         // We allow one toast window per UID being shown at a time.
722         // Also if the app is focused adding more than one toast at
723         // a time for better backwards compatibility.
724         boolean alreadyHasToastWindow = false;
725         final int windowCount = mWindows.size();
726         for (int i = 0; i < windowCount; i++) {
727             final WindowState window = mWindows.get(i);
728             if (window.isFocused() && window.getOwningUid() == uid) {
729                 return true;
730             }
731             if (window.mAttrs.type == TYPE_TOAST && window.getOwningUid() == uid
732                     && !window.isRemovedOrHidden()) {
733                 alreadyHasToastWindow = true;
734             }
735         }
736         return !alreadyHasToastWindow;
737     }
738 
scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)739     void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus,
740                                                    WindowState newFocus) {
741         if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
742             return;
743         }
744         final int lostFocusUid = oldFocus.mOwnerUid;
745         WindowList windows = getWindowList();
746         final int windowCount = windows.size();
747         for (int i = 0; i < windowCount; i++) {
748             WindowState window = windows.get(i);
749             if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
750                 if (!mService.mH.hasMessages(WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window)) {
751                     mService.mH.sendMessageDelayed(
752                             mService.mH.obtainMessage(
753                                     WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window),
754                             window.mAttrs.hideTimeoutMilliseconds);
755                 }
756             }
757         }
758     }
759 }
760