Spiffy new compatibility mode UI.
Change-Id: I1207eaafae59a434fcc979ad60a83e2d685288af
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a70a219..48b8ca8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -137,6 +137,25 @@
}
}
+ /** @hide */
+ public boolean getPackageAskScreenCompat(String packageName) {
+ try {
+ return ActivityManagerNative.getDefault().getPackageAskScreenCompat(packageName);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return false;
+ }
+ }
+
+ /** @hide */
+ public void setPackageAskScreenCompat(String packageName, boolean ask) {
+ try {
+ ActivityManagerNative.getDefault().setPackageAskScreenCompat(packageName, ask);
+ } 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
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4beb5cc..88293e8 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1437,6 +1437,26 @@
return true;
}
+ case GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ boolean ask = getPackageAskScreenCompat(pkg);
+ reply.writeNoException();
+ reply.writeInt(ask ? 1 : 0);
+ return true;
+ }
+
+ case SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ boolean ask = data.readInt() != 0;
+ setPackageAskScreenCompat(pkg, ask);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3208,7 +3228,8 @@
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ data.writeString(packageName);
+ mRemote.transact(GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
reply.readException();
int mode = reply.readInt();
reply.recycle();
@@ -3229,5 +3250,31 @@
data.recycle();
}
+ public boolean getPackageAskScreenCompat(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ mRemote.transact(GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean ask = reply.readInt() != 0;
+ reply.recycle();
+ data.recycle();
+ return ask;
+ }
+
+ public void setPackageAskScreenCompat(String packageName, boolean ask)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ data.writeInt(ask ? 1 : 0);
+ mRemote.transact(SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 24706f9..b0cbbb5 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -347,6 +347,9 @@
public int getPackageScreenCompatMode(String packageName) throws RemoteException;
public void setPackageScreenCompatMode(String packageName, int mode)
throws RemoteException;
+ public boolean getPackageAskScreenCompat(String packageName) throws RemoteException;
+ public void setPackageAskScreenCompat(String packageName, boolean ask)
+ throws RemoteException;
/*
* Private non-Binder interfaces
@@ -567,4 +570,6 @@
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;
+ int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127;
+ int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128;
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 854d410..dca53a8 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -113,8 +113,13 @@
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) {
int compatFlags = 0;
+ // We can't rely on the application always setting
+ // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input.
+ boolean anyResizeable = false;
+
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
compatFlags |= LARGE_SCREENS;
+ anyResizeable = true;
if (!forceCompat) {
// If we aren't forcing the app into compatibility mode, then
// assume if it supports large screens that we should allow it
@@ -123,9 +128,13 @@
}
}
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
- compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ anyResizeable = true;
+ if (!forceCompat) {
+ compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ }
}
if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+ anyResizeable = true;
compatFlags |= EXPANDABLE;
}
@@ -160,7 +169,7 @@
if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
if ((compatFlags&EXPANDABLE) != 0) {
supportsScreen = true;
- } else if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) == 0) {
+ } else if (!anyResizeable) {
compatFlags |= ALWAYS_COMPAT;
}
}
diff --git a/core/res/res/layout/am_compat_mode_dialog.xml b/core/res/res/layout/am_compat_mode_dialog.xml
new file mode 100644
index 0000000..a8d39cf
--- /dev/null
+++ b/core/res/res/layout/am_compat_mode_dialog.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent" android:layout_height="match_parent"
+ android:layout_marginLeft="40dp" android:layout_marginRight="40dp"
+ android:layout_marginTop="15dp" android:layout_marginBottom="15dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal" android:baselineAligned="true">
+ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="18sp"
+ android:text="@string/screen_compat_mode_scale"
+ />
+ <Switch
+ android:id="@+id/compat_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginRight="10dp"
+ />
+ </LinearLayout>
+
+ <View android:layout_width="wrap_content" android:layout_height="1dp"
+ android:layout_marginTop="10dp" android:layout_marginBottom="10dp"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <CheckBox android:id="@+id/ask_checkbox"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/screen_compat_mode_show"
+ />
+ <TextView
+ android:id="@+id/reask_hint"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:gravity="center"
+ android:visibility="invisible"
+ android:text="@string/screen_compat_mode_hint" />
+</LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b713b51..d5affae 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2337,6 +2337,12 @@
<string name="launch_warning_replace"><xliff:g id="app_name">%1$s</xliff:g> is now running.</string>
<!-- [CHAR LIMIT=50] Title of the alert when application launches on top of another. -->
<string name="launch_warning_original"><xliff:g id="app_name">%1$s</xliff:g> was originally launched.</string>
+ <!-- [CHAR LIMIT=50] Compat mode dialog: compat mode switch label. -->
+ <string name="screen_compat_mode_scale">Scale</string>
+ <!-- [CHAR LIMIT=50] Compat mode dialog: compat mode switch label. -->
+ <string name="screen_compat_mode_show">Always show</string>
+ <!-- [CHAR LIMIT=200] Compat mode dialog: hint to re-enable compat mode dialog. -->
+ <string name="screen_compat_mode_hint">Re-enable this with Settings > Applications > Manage applications.</string>
<!-- Text of the alert that is displayed when an application has violated StrictMode. -->
<string name="smv_application">The application <xliff:g id="application">%1$s</xliff:g>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
index f019e2d..42940be 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
@@ -24,23 +24,11 @@
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 7db1ce8..fd07a5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -358,15 +358,6 @@
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);
@@ -504,6 +495,9 @@
}
private void updateShownCompatMode() {
+ if (mCompatMode == null) {
+ return;
+ }
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
int mode = am.getFrontActivityScreenCompatMode();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6619caf..65b3258 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -974,8 +974,10 @@
static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
static final int CLEAR_DNS_CACHE = 28;
static final int UPDATE_HTTP_PROXY = 29;
+ static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
AlertDialog mUidAlert;
+ CompatModeDialog mCompatModeDialog;
final Handler mHandler = new Handler() {
//public Handler() {
@@ -1274,6 +1276,33 @@
sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
} break;
+ case SHOW_COMPAT_MODE_DIALOG_MSG: {
+ synchronized (ActivityManagerService.this) {
+ ActivityRecord ar = (ActivityRecord)msg.obj;
+ if (mCompatModeDialog != null) {
+ if (mCompatModeDialog.mAppInfo.packageName.equals(
+ ar.info.applicationInfo.packageName)) {
+ return;
+ }
+ mCompatModeDialog.dismiss();
+ mCompatModeDialog = null;
+ }
+ if (ar != null) {
+ if (mCompatModePackages.getPackageAskCompatModeLocked(
+ ar.packageName)) {
+ int mode = mCompatModePackages.computeCompatModeLocked(
+ ar.info.applicationInfo);
+ if (mode == ActivityManager.COMPAT_MODE_DISABLED
+ || mode == ActivityManager.COMPAT_MODE_ENABLED) {
+ mCompatModeDialog = new CompatModeDialog(
+ ActivityManagerService.this, mContext,
+ ar.info.applicationInfo);
+ mCompatModeDialog.show();
+ }
+ }
+ }
+ }
+ }
}
}
};
@@ -2101,6 +2130,18 @@
}
}
+ public boolean getPackageAskScreenCompat(String packageName) {
+ synchronized (this) {
+ return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
+ }
+ }
+
+ public void setPackageAskScreenCompat(String packageName, boolean ask) {
+ synchronized (this) {
+ mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
+ }
+ }
+
void reportResumedActivityLocked(ActivityRecord r) {
//Slog.i(TAG, "**** REPORT RESUME: " + r);
@@ -7819,8 +7860,14 @@
if (dumpAll) {
pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
if (mCompatModePackages.getPackages().size() > 0) {
- pw.print(" mScreenCompatPackages=");
- pw.println(mCompatModePackages.getPackages());
+ pw.println(" mScreenCompatPackages:");
+ for (Map.Entry<String, Integer> entry
+ : mCompatModePackages.getPackages().entrySet()) {
+ String pkg = entry.getKey();
+ int mode = entry.getValue();
+ pw.print(" "); pw.print(pkg); pw.print(": ");
+ pw.print(mode); pw.println();
+ }
}
}
pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index f385042..a704f88 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -483,6 +483,13 @@
return null;
}
+ final void showAskCompatModeDialogLocked(ActivityRecord r) {
+ Message msg = Message.obtain();
+ msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG;
+ msg.obj = r.task.askedCompatMode ? null : r;
+ mService.mHandler.sendMessage(msg);
+ }
+
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
@@ -538,6 +545,7 @@
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
r.forceNewConfig = false;
+ showAskCompatModeDialogLocked(r);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
System.identityHashCode(r),
r.info, mService.compatibilityInfoForPackageLocked(r.info.applicationInfo),
@@ -1430,6 +1438,7 @@
next.task.taskId, next.shortComponentName);
next.sleeping = false;
+ showAskCompatModeDialogLocked(next);
next.app.thread.scheduleResumeActivity(next,
mService.isNextTransitionForward());
diff --git a/services/java/com/android/server/am/CompatModeDialog.java b/services/java/com/android/server/am/CompatModeDialog.java
new file mode 100644
index 0000000..0442bda
--- /dev/null
+++ b/services/java/com/android/server/am/CompatModeDialog.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.server.am;
+
+import android.app.ActivityManager;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.view.Gravity;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+
+public class CompatModeDialog extends Dialog {
+ final ActivityManagerService mService;
+ final ApplicationInfo mAppInfo;
+
+ final Switch mCompatEnabled;
+ final CheckBox mAlwaysShow;
+ final View mHint;
+
+ public CompatModeDialog(ActivityManagerService service, Context context,
+ ApplicationInfo appInfo) {
+ super(context, com.android.internal.R.style.Theme_Holo_Dialog_MinWidth);
+ setCancelable(true);
+ setCanceledOnTouchOutside(true);
+ getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+ getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
+ getWindow().setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL);
+ mService = service;
+ mAppInfo = appInfo;
+
+ setContentView(com.android.internal.R.layout.am_compat_mode_dialog);
+ mCompatEnabled = (Switch)findViewById(com.android.internal.R.id.compat_checkbox);
+ mCompatEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ synchronized (mService) {
+ mService.mCompatModePackages.setPackageScreenCompatModeLocked(
+ mAppInfo.packageName,
+ mCompatEnabled.isChecked() ? ActivityManager.COMPAT_MODE_ENABLED
+ : ActivityManager.COMPAT_MODE_DISABLED);
+ updateControls();
+ }
+ }
+ });
+ mAlwaysShow = (CheckBox)findViewById(com.android.internal.R.id.ask_checkbox);
+ mAlwaysShow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ synchronized (mService) {
+ mService.mCompatModePackages.setPackageAskCompatModeLocked(
+ mAppInfo.packageName, mAlwaysShow.isChecked());
+ updateControls();
+ }
+ }
+ });
+ mHint = findViewById(com.android.internal.R.id.reask_hint);
+
+ updateControls();
+ }
+
+ void updateControls() {
+ synchronized (mService) {
+ int mode = mService.mCompatModePackages.computeCompatModeLocked(mAppInfo);
+ mCompatEnabled.setChecked(mode == ActivityManager.COMPAT_MODE_ENABLED);
+ boolean ask = mService.mCompatModePackages.getPackageAskCompatModeLocked(
+ mAppInfo.packageName);
+ mAlwaysShow.setChecked(ask);
+ mHint.setVisibility(ask ? View.INVISIBLE : View.VISIBLE);
+ }
+ }
+}
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index 1faf8da..1277bca 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -3,8 +3,10 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Map;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -31,7 +33,12 @@
private final ActivityManagerService mService;
private final AtomicFile mFile;
- private final HashSet<String> mPackages = new HashSet<String>();
+ // Compatibility state: no longer ask user to select the mode.
+ public static final int COMPAT_FLAG_DONT_ASK = 1<<0;
+ // Compatibility state: compatibility mode is enabled.
+ public static final int COMPAT_FLAG_ENABLED = 1<<1;
+
+ private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
private static final int MSG_WRITE = 1;
@@ -71,7 +78,15 @@
if ("pkg".equals(tagName)) {
String pkg = parser.getAttributeValue(null, "name");
if (pkg != null) {
- mPackages.add(pkg);
+ String mode = parser.getAttributeValue(null, "mode");
+ int modeInt = 0;
+ if (mode != null) {
+ try {
+ modeInt = Integer.parseInt(mode);
+ } catch (NumberFormatException e) {
+ }
+ }
+ mPackages.put(pkg, modeInt);
}
}
}
@@ -93,17 +108,22 @@
}
}
- public HashSet<String> getPackages() {
+ public HashMap<String, Integer> getPackages() {
return mPackages;
}
+ private int getPackageFlags(String packageName) {
+ Integer flags = mPackages.get(packageName);
+ return flags != null ? flags : 0;
+ }
+
public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
return new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
- mPackages.contains(ai.packageName));
+ (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
}
- private int computeCompatModeLocked(ApplicationInfo ai) {
- boolean enabled = mPackages.contains(ai.packageName);
+ public int computeCompatModeLocked(ApplicationInfo ai) {
+ boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
CompatibilityInfo info = new CompatibilityInfo(ai,
mService.mConfiguration.screenLayout, enabled);
if (info.alwaysSupportsScreen()) {
@@ -116,6 +136,40 @@
: ActivityManager.COMPAT_MODE_DISABLED;
}
+ public boolean getFrontActivityAskCompatModeLocked() {
+ ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
+ if (r == null) {
+ return false;
+ }
+ return getPackageAskCompatModeLocked(r.packageName);
+ }
+
+ public boolean getPackageAskCompatModeLocked(String packageName) {
+ return (getPackageFlags(packageName)&COMPAT_FLAG_DONT_ASK) == 0;
+ }
+
+ public void setFrontActivityAskCompatModeLocked(boolean ask) {
+ ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
+ if (r != null) {
+ setPackageAskCompatModeLocked(r.packageName, ask);
+ }
+ }
+
+ public void setPackageAskCompatModeLocked(String packageName, boolean ask) {
+ int curFlags = getPackageFlags(packageName);
+ int newFlags = ask ? (curFlags&~COMPAT_FLAG_DONT_ASK) : (curFlags|COMPAT_FLAG_DONT_ASK);
+ if (curFlags != newFlags) {
+ if (newFlags != 0) {
+ mPackages.put(packageName, newFlags);
+ } else {
+ mPackages.remove(packageName);
+ }
+ mHandler.removeMessages(MSG_WRITE);
+ Message msg = mHandler.obtainMessage(MSG_WRITE);
+ mHandler.sendMessageDelayed(msg, 10000);
+ }
+ }
+
public int getFrontActivityScreenCompatModeLocked() {
ActivityRecord r = mService.mMainStack.topRunningActivityLocked(null);
if (r == null) {
@@ -161,7 +215,8 @@
private void setPackageScreenCompatModeLocked(ApplicationInfo ai, int mode) {
final String packageName = ai.packageName;
- boolean changed = false;
+ int curFlags = getPackageFlags(packageName);
+
boolean enable;
switch (mode) {
case ActivityManager.COMPAT_MODE_DISABLED:
@@ -171,24 +226,26 @@
enable = true;
break;
case ActivityManager.COMPAT_MODE_TOGGLE:
- enable = !mPackages.contains(packageName);
+ enable = (curFlags&COMPAT_FLAG_ENABLED) == 0;
break;
default:
Slog.w(TAG, "Unknown screen compat mode req #" + mode + "; ignoring");
return;
}
+
+ int newFlags = curFlags;
if (enable) {
- if (!mPackages.contains(packageName)) {
- changed = true;
- mPackages.add(packageName);
- }
+ newFlags |= COMPAT_FLAG_ENABLED;
} else {
- if (mPackages.contains(packageName)) {
- changed = true;
+ newFlags &= ~COMPAT_FLAG_ENABLED;
+ }
+
+ if (newFlags != curFlags) {
+ if (newFlags != 0) {
+ mPackages.put(packageName, newFlags);
+ } else {
mPackages.remove(packageName);
}
- }
- if (changed) {
CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
if (ci.alwaysSupportsScreen()) {
Slog.w(TAG, "Ignoring compat mode change of " + packageName
@@ -241,9 +298,9 @@
}
void saveCompatModes() {
- HashSet<String> pkgs;
+ HashMap<String, Integer> pkgs;
synchronized (mService) {
- pkgs = new HashSet<String>(mPackages);
+ pkgs = new HashMap<String, Integer>(mPackages);
}
FileOutputStream fos = null;
@@ -258,9 +315,14 @@
final IPackageManager pm = AppGlobals.getPackageManager();
final int screenLayout = mService.mConfiguration.screenLayout;
- final Iterator<String> it = pkgs.iterator();
+ final Iterator<Map.Entry<String, Integer>> it = pkgs.entrySet().iterator();
while (it.hasNext()) {
- String pkg = it.next();
+ Map.Entry<String, Integer> entry = it.next();
+ String pkg = entry.getKey();
+ int mode = entry.getValue();
+ if (mode == 0) {
+ continue;
+ }
ApplicationInfo ai = null;
try {
ai = pm.getApplicationInfo(pkg, 0);
@@ -278,6 +340,7 @@
}
out.startTag(null, "pkg");
out.attribute(null, "name", pkg);
+ out.attribute(null, "mode", Integer.toString(mode));
out.endTag(null, "pkg");
}
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 86cec42..76b4914 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -34,6 +34,7 @@
long lastActiveTime; // Last time this task was active, including sleep.
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
+ boolean askedCompatMode;// Have asked the user about compat mode for this task.
Bitmap lastThumbnail; // Last thumbnail captured for this task.
CharSequence lastDescription; // Last description captured for this task.
@@ -114,6 +115,9 @@
pw.print(prefix); pw.print("realActivity=");
pw.println(realActivity.flattenToShortString());
}
+ if (!askedCompatMode) {
+ pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
+ }
pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
pw.print(" (inactive for ");
pw.print((getInactiveDuration()/1000)); pw.println("s)");