From 7916ac65dc492e4e1431879875c77d7121fbf82e Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 16 May 2011 20:45:48 -0700 Subject: Add new command line option to change global screen size. For example: adb shell am display-size 1024x600 Change-Id: I5df462acd3323bdaaaefa3126faea7dd8595b726 --- .../java/com/android/server/wm/BlackFrame.java | 139 +++++++++++++++ .../android/server/wm/ScreenRotationAnimation.java | 72 ++------ .../android/server/wm/WindowManagerService.java | 192 +++++++++++++++++---- 3 files changed, 308 insertions(+), 95 deletions(-) create mode 100644 services/java/com/android/server/wm/BlackFrame.java (limited to 'services') diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java new file mode 100644 index 0000000..f9f5758 --- /dev/null +++ b/services/java/com/android/server/wm/BlackFrame.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 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 android.graphics.Matrix; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.util.Slog; +import android.view.Surface; +import android.view.SurfaceSession; + +/** + * Four black surfaces put together to make a black frame. + */ +public class BlackFrame { + class BlackSurface { + final int left; + final int top; + final Surface surface; + + BlackSurface(SurfaceSession session, int layer, int l, int t, int w, int h) + throws Surface.OutOfResourcesException { + left = l; + top = t; + surface = new Surface(session, 0, "BlackSurface", + -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM); + surface.setAlpha(1.0f); + surface.setLayer(layer); + } + + void setMatrix(Matrix matrix) { + mTmpMatrix.setTranslate(left, top); + mTmpMatrix.postConcat(matrix); + mTmpMatrix.getValues(mTmpFloats); + surface.setPosition((int)mTmpFloats[Matrix.MTRANS_X], + (int)mTmpFloats[Matrix.MTRANS_Y]); + surface.setMatrix( + mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], + mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); + if (false) { + Slog.i(WindowManagerService.TAG, "Black Surface @ (" + left + "," + top + "): (" + + mTmpFloats[Matrix.MTRANS_X] + "," + + mTmpFloats[Matrix.MTRANS_Y] + ") matrix=[" + + mTmpFloats[Matrix.MSCALE_X] + "," + + mTmpFloats[Matrix.MSCALE_Y] + "][" + + mTmpFloats[Matrix.MSKEW_X] + "," + + mTmpFloats[Matrix.MSKEW_Y] + "]"); + } + } + + void clearMatrix() { + surface.setMatrix(1, 0, 0, 1); + } + } + + final Matrix mTmpMatrix = new Matrix(); + final float[] mTmpFloats = new float[9]; + final BlackSurface[] mBlackSurfaces = new BlackSurface[4]; + + public BlackFrame(SurfaceSession session, Rect outer, Rect inner, + int layer) throws Surface.OutOfResourcesException { + boolean success = false; + + try { + if (outer.top < inner.top) { + mBlackSurfaces[0] = new BlackSurface(session, layer, + outer.left, outer.top, inner.right, inner.top); + } + if (outer.left < inner.left) { + mBlackSurfaces[1] = new BlackSurface(session, layer, + outer.left, inner.top, inner.left, outer.bottom); + } + if (outer.bottom > inner.bottom) { + mBlackSurfaces[2] = new BlackSurface(session, layer, + inner.left, inner.bottom, outer.right, outer.bottom); + } + if (outer.right > inner.right) { + mBlackSurfaces[3] = new BlackSurface(session, layer, + inner.right, outer.top, outer.right, inner.bottom); + } + success = true; + } finally { + if (!success) { + kill(); + } + } + } + + public void kill() { + if (mBlackSurfaces != null) { + for (int i=0; i>> OPEN TRANSACTION ScreenRotationAnimation.dismiss"); Surface.openTransaction(); - mBlackSurfaces = new BlackSurface[4]; try { final int w = mDisplayMetrics.widthPixels; final int h = mDisplayMetrics.heightPixels; - mBlackSurfaces[0] = new BlackSurface(session, FREEZE_LAYER, -w, -h, w, h*2); - mBlackSurfaces[1] = new BlackSurface(session, FREEZE_LAYER, 0, -h, w*2, h); - mBlackSurfaces[2] = new BlackSurface(session, FREEZE_LAYER, w, 0, w, h*2); - mBlackSurfaces[3] = new BlackSurface(session, FREEZE_LAYER, -w, h, w*2, h); + Rect outer = new Rect(-w, -h, w*2, h*2); + Rect inner = new Rect(0, 0, w, h); + mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER); } catch (Surface.OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); } finally { @@ -326,13 +287,8 @@ class ScreenRotationAnimation { mSurface.destroy(); mSurface = null; } - if (mBlackSurfaces != null) { - for (int i=0; i=0; i--) { @@ -5484,8 +5509,8 @@ public class WindowManagerService extends IWindowManager.Stub // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270); - final int realdw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth; - final int realdh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight; + final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; + final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; if (mAltOrientation) { mCurDisplayWidth = realdw; @@ -5922,8 +5947,18 @@ public class WindowManagerService extends IWindowManager.Stub } WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = wm.getDefaultDisplay(); - mInitialDisplayWidth = mCurDisplayWidth = mDisplay.getRealWidth(); - mInitialDisplayHeight = mCurDisplayHeight = mDisplay.getRealHeight(); + mInitialDisplayWidth = mDisplay.getRealWidth(); + mInitialDisplayHeight = mDisplay.getRealHeight(); + int rot = mDisplay.getRotation(); + if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { + // If the screen is currently rotated, we need to swap the + // initial width and height to get the true natural values. + int tmp = mInitialDisplayWidth; + mInitialDisplayWidth = mInitialDisplayHeight; + mInitialDisplayHeight = tmp; + } + mBaseDisplayWidth = mCurDisplayWidth = mInitialDisplayWidth; + mBaseDisplayHeight = mCurDisplayHeight = mInitialDisplayHeight; mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight()); mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight); } @@ -6429,8 +6464,88 @@ public class WindowManagerService extends IWindowManager.Stub public int getMaximumSizeDimension() { synchronized(mWindowMap) { // Do this based on the raw screen size, until we are smarter. - return mInitialDisplayWidth > mInitialDisplayHeight - ? mInitialDisplayWidth : mInitialDisplayHeight; + return mBaseDisplayWidth > mBaseDisplayHeight + ? mBaseDisplayWidth : mBaseDisplayHeight; + } + } + + public void setForcedDisplaySize(int longDimen, int shortDimen) { + synchronized(mWindowMap) { + int width, height; + if (mInitialDisplayWidth < mInitialDisplayHeight) { + width = shortDimen < mInitialDisplayWidth + ? shortDimen : mInitialDisplayWidth; + height = longDimen < mInitialDisplayHeight + ? longDimen : mInitialDisplayHeight; + } else { + width = longDimen < mInitialDisplayWidth + ? longDimen : mInitialDisplayWidth; + height = shortDimen < mInitialDisplayHeight + ? shortDimen : mInitialDisplayHeight; + } + setForcedDisplaySizeLocked(width, height); + } + } + + private void rebuildBlackFrame(boolean inTransaction) { + if (!inTransaction) { + if (SHOW_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION rebuildBlackFrame"); + Surface.openTransaction(); + } + try { + if (mBlackFrame != null) { + mBlackFrame.kill(); + mBlackFrame = null; + } + if (mBaseDisplayWidth < mInitialDisplayWidth + || mBaseDisplayHeight < mInitialDisplayHeight) { + Rect outer = new Rect(0, 0, mInitialDisplayWidth, mInitialDisplayHeight); + Rect inner = new Rect(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); + try { + mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); + } catch (Surface.OutOfResourcesException e) { + } + } + } finally { + if (!inTransaction) { + Surface.closeTransaction(); + if (SHOW_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION rebuildBlackFrame"); + } + } + } + + private void setForcedDisplaySizeLocked(int width, int height) { + mBaseDisplayWidth = width; + mBaseDisplayHeight = height; + mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight); + + mLayoutNeeded = true; + + boolean configChanged = updateOrientationFromAppTokensLocked(false); + mTempConfiguration.setToDefaults(); + mTempConfiguration.fontScale = mCurConfiguration.fontScale; + if (computeNewConfigurationLocked(mTempConfiguration)) { + if (mCurConfiguration.diff(mTempConfiguration) != 0) { + configChanged = true; + } + } + + if (configChanged) { + mWaitingForConfig = true; + startFreezingDisplayLocked(false); + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + + rebuildBlackFrame(false); + + performLayoutAndPlaceSurfacesLocked(); + } + + public void clearForcedDisplaySize() { + synchronized(mWindowMap) { + setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); } } @@ -7983,6 +8098,15 @@ public class WindowManagerService extends IWindowManager.Stub } mBlurShown = false; } + + if (mBlackFrame != null) { + if (mScreenRotationAnimation != null) { + mBlackFrame.setMatrix( + mScreenRotationAnimation.getEnterTransformation().getMatrix()); + } else { + mBlackFrame.clearMatrix(); + } + } } catch (RuntimeException e) { Slog.e(TAG, "Unhandled exception in Window Manager", e); } @@ -8836,7 +8960,9 @@ public class WindowManagerService extends IWindowManager.Stub } if (mDisplay != null) { pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); - pw.print(mInitialDisplayHeight); pw.print(" cur="); + pw.print(mInitialDisplayHeight); pw.print(" base="); + pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); + pw.print(" cur="); pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); pw.print(" real="); pw.print(mDisplay.getRealWidth()); pw.print("x"); pw.print(mDisplay.getRealHeight()); -- cgit v1.1