am c404e9b2: Merge "More compatibility mode improvements." into honeycomb-mr2

* commit 'c404e9b20165f634904d1489216d17d8e09fe696':
  More compatibility mode improvements.
This commit is contained in:
Dianne Hackborn
2011-05-24 19:10:53 -07:00
committed by Android Git Automerger
11 changed files with 172 additions and 108 deletions

View File

@ -35,6 +35,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager; import android.content.pm.IPackageManager;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.DatabaseErrorHandler; import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
@ -78,6 +79,7 @@ import android.content.ClipboardManager;
import android.util.AndroidRuntimeException; import android.util.AndroidRuntimeException;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.WindowManagerImpl; import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@ -423,7 +425,11 @@ class ContextImpl extends Context {
registerService(WINDOW_SERVICE, new ServiceFetcher() { registerService(WINDOW_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) { public Object getService(ContextImpl ctx) {
return WindowManagerImpl.getDefault(); RuntimeException e = new RuntimeException("foo");
e.fillInStackTrace();
Log.i(TAG, "Getting window manager", e);
CompatibilityInfo ci = ctx.mResources.getCompatibilityInfo();
return WindowManagerImpl.getDefault(ci);
}}); }});
} }

View File

@ -1045,7 +1045,7 @@ public class Instrumentation {
} }
} }
activity.onCreate(icicle); activity.performCreate(icicle);
if (mActivityMonitors != null) { if (mActivityMonitors != null) {
synchronized (mSync) { synchronized (mSync) {

View File

@ -125,14 +125,16 @@ public class CompatibilityInfo implements Parcelable {
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
compatFlags |= XLARGE_SCREENS | EXPANDABLE; compatFlags |= XLARGE_SCREENS | EXPANDABLE;
} }
if (!forceCompat) { if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
compatFlags |= EXPANDABLE;
}
if (forceCompat) {
// If we are forcing compatibility mode, then ignore an app that // If we are forcing compatibility mode, then ignore an app that
// just says it is resizable for screens. We'll only have it fill // just says it is resizable for screens. We'll only have it fill
// the screen if it explicitly says it supports the screen size we // the screen if it explicitly says it supports the screen size we
// are running in. // are running in.
if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { compatFlags &= ~EXPANDABLE;
compatFlags |= EXPANDABLE;
}
} }
boolean supportsScreen = false; boolean supportsScreen = false;
@ -155,12 +157,10 @@ public class CompatibilityInfo implements Parcelable {
break; break;
} }
if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) { if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
if ((compatFlags&EXPANDABLE) != 0) { if ((compatFlags&EXPANDABLE) != 0) {
supportsScreen = true; supportsScreen = true;
} } else if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) == 0) {
if ((compatFlags&EXPANDABLE) == 0 &&
(appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) == 0) {
compatFlags |= ALWAYS_COMPAT; compatFlags |= ALWAYS_COMPAT;
} }
} }
@ -382,6 +382,9 @@ public class CompatibilityInfo implements Parcelable {
// This is a larger screen device and the app is not // This is a larger screen device and the app is not
// compatible with large screens, so diddle it. // compatible with large screens, so diddle it.
CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm); CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm);
} else {
inoutDm.widthPixels = inoutDm.realWidthPixels;
inoutDm.heightPixels = inoutDm.realHeightPixels;
} }
if (isScalingRequired()) { if (isScalingRequired()) {

View File

@ -316,10 +316,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
StringBuilder sb = new StringBuilder(128); StringBuilder sb = new StringBuilder(128);
sb.append("{"); sb.append("{");
sb.append(fontScale); sb.append(fontScale);
sb.append("x imsi="); sb.append(" ");
sb.append(mcc); sb.append(mcc);
sb.append("/"); sb.append("mcc");
sb.append(mnc); sb.append(mnc);
sb.append("mnc");
if (locale != null) { if (locale != null) {
sb.append(" "); sb.append(" ");
sb.append(locale); sb.append(locale);

View File

@ -115,7 +115,6 @@ public class Resources {
private NativePluralRules mPluralRule; private NativePluralRules mPluralRule;
private CompatibilityInfo mCompatibilityInfo; private CompatibilityInfo mCompatibilityInfo;
private Display mDefaultDisplay;
private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) { private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) {
@Override @Override
@ -1426,6 +1425,15 @@ public class Resources {
} }
if (metrics != null) { if (metrics != null) {
mMetrics.setTo(metrics); mMetrics.setTo(metrics);
// NOTE: We should re-arrange this code to create a Display
// with the CompatibilityInfo that is used everywhere we deal
// with the display in relation to this app, rather than
// doing the conversion here. This impl should be okay because
// we make sure to return a compatible display in the places
// where there are public APIs to retrieve the display... but
// it would be cleaner and more maintainble to just be
// consistently dealing with a compatible display everywhere in
// the framework.
mCompatibilityInfo.applyToDisplayMetrics(mMetrics); mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
} }
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
@ -2121,24 +2129,6 @@ public class Resources {
+ Integer.toHexString(id)); + Integer.toHexString(id));
} }
/**
* Returns the display adjusted for the Resources' metrics.
* @hide
*/
public Display getDefaultDisplay(Display defaultDisplay) {
if (mDefaultDisplay == null) {
if (!mCompatibilityInfo.isScalingRequired() && mCompatibilityInfo.supportsScreen()) {
// the app supports the display. just use the default one.
mDefaultDisplay = defaultDisplay;
} else {
// display needs adjustment.
mDefaultDisplay = Display.createMetricsBasedDisplay(
defaultDisplay.getDisplayId(), mMetrics);
}
}
return mDefaultDisplay;
}
private TypedArray getCachedStyledAttributes(int len) { private TypedArray getCachedStyledAttributes(int len) {
synchronized (mTmpValue) { synchronized (mTmpValue) {
TypedArray attrs = mCachedStyledAttributes; TypedArray attrs = mCachedStyledAttributes;

View File

@ -16,6 +16,7 @@
package android.view; package android.view;
import android.content.res.CompatibilityInfo;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.RemoteException; import android.os.RemoteException;
@ -37,7 +38,7 @@ public class Display {
* Display gives you access to some information about a particular display * Display gives you access to some information about a particular display
* connected to the device. * connected to the device.
*/ */
Display(int display) { Display(int display, CompatibilityInfo compatInfo) {
// initalize the statics when this class is first instansiated. This is // initalize the statics when this class is first instansiated. This is
// done here instead of in the static block because Zygote // done here instead of in the static block because Zygote
synchronized (sStaticInit) { synchronized (sStaticInit) {
@ -46,6 +47,12 @@ public class Display {
sInitialized = true; sInitialized = true;
} }
} }
if (compatInfo != null && (compatInfo.isScalingRequired()
|| !compatInfo.supportsScreen())) {
mCompatibilityInfo = compatInfo;
} else {
mCompatibilityInfo = null;
}
mDisplay = display; mDisplay = display;
init(display); init(display);
} }
@ -82,6 +89,16 @@ public class Display {
// system process before the window manager is up. // system process before the window manager is up.
outSize.y = getRealHeight(); outSize.y = getRealHeight();
} }
if (mCompatibilityInfo != null) {
synchronized (mTmpMetrics) {
mTmpMetrics.realWidthPixels = outSize.x;
mTmpMetrics.realHeightPixels = outSize.y;
mTmpMetrics.density = mDensity;
mCompatibilityInfo.applyToDisplayMetrics(mTmpMetrics);
outSize.x = mTmpMetrics.widthPixels;
outSize.y = mTmpMetrics.heightPixels;
}
}
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.w("Display", "Unable to get display size", e); Slog.w("Display", "Unable to get display size", e);
} }
@ -206,6 +223,10 @@ public class Display {
outMetrics.heightPixels = mTmpPoint.y; outMetrics.heightPixels = mTmpPoint.y;
} }
getNonSizeMetrics(outMetrics); getNonSizeMetrics(outMetrics);
if (mCompatibilityInfo != null) {
mCompatibilityInfo.applyToDisplayMetrics(outMetrics);
}
} }
/** /**
@ -249,7 +270,8 @@ public class Display {
private native void init(int display); private native void init(int display);
private int mDisplay; private final CompatibilityInfo mCompatibilityInfo;
private final int mDisplay;
// Following fields are initialized from native code // Following fields are initialized from native code
private int mPixelFormat; private int mPixelFormat;
private float mRefreshRate; private float mRefreshRate;
@ -258,6 +280,7 @@ public class Display {
private float mDpiY; private float mDpiY;
private final Point mTmpPoint = new Point(); private final Point mTmpPoint = new Point();
private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
private float mLastGetTime; private float mLastGetTime;
private static final Object sStaticInit = new Object(); private static final Object sStaticInit = new Object();
@ -268,27 +291,8 @@ public class Display {
* Returns a display object which uses the metric's width/height instead. * Returns a display object which uses the metric's width/height instead.
* @hide * @hide
*/ */
public static Display createMetricsBasedDisplay(int displayId, DisplayMetrics metrics) { public static Display createCompatibleDisplay(int displayId, CompatibilityInfo compat) {
return new CompatibleDisplay(displayId, metrics); return new Display(displayId, compat);
}
private static class CompatibleDisplay extends Display {
private final DisplayMetrics mMetrics;
private CompatibleDisplay(int displayId, DisplayMetrics metrics) {
super(displayId);
mMetrics = metrics;
}
@Override
public int getWidth() {
return mMetrics.widthPixels;
}
@Override
public int getHeight() {
return mMetrics.heightPixels;
}
} }
} }

