diff options
Diffstat (limited to 'services/core/java/com/android/server/wm/DisplayContent.java')
-rw-r--r-- | services/core/java/com/android/server/wm/DisplayContent.java | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java new file mode 100644 index 0000000..68834d8 --- /dev/null +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; +import static com.android.server.wm.WindowManagerService.TAG; + +import android.graphics.Rect; +import android.graphics.Region; +import android.util.Slog; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.Surface; + +import java.io.PrintWriter; +import java.util.ArrayList; + +class DisplayContentList extends ArrayList<DisplayContent> { +} + +/** + * Utility class for keeping track of the WindowStates and other pertinent contents of a + * particular Display. + * + * IMPORTANT: No method from this class should ever be used without holding + * WindowManagerService.mWindowMap. + */ +class DisplayContent { + + /** Unique identifier of this stack. */ + private final int mDisplayId; + + /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element + * from mDisplayWindows; */ + private final WindowList mWindows = new WindowList(); + + // This protects the following display size properties, so that + // getDisplaySize() doesn't need to acquire the global lock. This is + // needed because the window manager sometimes needs to use ActivityThread + // while it has its global state locked (for example to load animation + // resources), but the ActivityThread also needs get the current display + // size sometimes when it has its package lock held. + // + // These will only be modified with both mWindowMap and mDisplaySizeLock + // held (in that order) so the window manager doesn't need to acquire this + // lock when needing these values in its normal operation. + final Object mDisplaySizeLock = new Object(); + int mInitialDisplayWidth = 0; + int mInitialDisplayHeight = 0; + int mInitialDisplayDensity = 0; + int mBaseDisplayWidth = 0; + int mBaseDisplayHeight = 0; + int mBaseDisplayDensity = 0; + private final DisplayInfo mDisplayInfo = new DisplayInfo(); + private final Display mDisplay; + + Rect mBaseDisplayRect = new Rect(); + Rect mContentRect = new Rect(); + + // Accessed directly by all users. + boolean layoutNeeded; + int pendingLayoutChanges; + final boolean isDefaultDisplay; + + /** Window tokens that are in the process of exiting, but still on screen for animations. */ + final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>(); + + /** Array containing all TaskStacks on this display. Array + * is stored in display order with the current bottom stack at 0. */ + private final ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>(); + + /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack + * (except a future lockscreen TaskStack) moves to the top. */ + private TaskStack mHomeStack = null; + + /** Detect user tapping outside of current focused stack bounds .*/ + StackTapPointerEventListener mTapDetector; + + /** Detect user tapping outside of current focused stack bounds .*/ + Region mTouchExcludeRegion = new Region(); + + /** Save allocating when calculating rects */ + Rect mTmpRect = new Rect(); + + /** For gathering Task objects in order. */ + final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>(); + + final WindowManagerService mService; + + static final int DEFER_DETACH = 1; + static final int DEFER_REMOVAL = 2; + int mDeferredActions; + + /** + * @param display May not be null. + * @param service You know. + */ + DisplayContent(Display display, WindowManagerService service) { + mDisplay = display; + mDisplayId = display.getDisplayId(); + display.getDisplayInfo(mDisplayInfo); + isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; + mService = service; + } + + int getDisplayId() { + return mDisplayId; + } + + WindowList getWindowList() { + return mWindows; + } + + Display getDisplay() { + return mDisplay; + } + + DisplayInfo getDisplayInfo() { + return mDisplayInfo; + } + + /** + * Returns true if the specified UID has access to this display. + */ + public boolean hasAccess(int uid) { + return mDisplay.hasAccess(uid); + } + + public boolean isPrivate() { + return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; + } + + ArrayList<TaskStack> getStacks() { + return mStacks; + } + + /** + * Retrieve the tasks on this display in stack order from the bottommost TaskStack up. + * @return All the Tasks, in order, on this display. + */ + ArrayList<Task> getTasks() { + mTmpTaskHistory.clear(); + final int numStacks = mStacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks()); + } + return mTmpTaskHistory; + } + + TaskStack getHomeStack() { + if (mHomeStack == null) { + Slog.e(TAG, "getHomeStack: Returning null from this=" + this); + } + return mHomeStack; + } + + void updateDisplayInfo() { + mDisplay.getDisplayInfo(mDisplayInfo); + for (int i = mStacks.size() - 1; i >= 0; --i) { + mStacks.get(i).updateDisplayInfo(); + } + } + + void getLogicalDisplayRect(Rect out) { + // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. + final int orientation = mDisplayInfo.rotation; + boolean rotated = (orientation == Surface.ROTATION_90 + || orientation == Surface.ROTATION_270); + final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; + final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; + int width = mDisplayInfo.logicalWidth; + int left = (physWidth - width) / 2; + int height = mDisplayInfo.logicalHeight; + int top = (physHeight - height) / 2; + out.set(left, top, left + width, top + height); + } + + /** Refer to {@link WindowManagerService#attachStack(int, int)} */ + void attachStack(TaskStack stack) { + if (stack.mStackId == HOME_STACK_ID) { + if (mHomeStack != null) { + throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); + } + mHomeStack = stack; + } + mStacks.add(stack); + layoutNeeded = true; + } + + void moveStack(TaskStack stack, boolean toTop) { + mStacks.remove(stack); + mStacks.add(toTop ? mStacks.size() : 0, stack); + } + + void detachStack(TaskStack stack) { + mStacks.remove(stack); + } + + /** + * Propagate the new bounds to all child stacks. + * @param contentRect The bounds to apply at the top level. + */ + void resize(Rect contentRect) { + mContentRect.set(contentRect); + } + + int stackIdFromPoint(int x, int y) { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + stack.getBounds(mTmpRect); + if (mTmpRect.contains(x, y)) { + return stack.mStackId; + } + } + return -1; + } + + void setTouchExcludeRegion(TaskStack focusedStack) { + mTouchExcludeRegion.set(mBaseDisplayRect); + WindowList windows = getWindowList(); + for (int i = windows.size() - 1; i >= 0; --i) { + final WindowState win = windows.get(i); + final TaskStack stack = win.getStack(); + if (win.isVisibleLw() && stack != null && stack != focusedStack) { + mTmpRect.set(win.mVisibleFrame); + mTmpRect.intersect(win.mVisibleInsets); + mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); + } + } + } + + void switchUserStacks(int newUserId) { + final WindowList windows = getWindowList(); + for (int i = 0; i < windows.size(); i++) { + final WindowState win = windows.get(i); + if (win.isHiddenFromUserLocked()) { + if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding " + + win + ", attrs=" + win.mAttrs.type + ", belonging to " + + win.mOwnerUid); + win.hideLw(false); + } + } + + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).switchUser(newUserId); + } + } + + void resetAnimationBackgroundAnimator() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).resetAnimationBackgroundAnimator(); + } + } + + boolean animateDimLayers() { + boolean result = false; + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + result |= mStacks.get(stackNdx).animateDimLayers(); + } + return result; + } + + void resetDimming() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).resetDimmingTag(); + } + } + + boolean isDimming() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + if (mStacks.get(stackNdx).isDimming()) { + return true; + } + } + return false; + } + + void stopDimmingIfNeeded() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).stopDimmingIfNeeded(); + } + } + + void close() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + mStacks.get(stackNdx).close(); + } + } + + public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); + final String subPrefix = " " + prefix; + pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); + pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); + pw.print("dpi"); + if (mInitialDisplayWidth != mBaseDisplayWidth + || mInitialDisplayHeight != mBaseDisplayHeight + || mInitialDisplayDensity != mBaseDisplayDensity) { + pw.print(" base="); + pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); + pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); + } + pw.print(" cur="); + pw.print(mDisplayInfo.logicalWidth); + pw.print("x"); pw.print(mDisplayInfo.logicalHeight); + pw.print(" app="); + pw.print(mDisplayInfo.appWidth); + pw.print("x"); pw.print(mDisplayInfo.appHeight); + pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); + pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); + pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); + pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); + pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded); + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId); + stack.dump(prefix + " ", pw); + } + pw.println(); + pw.println(" Application tokens in bottom up Z order:"); + int ndx = 0; + final int numStacks = mStacks.size(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + AppTokenList tokens = tasks.get(taskNdx).mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + final AppWindowToken wtoken = tokens.get(tokenNdx); + pw.print(" App #"); pw.print(ndx++); + pw.print(' '); pw.print(wtoken); pw.println(":"); + wtoken.dump(pw, " "); + } + } + } + if (ndx == 0) { + pw.println(" None"); + } + pw.println(); + if (!mExitingTokens.isEmpty()) { + pw.println(); + pw.println(" Exiting tokens:"); + for (int i=mExitingTokens.size()-1; i>=0; i--) { + WindowToken token = mExitingTokens.get(i); + pw.print(" Exiting #"); pw.print(i); + pw.print(' '); pw.print(token); + pw.println(':'); + token.dump(pw, " "); + } + } + pw.println(); + } + + @Override + public String toString() { + return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks; + } +} |