Search in sources :

Example 21 with DisplayInfo

use of android.view.DisplayInfo in project platform_frameworks_base by android.

the class WallpaperController method updateWallpaperOffsetLocked.

void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
    final DisplayContent displayContent = changingTarget.getDisplayContent();
    if (displayContent == null) {
        return;
    }
    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    final int dw = displayInfo.logicalWidth;
    final int dh = displayInfo.logicalHeight;
    WindowState target = mWallpaperTarget;
    if (target != null) {
        if (target.mWallpaperX >= 0) {
            mLastWallpaperX = target.mWallpaperX;
        } else if (changingTarget.mWallpaperX >= 0) {
            mLastWallpaperX = changingTarget.mWallpaperX;
        }
        if (target.mWallpaperY >= 0) {
            mLastWallpaperY = target.mWallpaperY;
        } else if (changingTarget.mWallpaperY >= 0) {
            mLastWallpaperY = changingTarget.mWallpaperY;
        }
        if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
            mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
        } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
            mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
        }
        if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
            mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
        } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
            mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
        }
        if (target.mWallpaperXStep >= 0) {
            mLastWallpaperXStep = target.mWallpaperXStep;
        } else if (changingTarget.mWallpaperXStep >= 0) {
            mLastWallpaperXStep = changingTarget.mWallpaperXStep;
        }
        if (target.mWallpaperYStep >= 0) {
            mLastWallpaperYStep = target.mWallpaperYStep;
        } else if (changingTarget.mWallpaperYStep >= 0) {
            mLastWallpaperYStep = changingTarget.mWallpaperYStep;
        }
    }
    for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
        WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
        for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
            WindowState wallpaper = windows.get(wallpaperNdx);
            if (updateWallpaperOffset(wallpaper, dw, dh, sync)) {
                WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
                winAnimator.computeShownFrameLocked();
                // No need to lay out the windows - we can just set the wallpaper position
                // directly.
                winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
                // We only want to be synchronous with one wallpaper.
                sync = false;
            }
        }
    }
}
Also used : DisplayInfo(android.view.DisplayInfo)

Example 22 with DisplayInfo

use of android.view.DisplayInfo in project platform_frameworks_base by android.

the class WindowManagerService method updateDisplayAndOrientationLocked.

/** Do not call if mDisplayReady == false */
DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
    // TODO(multidisplay): For now, apply Configuration to main screen only.
    final DisplayContent displayContent = getDefaultDisplayContentLocked();
    // Use the effective "visual" dimensions based on current rotation
    final boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270);
    final int realdw = rotated ? displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
    final int realdh = rotated ? displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
    int dw = realdw;
    int dh = realdh;
    if (mAltOrientation) {
        if (realdw > realdh) {
            // Turn landscape into portrait.
            int maxw = (int) (realdh / 1.3f);
            if (maxw < realdw) {
                dw = maxw;
            }
        } else {
            // Turn portrait into landscape.
            int maxh = (int) (realdw / 1.3f);
            if (maxh < realdh) {
                dh = maxh;
            }
        }
    }
    // Update application display metrics.
    final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode);
    final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode);
    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    displayInfo.rotation = mRotation;
    displayInfo.logicalWidth = dw;
    displayInfo.logicalHeight = dh;
    displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
    displayInfo.appWidth = appWidth;
    displayInfo.appHeight = appHeight;
    displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
    displayInfo.getAppMetrics(mDisplayMetrics);
    if (displayContent.mDisplayScalingDisabled) {
        displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
    } else {
        displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
    }
    mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayContent.getDisplayId(), displayInfo);
    displayContent.mBaseDisplayRect.set(0, 0, dw, dh);
    if (false) {
        Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight);
    }
    mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, mCompatDisplayMetrics);
    return displayInfo;
}
Also used : DisplayInfo(android.view.DisplayInfo) Point(android.graphics.Point)

Example 23 with DisplayInfo

