diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-05-25 21:18:36 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-05-25 21:18:36 -0700 |
commit | 42f8094c066209a65b09d53611ef5c93daba4c51 (patch) | |
tree | edf0542248487db54f142f1f8a9b5111b722d6d2 /services | |
parent | fa574c0e0ce7f84eea34e96dededea35329dbd18 (diff) | |
parent | 36cd41f8efa6f6a683d3353d309ff548295af9e9 (diff) | |
download | frameworks_base-42f8094c066209a65b09d53611ef5c93daba4c51.zip frameworks_base-42f8094c066209a65b09d53611ef5c93daba4c51.tar.gz frameworks_base-42f8094c066209a65b09d53611ef5c93daba4c51.tar.bz2 |
Merge "Spiffy new compatibility mode UI." into honeycomb-mr2
Diffstat (limited to 'services')
5 files changed, 235 insertions, 22 deletions
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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 final class ActivityManagerService extends ActivityManagerNative } } + 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { 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 @@ package com.android.server.am; 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 @@ public class CompatModePackages { 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 @@ public class CompatModePackages { 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 class CompatModePackages { } } - 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 @@ public class CompatModePackages { : 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 @@ public class CompatModePackages { 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 @@ public class CompatModePackages { 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 @@ public class CompatModePackages { } 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 @@ public class CompatModePackages { 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 @@ public class CompatModePackages { } 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 @@ class TaskRecord { 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 @@ class TaskRecord { 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)"); |