summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2011-05-09 17:08:40 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2011-05-09 17:08:40 -0700
commit4907d1d5e2c7d244b07579b8c52153df69754e85 (patch)
tree6e670ce463590a36bcbdec8df5a093e6fc3d2f4e /core
parent45364dc4bfe3e6118ad61f1d38489fe63418699a (diff)
parent0c6cbf410a642f6e9cea7cca0a6e53a4a3cdd324 (diff)
downloadframeworks_base-4907d1d5e2c7d244b07579b8c52153df69754e85.zip
frameworks_base-4907d1d5e2c7d244b07579b8c52153df69754e85.tar.gz
frameworks_base-4907d1d5e2c7d244b07579b8c52153df69754e85.tar.bz2
am 0c6cbf41: Merge "Better compat mode part one: start scaling windows." into honeycomb-mr2
* commit '0c6cbf410a642f6e9cea7cca0a6e53a4a3cdd324': Better compat mode part one: start scaling windows.
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ActivityManagerNative.java23
-rw-r--r--core/java/android/app/ActivityThread.java167
-rw-r--r--core/java/android/app/ApplicationThreadNative.java65
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/IActivityManager.java4
-rw-r--r--core/java/android/app/IApplicationThread.java23
-rw-r--r--core/java/android/app/LoadedApk.java10
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java358
-rw-r--r--core/java/android/content/res/Configuration.java21
-rwxr-xr-xcore/java/android/content/res/Resources.java31
-rw-r--r--core/java/android/util/DisplayMetrics.java108
-rw-r--r--core/java/android/view/Display.java3
-rw-r--r--core/java/android/view/WindowManagerPolicy.java12
13 files changed, 485 insertions, 344 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6426635..11e9975 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1398,6 +1398,16 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ boolean enabled = data.readInt() != 0;
+ setPackageScreenCompatMode(pkg, enabled);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3142,5 +3152,18 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
+ public void setPackageScreenCompatMode(String packageName, boolean compatEnabled)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ data.writeInt(compatEnabled ? 1 : 0);
+ mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index bd83762..67e8839 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -202,7 +202,7 @@ public final class ActivityThread {
Bundle mCoreSettings = null;
- private static final class ActivityClientRecord {
+ static final class ActivityClientRecord {
IBinder token;
int ident;
Intent intent;
@@ -220,6 +220,7 @@ public final class ActivityThread {
ActivityClientRecord nextIdle;
ActivityInfo activityInfo;
+ CompatibilityInfo compatInfo;
LoadedApk packageInfo;
List<ResultInfo> pendingResults;
@@ -260,7 +261,7 @@ public final class ActivityThread {
}
}
- private final class ProviderClientRecord implements IBinder.DeathRecipient {
+ final class ProviderClientRecord implements IBinder.DeathRecipient {
final String mName;
final IContentProvider mProvider;
final ContentProvider mLocalProvider;
@@ -277,7 +278,7 @@ public final class ActivityThread {
}
}
- private static final class NewIntentData {
+ static final class NewIntentData {
List<Intent> intents;
IBinder token;
public String toString() {
@@ -285,7 +286,7 @@ public final class ActivityThread {
}
}
- private static final class ReceiverData extends BroadcastReceiver.PendingResult {
+ static final class ReceiverData extends BroadcastReceiver.PendingResult {
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, IBinder token) {
super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
@@ -294,6 +295,7 @@ public final class ActivityThread {
Intent intent;
ActivityInfo info;
+ CompatibilityInfo compatInfo;
public String toString() {
return "ReceiverData{intent=" + intent + " packageName=" +
info.packageName + " resultCode=" + getResultCode()
@@ -302,8 +304,9 @@ public final class ActivityThread {
}
}
- private static final class CreateBackupAgentData {
+ static final class CreateBackupAgentData {
ApplicationInfo appInfo;
+ CompatibilityInfo compatInfo;
int backupMode;
public String toString() {
return "CreateBackupAgentData{appInfo=" + appInfo
@@ -312,9 +315,10 @@ public final class ActivityThread {
}
}
- private static final class CreateServiceData {
+ static final class CreateServiceData {
IBinder token;
ServiceInfo info;
+ CompatibilityInfo compatInfo;
Intent intent;
public String toString() {
return "CreateServiceData{token=" + token + " className="
@@ -323,7 +327,7 @@ public final class ActivityThread {
}
}
- private static final class BindServiceData {
+ static final class BindServiceData {
IBinder token;
Intent intent;
boolean rebind;
@@ -332,7 +336,7 @@ public final class ActivityThread {
}
}
- private static final class ServiceArgsData {
+ static final class ServiceArgsData {
IBinder token;
int startId;
int flags;
@@ -343,7 +347,7 @@ public final class ActivityThread {
}
}
- private static final class AppBindData {
+ static final class AppBindData {
LoadedApk info;
String processName;
ApplicationInfo appInfo;
@@ -355,13 +359,14 @@ public final class ActivityThread {
int debugMode;
boolean restrictedBackupMode;
Configuration config;
+ CompatibilityInfo compatInfo;
boolean handlingProfiling;
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
}
}
- private static final class DumpComponentInfo {
+ static final class DumpComponentInfo {
FileDescriptor fd;
IBinder token;
String prefix;
@@ -369,7 +374,7 @@ public final class ActivityThread {
boolean dumped;
}
- private static final class ResultData {
+ static final class ResultData {
IBinder token;
List<ResultInfo> results;
public String toString() {
@@ -377,22 +382,27 @@ public final class ActivityThread {
}
}
- private static final class ContextCleanupInfo {
+ static final class ContextCleanupInfo {
ContextImpl context;
String what;
String who;
}
- private static final class ProfilerControlData {
+ static final class ProfilerControlData {
String path;
ParcelFileDescriptor fd;
}
- private static final class DumpHeapData {
+ static final class DumpHeapData {
String path;
ParcelFileDescriptor fd;
}
+ static final class UpdateCompatibilityData {
+ String pkg;
+ CompatibilityInfo info;
+ }
+
private final class ApplicationThread extends ApplicationThreadNative {
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -443,7 +453,8 @@ public final class ActivityThread {
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
+ ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
+ List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
ActivityClientRecord r = new ActivityClientRecord();
@@ -451,6 +462,7 @@ public final class ActivityThread {
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
+ r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
@@ -484,33 +496,40 @@ public final class ActivityThread {
}
public final void scheduleReceiver(Intent intent, ActivityInfo info,
- int resultCode, String data, Bundle extras, boolean sync) {
+ CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
+ boolean sync) {
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder());
r.info = info;
+ r.compatInfo = compatInfo;
queueOrSendMessage(H.RECEIVER, r);
}
- public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
+ public final void scheduleCreateBackupAgent(ApplicationInfo app,
+ CompatibilityInfo compatInfo, int backupMode) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
+ d.compatInfo = compatInfo;
d.backupMode = backupMode;
queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
}
- public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
+ public final void scheduleDestroyBackupAgent(ApplicationInfo app,
+ CompatibilityInfo compatInfo) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
+ d.compatInfo = compatInfo;
queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
}
public final void scheduleCreateService(IBinder token,
- ServiceInfo info) {
+ ServiceInfo info, CompatibilityInfo compatInfo) {
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
+ s.compatInfo = compatInfo;
queueOrSendMessage(H.CREATE_SERVICE, s);
}
@@ -553,7 +572,8 @@ public final class ActivityThread {
ComponentName instrumentationName, String profileFile,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean isRestrictedBackupMode, Configuration config,
- Map<String, IBinder> services, Bundle coreSettings) {
+ CompatibilityInfo compatInfo, Map<String, IBinder> services,
+ Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
@@ -573,6 +593,7 @@ public final class ActivityThread {
data.debugMode = debugMode;
data.restrictedBackupMode = isRestrictedBackupMode;
data.config = config;
+ data.compatInfo = compatInfo;
queueOrSendMessage(H.BIND_APPLICATION, data);
}
@@ -903,6 +924,13 @@ public final class ActivityThread {
public void setCoreSettings(Bundle coreSettings) {
queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings);
}
+
+ public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
+ UpdateCompatibilityData ucd = new UpdateCompatibilityData();
+ ucd.pkg = pkg;
+ ucd.info = info;
+ queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
+ }
}
private final class H extends Handler {
@@ -945,6 +973,7 @@ public final class ActivityThread {
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
public static final int SET_CORE_SETTINGS = 138;
+ public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
@@ -987,6 +1016,7 @@ public final class ActivityThread {
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
case SLEEPING: return "SLEEPING";
case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
+ case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
}
}
return "(unknown)";
@@ -998,7 +1028,7 @@ public final class ActivityThread {
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
- r.activityInfo.applicationInfo);
+ r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
} break;
case RELAUNCH_ACTIVITY: {
@@ -1072,7 +1102,7 @@ public final class ActivityThread {
handleRequestThumbnail((IBinder)msg.obj);
break;
case CONFIGURATION_CHANGED:
- handleConfigurationChanged((Configuration)msg.obj);
+ handleConfigurationChanged((Configuration)msg.obj, null);
break;
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
@@ -1125,6 +1155,8 @@ public final class ActivityThread {
case SET_CORE_SETTINGS:
handleSetCoreSettings((Bundle) msg.obj);
break;
+ case UPDATE_PACKAGE_COMPATIBILITY_INFO:
+ handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
}
@@ -1335,7 +1367,8 @@ public final class ActivityThread {
return mH;
}
- public final LoadedApk getPackageInfo(String packageName, int flags) {
+ public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
+ int flags) {
synchronized (mPackages) {
WeakReference<LoadedApk> ref;
if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
@@ -1369,13 +1402,14 @@ public final class ActivityThread {
}
if (ai != null) {
- return getPackageInfo(ai, flags);
+ return getPackageInfo(ai, compatInfo, flags);
}
return null;
}
- public final LoadedApk getPackageInfo(ApplicationInfo ai, int flags) {
+ public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
+ int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
@@ -1394,14 +1428,27 @@ public final class ActivityThread {
throw new SecurityException(msg);
}
}
- return getPackageInfo(ai, null, securityViolation, includeCode);
+ return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
}
- public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai) {
- return getPackageInfo(ai, null, false, true);
+ public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
+ CompatibilityInfo compatInfo) {
+ return getPackageInfo(ai, compatInfo, null, false, true);
}
- private final LoadedApk getPackageInfo(ApplicationInfo aInfo,
+ public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
+ synchronized (mPackages) {
+ WeakReference<LoadedApk> ref;
+ if (includeCode) {
+ ref = mPackages.get(packageName);
+ } else {
+ ref = mResourcePackages.get(packageName);
+ }
+ return ref != null ? ref.get() : null;
+ }
+ }
+
+ private final LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
synchronized (mPackages) {
WeakReference<LoadedApk> ref;
@@ -1419,7 +1466,7 @@ public final class ActivityThread {
? mBoundApplication.processName : null)
+ ")");
packageInfo =
- new LoadedApk(this, aInfo, this, baseLoader,
+ new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
if (includeCode) {
@@ -1476,7 +1523,8 @@ public final class ActivityThread {
if (mSystemContext == null) {
ContextImpl context =
ContextImpl.createSystemContext(this);
- LoadedApk info = new LoadedApk(this, "android", context, null);
+ LoadedApk info = new LoadedApk(this, "android", context, null,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
context.init(info, null, this);
context.getResources().updateConfiguration(
getConfiguration(), getDisplayMetricsLocked(false));
@@ -1491,7 +1539,8 @@ public final class ActivityThread {
public void installSystemApplicationInfo(ApplicationInfo info) {
synchronized (this) {
ContextImpl context = getSystemContext();
- context.init(new LoadedApk(this, "android", context, info), null, this);
+ context.init(new LoadedApk(this, "android", context, info,
+ new CompatibilityInfo(info, 0, false)), null, this);
}
}
@@ -1641,7 +1690,7 @@ public final class ActivityThread {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo,
+ r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
@@ -1865,7 +1914,7 @@ public final class ActivityThread {
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
- data.info.applicationInfo);
+ data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
@@ -1926,7 +1975,7 @@ public final class ActivityThread {
unscheduleGcIdler();
// instantiate the BackupAgent class named in the manifest
- LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
String packageName = packageInfo.mPackageName;
if (mBackupAgents.get(packageName) != null) {
Slog.d(TAG, "BackupAgent " + " for " + packageName
@@ -1988,7 +2037,7 @@ public final class ActivityThread {
private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
- LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
String packageName = packageInfo.mPackageName;
BackupAgent agent = mBackupAgents.get(packageName);
if (agent != null) {
@@ -2010,7 +2059,7 @@ public final class ActivityThread {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
- data.info.applicationInfo);
+ data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
@@ -2727,6 +2776,18 @@ public final class ActivityThread {
}
}
+ private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
+ LoadedApk apk = peekPackageInfo(data.pkg, false);
+ if (apk != null) {
+ apk.mCompatibilityInfo = data.info;
+ }
+ apk = peekPackageInfo(data.pkg, true);
+ if (apk != null) {
+ apk.mCompatibilityInfo = data.info;
+ }
+ handleConfigurationChanged(mConfiguration, data.info);
+ }
+
private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
final int N = results.size();
for (int i=0; i<N; i++) {
@@ -3064,7 +3125,7 @@ public final class ActivityThread {
// If there was a pending configuration change, execute it first.
if (changedConfig != null) {
- handleConfigurationChanged(changedConfig);
+ handleConfigurationChanged(changedConfig, null);
}
ActivityClientRecord r = mActivities.get(tmp.token);
@@ -3234,11 +3295,12 @@ public final class ActivityThread {
}
}
- final boolean applyConfigurationToResourcesLocked(Configuration config) {
+ final boolean applyConfigurationToResourcesLocked(Configuration config,
+ CompatibilityInfo compat) {
if (mResConfiguration == null) {
mResConfiguration = new Configuration();
}
- if (!mResConfiguration.isOtherSeqNewer(config)) {
+ if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
+ mResConfiguration.seq + ", newSeq=" + config.seq);
return false;
@@ -3251,7 +3313,7 @@ public final class ActivityThread {
Locale.setDefault(config.locale);
}
- Resources.updateSystemConfiguration(config, dm);
+ Resources.updateSystemConfiguration(config, dm, compat);
ApplicationPackageManager.configurationChanged();
//Slog.i(TAG, "Configuration changed in " + currentPackageName());
@@ -3266,7 +3328,7 @@ public final class ActivityThread {
if (r != null) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
+ r + " config to: " + config);
- r.updateConfiguration(config, dm);
+ r.updateConfiguration(config, dm, compat);
//Slog.i(TAG, "Updated app resources " + v.getKey()
// + " " + r + ": " + r.getConfiguration());
} else {
@@ -3278,7 +3340,7 @@ public final class ActivityThread {
return changes != 0;
}
- final void handleConfigurationChanged(Configuration config) {
+ final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
ArrayList<ComponentCallbacks> callbacks = null;
@@ -3297,15 +3359,21 @@ public final class ActivityThread {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
+ config);
- applyConfigurationToResourcesLocked(config);
+ applyConfigurationToResourcesLocked(config, compat);
if (mConfiguration == null) {
mConfiguration = new Configuration();
}
- if (!mConfiguration.isOtherSeqNewer(config)) {
+ if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
return;
}
mConfiguration.updateFrom(config);
+ if (compat != null) {
+ // Can't do this here, because it causes us to report the
+ // comatible config back to the am as the current config
+ // of the activity, and much unhappiness results.
+ //compat.applyToConfiguration(mConfiguration);
+ }
callbacks = collectComponentCallbacksLocked(false, config);
}
@@ -3445,9 +3513,10 @@ public final class ActivityThread {
* reflect configuration changes. The configuration object passed
* in AppBindData can be safely assumed to be up to date
*/
- Resources.getSystem().updateConfiguration(mConfiguration, null);
+ Resources.getSystem().updateConfiguration(mConfiguration,
+ Resources.getSystem().getDisplayMetrics(), data.compatInfo);
- data.info = getPackageInfoNoCheck(data.appInfo);
+ data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
/**
* For system applications on userdebug/eng builds, log stack
@@ -3539,7 +3608,7 @@ public final class ActivityThread {
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
- LoadedApk pi = getPackageInfo(instrApp,
+ LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true);
ContextImpl instrContext = new ContextImpl();
instrContext.init(pi, null, this);
@@ -3953,7 +4022,7 @@ public final class ActivityThread {
// We need to apply this change to the resources
// immediately, because upon returning the view
// hierarchy will be informed about it.
- if (applyConfigurationToResourcesLocked(newConfig)) {
+ if (applyConfigurationToResourcesLocked(newConfig, null)) {
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index aa26b04..e1d76a4 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -23,6 +23,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.Bundle;
@@ -131,12 +132,13 @@ public abstract class ApplicationThreadNative extends Binder
IBinder b = data.readStrongBinder();
int ident = data.readInt();
ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
Bundle state = data.readBundle();
List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
boolean notResumed = data.readInt() != 0;
boolean isForward = data.readInt() != 0;
- scheduleLaunchActivity(intent, b, ident, info, state, ri, pi,
+ scheduleLaunchActivity(intent, b, ident, info, compatInfo, state, ri, pi,
notResumed, isForward);
return true;
}
@@ -181,11 +183,12 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
Intent intent = Intent.CREATOR.createFromParcel(data);
ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
int resultCode = data.readInt();
String resultData = data.readString();
Bundle resultExtras = data.readBundle();
boolean sync = data.readInt() != 0;
- scheduleReceiver(intent, info, resultCode, resultData,
+ scheduleReceiver(intent, info, compatInfo, resultCode, resultData,
resultExtras, sync);
return true;
}
@@ -194,7 +197,8 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
- scheduleCreateService(token, info);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
+ scheduleCreateService(token, info, compatInfo);
return true;
}
@@ -256,12 +260,13 @@ public abstract class ApplicationThreadNative extends Binder
int testMode = data.readInt();
boolean restrictedBackupMode = (data.readInt() != 0);
Configuration config = Configuration.CREATOR.createFromParcel(data);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
HashMap<String, IBinder> services = data.readHashMap(null);
Bundle coreSettings = data.readBundle();
bindApplication(packageName, info,
providers, testName, profileName,
testArgs, testWatcher, testMode, restrictedBackupMode,
- config, services, coreSettings);
+ config, compatInfo, services, coreSettings);
return true;
}
@@ -389,8 +394,9 @@ public abstract class ApplicationThreadNative extends Binder
{
data.enforceInterface(IApplicationThread.descriptor);
ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
int backupMode = data.readInt();
- scheduleCreateBackupAgent(appInfo, backupMode);
+ scheduleCreateBackupAgent(appInfo, compatInfo, backupMode);
return true;
}
@@ -398,7 +404,8 @@ public abstract class ApplicationThreadNative extends Binder
{
data.enforceInterface(IApplicationThread.descriptor);
ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data);
- scheduleDestroyBackupAgent(appInfo);
+ CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
+ scheduleDestroyBackupAgent(appInfo, compatInfo);
return true;
}
@@ -456,12 +463,20 @@ public abstract class ApplicationThreadNative extends Binder
return true;
}
- case SET_CORE_SETTINGS: {
+ case SET_CORE_SETTINGS_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
Bundle settings = data.readBundle();
setCoreSettings(settings);
return true;
}
+
+ case UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION: {
+ data.enforceInterface(IApplicationThread.descriptor);
+ String pkg = data.readString();
+ CompatibilityInfo compat = CompatibilityInfo.CREATOR.createFromParcel(data);
+ updatePackageCompatibilityInfo(pkg, compat);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -554,7 +569,8 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
+ ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
+ List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -563,6 +579,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeStrongBinder(token);
data.writeInt(ident);
info.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
data.writeBundle(state);
data.writeTypedList(pendingResults);
data.writeTypedList(pendingNewIntents);
@@ -619,12 +636,13 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public final void scheduleReceiver(Intent intent, ActivityInfo info,
- int resultCode, String resultData,
+ CompatibilityInfo compatInfo, int resultCode, String resultData,
Bundle map, boolean sync) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
intent.writeToParcel(data, 0);
info.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
@@ -634,32 +652,36 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
- public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode)
- throws RemoteException {
+ public final void scheduleCreateBackupAgent(ApplicationInfo app,
+ CompatibilityInfo compatInfo, int backupMode) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
app.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
data.writeInt(backupMode);
mRemote.transact(SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
- public final void scheduleDestroyBackupAgent(ApplicationInfo app) throws RemoteException {
+ public final void scheduleDestroyBackupAgent(ApplicationInfo app,
+ CompatibilityInfo compatInfo) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
app.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
mRemote.transact(SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
- public final void scheduleCreateService(IBinder token, ServiceInfo info)
- throws RemoteException {
+ public final void scheduleCreateService(IBinder token, ServiceInfo info,
+ CompatibilityInfo compatInfo) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
@@ -719,7 +741,7 @@ class ApplicationThreadProxy implements IApplicationThread {
public final void bindApplication(String packageName, ApplicationInfo info,
List<ProviderInfo> providers, ComponentName testName,
String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
- boolean restrictedBackupMode, Configuration config,
+ boolean restrictedBackupMode, Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -738,6 +760,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeInt(debugMode);
data.writeInt(restrictedBackupMode ? 1 : 0);
config.writeToParcel(data, 0);
+ compatInfo.writeToParcel(data, 0);
data.writeMap(services);
data.writeBundle(coreSettings);
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
@@ -952,6 +975,16 @@ class ApplicationThreadProxy implements IApplicationThread {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeBundle(coreSettings);
- mRemote.transact(SET_CORE_SETTINGS, data, null, IBinder.FLAG_ONEWAY);
+ mRemote.transact(SET_CORE_SETTINGS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+ }
+
+ public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeString(pkg);
+ info.writeToParcel(data, 0);
+ mRemote.transact(UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION, data, null,
+ IBinder.FLAG_ONEWAY);
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index cc1f81c..36b9d72 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1372,7 +1372,7 @@ class ContextImpl extends Context {
}
LoadedApk pi =
- mMainThread.getPackageInfo(packageName, flags);
+ mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
if (pi != null) {
ContextImpl c = new ContextImpl();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
@@ -1454,7 +1454,7 @@ class ContextImpl extends Context {
" compatiblity info:" + container.getDisplayMetrics());
}
mResources = mainThread.getTopLevelResources(
- mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
+ mPackageInfo.getResDir(), container.getCompatibilityInfo());
}
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 61e6fc8..4c2ccf4 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -342,6 +342,9 @@ public interface IActivityManager extends IInterface {
public int startActivitiesInPackage(int uid,
Intent[] intents, String[] resolvedTypes, IBinder resultTo) throws RemoteException;
+ public void setPackageScreenCompatMode(String packageName, boolean compatEnabled)
+ throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -557,4 +560,5 @@ public interface IActivityManager extends IInterface {
int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
+ int SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 55177a9..93a8ff3 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -23,6 +23,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Debug;
@@ -52,7 +53,8 @@ public interface IApplicationThread extends IInterface {
void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
+ ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
+ List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
@@ -61,14 +63,17 @@ public interface IApplicationThread extends IInterface {
void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
- void scheduleReceiver(Intent intent, ActivityInfo info, int resultCode,
- String data, Bundle extras, boolean sync) throws RemoteException;
+ void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
+ int resultCode, String data, Bundle extras, boolean sync) throws RemoteException;
static final int BACKUP_MODE_INCREMENTAL = 0;
static final int BACKUP_MODE_FULL = 1;
static final int BACKUP_MODE_RESTORE = 2;
- void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) throws RemoteException;
- void scheduleDestroyBackupAgent(ApplicationInfo app) throws RemoteException;
- void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException;
+ void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,
+ int backupMode) throws RemoteException;
+ void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)
+ throws RemoteException;
+ void scheduleCreateService(IBinder token, ServiceInfo info,
+ CompatibilityInfo compatInfo) throws RemoteException;
void scheduleBindService(IBinder token,
Intent intent, boolean rebind) throws RemoteException;
void scheduleUnbindService(IBinder token,
@@ -82,7 +87,7 @@ public interface IApplicationThread extends IInterface {
void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
ComponentName testName, String profileName, Bundle testArguments,
IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
- Configuration config, Map<String, IBinder> services,
+ Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) throws RemoteException;
void scheduleExit() throws RemoteException;
void scheduleSuicide() throws RemoteException;
@@ -112,6 +117,7 @@ public interface IApplicationThread extends IInterface {
void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
throws RemoteException;
void setCoreSettings(Bundle coreSettings) throws RemoteException;
+ void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -153,5 +159,6 @@ public interface IApplicationThread extends IInterface {
int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
- int SET_CORE_SETTINGS = IBinder.FIRST_CALL_TRANSACTION+39;
+ int SET_CORE_SETTINGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39;
+ int UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index c406524..5307696 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -99,6 +99,7 @@ final class LoadedApk {
}
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
+ CompatibilityInfo compatInfo,
ActivityThread mainThread, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode) {
mActivityThread = activityThread;
@@ -114,7 +115,7 @@ final class LoadedApk {
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
- mCompatibilityInfo = new CompatibilityInfo(aInfo);
+ mCompatibilityInfo = compatInfo;
if (mAppDir == null) {
if (ActivityThread.mSystemContext == null) {
@@ -122,7 +123,8 @@ final class LoadedApk {
ContextImpl.createSystemContext(mainThread);
ActivityThread.mSystemContext.getResources().updateConfiguration(
mainThread.getConfiguration(),
- mainThread.getDisplayMetricsLocked(false));
+ mainThread.getDisplayMetricsLocked(false),
+ compatInfo);
//Slog.i(TAG, "Created system resources "
// + mSystemContext.getResources() + ": "
// + mSystemContext.getResources().getConfiguration());
@@ -133,7 +135,7 @@ final class LoadedApk {
}
public LoadedApk(ActivityThread activityThread, String name,
- Context systemContext, ApplicationInfo info) {
+ Context systemContext, ApplicationInfo info, CompatibilityInfo compatInfo) {
mActivityThread = activityThread;
mApplicationInfo = info != null ? info : new ApplicationInfo();
mApplicationInfo.packageName = name;
@@ -149,7 +151,7 @@ final class LoadedApk {
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
- mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
+ mCompatibilityInfo = compatInfo;
}
public String getPackageName() {
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index e403ac2..ab9bfce 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -21,9 +21,9 @@ import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -34,32 +34,27 @@ import android.view.WindowManager.LayoutParams;
*
* {@hide}
*/
-public class CompatibilityInfo {
- private static final boolean DBG = false;
- private static final String TAG = "CompatibilityInfo";
-
+public class CompatibilityInfo implements Parcelable {
/** default compatibility info object for compatible applications */
public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() {
- @Override
- public void setExpandable(boolean expandable) {
- throw new UnsupportedOperationException("trying to change default compatibility info");
- }
};
/**
- * The default width of the screen in portrait mode.
+ * This is the number of pixels we would like to have along the
+ * short axis of an app that needs to run on a normal size screen.
*/
- public static final int DEFAULT_PORTRAIT_WIDTH = 320;
+ public static final int DEFAULT_NORMAL_SHORT_DIMENSION = 320;
/**
- * The default height of the screen in portrait mode.
- */
- public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
+ * This is the maximum aspect ratio we will allow while keeping
+ * applications in a compatible screen size.
+ */
+ public static final float MAXIMUM_ASPECT_RATIO = (854f/480f);
/**
* A compatibility flags
*/
- private int mCompatibilityFlags;
+ private final int mCompatibilityFlags;
/**
* A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
@@ -68,54 +63,27 @@ public class CompatibilityInfo {
private static final int SCALING_REQUIRED = 1;
/**
- * A flag mask to indicates that the application can expand over the original size.
- * The flag is set to true if
- * 1) Application declares its expandable in manifest file using <supports-screens> or
- * 2) Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set
- * {@see compatibilityFlag}
+ * Has the application said that its UI is expandable? Based on the
+ * <supports-screen> android:expandible in the manifest.
*/
private static final int EXPANDABLE = 2;
/**
- * A flag mask to tell if the application is configured to be expandable. This differs
- * from EXPANDABLE in that the application that is not expandable will be
- * marked as expandable if Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set.
- */
- private static final int CONFIGURED_EXPANDABLE = 4;
-
- /**
- * A flag mask to indicates that the application supports large screens.
- * The flag is set to true if
- * 1) Application declares it supports large screens in manifest file using <supports-screens> or
- * 2) The screen size is not large
- * {@see compatibilityFlag}
+ * Has the application said that its UI supports large screens? Based on the
+ * <supports-screen> android:largeScreens in the manifest.
*/
private static final int LARGE_SCREENS = 8;
/**
- * A flag mask to tell if the application supports large screens. This differs
- * from LARGE_SCREENS in that the application that does not support large
- * screens will be marked as supporting them if the current screen is not
- * large.
- */
- private static final int CONFIGURED_LARGE_SCREENS = 16;
-
- /**
- * A flag mask to indicates that the application supports xlarge screens.
- * The flag is set to true if
- * 1) Application declares it supports xlarge screens in manifest file using <supports-screens> or
- * 2) The screen size is not xlarge
- * {@see compatibilityFlag}
+ * Has the application said that its UI supports xlarge screens? Based on the
+ * <supports-screen> android:xlargeScreens in the manifest.
*/
private static final int XLARGE_SCREENS = 32;
/**
- * A flag mask to tell if the application supports xlarge screens. This differs
- * from XLARGE_SCREENS in that the application that does not support xlarge
- * screens will be marked as supporting them if the current screen is not
- * xlarge.
+ * Set if the application needs to run in screen size compatibility mode.
*/
- private static final int CONFIGURED_XLARGE_SCREENS = 64;
+ private static final int NEEDS_SCREEN_COMPAT = 128;
/**
* The effective screen density we have selected for this application.
@@ -132,28 +100,55 @@ public class CompatibilityInfo {
*/
public final float applicationInvertedScale;
- /**
- * The flags from ApplicationInfo.
- */
- public final int appFlags;
-
- public CompatibilityInfo(ApplicationInfo appInfo) {
- appFlags = appInfo.flags;
-
+ public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) {
+ int compatFlags = 0;
+
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
- // Saying you support large screens also implies you support xlarge
- // screens; there is no compatibility mode for a large app on an
- // xlarge screen.
- mCompatibilityFlags |= LARGE_SCREENS | CONFIGURED_LARGE_SCREENS
- | XLARGE_SCREENS | CONFIGURED_XLARGE_SCREENS
- | EXPANDABLE | CONFIGURED_EXPANDABLE;
+ compatFlags |= LARGE_SCREENS;
+ if (!forceCompat) {
+ // If we aren't forcing the app into compatibility mode, then
+ // assume if it supports large screens that we should allow it
+ // to use the full space of an xlarge screen as well.
+ compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ }
}
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
- mCompatibilityFlags |= XLARGE_SCREENS | CONFIGURED_XLARGE_SCREENS
- | EXPANDABLE | CONFIGURED_EXPANDABLE;
+ compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ }
+ if (!forceCompat) {
+ // If we are forcing compatibility mode, then ignore an app that
+ // 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
+ // are running in.
+ if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+ compatFlags |= EXPANDABLE;
+ }
+ }
+
+ boolean supportsScreen = false;
+ switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) {
+ case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+ if ((compatFlags&XLARGE_SCREENS) != 0) {
+ supportsScreen = true;
+ }
+ break;
+ case Configuration.SCREENLAYOUT_SIZE_LARGE:
+ if ((compatFlags&LARGE_SCREENS) != 0) {
+ supportsScreen = true;
+ }
+ break;
+ }
+
+ if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) {
+ if ((compatFlags&EXPANDABLE) != 0) {
+ supportsScreen = true;
+ }
}
- if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
- mCompatibilityFlags |= EXPANDABLE | CONFIGURED_EXPANDABLE;
+
+ if (supportsScreen) {
+ compatFlags &= ~NEEDS_SCREEN_COMPAT;
+ } else {
+ compatFlags |= NEEDS_SCREEN_COMPAT;
}
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
@@ -165,13 +160,14 @@ public class CompatibilityInfo {
applicationScale = DisplayMetrics.DENSITY_DEVICE
/ (float) DisplayMetrics.DENSITY_DEFAULT;
applicationInvertedScale = 1.0f / applicationScale;
- mCompatibilityFlags |= SCALING_REQUIRED;
+ compatFlags |= SCALING_REQUIRED;
}
+
+ mCompatibilityFlags = compatFlags;
}
- private CompatibilityInfo(int appFlags, int compFlags,
+ private CompatibilityInfo(int compFlags,
int dens, float scale, float invertedScale) {
- this.appFlags = appFlags;
mCompatibilityFlags = compFlags;
applicationDensity = dens;
applicationScale = scale;
@@ -179,81 +175,13 @@ public class CompatibilityInfo {
}
private CompatibilityInfo() {
- this(ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
- | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
- | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
- | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS
- | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS,
- EXPANDABLE | CONFIGURED_EXPANDABLE,
+ this(XLARGE_SCREENS | LARGE_SCREENS | EXPANDABLE,
DisplayMetrics.DENSITY_DEVICE,
1.0f,
1.0f);
}
/**
- * Returns the copy of this instance.
- */
- public CompatibilityInfo copy() {
- CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags,
- applicationDensity, applicationScale, applicationInvertedScale);
- return info;
- }
-
- /**
- * Sets expandable bit in the compatibility flag.
- */
- public void setExpandable(boolean expandable) {
- if (expandable) {
- mCompatibilityFlags |= CompatibilityInfo.EXPANDABLE;
- } else {
- mCompatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
- }
- }
-
- /**
- * Sets large screen bit in the compatibility flag.
- */
- public void setLargeScreens(boolean expandable) {
- if (expandable) {
- mCompatibilityFlags |= CompatibilityInfo.LARGE_SCREENS;
- } else {
- mCompatibilityFlags &= ~CompatibilityInfo.LARGE_SCREENS;
- }
- }
-
- /**
- * Sets large screen bit in the compatibility flag.
- */
- public void setXLargeScreens(boolean expandable) {
- if (expandable) {
- mCompatibilityFlags |= CompatibilityInfo.XLARGE_SCREENS;
- } else {
- mCompatibilityFlags &= ~CompatibilityInfo.XLARGE_SCREENS;
- }
- }
-
- /**
- * @return true if the application is configured to be expandable.
- */
- public boolean isConfiguredExpandable() {
- return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
- }
-
- /**
- * @return true if the application is configured to be expandable.
- */
- public boolean isConfiguredLargeScreens() {
- return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_LARGE_SCREENS) != 0;
- }
-
- /**
- * @return true if the application is configured to be expandable.
- */
- public boolean isConfiguredXLargeScreens() {
- return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_XLARGE_SCREENS) != 0;
- }
-
- /**
* @return true if the scaling is required
*/
public boolean isScalingRequired() {
@@ -261,14 +189,12 @@ public class CompatibilityInfo {
}
public boolean supportsScreen() {
- return (mCompatibilityFlags & (EXPANDABLE|LARGE_SCREENS))
- == (EXPANDABLE|LARGE_SCREENS);
+ return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
}
@Override
public String toString() {
- return "CompatibilityInfo{scale=" + applicationScale +
- ", supports screen=" + supportsScreen() + "}";
+ return "CompatibilityInfo{scale=" + applicationScale + "}";
}
/**
@@ -423,24 +349,144 @@ public class CompatibilityInfo {
}
}
+ public void applyToDisplayMetrics(DisplayMetrics inoutDm) {
+ if (!supportsScreen()) {
+ // This is a larger screen device and the app is not
+ // compatible with large screens, so diddle it.
+ CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm);
+ }
+
+ if (isScalingRequired()) {
+ float invertedRatio = applicationInvertedScale;
+ inoutDm.density *= invertedRatio;
+ inoutDm.densityDpi = (int)((inoutDm.density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
+ inoutDm.scaledDensity *= invertedRatio;
+ inoutDm.xdpi *= invertedRatio;
+ inoutDm.ydpi *= invertedRatio;
+ inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
+ inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
+ }
+ }
+
+ public void applyToConfiguration(Configuration inoutConfig) {
+ if (!supportsScreen()) {
+ // This is a larger screen device and the app is not
+ // compatible with large screens, so we are forcing it to
+ // run as if the screen is normal size.
+ inoutConfig.screenLayout =
+ (inoutConfig.screenLayout&~Configuration.SCREENLAYOUT_SIZE_MASK)
+ | Configuration.SCREENLAYOUT_SIZE_NORMAL;
+ }
+ }
+
/**
- * Returns the frame Rect for applications runs under compatibility mode.
+ * Compute the frame Rect for applications runs under compatibility mode.
*
* @param dm the display metrics used to compute the frame size.
* @param orientation the orientation of the screen.
* @param outRect the output parameter which will contain the result.
+ * @return Returns the scaling factor for the window.
*/
- public static void updateCompatibleScreenFrame(DisplayMetrics dm, int orientation,
- Rect outRect) {
- int width = dm.widthPixels;
- int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density + 0.5f);
- int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density + 0.5f);
- if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
- int xOffset = (width - portraitHeight) / 2 ;
- outRect.set(xOffset, 0, xOffset + portraitHeight, portraitWidth);
+ public static float updateCompatibleScreenFrame(DisplayMetrics dm,
+ Rect outRect, DisplayMetrics outDm) {
+ final int width = dm.realWidthPixels;
+ final int height = dm.realHeightPixels;
+ int shortSize, longSize;
+ if (width < height) {
+ shortSize = width;
+ longSize = height;
+ } else {
+ shortSize = height;
+ longSize = width;
+ }
+ int newShortSize = (int)(DEFAULT_NORMAL_SHORT_DIMENSION * dm.density + 0.5f);
+ float aspect = ((float)longSize) / shortSize;
+ if (aspect > MAXIMUM_ASPECT_RATIO) {
+ aspect = MAXIMUM_ASPECT_RATIO;
+ }
+ int newLongSize = (int)(newShortSize * aspect + 0.5f);
+ int newWidth, newHeight;
+ if (width < height) {
+ newWidth = newShortSize;
+ newHeight = newLongSize;
} else {
- int xOffset = (width - portraitWidth) / 2 ;
- outRect.set(xOffset, 0, xOffset + portraitWidth, portraitHeight);
+ newWidth = newLongSize;
+ newHeight = newShortSize;
+ }
+
+ float sw = width/(float)newWidth;
+ float sh = height/(float)newHeight;
+ float scale = sw < sh ? sw : sh;
+ if (scale < 1) {
+ scale = 1;
}
+
+ if (outRect != null) {
+ final int left = (int)((width-(newWidth*scale))/2);
+ final int top = (int)((height-(newHeight*scale))/2);
+ outRect.set(left, top, left+newWidth, top+newHeight);
+ }
+
+ if (outDm != null) {
+ outDm.widthPixels = newWidth;
+ outDm.heightPixels = newHeight;
+ }
+
+ return scale;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ try {
+ CompatibilityInfo oc = (CompatibilityInfo)o;
+ if (mCompatibilityFlags != oc.mCompatibilityFlags) return false;
+ if (applicationDensity != oc.applicationDensity) return false;
+ if (applicationScale != oc.applicationScale) return false;
+ if (applicationInvertedScale != oc.applicationInvertedScale) return false;
+ return true;
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + mCompatibilityFlags;
+ result = 31 * result + applicationDensity;
+ result = 31 * result + Float.floatToIntBits(applicationScale);
+ result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
+ return result;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mCompatibilityFlags);
+ dest.writeInt(applicationDensity);
+ dest.writeFloat(applicationScale);
+ dest.writeFloat(applicationInvertedScale);
+ }
+
+ public static final Parcelable.Creator<CompatibilityInfo> CREATOR
+ = new Parcelable.Creator<CompatibilityInfo>() {
+ public CompatibilityInfo createFromParcel(Parcel source) {
+ return new CompatibilityInfo(source);
+ }
+
+ public CompatibilityInfo[] newArray(int size) {
+ return new CompatibilityInfo[size];
+ }
+ };
+
+ private CompatibilityInfo(Parcel source) {
+ mCompatibilityFlags = source.readInt();
+ applicationDensity = source.readInt();
+ applicationScale = source.readFloat();
+ applicationInvertedScale = source.readFloat();
}
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 47c2623..908db11 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -703,11 +703,20 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
public int hashCode() {
- return ((int)this.fontScale) + this.mcc + this.mnc
- + (this.locale != null ? this.locale.hashCode() : 0)
- + this.touchscreen
- + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
- + this.navigation + this.navigationHidden
- + this.orientation + this.screenLayout + this.uiMode;
+ int result = 17;
+ result = 31 * result + Float.floatToIntBits(fontScale);
+ result = 31 * result + mcc;
+ result = 31 * result + mnc;
+ result = 31 * result + (locale != null ? locale.hashCode() : 0);
+ result = 31 * result + touchscreen;
+ result = 31 * result + keyboard;
+ result = 31 * result + keyboardHidden;
+ result = 31 * result + hardKeyboardHidden;
+ result = 31 * result + navigation;
+ result = 31 * result + navigationHidden;
+ result = 31 * result + orientation;
+ result = 31 * result + screenLayout;
+ result = 31 * result + uiMode;
+ return result;
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 81eb09c..00b49e8 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -91,6 +91,7 @@ public class Resources {
private static boolean mPreloaded;
/*package*/ final TypedValue mTmpValue = new TypedValue();
+ /*package*/ final Configuration mTmpConfig = new Configuration();
// These are protected by the mTmpValue lock.
private final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
@@ -1400,18 +1401,30 @@ public class Resources {
*/
public void updateConfiguration(Configuration config,
DisplayMetrics metrics) {
+ updateConfiguration(config, metrics, null);
+ }
+
+ /**
+ * @hide
+ */
+ public void updateConfiguration(Configuration config,
+ DisplayMetrics metrics, CompatibilityInfo compat) {
synchronized (mTmpValue) {
+ if (compat != null) {
+ mCompatibilityInfo = compat;
+ }
int configChanges = 0xfffffff;
if (config != null) {
- configChanges = mConfiguration.updateFrom(config);
+ mTmpConfig.setTo(config);
+ mCompatibilityInfo.applyToConfiguration(mTmpConfig);
+ configChanges = mConfiguration.updateFrom(mTmpConfig);
}
if (mConfiguration.locale == null) {
mConfiguration.locale = Locale.getDefault();
}
if (metrics != null) {
mMetrics.setTo(metrics);
- mMetrics.updateMetrics(mCompatibilityInfo,
- mConfiguration.orientation, mConfiguration.screenLayout);
+ mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
@@ -1500,15 +1513,23 @@ public class Resources {
*
* @hide
*/
- public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
+ public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics,
+ CompatibilityInfo compat) {
if (mSystem != null) {
- mSystem.updateConfiguration(config, metrics);
+ mSystem.updateConfiguration(config, metrics, compat);
//Log.i(TAG, "Updated system resources " + mSystem
// + ": " + mSystem.getConfiguration());
}
}
/**
+ * @hide
+ */
+ public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
+ updateSystemConfiguration(config, metrics, null);
+ }
+
+ /**
* Return the current display metrics that are in effect for this resource
* object. The returned object should be treated as read-only.
*
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 63baf14..8018ff9 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,9 +16,7 @@
package android.util;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.os.*;
+import android.os.SystemProperties;
/**
@@ -107,6 +105,11 @@ public class DisplayMetrics {
*/
public float ydpi;
+ /** @hide */
+ public int realWidthPixels;
+ /** @hide */
+ public int realHeightPixels;
+
public DisplayMetrics() {
}
@@ -118,6 +121,8 @@ public class DisplayMetrics {
scaledDensity = o.scaledDensity;
xdpi = o.xdpi;
ydpi = o.ydpi;
+ realWidthPixels = o.realWidthPixels;
+ realHeightPixels = o.realHeightPixels;
}
public void setToDefaults() {
@@ -128,101 +133,8 @@ public class DisplayMetrics {
scaledDensity = density;
xdpi = DENSITY_DEVICE;
ydpi = DENSITY_DEVICE;
- }
-
- /**
- * Update the display metrics based on the compatibility info and orientation
- * NOTE: DO NOT EXPOSE THIS API! It is introducing a circular dependency
- * with the higher-level android.res package.
- * {@hide}
- */
- public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
- int screenLayout) {
- boolean expandable = compatibilityInfo.isConfiguredExpandable();
- boolean largeScreens = compatibilityInfo.isConfiguredLargeScreens();
- boolean xlargeScreens = compatibilityInfo.isConfiguredXLargeScreens();
-
- // Note: this assume that configuration is updated before calling
- // updateMetrics method.
- if (!expandable) {
- if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) {
- expandable = true;
- // the current screen size is compatible with non-resizing apps.
- compatibilityInfo.setExpandable(true);
- } else {
- compatibilityInfo.setExpandable(false);
- }
- }
- if (!largeScreens) {
- if ((screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
- != Configuration.SCREENLAYOUT_SIZE_LARGE) {
- largeScreens = true;
- // the current screen size is not large.
- compatibilityInfo.setLargeScreens(true);
- } else {
- compatibilityInfo.setLargeScreens(false);
- }
- }
- if (!xlargeScreens) {
- if ((screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
- != Configuration.SCREENLAYOUT_SIZE_XLARGE) {
- xlargeScreens = true;
- // the current screen size is not large.
- compatibilityInfo.setXLargeScreens(true);
- } else {
- compatibilityInfo.setXLargeScreens(false);
- }
- }
-
- if (!expandable || (!largeScreens && !xlargeScreens)) {
- // This is a larger screen device and the app is not
- // compatible with large screens, so diddle it.
-
- // Figure out the compatibility width and height of the screen.
- int defaultWidth;
- int defaultHeight;
- switch (orientation) {
- case Configuration.ORIENTATION_LANDSCAPE: {
- defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density +
- 0.5f);
- defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density +
- 0.5f);
- break;
- }
- case Configuration.ORIENTATION_PORTRAIT:
- case Configuration.ORIENTATION_SQUARE:
- default: {
- defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density +
- 0.5f);
- defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density +
- 0.5f);
- break;
- }
- case Configuration.ORIENTATION_UNDEFINED: {
- // don't change
- return;
- }
- }
-
- if (defaultWidth < widthPixels) {
- // content/window's x offset in original pixels
- widthPixels = defaultWidth;
- }
- if (defaultHeight < heightPixels) {
- heightPixels = defaultHeight;
- }
- }
-
- if (compatibilityInfo.isScalingRequired()) {
- float invertedRatio = compatibilityInfo.applicationInvertedScale;
- density *= invertedRatio;
- densityDpi = (int)((density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
- scaledDensity *= invertedRatio;
- xdpi *= invertedRatio;
- ydpi *= invertedRatio;
- widthPixels = (int) (widthPixels * invertedRatio + 0.5f);
- heightPixels = (int) (heightPixels * invertedRatio + 0.5f);
- }
+ realWidthPixels = 0;
+ realHeightPixels = 0;
}
@Override
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 126f409..89767f2 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -139,6 +139,9 @@ public class Display
outMetrics.scaledDensity= outMetrics.density;
outMetrics.xdpi = mDpiX;
outMetrics.ydpi = mDpiY;
+
+ outMetrics.realWidthPixels = outMetrics.widthPixels;
+ outMetrics.realHeightPixels = outMetrics.heightPixels;
}
/*
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 334c68e..2058991 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -458,6 +458,18 @@ public interface WindowManagerPolicy {
public int getMaxWallpaperLayer();
/**
+ * Return the display width available after excluding the window
+ * decor.
+ */
+ public int getNonDecorDisplayWidth(int fullWidth);
+
+ /**
+ * Return the display height available after excluding the screen
+ * decor.
+ */
+ public int getNonDecorDisplayHeight(int fullHeight);
+
+ /**
* Return whether the given window should forcibly hide everything
* behind it. Typically returns true for the keyguard.
*/