summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java76
-rw-r--r--core/java/android/app/ApplicationContext.java17
-rw-r--r--core/java/android/content/Context.java10
-rw-r--r--core/java/android/content/ContextWrapper.java8
-rw-r--r--core/java/android/content/res/Resources.java42
-rw-r--r--core/java/android/view/MotionEvent.java27
-rw-r--r--core/java/android/view/SurfaceView.java33
-rw-r--r--core/java/android/view/ViewRoot.java130
-rw-r--r--core/java/android/view/WindowManager.java2
-rw-r--r--graphics/java/android/graphics/Rect.java13
-rw-r--r--test-runner/android/test/mock/MockContext.java8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java8
12 files changed, 324 insertions, 50 deletions
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 @@ public final class ActivityThread {
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 @@ public final class ActivityThread {
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 @@ public final class ActivityThread {
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 @@ public final class ActivityThread {
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 @@ public final class ActivityThread {
mClassLoader = mSystemContext.getClassLoader();
mResources = mSystemContext.getResources();
}
+
+ mApplicationScale = -1.0f;
}
public PackageInfo(ActivityThread activityThread, String name,
@@ -268,6 +292,7 @@ public final class ActivityThread {
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
+ mApplicationScale = systemContext.getApplicationScale();
}
public String getPackageName() {
@@ -278,6 +303,47 @@ public final class ActivityThread {
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 final class ActivityThread {
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 @@ class ApplicationContext extends Context {
}
}
+ /**
+ * @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 @@ class ApplicationContext extends Context {
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 class Context {
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 @@ public class ContextWrapper extends Context {
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 org.xmlpull.v1.XmlPullParserException;
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 @@ public class Resources {
// 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 @@ public class Resources {
/*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 class Resources {
*/
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 @@ public class Resources {
mMetrics.setTo(metrics);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
String locale = null;
if (mConfiguration.locale != null) {
locale = mConfiguration.locale.getLanguage();
@@ -1653,7 +1689,7 @@ public class Resources {
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 @@ public class Resources {
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 @@ public final class MotionEvent implements Parcelable {
private float mYPrecision;
private int mDeviceId;
private int mEdgeFlags;
-
+
private MotionEvent mNext;
private RuntimeException mRecycledLocation;
private boolean mRecycled;
@@ -210,7 +210,29 @@ public final class MotionEvent implements Parcelable {
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 @@ public final class MotionEvent implements Parcelable {
}
}
-
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 @@ public class SurfaceView extends View {
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 @@ public class SurfaceView extends View {
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 @@ public class SurfaceView extends View {
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 @@ public class SurfaceView extends View {
}
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 @@ public class SurfaceView extends View {
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 @@ public class SurfaceView extends View {
}
};
}
-
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
// 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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
synchronized (this) {
int oldSoftInputMode = mWindowAttributes.softInputMode;
mWindowAttributes.copyFrom(attrs);
+ mWindowAttributes.scale(mAppScale);
+
if (newView) {
mSoftInputMode = attrs.softInputMode;
requestLayout();
@@ -521,9 +529,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) {
+ 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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
mHeight = frame.height();
if (initialized) {
- mGlCanvas.setViewport(mWidth, mHeight);
+ mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
}
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -944,6 +959,11 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
int yoff;
final boolean scrolling = mScroller != null
- && mScroller.computeScrollOffset();
+ && mScroller.computeScrollOffset();
if (scrolling) {
yoff = mScroller.getCurrY();
} else {
@@ -1135,10 +1158,19 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
}
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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
+ if (event != null) {
+ event.scale(mAppScaleInverted);
+ }
try {
boolean handled;
@@ -1628,7 +1677,8 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
- mGlCanvas.setViewport(mWidth, mHeight);
+ mGlCanvas.setViewport((int) (mWidth * mAppScale),
+ (int) (mHeight * mAppScale));
}
}
}
@@ -1828,6 +1878,9 @@ public final class ViewRoot extends Handler implements ViewParent,
} else {
didFinish = false;
}
+ if (event != null) {
+ event.scale(mAppScaleInverted);
+ }
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2254,6 +2307,20 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
// 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 @@ public final class ViewRoot extends Handler implements ViewParent,
+ " 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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public interface WindowManager extends ViewManager {
return sb.toString();
}
- void scaleUp(float scale) {
+ void scale(float scale) {
if (scale != 1.0f) {
x *= scale;
y *= scale;
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 2005344..dda37e5 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -517,4 +517,17 @@ public final class Rect implements Parcelable {
right = in.readInt();
bottom = in.readInt();
}
+
+ /**
+ * Scales up the rect by the given scale.
+ * @hide
+ */
+ public void scale(float scale) {
+ if (scale != 1.0f) {
+ left *= scale;
+ top *= scale;
+ right *= scale;
+ bottom*= scale;
+ }
+ }
}
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index e733dd1..bd39a14 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -386,4 +386,12 @@ public class MockContext extends Context {
throws PackageManager.NameNotFoundException {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public float getApplicationScale() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index baa3d53..f434e14 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -1145,4 +1145,12 @@ public final class BridgeContext extends Context {
public Context getApplicationContext() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public float getApplicationScale() {
+ throw new UnsupportedOperationException();
+ }
}