use of android.view.DisplayInfo in project platform_frameworks_base by android.

the class WindowManagerService method screenshotApplicationsInner.

/**
     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
     * In portrait mode, it grabs the full screenshot.
     *
     * @param displayId the Display to take a screenshot of.
     * @param width the width of the target bitmap
     * @param height the height of the target bitmap
     * @param includeFullDisplay true if the screen should not be cropped before capture
     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
     * @param config of the output bitmap
     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
     */
Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly) {
    final DisplayContent displayContent;
    synchronized (mWindowMap) {
        displayContent = getDisplayContentLocked(displayId);
        if (displayContent == null) {
            if (DEBUG_SCREENSHOT)
                Slog.i(TAG_WM, "Screenshot of " + appToken + ": returning null. No Display for displayId=" + displayId);
            return null;
        }
    }
    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    int dw = displayInfo.logicalWidth;
    int dh = displayInfo.logicalHeight;
    if (dw == 0 || dh == 0) {
        if (DEBUG_SCREENSHOT)
            Slog.i(TAG_WM, "Screenshot of " + appToken + ": returning null. logical widthxheight=" + dw + "x" + dh);
        return null;
    }
    Bitmap bm = null;
    int maxLayer = 0;
    final Rect frame = new Rect();
    final Rect stackBounds = new Rect();
    boolean screenshotReady;
    int minLayer;
    if (appToken == null && !wallpaperOnly) {
        screenshotReady = true;
        minLayer = 0;
    } else {
        screenshotReady = false;
        minLayer = Integer.MAX_VALUE;
    }
    WindowState appWin = null;
    boolean includeImeInScreenshot;
    synchronized (mWindowMap) {
        final AppWindowToken imeTargetAppToken = mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null;
        // We only include the Ime in the screenshot if the app we are screenshoting is the IME
        // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
        // mode because the frame of the IME might not overlap with that of the app.
        // E.g. IME target app at the top in split-screen mode and the IME at the bottom
        // overlapping with the bottom app.
        includeImeInScreenshot = imeTargetAppToken != null && imeTargetAppToken.appToken != null && imeTargetAppToken.appToken.asBinder() == appToken && !mInputMethodTarget.isInMultiWindowMode();
    }
    final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
    synchronized (mWindowMap) {
        // Figure out the part of the screen that is actually the app.
        appWin = null;
        final WindowList windows = displayContent.getWindowList();
        for (int i = windows.size() - 1; i >= 0; i--) {
            WindowState ws = windows.get(i);
            if (!ws.mHasSurface) {
                continue;
            }
            if (ws.mLayer >= aboveAppLayer) {
                continue;
            }
            if (wallpaperOnly && !ws.mIsWallpaper) {
                continue;
            }
            if (ws.mIsImWindow) {
                if (!includeImeInScreenshot) {
                    continue;
                }
            } else if (ws.mIsWallpaper) {
                // then the target window state is this one.
                if (wallpaperOnly) {
                    appWin = ws;
                }
                if (appWin == null) {
                    // the layer of the target window.
                    continue;
                }
            // Fall through. The target window is in front of the wallpaper. For this
            // case we want to include the wallpaper layer in the screenshot because
            // the target window might have some transparent areas.
            } else if (appToken != null) {
                if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
                    // screenshot app.
                    continue;
                }
                appWin = ws;
            }
            // Include this window.
            final WindowStateAnimator winAnim = ws.mWinAnimator;
            int layer = winAnim.mSurfaceController.getLayer();
            if (maxLayer < layer) {
                maxLayer = layer;
            }
            if (minLayer > layer) {
                minLayer = layer;
            }
            // Don't include wallpaper in bounds calculation
            if (!includeFullDisplay && !ws.mIsWallpaper) {
                final Rect wf = ws.mFrame;
                final Rect cr = ws.mContentInsets;
                int left = wf.left + cr.left;
                int top = wf.top + cr.top;
                int right = wf.right - cr.right;
                int bottom = wf.bottom - cr.bottom;
                frame.union(left, top, right, bottom);
                ws.getVisibleBounds(stackBounds);
                if (!Rect.intersects(frame, stackBounds)) {
                    // Set frame empty if there's no intersection.
                    frame.setEmpty();
                }
            }
            final boolean foundTargetWs = (ws.mAppToken != null && ws.mAppToken.token == appToken) || (appWin != null && wallpaperOnly);
            if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
                screenshotReady = true;
            }
            if (ws.isObscuringFullscreen(displayInfo)) {
                break;
            }
        }
        if (appToken != null && appWin == null) {
            // Can't find a window to snapshot.
            if (DEBUG_SCREENSHOT)
                Slog.i(TAG_WM, "Screenshot: Couldn't find a surface matching " + appToken);
            return null;
        }
        if (!screenshotReady) {
            Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
            return null;
        }
        if (maxLayer == 0) {
            if (DEBUG_SCREENSHOT)
                Slog.i(TAG_WM, "Screenshot of " + appToken + ": returning null maxLayer=" + maxLayer);
            return null;
        }
        if (!includeFullDisplay) {
            // Constrain frame to the screen size.
            if (!frame.intersect(0, 0, dw, dh)) {
                frame.setEmpty();
            }
        } else {
            // Caller just wants entire display.
            frame.set(0, 0, dw, dh);
        }
        if (frame.isEmpty()) {
            return null;
        }
        if (width < 0) {
            width = (int) (frame.width() * frameScale);
        }
        if (height < 0) {
            height = (int) (frame.height() * frameScale);
        }
        // Tell surface flinger what part of the image to crop. Take the top
        // right part of the application, and crop the larger dimension to fit.
        Rect crop = new Rect(frame);
        if (width / (float) frame.width() < height / (float) frame.height()) {
            int cropWidth = (int) ((float) width / (float) height * frame.height());
            crop.right = crop.left + cropWidth;
        } else {
            int cropHeight = (int) ((float) height / (float) width * frame.width());
            crop.bottom = crop.top + cropHeight;
        }
        // The screenshot API does not apply the current screen rotation.
        int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
            rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
        }
        // Surfaceflinger is not aware of orientation, so convert our logical
        // crop to surfaceflinger's portrait orientation.
        convertCropForSurfaceFlinger(crop, rot, dw, dh);
        if (DEBUG_SCREENSHOT) {
            Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " + maxLayer + " appToken=" + appToken);
            for (int i = 0; i < windows.size(); i++) {
                WindowState win = windows.get(i);
                WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
                Slog.i(TAG_WM, win + ": " + win.mLayer + " animLayer=" + win.mWinAnimator.mAnimLayer + " surfaceLayer=" + ((controller == null) ? "null" : controller.getLayer()));
            }
        }
        ScreenRotationAnimation screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
        final boolean inRotation = screenRotationAnimation != null && screenRotationAnimation.isAnimating();
        if (DEBUG_SCREENSHOT && inRotation)
            Slog.v(TAG_WM, "Taking screenshot while rotating");
        // We force pending transactions to flush before taking
        // the screenshot by pushing an empty synchronous transaction.
        SurfaceControl.openTransaction();
        SurfaceControl.closeTransactionSync();
        bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, inRotation, rot);
        if (bm == null) {
            Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh + ") to layer " + maxLayer);
            return null;
        }
    }
    if (DEBUG_SCREENSHOT) {
        // TEST IF IT's ALL BLACK
        int[] buffer = new int[bm.getWidth() * bm.getHeight()];
        bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
        boolean allBlack = true;
        final int firstColor = buffer[0];
        for (int i = 0; i < buffer.length; i++) {
            if (buffer[i] != firstColor) {
                allBlack = false;
                break;
            }
        }
        if (allBlack) {
            Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + (appWin != null ? appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + " minLayer=" + minLayer + " maxLayer=" + maxLayer);
        }
    }
    // Create a copy of the screenshot that is immutable and backed in ashmem.
    // This greatly reduces the overhead of passing the bitmap between processes.
    Bitmap ret = bm.createAshmemBitmap(config);
    bm.recycle();
    return ret;
}
Also used : Rect(android.graphics.Rect) DisplayInfo(android.view.DisplayInfo) Point(android.graphics.Point) Bitmap(android.graphics.Bitmap)

