summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java5
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java19
-rw-r--r--core/java/android/app/ActivityManager.java76
-rw-r--r--core/java/android/app/ActivityManagerNative.java72
-rw-r--r--core/java/android/app/IActivityManager.java10
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java30
-rw-r--r--packages/SystemUI/res/drawable-mdpi/hd_off.pngbin0 -> 3634 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/hd_on.pngbin0 -> 3507 bytes
-rw-r--r--packages/SystemUI/res/drawable/hd.xml21
-rw-r--r--packages/SystemUI/res/layout-large/status_bar_recent_panel.xml12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java31
-rw-r--r--services/java/com/android/server/PackageManagerService.java7
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java112
-rw-r--r--services/java/com/android/server/am/CompatModePackages.java295
14 files changed, 602 insertions, 88 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 5c8abe4..8a9144c 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -18,6 +18,7 @@
package com.android.commands.am;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityController;
import android.app.IActivityManager;
@@ -794,7 +795,9 @@ public class Am {
String packageName = nextArgRequired();
do {
try {
- mAm.setPackageScreenCompatMode(packageName, enabled);
+ mAm.setPackageScreenCompatMode(packageName, enabled
+ ? ActivityManager.COMPAT_MODE_ENABLED
+ : ActivityManager.COMPAT_MODE_DISABLED);
} catch (RemoteException e) {
}
packageName = nextArg();
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index d058e38..b759de0 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -193,6 +193,7 @@ public final class Pm {
private void runListPackages(boolean showApplicationPackage) {
int getFlags = 0;
boolean listDisabled = false, listEnabled = false;
+ boolean listSystem = false, listThirdParty = false;
try {
String opt;
while ((opt=nextOption()) != null) {
@@ -206,6 +207,10 @@ public final class Pm {
listDisabled = true;
} else if (opt.equals("-e")) {
listEnabled = true;
+ } else if (opt.equals("-s")) {
+ listSystem = true;
+ } else if (opt.equals("-3")) {
+ listThirdParty = true;
} else if (opt.equals("-u")) {
getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
} else {
@@ -231,8 +236,12 @@ public final class Pm {
if (filter != null && !info.packageName.contains(filter)) {
continue;
}
+ final boolean isSystem =
+ (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
if ((!listDisabled || !info.applicationInfo.enabled) &&
- (!listEnabled || info.applicationInfo.enabled)) {
+ (!listEnabled || info.applicationInfo.enabled) &&
+ (!listSystem || isSystem) &&
+ (!listThirdParty || !isSystem)) {
System.out.print("package:");
if (showApplicationPackage) {
System.out.print(info.applicationInfo.sourceDir);
@@ -993,7 +1002,7 @@ public final class Pm {
private static void showUsage() {
System.err.println("usage: pm [list|path|install|uninstall]");
- System.err.println(" pm list packages [-f] [-d] [-e] [-u] [FILTER]");
+ System.err.println(" pm list packages [-f] [-d] [-e] [-s] [-e] [-u] [FILTER]");
System.err.println(" pm list permission-groups");
System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
@@ -1010,8 +1019,10 @@ public final class Pm {
System.err.println("The list packages command prints all packages, optionally only");
System.err.println("those whose package name contains the text in FILTER. Options:");
System.err.println(" -f: see their associated file.");
- System.err.println(" -d: filter to include disbled packages.");
- System.err.println(" -e: filter to include enabled packages.");
+ System.err.println(" -d: filter to only show disbled packages.");
+ System.err.println(" -e: filter to only show enabled packages.");
+ System.err.println(" -s: filter to only show system packages.");
+ System.err.println(" -3: filter to only show third party packages.");
System.err.println(" -u: also include uninstalled packages.");
System.err.println("");
System.err.println("The list permission-groups command prints all known");
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b6581e9..e4499797 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -59,6 +59,82 @@ public class ActivityManager {
}
/**
+ * Screen compatibility mode: the application most always run in
+ * compatibility mode.
+ * @hide
+ */
+ public static final int COMPAT_MODE_ALWAYS = -1;
+
+ /**
+ * Screen compatibility mode: the application can never run in
+ * compatibility mode.
+ * @hide
+ */
+ public static final int COMPAT_MODE_NEVER = -2;
+
+ /**
+ * Screen compatibility mode: unknown.
+ * @hide
+ */
+ public static final int COMPAT_MODE_UNKNOWN = -3;
+
+ /**
+ * Screen compatibility mode: the application currently has compatibility
+ * mode disabled.
+ * @hide
+ */
+ public static final int COMPAT_MODE_DISABLED = 0;
+
+ /**
+ * Screen compatibility mode: the application currently has compatibility
+ * mode enabled.
+ * @hide
+ */
+ public static final int COMPAT_MODE_ENABLED = 1;
+
+ /**
+ * Screen compatibility mode: request to toggle the application's
+ * compatibility mode.
+ * @hide
+ */
+ public static final int COMPAT_MODE_TOGGLE = 2;
+
+ /** @hide */
+ public int getFrontActivityScreenCompatMode() {
+ try {
+ return ActivityManagerNative.getDefault().getFrontActivityScreenCompatMode();
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return 0;
+ }
+ }
+
+ public void setFrontActivityScreenCompatMode(int mode) {
+ try {
+ ActivityManagerNative.getDefault().setFrontActivityScreenCompatMode(mode);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ }
+ }
+
+ public int getPackageScreenCompatMode(String packageName) {
+ try {
+ return ActivityManagerNative.getDefault().getPackageScreenCompatMode(packageName);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return 0;
+ }
+ }
+
+ public void setPackageScreenCompatMode(String packageName, int mode) {
+ try {
+ ActivityManagerNative.getDefault().setPackageScreenCompatMode(packageName, mode);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ }
+ }
+
+ /**
* Return the approximate per-application memory class of the current
* device. This gives you an idea of how hard a memory limit you should
* impose on your application to let the overall system work best. The
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 11e9975..4beb5cc 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1398,12 +1398,41 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ int mode = getFrontActivityScreenCompatMode();
+ reply.writeNoException();
+ reply.writeInt(mode);
+ return true;
+ }
+
+ case SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ int mode = data.readInt();
+ setFrontActivityScreenCompatMode(mode);
+ reply.writeNoException();
+ reply.writeInt(mode);
+ return true;
+ }
+
+ case GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ int mode = getPackageScreenCompatMode(pkg);
+ reply.writeNoException();
+ reply.writeInt(mode);
+ 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);
+ int mode = data.readInt();
+ setPackageScreenCompatMode(pkg, mode);
reply.writeNoException();
return true;
}
@@ -3152,13 +3181,48 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
- public void setPackageScreenCompatMode(String packageName, boolean compatEnabled)
+ public int getFrontActivityScreenCompatMode() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int mode = reply.readInt();
+ reply.recycle();
+ data.recycle();
+ return mode;
+ }
+
+ public void setFrontActivityScreenCompatMode(int mode) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(mode);
+ mRemote.transact(SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
+ public int getPackageScreenCompatMode(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int mode = reply.readInt();
+ reply.recycle();
+ data.recycle();
+ return mode;
+ }
+
+ public void setPackageScreenCompatMode(String packageName, int mode)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(packageName);
- data.writeInt(compatEnabled ? 1 : 0);
+ data.writeInt(mode);
mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
reply.readException();
reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 4c2ccf4..24706f9 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -342,7 +342,10 @@ 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)
+ public int getFrontActivityScreenCompatMode() throws RemoteException;
+ public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
+ public int getPackageScreenCompatMode(String packageName) throws RemoteException;
+ public void setPackageScreenCompatMode(String packageName, int mode)
throws RemoteException;
/*
@@ -560,5 +563,8 @@ 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;
+ int GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
+ int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
+ int GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+125;
+ int SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+126;
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index ab9bfce..8bcb005 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -81,9 +81,19 @@ public class CompatibilityInfo implements Parcelable {
private static final int XLARGE_SCREENS = 32;
/**
+ * Application must always run in compatibility mode?
+ */
+ private static final int ALWAYS_COMPAT = 64;
+
+ /**
+ * Application never should run in compatibility mode?
+ */
+ private static final int NEVER_COMPAT = 128;
+
+ /**
* Set if the application needs to run in screen size compatibility mode.
*/
- private static final int NEEDS_SCREEN_COMPAT = 128;
+ private static final int NEEDS_SCREEN_COMPAT = 256;
/**
* The effective screen density we have selected for this application.
@@ -131,11 +141,17 @@ public class CompatibilityInfo implements Parcelable {
if ((compatFlags&XLARGE_SCREENS) != 0) {
supportsScreen = true;
}
+ if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
+ compatFlags |= NEVER_COMPAT;
+ }
break;
case Configuration.SCREENLAYOUT_SIZE_LARGE:
if ((compatFlags&LARGE_SCREENS) != 0) {
supportsScreen = true;
}
+ if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+ compatFlags |= NEVER_COMPAT;
+ }
break;
}
@@ -143,6 +159,10 @@ public class CompatibilityInfo implements Parcelable {
if ((compatFlags&EXPANDABLE) != 0) {
supportsScreen = true;
}
+ if ((compatFlags&EXPANDABLE) == 0 &&
+ (appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) == 0) {
+ compatFlags |= ALWAYS_COMPAT;
+ }
}
if (supportsScreen) {
@@ -192,6 +212,14 @@ public class CompatibilityInfo implements Parcelable {
return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
}
+ public boolean neverSupportsScreen() {
+ return (mCompatibilityFlags&NEVER_COMPAT) != 0;
+ }
+
+ public boolean alwaysSupportsScreen() {
+ return (mCompatibilityFlags&ALWAYS_COMPAT) != 0;
+ }
+
@Override
public String toString() {
return "CompatibilityInfo{scale=" + applicationScale + "}";
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_off.png b/packages/SystemUI/res/drawable-mdpi/hd_off.png
new file mode 100644
index 0000000..ad09eef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_on.png b/packages/SystemUI/res/drawable-mdpi/hd_on.png
new file mode 100644
index 0000000..1471c13
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/hd.xml b/packages/SystemUI/res/drawable/hd.xml
new file mode 100644
index 0000000..73867a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/hd.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="false"
+ android:drawable="@drawable/hd_off" />
+ <item android:drawable="@drawable/hd_on" />
+</selector>
diff --git a/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
index 42940be..f019e2d 100644
--- a/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-large/status_bar_recent_panel.xml
@@ -24,11 +24,23 @@
android:layout_height="match_parent"
android:layout_width="wrap_content">
+ <CheckBox android:id="@+id/recents_compat_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginBottom="@*android:dimen/status_bar_height"
+ android:background="@drawable/hd"
+ android:button="@null"
+ />
+
<FrameLayout
android:id="@+id/recents_bg_protect"
android:background="@drawable/recents_bg_protect_tile"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_toLeftOf="@id/recents_compat_mode"
android:layout_alignParentBottom="true"
android:paddingBottom="@*android:dimen/status_bar_height"
android:clipToPadding="false">
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index c5a7df2..7db1ce8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -50,6 +50,7 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
+import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
@@ -69,6 +70,7 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
private View mRecentsScrim;
private View mRecentsGlowView;
private ListView mRecentsContainer;
+ private CheckBox mCompatMode;
private Bitmap mGlowBitmap;
private boolean mShowing;
private Choreographer mChoreo;
@@ -356,6 +358,15 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRecentsContainer = (ListView) findViewById(R.id.recents_container);
+ mCompatMode = (CheckBox) findViewById(R.id.recents_compat_mode);
+ mCompatMode.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ final ActivityManager am = (ActivityManager)
+ mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ am.setFrontActivityScreenCompatMode(ActivityManager.COMPAT_MODE_TOGGLE);
+ hide(true);
+ }
+ });
View footer = inflater.inflate(R.layout.status_bar_recent_panel_footer,
mRecentsContainer, false);
mRecentsContainer.setScrollbarFadingEnabled(true);
@@ -492,12 +503,32 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O
return desc;
}
+ private void updateShownCompatMode() {
+ final ActivityManager am = (ActivityManager)
+ mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ int mode = am.getFrontActivityScreenCompatMode();
+ switch (mode) {
+ case ActivityManager.COMPAT_MODE_DISABLED:
+ mCompatMode.setVisibility(View.VISIBLE);
+ mCompatMode.setChecked(true);
+ break;
+ case ActivityManager.COMPAT_MODE_ENABLED:
+ mCompatMode.setVisibility(View.VISIBLE);
+ mCompatMode.setChecked(false);
+ break;
+ default:
+ mCompatMode.setVisibility(View.GONE);
+ break;
+ }
+ }
+
private void refreshApplicationList() {
mActivityDescriptions = getRecentTasks();
mListAdapter.notifyDataSetInvalidated();
if (mActivityDescriptions.size() > 0) {
mLastVisibleItem = mActivityDescriptions.size() - 1; // scroll to bottom after reloading
updateUiElements(getResources().getConfiguration());
+ updateShownCompatMode();
} else {
// Immediately hide this panel
hide(false);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5cd942c..4a66a40 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -8088,18 +8088,11 @@ class PackageManagerService extends IPackageManager.Stub {
Settings() {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
- // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
- File systemSecureDir = new File(dataDir, "secure/system");
systemDir.mkdirs();
- systemSecureDir.mkdirs();
FileUtils.setPermissions(systemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
- FileUtils.setPermissions(systemSecureDir.toString(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG
- |FileUtils.S_IROTH|FileUtils.S_IXOTH,
- -1, -1);
mSettingsFilename = new File(systemDir, "packages.xml");
mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
mPackageListFilename = new File(systemDir, "packages.list");
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 811221e..6a5ca1f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -550,7 +550,7 @@ public final class ActivityManagerService extends ActivityManagerNative
* Packages that the user has asked to have run in screen size
* compatibility mode instead of filling the screen.
*/
- final HashSet<String> mScreenCompatPackages = new HashSet<String>();
+ final CompatModePackages mCompatModePackages;
/**
* Set of PendingResultRecord objects that are currently active.
@@ -1485,6 +1485,8 @@ public final class ActivityManagerService extends ActivityManagerNative
mConfiguration.locale = Locale.getDefault();
mProcessStats.init();
+ mCompatModePackages = new CompatModePackages(this, systemDir);
+
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
@@ -2099,70 +2101,30 @@ public final class ActivityManagerService extends ActivityManagerNative
}
CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
- return new CompatibilityInfo(ai, mConfiguration.screenLayout,
- mScreenCompatPackages.contains(ai.packageName));
+ return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
}
- public void setPackageScreenCompatMode(String packageName, boolean compatEnabled) {
+ public int getFrontActivityScreenCompatMode() {
synchronized (this) {
- ApplicationInfo ai = null;
- try {
- ai = AppGlobals.getPackageManager().
- getApplicationInfo(packageName, STOCK_PM_FLAGS);
- } catch (RemoteException e) {
- }
- if (ai == null) {
- Slog.w(TAG, "setPackageScreenCompatMode failed: unknown package " + packageName);
- return;
- }
- boolean changed = false;
- if (compatEnabled) {
- if (!mScreenCompatPackages.contains(packageName)) {
- changed = true;
- mScreenCompatPackages.add(packageName);
- }
- } else {
- if (mScreenCompatPackages.contains(packageName)) {
- changed = true;
- mScreenCompatPackages.remove(packageName);
- }
- }
- if (changed) {
- CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
+ return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
+ }
+ }
- // Tell all processes that loaded this package about the change.
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- if (!app.pkgList.contains(packageName)) {
- continue;
- }
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
- + app.processName + " new compat " + ci);
- app.thread.updatePackageCompatibilityInfo(packageName, ci);
- }
- } catch (Exception e) {
- }
- }
+ public void setFrontActivityScreenCompatMode(int mode) {
+ synchronized (this) {
+ mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
+ }
+ }
- // All activities that came from the packge must be
- // restarted as if there was a config change.
- for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
- ActivityRecord a = (ActivityRecord)mMainStack.mHistory.get(i);
- if (a.info.packageName.equals(packageName)) {
- a.forceNewConfig = true;
- }
- }
+ public int getPackageScreenCompatMode(String packageName) {
+ synchronized (this) {
+ return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
+ }
+ }
- ActivityRecord starting = mMainStack.topRunningActivityLocked(null);
- if (starting != null) {
- mMainStack.ensureActivityConfigurationLocked(starting, 0);
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- mMainStack.ensureActivitiesVisibleLocked(starting, 0);
- }
- }
+ public void setPackageScreenCompatMode(String packageName, int mode) {
+ synchronized (this) {
+ mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
}
}
@@ -7855,9 +7817,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println(" mConfiguration: " + mConfiguration);
pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
- if (mScreenCompatPackages.size() > 0) {
+ if (mCompatModePackages.getPackages().size() > 0) {
pw.print(" mScreenCompatPackages=");
- pw.println(mScreenCompatPackages);
+ pw.println(mCompatModePackages.getPackages());
}
pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
@@ -10706,10 +10668,10 @@ public final class ActivityManagerService extends ActivityManagerNative
// Handle special intents: if this broadcast is from the package
// manager about a package being removed, we need to remove all of
// its activities from the history stack.
- final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
+ final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
intent.getAction());
- if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
- || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+ if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
+ || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
|| Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
|| uidRemoved) {
if (checkComponentPermission(
@@ -10746,7 +10708,7 @@ public final class ActivityManagerService extends ActivityManagerNative
forceStopPackageLocked(ssp,
intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
}
- if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
new String[] {ssp});
}
@@ -10762,6 +10724,18 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
+
+ // Special case for adding a package: by default turn on compatibility
+ // mode.
+ } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ mCompatModePackages.setPackageScreenCompatModeLocked(ssp,
+ ActivityManager.COMPAT_MODE_ENABLED);
+ }
+ }
}
/*
@@ -10920,9 +10894,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
String skipPackages[] = null;
- if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
- || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
- || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
+ if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
+ || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
+ || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null) {
String pkgName = data.getSchemeSpecificPart();
@@ -10930,7 +10904,7 @@ public final class ActivityManagerService extends ActivityManagerNative
skipPackages = new String[] { pkgName };
}
}
- } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
+ } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if (skipPackages != null && (skipPackages.length > 0)) {
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
new file mode 100644
index 0000000..1faf8da
--- /dev/null
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -0,0 +1,295 @@
+package com.android.server.am;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import com.android.internal.os.AtomicFile;
+import com.android.internal.util.FastXmlSerializer;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.res.CompatibilityInfo;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.util.Xml;
+
+public class CompatModePackages {
+ private final String TAG = ActivityManagerService.TAG;
+ private final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
+
+ private final ActivityManagerService mService;
+ private final AtomicFile mFile;
+
+ private final HashSet<String> mPackages = new HashSet<String>();
+
+ private static final int MSG_WRITE = 1;
+
+ private final Handler mHandler = new Handler() {
+ @Override public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_WRITE:
+ saveCompatModes();
+ break;
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+ };
+
+ public CompatModePackages(ActivityManagerService service, File systemDir) {
+ mService = service;
+ mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
+
+ FileInputStream fis = null;
+ try {
+ fis = mFile.openRead();
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(fis, null);
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.START_TAG) {
+ eventType = parser.next();
+ }
+ String tagName = parser.getName();
+ if ("compat-packages".equals(tagName)) {
+ eventType = parser.next();
+ do {
+ if (eventType == XmlPullParser.START_TAG) {
+ tagName = parser.getName();
+ if (parser.getDepth() == 2) {
+ if ("pkg".equals(tagName)) {
+ String pkg = parser.getAttributeValue(null, "name");
+ if (pkg != null) {
+ mPackages.add(pkg);
+ }
+ }
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+ }
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Error reading compat-packages", e);
+ } catch (java.io.IOException e) {
+ if (fis != null) Slog.w(TAG, "Error reading compat-packages", e);
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ } catch (java.io.IOException e1) {
+ }
+ }
+ }
+ }
+
+ public HashSet<String> getPackages() {
+ return mPackages;
+ }
+
+ public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
+ return new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
+ mPackages.contains(ai.packageName));
+ }
+
+ private int computeCompatModeLocked(ApplicationInfo ai) {
+ boolean enabled = mPackages.contains(ai.packageName);
+ CompatibilityInfo info = new CompatibilityInfo(ai,
+ mService.mConfiguration.screenLayout, enabled);
+ if (info.alwaysSupportsScreen()) {
+ return ActivityManager.COMPAT_MODE_NEVER;
+ }
+ if (info.neverSupportsScreen()) {
+ return ActivityManager.COMPAT_MODE_ALWAYS;
+ }
+ return enabled ? ActivityManager.COMPAT_MODE_ENABLED
+ : ActivityManager.COMPAT_MODE_DISABLED;
+ }
+
+ public int getFrontActivityScreenCompatModeLocked() {
+ ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
+ if (r == null) {
+ return ActivityManager.COMPAT_MODE_UNKNOWN;
+ }
+ return computeCompatModeLocked(r.info.applicationInfo);
+ }
+
+ public void setFrontActivityScreenCompatModeLocked(int mode) {
+ ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
+ if (r == null) {
+ Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
+ return;
+ }
+ setPackageScreenCompatModeLocked(r.info.applicationInfo, mode);
+ }
+
+ public int getPackageScreenCompatModeLocked(String packageName) {
+ ApplicationInfo ai = null;
+ try {
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ } catch (RemoteException e) {
+ }
+ if (ai == null) {
+ return ActivityManager.COMPAT_MODE_UNKNOWN;
+ }
+ return computeCompatModeLocked(ai);
+ }
+
+ public void setPackageScreenCompatModeLocked(String packageName, int mode) {
+ ApplicationInfo ai = null;
+ try {
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ } catch (RemoteException e) {
+ }
+ if (ai == null) {
+ Slog.w(TAG, "setPackageScreenCompatMode failed: unknown package " + packageName);
+ return;
+ }
+ setPackageScreenCompatModeLocked(ai, mode);
+ }
+
+ private void setPackageScreenCompatModeLocked(ApplicationInfo ai, int mode) {
+ final String packageName = ai.packageName;
+
+ boolean changed = false;
+ boolean enable;
+ switch (mode) {
+ case ActivityManager.COMPAT_MODE_DISABLED:
+ enable = false;
+ break;
+ case ActivityManager.COMPAT_MODE_ENABLED:
+ enable = true;
+ break;
+ case ActivityManager.COMPAT_MODE_TOGGLE:
+ enable = !mPackages.contains(packageName);
+ break;
+ default:
+ Slog.w(TAG, "Unknown screen compat mode req #" + mode + "; ignoring");
+ return;
+ }
+ if (enable) {
+ if (!mPackages.contains(packageName)) {
+ changed = true;
+ mPackages.add(packageName);
+ }
+ } else {
+ if (mPackages.contains(packageName)) {
+ changed = true;
+ mPackages.remove(packageName);
+ }
+ }
+ if (changed) {
+ CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
+ if (ci.alwaysSupportsScreen()) {
+ Slog.w(TAG, "Ignoring compat mode change of " + packageName
+ + "; compatibility never needed");
+ return;
+ }
+ if (ci.neverSupportsScreen()) {
+ Slog.w(TAG, "Ignoring compat mode change of " + packageName
+ + "; compatibility always needed");
+ return;
+ }
+
+ mHandler.removeMessages(MSG_WRITE);
+ Message msg = mHandler.obtainMessage(MSG_WRITE);
+ mHandler.sendMessageDelayed(msg, 10000);
+
+ // Tell all processes that loaded this package about the change.
+ for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
+ ProcessRecord app = mService.mLruProcesses.get(i);
+ if (!app.pkgList.contains(packageName)) {
+ continue;
+ }
+ try {
+ if (app.thread != null) {
+ if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
+ + app.processName + " new compat " + ci);
+ app.thread.updatePackageCompatibilityInfo(packageName, ci);
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ // All activities that came from the packge must be
+ // restarted as if there was a config change.
+ for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
+ if (a.info.packageName.equals(packageName)) {
+ a.forceNewConfig = true;
+ }
+ }
+
+ ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
+ if (starting != null) {
+ mService.mMainStack.ensureActivityConfigurationLocked(starting, 0);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mService.mMainStack.ensureActivitiesVisibleLocked(starting, 0);
+ }
+ }
+ }
+
+ void saveCompatModes() {
+ HashSet<String> pkgs;
+ synchronized (mService) {
+ pkgs = new HashSet<String>(mPackages);
+ }
+
+ FileOutputStream fos = null;
+
+ try {
+ fos = mFile.startWrite();
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(fos, "utf-8");
+ out.startDocument(null, true);
+ out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ out.startTag(null, "compat-packages");
+
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ final int screenLayout = mService.mConfiguration.screenLayout;
+ final Iterator<String> it = pkgs.iterator();
+ while (it.hasNext()) {
+ String pkg = it.next();
+ ApplicationInfo ai = null;
+ try {
+ ai = pm.getApplicationInfo(pkg, 0);
+ } catch (RemoteException e) {
+ }
+ if (ai == null) {
+ continue;
+ }
+ CompatibilityInfo info = new CompatibilityInfo(ai, screenLayout, false);
+ if (info.alwaysSupportsScreen()) {
+ continue;
+ }
+ if (info.neverSupportsScreen()) {
+ continue;
+ }
+ out.startTag(null, "pkg");
+ out.attribute(null, "name", pkg);
+ out.endTag(null, "pkg");
+ }
+
+ out.endTag(null, "compat-packages");
+ out.endDocument();
+
+ mFile.finishWrite(fos);
+ } catch (java.io.IOException e1) {
+ Slog.w(TAG, "Error writing compat packages", e1);
+ if (fos != null) {
+ mFile.failWrite(fos);
+ }
+ }
+ }
+}