AI 147976: Compatibility mode support. Part 2.
* Introduced ApplicationScale (may not be good name. CompatibilityScale? CanvasScale? Pls let me know if you have better idea)
* Changes to RootView / SurfaceView
- Makes the app believe it's running in the supported density/resolution.
- Makes the window manager believe it's running at the right density/resolution.
* Added methods to Rect/Event for scaling up/down.
Known issues:
* certain kind of images (such as nine patch for buttons) seesm to be loaded not by app, thus does not take the scale into account,
which, in turn, is causing layout issue.
* ZoomButton in MapView is rendered in wrong place
* Transparent region on Surface is not correct
* Specifying different densities in one process is not working.
BUG=1770627
Automated import of CL 147976
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d816193..b7cd080 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -161,7 +161,7 @@
return metrics;
}
- Resources getTopLevelResources(String appDir) {
+ Resources getTopLevelResources(String appDir, float applicationScale) {
synchronized (mPackages) {
//Log.w(TAG, "getTopLevelResources: " + appDir);
WeakReference<Resources> wr = mActiveResources.get(appDir);
@@ -181,7 +181,27 @@
return null;
}
DisplayMetrics metrics = getDisplayMetricsLocked(false);
- r = new Resources(assets, metrics, getConfiguration());
+ // density used to load resources
+ // scaledDensity is calculated in Resources constructor
+ //
+ boolean usePreloaded = true;
+
+ // TODO: use explicit flag to indicate the compatibility mode.
+ if (applicationScale != 1.0f) {
+ usePreloaded = false;
+ DisplayMetrics newMetrics = new DisplayMetrics();
+ newMetrics.setTo(metrics);
+ float invertedScale = 1.0f / applicationScale;
+ newMetrics.density *= invertedScale;
+ newMetrics.xdpi *= invertedScale;
+ newMetrics.ydpi *= invertedScale;
+ newMetrics.widthPixels *= invertedScale;
+ newMetrics.heightPixels *= invertedScale;
+ metrics = newMetrics;
+ }
+ //Log.i(TAG, "Resource:" + appDir + ", density " + newMetrics.density + ", orig density:" +
+ // metrics.density);
+ r = new Resources(assets, metrics, getConfiguration(), usePreloaded);
//Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
// XXX need to remove entries when weak references go away
mActiveResources.put(appDir, new WeakReference<Resources>(r));
@@ -209,6 +229,8 @@
private Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
+ private float mApplicationScale;
+
private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
@@ -241,8 +263,8 @@
mSystemContext =
ApplicationContext.createSystemContext(mainThread);
mSystemContext.getResources().updateConfiguration(
- mainThread.getConfiguration(),
- mainThread.getDisplayMetricsLocked(false));
+ mainThread.getConfiguration(),
+ mainThread.getDisplayMetricsLocked(false));
//Log.i(TAG, "Created system resources "
// + mSystemContext.getResources() + ": "
// + mSystemContext.getResources().getConfiguration());
@@ -250,6 +272,8 @@
mClassLoader = mSystemContext.getClassLoader();
mResources = mSystemContext.getResources();
}
+
+ mApplicationScale = -1.0f;
}
public PackageInfo(ActivityThread activityThread, String name,
@@ -268,6 +292,7 @@
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
+ mApplicationScale = systemContext.getApplicationScale();
}
public String getPackageName() {
@@ -278,6 +303,47 @@
return mSecurityViolation;
}
+ public float getApplicationScale() {
+ if (mApplicationScale > 0.0f) {
+ return mApplicationScale;
+ }
+ DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false);
+ // Find out the density scale (relative to 160) of the supported density that
+ // is closest to the system's density.
+ try {
+ ApplicationInfo ai = getPackageManager().getApplicationInfo(
+ mPackageName, PackageManager.GET_SUPPORTS_DENSITIES);
+
+ float appScale = -1.0f;
+ if (ai.supportsDensities != null) {
+ // TODO: precompute this in DisplayMetrics
+ float systemDensityDpi = metrics.density * DisplayMetrics.DEFAULT_DENSITY;
+ int minDiff = Integer.MAX_VALUE;
+ for (int density : ai.supportsDensities) {
+ int tmpDiff = (int) Math.abs(systemDensityDpi - density);
+ if (tmpDiff == 0) {
+ appScale = 1.0f;
+ break;
+ }
+ // prefer higher density (appScale>1.0), unless that's only option.
+ if (tmpDiff < minDiff && appScale < 1.0f) {
+ appScale = systemDensityDpi / density;
+ minDiff = tmpDiff;
+ }
+ }
+ }
+ if (appScale < 0.0f) {
+ mApplicationScale = metrics.density;
+ } else {
+ mApplicationScale = appScale;
+ }
+ } catch (RemoteException e) {
+ throw new AssertionError(e);
+ }
+ if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName);
+ return mApplicationScale;
+ }
+
/**
* Gets the array of shared libraries that are listed as
* used by the given package.
@@ -435,7 +501,7 @@
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir);
+ mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale());
}
return mResources;
}
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 55fce49..a1f5a58 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -550,6 +550,19 @@
}
}
+ /**
+ * @hide
+ */
+ @Override
+ public float getApplicationScale() {
+ if (mPackageInfo != null) {
+ return mPackageInfo.getApplicationScale();
+ } else {
+ // same as system density
+ return 1.0f;
+ }
+ }
+
@Override
public void setWallpaper(Bitmap bitmap) throws IOException {
try {
@@ -2008,9 +2021,11 @@
if (app.packageName.equals("system")) {
return mContext.mMainThread.getSystemContext().getResources();
}
+ ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir
- : app.publicSourceDir);
+ : app.publicSourceDir,
+ pi.getApplicationScale());
if (r != null) {
return r;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 600dfa4..a301449 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -527,6 +527,16 @@
public abstract int getWallpaperDesiredMinimumHeight();
/**
+ * Returns the scale in which the application will be drawn on the
+ * screen. This is usually 1.0f if the application supports the device's
+ * resolution/density. This will be 1.5f, for example, if the application
+ * that supports only 160 density runs on 240 density screen.
+ *
+ * @hide
+ */
+ public abstract float getApplicationScale();
+
+ /**
* Change the current system wallpaper to a bitmap. The given bitmap is
* converted to a PNG and stored as the wallpaper. On success, the intent
* {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 36e1c34..25b2cae 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -419,4 +419,12 @@
throws PackageManager.NameNotFoundException {
return mBase.createPackageContext(packageName, flags);
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public float getApplicationScale() {
+ return mBase.getApplicationScale();
+ }
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e020462..665e40c 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -24,6 +24,7 @@
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.SystemProperties;
@@ -56,12 +57,14 @@
// Information about preloaded resources. Note that they are not
// protected by a lock, because while preloading in zygote we are all
// single-threaded, and after that these are immutable.
- private static final SparseArray<Drawable.ConstantState> mPreloadedDrawables
+ private static final SparseArray<Drawable.ConstantState> sPreloadedDrawables
= new SparseArray<Drawable.ConstantState>();
private static final SparseArray<ColorStateList> mPreloadedColorStateLists
= new SparseArray<ColorStateList>();
private static boolean mPreloaded;
+ private final SparseArray<Drawable.ConstantState> mPreloadedDrawables;
+
/*package*/ final TypedValue mTmpValue = new TypedValue();
// These are protected by the mTmpValue lock.
@@ -82,6 +85,22 @@
/*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
PluralRules mPluralRule;
+ private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
+ @Override
+ public void put(int k, Object o) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public void append(int k, Object o) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ @SuppressWarnings("unchecked")
+ private static <T> SparseArray<T> emptySparseArray() {
+ return (SparseArray<T>) EMPTY_ARRAY;
+ }
+
/**
* This exception is thrown by the resource APIs when a requested resource
* can not be found.
@@ -107,11 +126,27 @@
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
Configuration config) {
+ this(assets, metrics, config, true);
+ }
+
+ /**
+ * Create a resource with an additional flag for preloaded
+ * drawable cache. Used by {@link ActivityThread}.
+ *
+ * @hide
+ */
+ public Resources(AssetManager assets, DisplayMetrics metrics,
+ Configuration config, boolean usePreloadedCache) {
mAssets = assets;
mConfiguration.setToDefaults();
mMetrics.setToDefaults();
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
+ if (usePreloadedCache) {
+ mPreloadedDrawables = sPreloadedDrawables;
+ } else {
+ mPreloadedDrawables = emptySparseArray();
+ }
}
/**
@@ -1218,6 +1253,7 @@
mMetrics.setTo(metrics);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
String locale = null;
if (mConfiguration.locale != null) {
locale = mConfiguration.locale.getLanguage();
@@ -1653,7 +1689,7 @@
cs = dr.getConstantState();
if (cs != null) {
if (mPreloading) {
- mPreloadedDrawables.put(key, cs);
+ sPreloadedDrawables.put(key, cs);
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached drawable @ #" +
@@ -1883,6 +1919,6 @@
mMetrics.setToDefaults();
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
+ mPreloadedDrawables = sPreloadedDrawables;
}
}
-
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 882a079..2402660 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -102,7 +102,7 @@
private float mYPrecision;
private int mDeviceId;
private int mEdgeFlags;
-
+
private MotionEvent mNext;
private RuntimeException mRecycledLocation;
private boolean mRecycled;
@@ -210,7 +210,29 @@
return ev;
}
-
+
+ /**
+ * Scales down the cood 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;
+ float[] history = mHistory;
+ int length = history.length;
+ for (int i = 0; i < length; i++) {
+ history[i] *= scale;
+ }
+ }
+ }
+
/**
* Create a new MotionEvent, copying from an existing one.
*/
@@ -682,4 +704,3 @@
}
}
-
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index e928998..61dca4c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -135,20 +135,28 @@
int mFormat = -1;
int mType = -1;
final Rect mSurfaceFrame = new Rect();
+ private final float mAppScale;
+ private final float mAppScaleInverted;
public SurfaceView(Context context) {
super(context);
setWillNotDraw(true);
+ mAppScale = context.getApplicationScale();
+ mAppScaleInverted = 1.0f / mAppScale;
}
public SurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(true);
+ mAppScale = context.getApplicationScale();
+ mAppScaleInverted = 1.0f / mAppScale;
}
public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(true);
+ mAppScale = context.getApplicationScale();
+ mAppScaleInverted = 1.0f / mAppScale;
}
/**
@@ -297,8 +305,8 @@
mLayout.x = mLeft;
mLayout.y = mTop;
- mLayout.width = getWidth();
- mLayout.height = getHeight();
+ mLayout.width = (int) (getWidth() * mAppScale);
+ mLayout.height = (int) (getHeight() * mAppScale);
mLayout.format = mRequestedFormat;
mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_SCALED
@@ -325,9 +333,14 @@
mSurfaceLock.lock();
mDrawingStopped = !visible;
final int relayoutResult = mSession.relayout(
- mWindow, mLayout, mWidth, mHeight,
+ mWindow, mLayout, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale),
visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
mVisibleInsets, mSurface);
+
+ mContentInsets.scale(mAppScaleInverted);
+ mVisibleInsets.scale(mAppScaleInverted);
+ mWinFrame.scale(mAppScaleInverted);
+
if (localLOGV) Log.i(TAG, "New surface: " + mSurface
+ ", vis=" + visible + ", frame=" + mWinFrame);
mSurfaceFrame.left = 0;
@@ -395,15 +408,25 @@
}
private static class MyWindow extends IWindow.Stub {
- private WeakReference<SurfaceView> mSurfaceView;
+ private final WeakReference<SurfaceView> mSurfaceView;
+ private final float mAppScale;
+ private final float mAppScaleInverted;
public MyWindow(SurfaceView surfaceView) {
mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
+ mAppScale = surfaceView.getContext().getApplicationScale();
+ mAppScaleInverted = 1.0f / mAppScale;
}
public void resized(int w, int h, Rect coveredInsets,
Rect visibleInsets, boolean reportDraw) {
SurfaceView surfaceView = mSurfaceView.get();
+ float scale = mAppScaleInverted;
+ w *= scale;
+ h *= scale;
+ coveredInsets.scale(scale);
+ visibleInsets.scale(scale);
+
if (surfaceView != null) {
if (localLOGV) Log.v(
"SurfaceView", surfaceView + " got resized: w=" +
@@ -566,6 +589,7 @@
Canvas c = null;
if (!mDrawingStopped && mWindow != null) {
Rect frame = dirty != null ? dirty : mSurfaceFrame;
+ frame.scale(mAppScale);
try {
c = mSurface.lockCanvas(frame);
} catch (Exception e) {
@@ -611,4 +635,3 @@
}
};
}
-
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 18ee9ae..0b03626 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -128,6 +128,9 @@
int mHeight;
Rect mDirty; // will be a graphics.Region soon
boolean mIsAnimating;
+ // TODO: change these to scaler class.
+ float mAppScale;
+ float mAppScaleInverted; // = 1.0f / mAppScale
final View.AttachInfo mAttachInfo;
@@ -384,10 +387,12 @@
View panelParentView) {
synchronized (this) {
if (mView == null) {
+ mView = view;
+ mAppScale = mView.getContext().getApplicationScale();
+ mAppScaleInverted = 1.0f / mAppScale;
mWindowAttributes.copyFrom(attrs);
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
- mView = view;
mAttachInfo.mRootView = view;
if (panelParentView != null) {
mAttachInfo.mPanelParentWindowToken
@@ -400,7 +405,7 @@
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
-
+
try {
res = sWindowSession.add(mWindow, attrs,
getHostVisibility(), mAttachInfo.mContentInsets);
@@ -411,6 +416,7 @@
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
}
+ mAttachInfo.mContentInsets.scale(mAppScaleInverted);
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
@@ -472,6 +478,8 @@
synchronized (this) {
int oldSoftInputMode = mWindowAttributes.softInputMode;
mWindowAttributes.copyFrom(attrs);
+ mWindowAttributes.scale(mAppScale);
+
if (newView) {
mSoftInputMode = attrs.softInputMode;
requestLayout();
@@ -521,9 +529,14 @@
public void invalidateChild(View child, Rect dirty) {
checkThread();
if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
- if (mCurScrollY != 0) {
+ if (mCurScrollY != 0 || mAppScale != 1.0f) {
mTempRect.set(dirty);
- mTempRect.offset(0, -mCurScrollY);
+ if (mCurScrollY != 0) {
+ mTempRect.offset(0, -mCurScrollY);
+ }
+ if (mAppScale != 1.0f) {
+ mTempRect.scale(mAppScale);
+ }
dirty = mTempRect;
}
mDirty.union(dirty);
@@ -613,8 +626,8 @@
mLayoutRequested = true;
Display d = new Display(0);
- desiredWindowWidth = d.getWidth();
- desiredWindowHeight = d.getHeight();
+ desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
+ desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
// For the very first time, tell the view hierarchy that it
// is attached to the window. Note that at this point the surface
@@ -683,8 +696,8 @@
windowResizesToFitContent = true;
Display d = new Display(0);
- desiredWindowWidth = d.getWidth();
- desiredWindowHeight = d.getHeight();
+ desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
+ desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
}
}
@@ -792,10 +805,12 @@
params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
}
}
- relayoutResult = sWindowSession.relayout(
- mWindow, params, host.mMeasuredWidth, host.mMeasuredHeight,
- viewVisibility, insetsPending, frame,
- mPendingContentInsets, mPendingVisibleInsets, mSurface);
+ if (DEBUG_LAYOUT) {
+ Log.i(TAG, "host=w:" + host.mMeasuredWidth + ", h:" +
+ host.mMeasuredHeight + ", params=" + params);
+ }
+ relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
+
if (params != null) {
params.flags = fl;
}
@@ -862,7 +877,7 @@
mHeight = frame.height();
if (initialized) {
- mGlCanvas.setViewport(mWidth, mHeight);
+ mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
}
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -944,6 +959,11 @@
mTmpLocation[1] + host.mBottom - host.mTop);
host.gatherTransparentRegion(mTransparentRegion);
+
+ // TODO: scale the region, like:
+ // Region uses native methods. We probabl should have ScalableRegion class.
+
+ // Region does not have equals method ?
if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
mPreviousTransparentRegion.set(mTransparentRegion);
// reconfigure window manager
@@ -974,6 +994,9 @@
givenContent.left = givenContent.top = givenContent.right
= givenContent.bottom = givenVisible.left = givenVisible.top
= givenVisible.right = givenVisible.bottom = 0;
+ insets.contentInsets.scale(mAppScale);
+ insets.visibleInsets.scale(mAppScale);
+
attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
if (insetsPending || !mLastGivenInsets.equals(insets)) {
mLastGivenInsets.set(insets);
@@ -1113,7 +1136,7 @@
int yoff;
final boolean scrolling = mScroller != null
- && mScroller.computeScrollOffset();
+ && mScroller.computeScrollOffset();
if (scrolling) {
yoff = mScroller.getCurrY();
} else {
@@ -1135,10 +1158,19 @@
mGL.glEnable(GL_SCISSOR_TEST);
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
- canvas.translate(0, -yoff);
mView.mPrivateFlags |= View.DRAWN;
- mView.draw(canvas);
- canvas.translate(0, yoff);
+
+ float scale = mAppScale;
+ int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ try {
+ canvas.translate(0, -yoff);
+ if (scale != 1.0f) {
+ canvas.scale(scale, scale);
+ }
+ mView.draw(canvas);
+ } finally {
+ canvas.restoreToCount(saveCount);
+ }
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
checkEglErrors();
@@ -1160,7 +1192,7 @@
}
if (fullRedrawNeeded)
- dirty.union(0, 0, mWidth, mHeight);
+ dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Log.v("ViewRoot", "Draw " + mView + "/"
@@ -1212,10 +1244,24 @@
dirty.setEmpty();
mIsAnimating = false;
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
- canvas.translate(0, -yoff);
- mView.mPrivateFlags |= View.DRAWN;
- mView.draw(canvas);
- canvas.translate(0, yoff);
+ mView.mPrivateFlags |= View.DRAWN;
+
+ float scale = mAppScale;
+ Context cxt = mView.getContext();
+ if (DEBUG_DRAW) {
+ Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + ", appScale=" + mAppScale);
+ }
+ int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ try {
+ canvas.translate(0, -yoff);
+ if (scale != 1.0f) {
+ // re-scale this
+ canvas.scale(scale, scale);
+ }
+ mView.draw(canvas);
+ } finally {
+ canvas.restoreToCount(saveCount);
+ }
if (SHOW_FPS) {
int now = (int)SystemClock.elapsedRealtime();
@@ -1508,6 +1554,9 @@
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
+ if (event != null) {
+ event.scale(mAppScaleInverted);
+ }
try {
boolean handled;
@@ -1628,7 +1677,8 @@
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
- mGlCanvas.setViewport(mWidth, mHeight);
+ mGlCanvas.setViewport((int) (mWidth * mAppScale),
+ (int) (mHeight * mAppScale));
}
}
}
@@ -1828,6 +1878,9 @@
} else {
didFinish = false;
}
+ if (event != null) {
+ event.scale(mAppScaleInverted);
+ }
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2254,6 +2307,20 @@
return mAudioManager;
}
+ private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
+ boolean insetsPending) throws RemoteException {
+ int relayoutResult = sWindowSession.relayout(
+ mWindow, params,
+ (int) (mView.mMeasuredWidth * mAppScale),
+ (int) (mView.mMeasuredHeight * mAppScale),
+ viewVisibility, insetsPending, mWinFrame,
+ mPendingContentInsets, mPendingVisibleInsets, mSurface);
+ mPendingContentInsets.scale(mAppScaleInverted);
+ mPendingVisibleInsets.scale(mAppScaleInverted);
+ mWinFrame.scale(mAppScaleInverted);
+ return relayoutResult;
+ }
+
/**
* {@inheritDoc}
*/
@@ -2322,12 +2389,8 @@
// to the window manager to make sure it has the correct
// animation info.
try {
- if ((sWindowSession.relayout(
- mWindow, mWindowAttributes,
- mView.mMeasuredWidth, mView.mMeasuredHeight,
- viewVisibility, false, mWinFrame, mPendingContentInsets,
- mPendingVisibleInsets, mSurface)
- &WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+ if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
+ & WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
sWindowSession.finishDrawing(mWindow);
}
} catch (RemoteException e) {
@@ -2361,8 +2424,11 @@
+ " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw);
Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
- msg.arg1 = w;
- msg.arg2 = h;
+
+ coveredInsets.scale(mAppScaleInverted);
+ visibleInsets.scale(mAppScaleInverted);
+ msg.arg1 = (int) (w * mAppScaleInverted);
+ msg.arg2 = (int) (h * mAppScaleInverted);
msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
sendMessage(msg);
}
@@ -2493,7 +2559,7 @@
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
}
- } else if (mIsPointer) {
+ } else if (mIsPointer) {
boolean didFinish;
MotionEvent event = mMotionEvent;
if (event == null) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 34e65ad..f6a171d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -954,7 +954,7 @@
return sb.toString();
}
- void scaleUp(float scale) {
+ void scale(float scale) {
if (scale != 1.0f) {
x *= scale;
y *= scale;