diff options
-rw-r--r-- | core/java/android/content/res/CompatibilityInfo.java | 393 | ||||
-rw-r--r-- | core/java/android/content/res/Resources.java | 6 | ||||
-rw-r--r-- | core/java/android/util/DisplayMetrics.java | 29 | ||||
-rw-r--r-- | core/java/android/view/MotionEvent.java | 55 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 58 | ||||
-rw-r--r-- | core/java/android/view/View.java | 2 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 168 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 15 | ||||
-rw-r--r-- | core/java/android/widget/PopupWindow.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 30 |
10 files changed, 534 insertions, 224 deletions
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 680fef8..179b9bd 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -17,8 +17,15 @@ package android.content.res; import android.content.pm.ApplicationInfo; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.Region; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Gravity; +import android.view.MotionEvent; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; /** * CompatibilityInfo class keeps the information about compatibility mode that the application is @@ -27,6 +34,9 @@ import android.view.Gravity; * {@hide} */ public class CompatibilityInfo { + private static final boolean DBG = false; + private static final String TAG = "CompatibilityInfo"; + /** default compatibility info object for compatible applications */ public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); @@ -41,36 +51,75 @@ public class CompatibilityInfo { public static final int DEFAULT_PORTRAIT_HEIGHT = 480; /** - * Application's scale. + * The x-shift mode that controls the position of the content or the window under + * compatibility mode. + * {@see getTranslator} + * {@see Translator#mShiftMode} */ - public final float mApplicationScale; + private static final int X_SHIFT_NONE = 0; + private static final int X_SHIFT_CONTENT = 1; + private static final int X_SHIFT_AND_CLIP_CONTENT = 2; + private static final int X_SHIFT_WINDOW = 3; + /** - * Application's inverted scale. + * A compatibility flags */ - public final float mApplicationInvertedScale; + private int compatibilityFlags; /** - * A boolean flag to indicates that the application can expand over the original size. + * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f) + * {@see compatibilityFlag} + */ + private static final int SCALING_REQUIRED = 1; + + /** + * A flag mask to indicates that the application can expand over the original size. * The flag is set to true if * 1) Application declares its expandable in manifest file using <expandable /> or * 2) The screen size is same as (320 x 480) * density. + * {@see compatibilityFlag} + */ + private static final int EXPANDABLE = 2; + + /** + * A flag mask to tell if the application is configured to be expandable. This differs + * from EXPANDABLE in that the application that is not expandable will be + * marked as expandable if it runs in (320x 480) * density screen size. + */ + private static final int CONFIGURED_EXPANDABLE = 4; + + private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE; + + /** + * Application's scale. */ - public boolean mExpandable; + public final float applicationScale; /** - * A expandable flag in the configuration. + * Application's inverted scale. */ - public final boolean mConfiguredExpandable; + public final float applicationInvertedScale; + + + /** + * Window size in Compatibility Mode, in real pixels. This is updated by + * {@link DisplayMetrics#updateMetrics}. + */ + private int mWidth; + private int mHeight; /** - * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f) + * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added + * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset + * is used to translate the Canvas. */ - public final boolean mScalingRequired; + private int mXOffset; public CompatibilityInfo(ApplicationInfo appInfo) { - mExpandable = mConfiguredExpandable = - (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0; + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE; + } float packageDensityScale = -1.0f; if (appInfo.supportsDensities != null) { @@ -93,23 +142,323 @@ public class CompatibilityInfo { } } if (packageDensityScale > 0.0f) { - mApplicationScale = packageDensityScale; + applicationScale = packageDensityScale; } else { - mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; + applicationScale = + DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; + } + applicationInvertedScale = 1.0f / applicationScale; + if (applicationScale != 1.0f) { + compatibilityFlags |= SCALING_REQUIRED; } - mApplicationInvertedScale = 1.0f / mApplicationScale; - mScalingRequired = mApplicationScale != 1.0f; } private CompatibilityInfo() { - mApplicationScale = mApplicationInvertedScale = 1.0f; - mExpandable = mConfiguredExpandable = true; - mScalingRequired = false; + applicationScale = applicationInvertedScale = 1.0f; + compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE; } + /** + * Sets the application's visible rect in compatibility mode. + * @param xOffset the application's x offset that is added to center the content. + * @param widthPixels the application's width in real pixels on the screen. + * @param heightPixels the application's height in real pixels on the screen. + */ + public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) { + this.mXOffset = xOffset; + mWidth = widthPixels; + mHeight = heightPixels; + } + + /** + * Sets expandable bit in the compatibility flag. + */ + public void setExpandable(boolean expandable) { + if (expandable) { + compatibilityFlags |= CompatibilityInfo.EXPANDABLE; + } else { + compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE; + } + } + + /** + * @return true if the application is configured to be expandable. + */ + public boolean isConfiguredExpandable() { + return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0; + } + + /** + * @return true if the scaling is required + */ + public boolean isScalingRequired() { + return (compatibilityFlags & SCALING_REQUIRED) != 0; + } + @Override public String toString() { - return "CompatibilityInfo{scale=" + mApplicationScale + - ", expandable=" + mExpandable + "}"; + return "CompatibilityInfo{scale=" + applicationScale + + ", compatibility flag=" + compatibilityFlags + "}"; + } + + /** + * Returns the translator which can translate the coordinates of the window. + * There are five different types of Translator. + * + * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT} + * Shift and clip the content of the window at drawing time. Used for activities' + * main window (with no gravity). + * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT} + * Shift the content of the window at drawing time. Used for windows that is created by + * an application and expected to be aligned with the application window. + * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW} + * Create the window with adjusted x- coordinates. This is typically used + * in popup window, where it has to be placed relative to main window. + * 4) {@link CompatibilityInfo#X_SHIFT_NONE} + * No adjustment required, such as dialog. + * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which + * does not require scaling, but its window's location has to be adjusted. + * + * @param params the window's parameter + */ + public Translator getTranslator(WindowManager.LayoutParams params) { + if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK) + == CompatibilityInfo.EXPANDABLE) { + if (DBG) Log.d(TAG, "no translation required"); + return null; + } + + if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) { + if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) { + if (DBG) Log.d(TAG, "translation for surface view selected"); + return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f); + } else { + int shiftMode; + if (params.gravity == Gravity.NO_GRAVITY) { + // For Regular Application window + shiftMode = X_SHIFT_AND_CLIP_CONTENT; + if (DBG) Log.d(TAG, "shift and clip translator"); + } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) { + // For Regular Application window + shiftMode = X_SHIFT_CONTENT; + if (DBG) Log.d(TAG, "shift content translator"); + } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) { + shiftMode = X_SHIFT_WINDOW; + if (DBG) Log.d(TAG, "shift window translator"); + } else { + shiftMode = X_SHIFT_NONE; + if (DBG) Log.d(TAG, "no content/window translator"); + } + return new Translator(shiftMode); + } + } else if (isScalingRequired()) { + return new Translator(); + } else { + return null; + } + } + + /** + * A helper object to translate the screen and window coordinates back and forth. + * @hide + */ + public class Translator { + final private int mShiftMode; + final public boolean scalingRequired; + final public float applicationScale; + final public float applicationInvertedScale; + + private Rect mContentInsetsBuffer = null; + private Rect mVisibleInsets = null; + + Translator(int shiftMode, boolean scalingRequired, float applicationScale, + float applicationInvertedScale) { + mShiftMode = shiftMode; + this.scalingRequired = scalingRequired; + this.applicationScale = applicationScale; + this.applicationInvertedScale = applicationInvertedScale; + } + + Translator(int shiftMode) { + this(shiftMode, + isScalingRequired(), + CompatibilityInfo.this.applicationScale, + CompatibilityInfo.this.applicationInvertedScale); + } + + Translator() { + this(X_SHIFT_NONE); + } + + /** + * Translate the screen rect to the application frame. + */ + public void translateRectInScreenToAppWinFrame(Rect rect) { + if (rect.isEmpty()) return; // skip if the window size is empty. + switch (mShiftMode) { + case X_SHIFT_AND_CLIP_CONTENT: + rect.intersect(0, 0, mWidth, mHeight); + break; + case X_SHIFT_CONTENT: + rect.intersect(0, 0, mWidth + mXOffset, mHeight); + break; + case X_SHIFT_WINDOW: + case X_SHIFT_NONE: + break; + } + if (scalingRequired) { + rect.scale(applicationInvertedScale); + } + } + + /** + * Translate the region in window to screen. + */ + public void translateRegionInWindowToScreen(Region transparentRegion) { + switch (mShiftMode) { + case X_SHIFT_AND_CLIP_CONTENT: + case X_SHIFT_CONTENT: + transparentRegion.scale(applicationScale); + transparentRegion.translate(mXOffset, 0); + break; + case X_SHIFT_WINDOW: + case X_SHIFT_NONE: + transparentRegion.scale(applicationScale); + } + } + + /** + * Apply translation to the canvas that is necessary to draw the content. + */ + public void translateCanvas(Canvas canvas) { + if (mShiftMode == X_SHIFT_CONTENT || + mShiftMode == X_SHIFT_AND_CLIP_CONTENT) { + // TODO: clear outside when rotation is changed. + + // Translate x-offset only when the content is shifted. + canvas.translate(mXOffset, 0); + } + if (scalingRequired) { + canvas.scale(applicationScale, applicationScale); + } + } + + /** + * Translate the motion event captured on screen to the application's window. + */ + public void translateEventInScreenToAppWindow(MotionEvent event) { + if (mShiftMode == X_SHIFT_CONTENT || + mShiftMode == X_SHIFT_AND_CLIP_CONTENT) { + event.translate(-mXOffset, 0); + } + if (scalingRequired) { + event.scale(applicationInvertedScale); + } + } + + /** + * Translate the window's layout parameter, from application's view to + * Screen's view. + */ + public void translateWindowLayout(WindowManager.LayoutParams params) { + switch (mShiftMode) { + case X_SHIFT_NONE: + case X_SHIFT_AND_CLIP_CONTENT: + case X_SHIFT_CONTENT: + params.scale(applicationScale); + break; + case X_SHIFT_WINDOW: + params.scale(applicationScale); + params.x += mXOffset; + break; + } + } + + /** + * Translate a Rect in application's window to screen. + */ + public void translateRectInAppWindowToScreen(Rect rect) { + // TODO Auto-generated method stub + if (scalingRequired) { + rect.scale(applicationScale); + } + switch(mShiftMode) { + case X_SHIFT_NONE: + case X_SHIFT_WINDOW: + break; + case X_SHIFT_CONTENT: + case X_SHIFT_AND_CLIP_CONTENT: + rect.offset(mXOffset, 0); + break; + } + } + + /** + * Translate a Rect in screen coordinates into the app window's coordinates. + */ + public void translateRectInScreenToAppWindow(Rect rect) { + switch (mShiftMode) { + case X_SHIFT_NONE: + case X_SHIFT_WINDOW: + break; + case X_SHIFT_CONTENT: { + rect.intersects(mXOffset, 0, rect.right, rect.bottom); + int dx = Math.min(mXOffset, rect.left); + rect.offset(-dx, 0); + break; + } + case X_SHIFT_AND_CLIP_CONTENT: { + rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight); + int dx = Math.min(mXOffset, rect.left); + rect.offset(-dx, 0); + break; + } + } + if (scalingRequired) { + rect.scale(applicationInvertedScale); + } + } + + /** + * Translate the location of the sub window. + * @param params + */ + public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) { + if (scalingRequired) { + params.scale(applicationScale); + } + switch (mShiftMode) { + // the window location on these mode does not require adjustmenet. + case X_SHIFT_NONE: + case X_SHIFT_WINDOW: + break; + case X_SHIFT_CONTENT: + case X_SHIFT_AND_CLIP_CONTENT: + params.x += mXOffset; + break; + } + } + + /** + * Translate the content insets in application window to Screen. This uses + * the internal buffer for content insets to avoid extra object allocation. + */ + public Rect getTranslatedContentInsets(Rect contentInsets) { + if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect(); + mContentInsetsBuffer.set(contentInsets); + translateRectInAppWindowToScreen(mContentInsetsBuffer); + return mContentInsetsBuffer; + } + + /** + * Translate the visible insets in application window to Screen. This uses + * the internal buffer for content insets to avoid extra object allocation. + */ + public Rect getTranslatedVisbileInsets(Rect visibleInsets) { + if (mVisibleInsets == null) mVisibleInsets = new Rect(); + mVisibleInsets.set(visibleInsets); + translateRectInAppWindowToScreen(mVisibleInsets); + return mVisibleInsets; + } } -} +}
\ No newline at end of file diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 71dbd38..cb9d46e 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -158,10 +158,10 @@ public class Resources { } updateConfiguration(config, metrics); assets.ensureStringBlocks(); - if (!mCompatibilityInfo.mScalingRequired) { - mPreloadedDrawables = sPreloadedDrawables; - } else { + if (mCompatibilityInfo.isScalingRequired()) { mPreloadedDrawables = emptySparseArray(); + } else { + mPreloadedDrawables = sPreloadedDrawables; } } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index a095913..d89ada0 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -106,16 +106,8 @@ public class DisplayMetrics { * {@hide} */ public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) { - if (compatibilityInfo.mScalingRequired) { - float invertedRatio = compatibilityInfo.mApplicationInvertedScale; - density *= invertedRatio; - scaledDensity *= invertedRatio; - xdpi *= invertedRatio; - ydpi *= invertedRatio; - widthPixels *= invertedRatio; - heightPixels *= invertedRatio; - } - if (!compatibilityInfo.mConfiguredExpandable) { + int xOffset = 0; + if (!compatibilityInfo.isConfiguredExpandable()) { // Note: this assume that configuration is updated before calling // updateMetrics method. int defaultWidth; @@ -141,11 +133,13 @@ public class DisplayMetrics { if (defaultWidth == widthPixels && defaultHeight == heightPixels) { // the screen size is same as expected size. make it expandable - compatibilityInfo.mExpandable = true; + compatibilityInfo.setExpandable(true); } else { - compatibilityInfo.mExpandable = false; + compatibilityInfo.setExpandable(false); // adjust the size only when the device's screen is bigger. if (defaultWidth < widthPixels) { + // content/window's x offset in original pixels + xOffset = ((widthPixels - defaultWidth) / 2); widthPixels = defaultWidth; } if (defaultHeight < heightPixels) { @@ -153,8 +147,19 @@ public class DisplayMetrics { } } } + compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels); + if (compatibilityInfo.isScalingRequired()) { + float invertedRatio = compatibilityInfo.applicationInvertedScale; + density *= invertedRatio; + scaledDensity *= invertedRatio; + xdpi *= invertedRatio; + ydpi *= invertedRatio; + widthPixels *= invertedRatio; + heightPixels *= invertedRatio; + } } + @Override public String toString() { return "DisplayMetrics{density=" + density + ", width=" + widthPixels + ", height=" + heightPixels + ", scaledDensity=" + scaledDensity + diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index ca01448..a224ed3 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -212,28 +212,47 @@ public final class MotionEvent implements Parcelable { } /** - * Scales down the cood of this event by the given scale. + * Scales down the coordination of this event by the given scale. * * @hide */ public void scale(float scale) { - if (scale != 1.0f) { - mX *= scale; - mY *= scale; - mRawX *= scale; - mRawY *= scale; - mSize *= scale; - mXPrecision *= scale; - mYPrecision *= scale; - if (mHistory != null) { - float[] history = mHistory; - int length = history.length; - for (int i = 0; i < length; i += 4) { - history[i] *= scale; // X - // history[i + 2] == pressure - history[i + 1] *= scale; // Y - history[i + 3] *= scale; // Size, TODO: square this? - } + mX *= scale; + mY *= scale; + mRawX *= scale; + mRawY *= scale; + mSize *= scale; + mXPrecision *= scale; + mYPrecision *= scale; + if (mHistory != null) { + float[] history = mHistory; + int length = history.length; + for (int i = 0; i < length; i += 4) { + history[i] *= scale; // X + history[i + 1] *= scale; // Y + // no need to scale pressure ([i+2]) + history[i + 3] *= scale; // Size, TODO: square this? + } + } + } + + /** + * Translate the coordination of the event by given x and y. + * + * @hide + */ + public void translate(float dx, float dy) { + mX += dx; + mY += dy; + mRawX += dx; + mRawY += dx; + if (mHistory != null) { + float[] history = mHistory; + int length = history.length; + for (int i = 0; i < length; i += 4) { + history[i] += dx; // X + history[i + 1] += dy; // Y + // no need to translate pressure (i+2) and size (i+3) } } } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 082cca2..45b0f0a 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -18,6 +18,7 @@ package android.view; import android.content.Context; import android.content.res.CompatibilityInfo; +import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.PorterDuff; @@ -138,24 +139,21 @@ public class SurfaceView extends View { int mFormat = -1; int mType = -1; final Rect mSurfaceFrame = new Rect(); - private final CompatibilityInfo mCompatibilityInfo; + private Translator mTranslator; public SurfaceView(Context context) { super(context); setWillNotDraw(true); - mCompatibilityInfo = context.getResources().getCompatibilityInfo(); } public SurfaceView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(true); - mCompatibilityInfo = context.getResources().getCompatibilityInfo(); } public SurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setWillNotDraw(true); - mCompatibilityInfo = context.getResources().getCompatibilityInfo(); } /** @@ -258,9 +256,9 @@ public class SurfaceView extends View { public boolean dispatchTouchEvent(MotionEvent event) { // SurfaceView uses pre-scaled size unless fixed size is requested. This hook // scales the event back to the pre-scaled coordinates for such surface. - if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) { + if (mRequestedWidth < 0 && mTranslator != null) { MotionEvent scaledBack = MotionEvent.obtain(event); - scaledBack.scale(mCompatibilityInfo.mApplicationScale); + scaledBack.scale(mTranslator.applicationScale); try { return super.dispatchTouchEvent(scaledBack); } finally { @@ -297,15 +295,18 @@ public class SurfaceView extends View { if (!mHaveFrame) { return; } - float appScale = mCompatibilityInfo.mApplicationScale; + mTranslator = ((ViewRoot)getRootView().getParent()).mTranslator; + + float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale; int myWidth = mRequestedWidth; if (myWidth <= 0) myWidth = getWidth(); int myHeight = mRequestedHeight; if (myHeight <= 0) myHeight = getHeight(); - // Use original size for surface unless fixed size is requested. - if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) { + // Use original size if the app specified the size of the view, + // and let the flinger to scale up. + if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) { myWidth *= appScale; myHeight *= appScale; } @@ -325,7 +326,7 @@ public class SurfaceView extends View { + " visible=" + visibleChanged + " left=" + (mLeft != mLocation[0]) + " top=" + (mTop != mLocation[1])); - + try { final boolean visible = mVisible = mRequestedVisible; mLeft = mLocation[0]; @@ -335,16 +336,23 @@ public class SurfaceView extends View { mFormat = mRequestedFormat; mType = mRequestedType; - // Scaling window's layout here because mLayout is not used elsewhere. - mLayout.x = (int) (mLeft * appScale); - mLayout.y = (int) (mTop * appScale); - mLayout.width = (int) (getWidth() * appScale); - mLayout.height = (int) (getHeight() * appScale); + // Scaling/Translate window's layout here because mLayout is not used elsewhere. + + // Places the window relative + mLayout.x = mLeft; + mLayout.y = mTop; + mLayout.width = getWidth(); + mLayout.height = getHeight(); + if (mTranslator != null) { + mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout); + } + mLayout.format = mRequestedFormat; mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_SCALED | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING ; mLayout.memoryType = mRequestedType; @@ -371,13 +379,6 @@ public class SurfaceView extends View { visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets, mVisibleInsets, mSurface); - if (mCompatibilityInfo.mScalingRequired) { - float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; - mContentInsets.scale(invertedScale); - mVisibleInsets.scale(invertedScale); - mWinFrame.scale(invertedScale); - } - if (localLOGV) Log.i(TAG, "New surface: " + mSurface + ", vis=" + visible + ", frame=" + mWinFrame); mSurfaceFrame.left = 0; @@ -446,24 +447,14 @@ public class SurfaceView extends View { private static class MyWindow extends IWindow.Stub { private final WeakReference<SurfaceView> mSurfaceView; - private final CompatibilityInfo mCompatibilityInfo; public MyWindow(SurfaceView surfaceView) { mSurfaceView = new WeakReference<SurfaceView>(surfaceView); - mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo(); } public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw) { SurfaceView surfaceView = mSurfaceView.get(); - if (mCompatibilityInfo.mScalingRequired) { - float scale = mCompatibilityInfo.mApplicationInvertedScale; - w *= scale; - h *= scale; - coveredInsets.scale(scale); - visibleInsets.scale(scale); - } - if (surfaceView != null) { if (localLOGV) Log.v( "SurfaceView", surfaceView + " got resized: w=" + @@ -626,9 +617,6 @@ public class SurfaceView extends View { Canvas c = null; if (!mDrawingStopped && mWindow != null) { Rect frame = dirty != null ? dirty : mSurfaceFrame; - if (mCompatibilityInfo.mScalingRequired) { - frame.scale(mCompatibilityInfo.mApplicationScale); - } try { c = mSurface.lockCanvas(frame); } catch (Exception e) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f17f0e4..3bfdde8 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6543,7 +6543,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility boolean changed = false; if (DBG) { - System.out.println(this + " View.setFrame(" + left + "," + top + "," + Log.d("View", this + " View.setFrame(" + left + "," + top + "," + right + "," + bottom + ")"); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index d35b048..65457c5 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -128,13 +128,12 @@ public final class ViewRoot extends Handler implements ViewParent, Rect mDirty; // will be a graphics.Region soon boolean mIsAnimating; - private CompatibilityInfo mCompatibilityInfo; + CompatibilityInfo.Translator mTranslator; final View.AttachInfo mAttachInfo; final Rect mTempRect; // used in the transaction to not thrash the heap. final Rect mVisRect; // used to retrieve visible rect of focused view. - final Point mVisPoint; // used to retrieve global offset of focused view. boolean mTraversalScheduled; boolean mWillDrawSoon; @@ -218,7 +217,6 @@ public final class ViewRoot extends Handler implements ViewParent, mDirty = new Rect(); mTempRect = new Rect(); mVisRect = new Rect(); - mVisPoint = new Point(); mWinFrame = new Rect(); mWindow = new W(this, context); mInputMethodCallback = new InputMethodCallback(this); @@ -387,20 +385,25 @@ public final class ViewRoot extends Handler implements ViewParent, if (mView == null) { mView = view; mWindowAttributes.copyFrom(attrs); - mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo(); + + CompatibilityInfo compatibilityInfo = + mView.getContext().getResources().getCompatibilityInfo(); + mTranslator = compatibilityInfo.getTranslator(attrs); boolean restore = false; - if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) { + if (attrs != null && mTranslator != null) { restore = true; - mWindowAttributes.backup(); - } - if (!mCompatibilityInfo.mExpandable) { - adjustWindowAttributesForCompatibleMode(mWindowAttributes); + attrs.backup(); + mTranslator.translateWindowLayout(attrs); } + if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs); + mSoftInputMode = attrs.softInputMode; mWindowAttributesChanged = true; mAttachInfo.mRootView = view; - mAttachInfo.mScalingRequired = mCompatibilityInfo.mScalingRequired; - mAttachInfo.mApplicationScale = mCompatibilityInfo.mApplicationScale; + mAttachInfo.mScalingRequired = + mTranslator == null ? false : mTranslator.scalingRequired; + mAttachInfo.mApplicationScale = + mTranslator == null ? 1.0f : mTranslator.applicationScale; if (panelParentView != null) { mAttachInfo.mPanelParentWindowToken = panelParentView.getApplicationWindowToken(); @@ -421,15 +424,14 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mRootView = null; unscheduleTraversals(); throw new RuntimeException("Adding window failed", e); + } finally { + if (restore) { + attrs.restore(); + } } - if (restore) { - mWindowAttributes.restore(); - } - - if (mCompatibilityInfo.mScalingRequired) { - mAttachInfo.mContentInsets.scale( - mCompatibilityInfo.mApplicationInvertedScale); + if (mTranslator != null) { + mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets); } mPendingContentInsets.set(mAttachInfo.mContentInsets); mPendingVisibleInsets.set(0, 0, 0, 0); @@ -541,14 +543,14 @@ public final class ViewRoot extends Handler implements ViewParent, public void invalidateChild(View child, Rect dirty) { checkThread(); - if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty); - if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) { + if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty); + if (mCurScrollY != 0 || mTranslator != null) { mTempRect.set(dirty); if (mCurScrollY != 0) { mTempRect.offset(0, -mCurScrollY); } - if (mCompatibilityInfo.mScalingRequired) { - mTempRect.scale(mCompatibilityInfo.mApplicationScale); + if (mTranslator != null) { + mTranslator.translateRectInAppWindowToScreen(mTempRect); } dirty = mTempRect; } @@ -567,7 +569,7 @@ public final class ViewRoot extends Handler implements ViewParent, return null; } - public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { + public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { if (child != mView) { throw new RuntimeException("child is not mine, honest!"); } @@ -628,14 +630,14 @@ public final class ViewRoot extends Handler implements ViewParent, boolean viewVisibilityChanged = mViewVisibility != viewVisibility || mNewSurfaceNeeded; - float appScale = mCompatibilityInfo.mApplicationScale; + float appScale = mAttachInfo.mApplicationScale; WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; params = lp; } - + Rect frame = mWinFrame; if (mFirst) { fullRedrawNeeded = true; mLayoutRequested = true; @@ -660,11 +662,11 @@ public final class ViewRoot extends Handler implements ViewParent, //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn); } else { - desiredWindowWidth = mWinFrame.width(); - desiredWindowHeight = mWinFrame.height(); + desiredWindowWidth = frame.width(); + desiredWindowHeight = frame.height(); if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) { if (DEBUG_ORIENTATION) Log.v("ViewRoot", - "View " + host + " resized to: " + mWinFrame); + "View " + host + " resized to: " + frame); fullRedrawNeeded = true; mLayoutRequested = true; windowResizesToFitContent = true; @@ -810,7 +812,6 @@ public final class ViewRoot extends Handler implements ViewParent, } } - final Rect frame = mWinFrame; boolean initialized = false; boolean contentInsetsChanged = false; boolean visibleInsetsChanged; @@ -883,7 +884,7 @@ public final class ViewRoot extends Handler implements ViewParent, } catch (RemoteException e) { } if (DEBUG_ORIENTATION) Log.v( - "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface); + "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface); attachInfo.mWindowLeft = frame.left; attachInfo.mWindowTop = frame.top; @@ -958,7 +959,6 @@ public final class ViewRoot extends Handler implements ViewParent, if (Config.DEBUG && ViewDebug.profileLayout) { startTime = SystemClock.elapsedRealtime(); } - host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight); if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { @@ -985,7 +985,10 @@ public final class ViewRoot extends Handler implements ViewParent, mTmpLocation[1] + host.mBottom - host.mTop); host.gatherTransparentRegion(mTransparentRegion); - mTransparentRegion.scale(appScale); + if (mTranslator != null) { + mTranslator.translateRegionInWindowToScreen(mTransparentRegion); + } + if (!mTransparentRegion.equals(mPreviousTransparentRegion)) { mPreviousTransparentRegion.set(mTransparentRegion); // reconfigure window manager @@ -1016,15 +1019,17 @@ public final class ViewRoot extends Handler implements ViewParent, = givenContent.bottom = givenVisible.left = givenVisible.top = givenVisible.right = givenVisible.bottom = 0; attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); - if (mCompatibilityInfo.mScalingRequired) { - insets.contentInsets.scale(appScale); - insets.visibleInsets.scale(appScale); + Rect contentInsets = insets.contentInsets; + Rect visibleInsets = insets.visibleInsets; + if (mTranslator != null) { + contentInsets = mTranslator.getTranslatedContentInsets(contentInsets); + visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets); } if (insetsPending || !mLastGivenInsets.equals(insets)) { mLastGivenInsets.set(insets); try { sWindowSession.setInsets(mWindow, insets.mTouchableInsets, - insets.contentInsets, insets.visibleInsets); + contentInsets, visibleInsets); } catch (RemoteException e) { } } @@ -1167,8 +1172,8 @@ public final class ViewRoot extends Handler implements ViewParent, mCurScrollY = yoff; fullRedrawNeeded = true; } - float appScale = mCompatibilityInfo.mApplicationScale; - boolean scalingRequired = mCompatibilityInfo.mScalingRequired; + float appScale = mAttachInfo.mApplicationScale; + boolean scalingRequired = mAttachInfo.mScalingRequired; Rect dirty = mDirty; if (mUseGL) { @@ -1187,8 +1192,8 @@ public final class ViewRoot extends Handler implements ViewParent, int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); - if (scalingRequired) { - canvas.scale(appScale, appScale); + if (mTranslator != null) { + mTranslator.translateCanvas(canvas); } mView.draw(canvas); if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { @@ -1239,7 +1244,6 @@ public final class ViewRoot extends Handler implements ViewParent, int top = dirty.top; int right = dirty.right; int bottom = dirty.bottom; - canvas = surface.lockCanvas(dirty); if (left != dirty.left || top != dirty.top || right != dirty.right || @@ -1295,8 +1299,8 @@ public final class ViewRoot extends Handler implements ViewParent, int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); - if (scalingRequired) { - canvas.scale(appScale, appScale); + if (mTranslator != null) { + mTranslator.translateCanvas(canvas); } mView.draw(canvas); } finally { @@ -1599,10 +1603,9 @@ public final class ViewRoot extends Handler implements ViewParent, } else { didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE; } - if (event != null && mCompatibilityInfo.mScalingRequired) { - event.scale(mCompatibilityInfo.mApplicationInvertedScale); + if (event != null && mTranslator != null) { + mTranslator.translateEventInScreenToAppWindow(event); } - try { boolean handled; if (mView != null && mAdded && event != null) { @@ -1688,6 +1691,7 @@ public final class ViewRoot extends Handler implements ViewParent, case RESIZED: Rect coveredInsets = ((Rect[])msg.obj)[0]; Rect visibleInsets = ((Rect[])msg.obj)[1]; + if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2 && mPendingContentInsets.equals(coveredInsets) && mPendingVisibleInsets.equals(visibleInsets)) { @@ -1722,7 +1726,7 @@ public final class ViewRoot extends Handler implements ViewParent, if (mGlWanted && !mUseGL) { initializeGL(); if (mGlCanvas != null) { - float appScale = mCompatibilityInfo.mApplicationScale; + float appScale = mAttachInfo.mApplicationScale; mGlCanvas.setViewport( (int) (mWidth * appScale), (int) (mHeight * appScale)); } @@ -2356,18 +2360,16 @@ public final class ViewRoot extends Handler implements ViewParent, private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException { + + float appScale = mAttachInfo.mApplicationScale; boolean restore = false; - float appScale = mCompatibilityInfo.mApplicationScale; - boolean scalingRequired = mCompatibilityInfo.mScalingRequired; - if (params != null && !mCompatibilityInfo.mExpandable) { + if (params != null && mTranslator != null) { restore = true; params.backup(); - adjustWindowAttributesForCompatibleMode(params); + mTranslator.translateWindowLayout(params); } - if (params != null && scalingRequired) { - if (!restore) params.backup(); - restore = true; - params.scale(appScale); + if (params != null) { + if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params); } int relayoutResult = sWindowSession.relayout( mWindow, params, @@ -2378,44 +2380,16 @@ public final class ViewRoot extends Handler implements ViewParent, if (restore) { params.restore(); } - if (scalingRequired) { - float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; - mPendingContentInsets.scale(invertedScale); - mPendingVisibleInsets.scale(invertedScale); - mWinFrame.scale(invertedScale); + + if (mTranslator != null) { + mTranslator.translateRectInScreenToAppWinFrame(mWinFrame); + mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets); + mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets); } return relayoutResult; } /** - * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT - * with the default window size, and centers if the window wanted to fill - * horizontally. - * - * @param attrs the window's layout params to adjust - */ - private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) { - // fix app windows only - if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics(); - // TODO: improve gravity logic - if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) { - attrs.width = metrics.widthPixels; - attrs.gravity |= Gravity.CENTER_HORIZONTAL; - mWindowAttributesChanged = attrs == mWindowAttributes; - } - if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) { - attrs.height = metrics.heightPixels; - attrs.gravity |= Gravity.TOP; - mWindowAttributesChanged = attrs == mWindowAttributes; - } - if (DEBUG_LAYOUT) { - Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs); - } - } - } - - /** * {@inheritDoc} */ public void playSoundEffect(int effectId) { @@ -2518,16 +2492,14 @@ public final class ViewRoot extends Handler implements ViewParent, + " visibleInsets=" + visibleInsets.toShortString() + " reportDraw=" + reportDraw); Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED); - if (mCompatibilityInfo.mScalingRequired) { - float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; - coveredInsets.scale(invertedScale); - visibleInsets.scale(invertedScale); - msg.arg1 = (int) (w * invertedScale); - msg.arg2 = (int) (h * invertedScale); - } else { - msg.arg1 = w; - msg.arg2 = h; - } + if (mTranslator != null) { + mTranslator.translateRectInScreenToAppWindow(coveredInsets); + mTranslator.translateRectInScreenToAppWindow(visibleInsets); + w *= mTranslator.applicationInvertedScale; + h *= mTranslator.applicationInvertedScale; + } + msg.arg1 = w; + msg.arg2 = h; msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) }; sendMessage(msg); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e295d15..bdb86d7 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -483,6 +483,12 @@ public interface WindowManager extends ViewManager { * {@hide} */ public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; + /** Window flag: special flag to let a window ignore the compatibility scaling. + * This is used by SurfaceView to create a window that does not scale the content. + * + * {@hide} */ + public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000; + /** Window flag: a special option intended for system dialogs. When * this flag is set, the window will demand focus unconditionally when * it is created. @@ -978,8 +984,9 @@ public interface WindowManager extends ViewManager { /** * Scale the layout params' coordinates and size. + * @hide */ - void scale(float scale) { + public void scale(float scale) { x *= scale; y *= scale; if (width > 0) { @@ -997,14 +1004,13 @@ public interface WindowManager extends ViewManager { void backup() { int[] backup = mCompatibilityParamsBackup; if (backup == null) { - // we backup 5 elements, x, y, width, height and gravity. - backup = mCompatibilityParamsBackup = new int[5]; + // we backup 4 elements, x, y, width, height + backup = mCompatibilityParamsBackup = new int[4]; } backup[0] = x; backup[1] = y; backup[2] = width; backup[3] = height; - backup[4] = gravity; } /** @@ -1018,7 +1024,6 @@ public interface WindowManager extends ViewManager { y = backup[1]; width = backup[2]; height = backup[3]; - gravity = backup[4]; } } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index bd6edfb..0c2cd55 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -990,7 +990,7 @@ public class PopupWindow { int bottomEdge = displayFrame.bottom; if (ignoreBottomDecorations) { - bottomEdge = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight(); + bottomEdge = anchor.getContext().getResources().getDisplayMetrics().heightPixels; } final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset; final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset; diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 048669a..972aa98 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -968,35 +968,7 @@ class PackageManagerService extends IPackageManager.Stub { if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a); if (a != null && mSettings.isEnabledLP(a.info, flags)) { - ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags); - if (ainfo != null) { - ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(), - PackageManager.GET_SUPPORTS_DENSITIES); - if (appInfo != null && - (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) == 0) { - // Check if the screen size is same as what the application expect. - CompatibilityInfo info = new CompatibilityInfo(appInfo); - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setTo(mMetrics); - int orientation = mMetrics.widthPixels > mMetrics.heightPixels ? - Configuration.ORIENTATION_LANDSCAPE : - Configuration.ORIENTATION_PORTRAIT; - metrics.updateMetrics(info, orientation); - if (!info.mExpandable) { - // Don't allow an app that cannot expand to handle rotation. - ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION; - } else { - appInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; - } - if (DEBUG_SETTINGS) { - Log.d(TAG, "component=" + component + - ", expandable:" + - ((appInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0)); - } - } - } - return ainfo; + return PackageParser.generateActivityInfo(a, flags); } if (mResolveComponentName.equals(component)) { return mResolveActivity; |