summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorMitsuru Oshima <>2009-04-28 18:12:09 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-28 18:12:09 -0700
commit8169daed2f7a8731d478b884b1f455c747b88478 (patch)
tree3ab1f44b128cef2f18f470af7483a8405329da23 /core/java
parent8d112675879a2b83197d3b4ae4fb623abd1a1ec3 (diff)
downloadframeworks_base-8169daed2f7a8731d478b884b1f455c747b88478.zip
frameworks_base-8169daed2f7a8731d478b884b1f455c747b88478.tar.gz
frameworks_base-8169daed2f7a8731d478b884b1f455c747b88478.tar.bz2
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
Diffstat (limited to 'core/java')
-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
9 files changed, 295 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;