View File

@ -20,7 +20,6 @@ import android.content.res.CompatibilityInfo.Translator;
import android.graphics.*; import android.graphics.*;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.Parcel; import android.os.Parcel;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
/** /**
@ -174,9 +173,9 @@ public class Surface implements Parcelable {
private int mSurfaceGenerationId; private int mSurfaceGenerationId;
private String mName; private String mName;
// The display metrics used to provide the pseudo canvas size for applications // The Translator for density compatibility mode. This is used for scaling
// running in compatibility mode. This is set to null for non compatibility mode. // the canvas to perform the appropriate density transformation.
private DisplayMetrics mCompatibleDisplayMetrics; private Translator mCompatibilityTranslator;
// A matrix to scale the matrix set by application. This is set to null for // A matrix to scale the matrix set by application. This is set to null for
// non compatibility mode. // non compatibility mode.
@ -263,14 +262,20 @@ public class Surface implements Parcelable {
@Override @Override
public int getWidth() { public int getWidth() {
return mCompatibleDisplayMetrics == null ? int w = super.getWidth();
super.getWidth() : mCompatibleDisplayMetrics.widthPixels; if (mCompatibilityTranslator != null) {
w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f);
}
return w;
} }
@Override @Override
public int getHeight() { public int getHeight() {
return mCompatibleDisplayMetrics == null ? int h = super.getHeight();
super.getHeight() : mCompatibleDisplayMetrics.heightPixels; if (mCompatibilityTranslator != null) {
h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f);
}
return h;
} }
@Override @Override
@ -297,10 +302,9 @@ public class Surface implements Parcelable {
} }
/** /**
* Sets the display metrics used to provide canvas's width/height in compatibility mode. * Sets the translator used to scale canvas's width/height in compatibility mode.
*/ */
void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) { void setCompatibilityTranslator(Translator translator) {
mCompatibleDisplayMetrics = metrics;
if (translator != null) { if (translator != null) {
float appScale = translator.applicationScale; float appScale = translator.applicationScale;
mCompatibleMatrix = new Matrix(); mCompatibleMatrix = new Matrix();

View File

@ -21,7 +21,6 @@ import com.android.internal.view.BaseIWindow;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.CompatibilityInfo.Translator; import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
@ -433,9 +432,8 @@ public class SurfaceView extends View {
mTranslator = viewRoot.mTranslator; mTranslator = viewRoot.mTranslator;
} }
Resources res = getContext().getResources(); if (mTranslator != null) {
if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) { mSurface.setCompatibilityTranslator(mTranslator);
mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics(), mTranslator);
} }
int myWidth = mRequestedWidth; int myWidth = mRequestedWidth;

View File

@ -373,9 +373,8 @@ public final class ViewRoot extends Handler implements ViewParent,
CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo(); CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator(); mTranslator = compatibilityInfo.getTranslator();
if (mTranslator != null || !compatibilityInfo.supportsScreen()) { if (mTranslator != null) {
mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics(), mSurface.setCompatibilityTranslator(mTranslator);
mTranslator);
} }
boolean restore = false; boolean restore = false;

