* Moved supports-density tag under manifest
* Refactored Compatibility code
* Added CompatibilityInfo class
* Removed getApplicationScale from Context
* Added Resources#getCompatibilityInfo so that RootView can get the compatibility info w/o going through Context
* Expandable support
* Added expandable tag under manifest
* Old application w/o expandable is given the default screen size ([320, 480] x density).
* The non-expandable window is centered.
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 7cd65e2..d8bab56 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -30,6 +30,7 @@
import android.os.SystemProperties;
import android.util.AndroidRuntimeException;
import android.util.Config;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.EventLog;
import android.util.SparseArray;
@@ -40,6 +41,7 @@
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
import android.content.pm.PackageManager;
+import android.content.res.CompatibilityInfo;
import android.content.Context;
import android.app.ActivityManagerNative;
import android.Manifest;
@@ -125,9 +127,8 @@
int mHeight;
Rect mDirty; // will be a graphics.Region soon
boolean mIsAnimating;
- // TODO: change these to scalar class.
- private float mAppScale;
- private float mAppScaleInverted; // = 1.0f / mAppScale
+
+ private CompatibilityInfo mCompatibilityInfo;
private int[] mWindowLayoutParamsBackup = null;
final View.AttachInfo mAttachInfo;
@@ -386,12 +387,15 @@
synchronized (this) {
if (mView == null) {
mView = view;
- mAppScale = mView.getContext().getApplicationScale();
- if (mAppScale != 1.0f) {
+ mWindowAttributes.copyFrom(attrs);
+ mCompatibilityInfo =
+ mView.getContext().getResources().getCompatibilityInfo();
+ if (mCompatibilityInfo.mScalingRequired) {
mWindowLayoutParamsBackup = new int[4];
}
- mAppScaleInverted = 1.0f / mAppScale;
- mWindowAttributes.copyFrom(attrs);
+ if (!mCompatibilityInfo.mExpandable) {
+ adjustWindowAttributesForCompatibleMode(mWindowAttributes);
+ }
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
mAttachInfo.mRootView = view;
@@ -406,9 +410,8 @@
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
-
try {
- res = sWindowSession.add(mWindow, attrs,
+ res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets);
} catch (RemoteException e) {
mAdded = false;
@@ -417,7 +420,10 @@
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
}
- mAttachInfo.mContentInsets.scale(mAppScaleInverted);
+ if (mCompatibilityInfo.mScalingRequired) {
+ mAttachInfo.mContentInsets.scale(
+ mCompatibilityInfo.mApplicationInvertedScale);
+ }
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
@@ -529,13 +535,13 @@
public void invalidateChild(View child, Rect dirty) {
checkThread();
if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
- if (mCurScrollY != 0 || mAppScale != 1.0f) {
+ if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
mTempRect.set(dirty);
if (mCurScrollY != 0) {
mTempRect.offset(0, -mCurScrollY);
}
- if (mAppScale != 1.0f) {
- mTempRect.scale(mAppScale);
+ if (mCompatibilityInfo.mScalingRequired) {
+ mTempRect.scale(mCompatibilityInfo.mApplicationScale);
}
dirty = mTempRect;
}
@@ -615,6 +621,8 @@
boolean viewVisibilityChanged = mViewVisibility != viewVisibility
|| mNewSurfaceNeeded;
+ float appScale = mCompatibilityInfo.mApplicationScale;
+
WindowManager.LayoutParams params = null;
if (mWindowAttributesChanged) {
mWindowAttributesChanged = false;
@@ -625,9 +633,10 @@
fullRedrawNeeded = true;
mLayoutRequested = true;
- Display d = new Display(0);
- desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
- desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+ DisplayMetrics packageMetrics =
+ mView.getContext().getResources().getDisplayMetrics();
+ desiredWindowWidth = packageMetrics.widthPixels;
+ desiredWindowHeight = packageMetrics.heightPixels;
// For the very first time, tell the view hierarchy that it
// is attached to the window. Note that at this point the surface
@@ -696,9 +705,10 @@
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
windowResizesToFitContent = true;
- Display d = new Display(0);
- desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
- desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+ DisplayMetrics packageMetrics =
+ mView.getContext().getResources().getDisplayMetrics();
+ desiredWindowWidth = packageMetrics.widthPixels;
+ desiredWindowHeight = packageMetrics.heightPixels;
}
}
@@ -878,7 +888,7 @@
mHeight = frame.height();
if (initialized) {
- mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+ mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale));
}
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -968,11 +978,7 @@
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 ?
+ mTransparentRegion.scale(appScale);
if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
mPreviousTransparentRegion.set(mTransparentRegion);
// reconfigure window manager
@@ -983,7 +989,6 @@
}
}
-
if (DBG) {
System.out.println("======================================");
System.out.println("performTraversals -- after setFrame");
@@ -1003,10 +1008,11 @@
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 (mCompatibilityInfo.mScalingRequired) {
+ insets.contentInsets.scale(appScale);
+ insets.visibleInsets.scale(appScale);
+ }
if (insetsPending || !mLastGivenInsets.equals(insets)) {
mLastGivenInsets.set(insets);
try {
@@ -1154,6 +1160,8 @@
mCurScrollY = yoff;
fullRedrawNeeded = true;
}
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
Rect dirty = mDirty;
if (mUseGL) {
@@ -1169,12 +1177,11 @@
mAttachInfo.mIgnoreDirtyState = true;
mView.mPrivateFlags |= View.DRAWN;
- float scale = mAppScale;
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scale != 1.0f) {
- canvas.scale(scale, scale);
+ if (scalingRequired) {
+ canvas.scale(appScale, appScale);
}
mView.draw(canvas);
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1206,8 +1213,8 @@
}
if (fullRedrawNeeded) {
- mAttachInfo.mIgnoreDirtyState = true;
- dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+ mAttachInfo.mIgnoreDirtyState = true;
+ dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale));
}
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
@@ -1215,7 +1222,8 @@
+ mWindowAttributes.getTitle()
+ ": dirty={" + dirty.left + "," + dirty.top
+ "," + dirty.right + "," + dirty.bottom + "} surface="
- + surface + " surface.isValid()=" + surface.isValid());
+ + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" +
+ appScale + ", width=" + mWidth + ", height=" + mHeight);
}
Canvas canvas;
@@ -1272,18 +1280,16 @@
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.DRAWN;
- float scale = mAppScale;
if (DEBUG_DRAW) {
Context cxt = mView.getContext();
Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
- ", appScale=" + mAppScale);
+ ", metrics=" + mView.getContext().getResources().getDisplayMetrics());
}
- int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scale != 1.0f) {
- // re-scale this
- canvas.scale(scale, scale);
+ if (scalingRequired) {
+ canvas.scale(appScale, appScale);
}
mView.draw(canvas);
} finally {
@@ -1586,8 +1592,8 @@
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
- if (event != null) {
- event.scale(mAppScaleInverted);
+ if (event != null && mCompatibilityInfo.mScalingRequired) {
+ event.scale(mCompatibilityInfo.mApplicationInvertedScale);
}
try {
@@ -1709,8 +1715,9 @@
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
- mGlCanvas.setViewport((int) (mWidth * mAppScale),
- (int) (mHeight * mAppScale));
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ mGlCanvas.setViewport(
+ (int) (mWidth * appScale), (int) (mHeight * appScale));
}
}
}
@@ -1914,8 +1921,8 @@
} else {
didFinish = false;
}
- if (event != null) {
- event.scale(mAppScaleInverted);
+ if (event != null && mCompatibilityInfo.mScalingRequired) {
+ event.scale(mCompatibilityInfo.mApplicationInvertedScale);
}
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2345,27 +2352,59 @@
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
-
boolean restore = false;
- if (params != null && mAppScale != 1.0f) {
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+
+ if (params != null && !mCompatibilityInfo.mExpandable) {
+ adjustWindowAttributesForCompatibleMode(params);
+ }
+ if (params != null && scalingRequired) {
restore = true;
- params.scale(mAppScale, mWindowLayoutParamsBackup);
+ params.scale(appScale, mWindowLayoutParamsBackup);
}
int relayoutResult = sWindowSession.relayout(
mWindow, params,
- (int) (mView.mMeasuredWidth * mAppScale),
- (int) (mView.mMeasuredHeight * mAppScale),
+ (int) (mView.mMeasuredWidth * appScale),
+ (int) (mView.mMeasuredHeight * appScale),
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets, mSurface);
if (restore) {
params.restore(mWindowLayoutParamsBackup);
}
-
- mPendingContentInsets.scale(mAppScaleInverted);
- mPendingVisibleInsets.scale(mAppScaleInverted);
- mWinFrame.scale(mAppScaleInverted);
+ if (scalingRequired) {
+ float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+ mPendingContentInsets.scale(invertedScale);
+ mPendingVisibleInsets.scale(invertedScale);
+ mWinFrame.scale(invertedScale);
+ }
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;
+ }
+ if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
+ attrs.height = metrics.heightPixels;
+ }
+ if (DEBUG_LAYOUT) {
+ Log.d(TAG, "Attributes fixed for compatibility : " + attrs);
+ }
+ }
+ }
/**
* {@inheritDoc}
@@ -2470,11 +2509,16 @@
+ " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw);
Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-
- coveredInsets.scale(mAppScaleInverted);
- visibleInsets.scale(mAppScaleInverted);
- msg.arg1 = (int) (w * mAppScaleInverted);
- msg.arg2 = (int) (h * mAppScaleInverted);
+ 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;
+ }
msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
sendMessage(msg);
}