Example 24 with DisplayInfo

use of android.view.DisplayInfo in project platform_frameworks_base by android.

the class WindowManagerService method getNonDecorInsetsLocked.

private void getNonDecorInsetsLocked(Rect outInsets) {
    final DisplayInfo di = getDefaultDisplayInfoLocked();
    mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
}
Also used : DisplayInfo(android.view.DisplayInfo)

Example 25 with DisplayInfo

use of android.view.DisplayInfo in project platform_frameworks_base by android.

the class WindowManagerService method addWindow.

public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
    int[] appOp = new int[1];
    int res = mPolicy.checkAddPermission(attrs, appOp);
    if (res != WindowManagerGlobal.ADD_OKAY) {
        return res;
    }
    boolean reportNewConfig = false;
    WindowState attachedWindow = null;
    long origId;
    final int callingUid = Binder.getCallingUid();
    final int type = attrs.type;
    synchronized (mWindowMap) {
        if (!mDisplayReady) {
            throw new IllegalStateException("Display has not been initialialized");
        }
        final DisplayContent displayContent = getDisplayContentLocked(displayId);
        if (displayContent == null) {
            Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: " + displayId + ".  Aborting.");
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        if (!displayContent.hasAccess(session.mUid)) {
            Slog.w(TAG_WM, "Attempted to add window to a display for which the application " + "does not have access: " + displayId + ".  Aborting.");
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        if (mWindowMap.containsKey(client.asBinder())) {
            Slog.w(TAG_WM, "Window " + client + " is already added");
            return WindowManagerGlobal.ADD_DUPLICATE_ADD;
        }
        if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
            attachedWindow = windowForClientLocked(null, attrs.token, false);
            if (attachedWindow == null) {
                Slog.w(TAG_WM, "Attempted to add window with token that is not a window: " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
            }
            if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
            }
        }
        if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
            Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display.  Aborting.");
            return WindowManagerGlobal.ADD_PERMISSION_DENIED;
        }
        boolean addToken = false;
        WindowToken token = mTokenMap.get(attrs.token);
        AppWindowToken atoken = null;
        boolean addToastWindowRequiresToken = false;
        if (token == null) {
            if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
                Slog.w(TAG_WM, "Attempted to add application window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_INPUT_METHOD) {
                Slog.w(TAG_WM, "Attempted to add input method window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_VOICE_INTERACTION) {
                Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_WALLPAPER) {
                Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_DREAM) {
                Slog.w(TAG_WM, "Attempted to add Dream window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_QS_DIALOG) {
                Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_ACCESSIBILITY_OVERLAY) {
                Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            if (type == TYPE_TOAST) {
                // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
                if (doesAddToastWindowRequireToken(attrs.packageName, callingUid, attachedWindow)) {
                    Slog.w(TAG_WM, "Attempted to add a toast window with unknown token " + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            }
            token = new WindowToken(this, attrs.token, -1, false);
            addToken = true;
        } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
            atoken = token.appWindowToken;
            if (atoken == null) {
                Slog.w(TAG_WM, "Attempted to add window with non-application token " + token + ".  Aborting.");
                return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
            } else if (atoken.removed) {
                Slog.w(TAG_WM, "Attempted to add window with exiting application token " + token + ".  Aborting.");
                return WindowManagerGlobal.ADD_APP_EXITING;
            }
            if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
                // No need for this guy!
                if (DEBUG_STARTING_WINDOW || localLOGV)
                    Slog.v(TAG_WM, "**** NO NEED TO START: " + attrs.getTitle());
                return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
            }
        } else if (type == TYPE_INPUT_METHOD) {
            if (token.windowType != TYPE_INPUT_METHOD) {
                Slog.w(TAG_WM, "Attempted to add input method window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_VOICE_INTERACTION) {
            if (token.windowType != TYPE_VOICE_INTERACTION) {
                Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_WALLPAPER) {
            if (token.windowType != TYPE_WALLPAPER) {
                Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_DREAM) {
            if (token.windowType != TYPE_DREAM) {
                Slog.w(TAG_WM, "Attempted to add Dream window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
            if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
                Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_TOAST) {
            // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
            addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName, callingUid, attachedWindow);
            if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
                Slog.w(TAG_WM, "Attempted to add a toast window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (type == TYPE_QS_DIALOG) {
            if (token.windowType != TYPE_QS_DIALOG) {
                Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token " + attrs.token + ".  Aborting.");
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (token.appWindowToken != null) {
            Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type);
            // It is not valid to use an app token with other system types; we will
            // instead make a new token for it (as if null had been passed in for the token).
            attrs.token = null;
            token = new WindowToken(this, null, -1, false);
            addToken = true;
        }
        WindowState win = new WindowState(this, session, client, token, attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
        if (win.mDeathRecipient == null) {
            // Client has apparently died, so there is no reason to
            // continue.
            Slog.w(TAG_WM, "Adding window client " + client.asBinder() + " that is dead, aborting.");
            return WindowManagerGlobal.ADD_APP_EXITING;
        }
        if (win.getDisplayContent() == null) {
            Slog.w(TAG_WM, "Adding window to Display that has been removed.");
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        mPolicy.adjustWindowParamsLw(win.mAttrs);
        win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
        res = mPolicy.prepareAddWindowLw(win, attrs);
        if (res != WindowManagerGlobal.ADD_OKAY) {
            return res;
        }
        final boolean openInputChannels = (outInputChannel != null && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
        if (openInputChannels) {
            win.openInputChannel(outInputChannel);
        }
        // schedule hiding all of its toast windows.
        if (type == TYPE_TOAST) {
            if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
                Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
            }
            // the screen after the activity goes away.
            if (addToastWindowRequiresToken || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0 || mCurrentFocus == null || mCurrentFocus.mOwnerUid != callingUid) {
                mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win), win.mAttrs.hideTimeoutMilliseconds);
            }
        }
        // From now on, no exceptions or errors allowed!
        res = WindowManagerGlobal.ADD_OKAY;
        if (excludeWindowTypeFromTapOutTask(type)) {
            displayContent.mTapExcludedWindows.add(win);
        }
        origId = Binder.clearCallingIdentity();
        if (addToken) {
            mTokenMap.put(attrs.token, token);
        }
        win.attach();
        mWindowMap.put(client.asBinder(), win);
        if (win.mAppOp != AppOpsManager.OP_NONE) {
            int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
            if ((startOpResult != AppOpsManager.MODE_ALLOWED) && (startOpResult != AppOpsManager.MODE_DEFAULT)) {
                win.setAppOpVisibilityLw(false);
            }
        }
        if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
            token.appWindowToken.startingWindow = win;
            if (DEBUG_STARTING_WINDOW)
                Slog.v(TAG_WM, "addWindow: " + token.appWindowToken + " startingWindow=" + win);
        }
        boolean imMayMove = true;
        if (type == TYPE_INPUT_METHOD) {
            win.mGivenInsetsPending = true;
            mInputMethodWindow = win;
            addInputMethodWindowToListLocked(win);
            imMayMove = false;
        } else if (type == TYPE_INPUT_METHOD_DIALOG) {
            mInputMethodDialogs.add(win);
            addWindowToListInOrderLocked(win, true);
            moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
            imMayMove = false;
        } else {
            addWindowToListInOrderLocked(win, true);
            if (type == TYPE_WALLPAPER) {
                mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            } else if ((attrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) {
                // If there is currently a wallpaper being shown, and
                // the base layer of the new window is below the current
                // layer of the target window, then adjust the wallpaper.
                // This is to avoid a new window being placed between the
                // wallpaper and its target.
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            }
        }
        // If the window is being added to a task that's docked but non-resizeable,
        // we need to update this new window's scroll position when it's added.
        win.applyScrollIfNeeded();
        // If the window is being added to a stack that's currently adjusted for IME,
        // make sure to apply the same adjust to this new window.
        win.applyAdjustForImeIfNeeded();
        if (type == TYPE_DOCK_DIVIDER) {
            getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win);
        }
        final WindowStateAnimator winAnimator = win.mWinAnimator;
        winAnimator.mEnterAnimationPending = true;
        winAnimator.mEnteringAnimation = true;
        // Check if we need to prepare a transition for replacing window first.
        if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
            // If not, check if need to set up a dummy transition during display freeze
            // so that the unfreeze wait for the apps to draw. This might be needed if
            // the app is relaunching.
            prepareNoneTransitionForRelaunching(atoken);
        }
        if (displayContent.isDefaultDisplay) {
            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
            final Rect taskBounds;
            if (atoken != null && atoken.mTask != null) {
                taskBounds = mTmpRect;
                atoken.mTask.getBounds(mTmpRect);
            } else {
                taskBounds = null;
            }
            if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, mRotation, displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets, outStableInsets, outOutsets)) {
                res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
            }
        } else {
            outContentInsets.setEmpty();
            outStableInsets.setEmpty();
        }
        if (mInTouchMode) {
            res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
        }
        if (win.mAppToken == null || !win.mAppToken.clientHidden) {
            res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
        }
        mInputMonitor.setUpdateInputWindowsNeededLw();
        boolean focusChanged = false;
        if (win.canReceiveKeys()) {
            focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, false);
            if (focusChanged) {
                imMayMove = false;
            }
        }
        if (imMayMove) {
            moveInputMethodWindowsIfNeededLocked(false);
        }
        mLayersController.assignLayersLocked(displayContent.getWindowList());
        if (focusChanged) {
            mInputMonitor.setInputFocusLw(mCurrentFocus, false);
        }
        mInputMonitor.updateInputWindowsLw(false);
        if (localLOGV || DEBUG_ADD_REMOVE)
            Slog.v(TAG_WM, "addWindow: New client " + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
        if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
            reportNewConfig = true;
        }
    }
    if (reportNewConfig) {
        sendNewConfiguration();
    }
    Binder.restoreCallingIdentity(origId);
    return res;
}
Also used : Rect(android.graphics.Rect) DisplayInfo(android.view.DisplayInfo) Point(android.graphics.Point)

Aggregations

DisplayInfo (android.view.DisplayInfo)186 Point (android.graphics.Point)53 Rect (android.graphics.Rect)29 RemoteException (android.os.RemoteException)19 Display (android.view.Display)11 Animation (android.view.animation.Animation)10 Bitmap (android.graphics.Bitmap)9 WindowManager (android.view.WindowManager)8 DividerSnapAlgorithm (com.android.internal.policy.DividerSnapAlgorithm)8 Canvas (android.graphics.Canvas)6 SurfaceControl (android.view.SurfaceControl)6 LayoutParams (android.view.WindowManager.LayoutParams)6 DisplayManager (android.hardware.display.DisplayManager)5 DisplayMetrics (android.util.DisplayMetrics)5 Surface (android.view.Surface)5 InputDevice (android.view.InputDevice)4 SnapTarget (com.android.internal.policy.DividerSnapAlgorithm.SnapTarget)4 FileNotFoundException (java.io.FileNotFoundException)4 IOException (java.io.IOException)4 OutOfResourcesException (android.view.Surface.OutOfResourcesException)3