View File

@ -17,6 +17,7 @@
package android.view; package android.view;
import android.content.Context; import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
@ -462,13 +463,11 @@ public abstract class Window {
mWindowManager = new LocalWindowManager(wm, hardwareAccelerated); mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
} }
private class LocalWindowManager implements WindowManager { private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
private boolean mHardwareAccelerated; private final boolean mHardwareAccelerated;
LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) { LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {
mWindowManager = wm; super(wm, mContext.getResources().getCompatibilityInfo());
mDefaultDisplay = mContext.getResources().getDefaultDisplay(
mWindowManager.getDefaultDisplay());
mHardwareAccelerated = hardwareAccelerated; mHardwareAccelerated = hardwareAccelerated;
} }
@ -523,28 +522,8 @@ public abstract class Window {
if (mHardwareAccelerated) { if (mHardwareAccelerated) {
wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
} }
mWindowManager.addView(view, params); super.addView(view, params);
} }
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
mWindowManager.updateViewLayout(view, params);
}
public final void removeView(View view) {
mWindowManager.removeView(view);
}
public final void removeViewImmediate(View view) {
mWindowManager.removeViewImmediate(view);
}
public Display getDefaultDisplay() {
return mDefaultDisplay;
}
private final WindowManager mWindowManager;
private final Display mDefaultDisplay;
} }
/** /**

View File

@ -16,6 +16,9 @@
package android.view; package android.view;
import java.util.HashMap;
import android.content.res.CompatibilityInfo;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.IBinder; import android.os.IBinder;
import android.util.AndroidRuntimeException; import android.util.AndroidRuntimeException;
@ -75,9 +78,92 @@ public class WindowManagerImpl implements WindowManager {
public static final int ADD_MULTIPLE_SINGLETON = -7; public static final int ADD_MULTIPLE_SINGLETON = -7;
public static final int ADD_PERMISSION_DENIED = -8; public static final int ADD_PERMISSION_DENIED = -8;
public static WindowManagerImpl getDefault() private View[] mViews;
{ private ViewRoot[] mRoots;
return mWindowManager; private WindowManager.LayoutParams[] mParams;
private final static Object sLock = new Object();
private final static WindowManagerImpl sWindowManager = new WindowManagerImpl();
private final static HashMap<CompatibilityInfo, WindowManager> sCompatWindowManagers
= new HashMap<CompatibilityInfo, WindowManager>();
static class CompatModeWrapper implements WindowManager {
private final WindowManager mWindowManager;
private final Display mDefaultDisplay;
CompatModeWrapper(WindowManager wm, CompatibilityInfo ci) {
mWindowManager = wm;
// Use the original display if there is no compatibility mode
// to apply, or the underlying window manager is already a
// compatibility mode wrapper. (We assume that if it is a
// wrapper, it is applying the same compatibility mode.)
if (ci == null || wm instanceof CompatModeWrapper
|| (!ci.isScalingRequired() && ci.supportsScreen())) {
mDefaultDisplay = mWindowManager.getDefaultDisplay();
} else {
//mDefaultDisplay = mWindowManager.getDefaultDisplay();
mDefaultDisplay = Display.createCompatibleDisplay(
mWindowManager.getDefaultDisplay().getDisplayId(), ci);
}
}
@Override
public void addView(View view, android.view.ViewGroup.LayoutParams params) {
mWindowManager.addView(view, params);
}
@Override
public void updateViewLayout(View view, android.view.ViewGroup.LayoutParams params) {
mWindowManager.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mWindowManager.removeView(view);
}
@Override
public Display getDefaultDisplay() {
return mDefaultDisplay;
}
@Override
public void removeViewImmediate(View view) {
mWindowManager.removeViewImmediate(view);
}
@Override
public boolean isHardwareAccelerated() {
return mWindowManager.isHardwareAccelerated();
}
}
public static WindowManagerImpl getDefault() {
return sWindowManager;
}
public static WindowManager getDefault(CompatibilityInfo compatInfo) {
if (compatInfo == null || (!compatInfo.isScalingRequired()
&& compatInfo.supportsScreen())) {
return sWindowManager;
}
synchronized (sLock) {
// NOTE: It would be cleaner to move the implementation of
// WindowManagerImpl into a static inner class, and have this
// public impl just call into that. Then we can make multiple
// instances of WindowManagerImpl for compat mode rather than
// having to make wrappers.
WindowManager wm = sCompatWindowManagers.get(compatInfo);
if (wm == null) {
wm = new CompatModeWrapper(sWindowManager, compatInfo);
sCompatWindowManagers.put(compatInfo, wm);
}
return wm;
}
} }
public boolean isHardwareAccelerated() { public boolean isHardwareAccelerated() {
@ -341,13 +427,9 @@ public class WindowManagerImpl implements WindowManager {
} }
public Display getDefaultDisplay() { public Display getDefaultDisplay() {
return new Display(Display.DEFAULT_DISPLAY); return new Display(Display.DEFAULT_DISPLAY, null);
} }
private View[] mViews;
private ViewRoot[] mRoots;
private WindowManager.LayoutParams[] mParams;
private static void removeItem(Object[] dst, Object[] src, int index) private static void removeItem(Object[] dst, Object[] src, int index)
{ {
if (dst.length > 0) { if (dst.length > 0) {
@ -376,6 +458,4 @@ public class WindowManagerImpl implements WindowManager {
return -1; return -1;
} }
} }
private static WindowManagerImpl mWindowManager = new WindowManagerImpl();
} }