From 2ccda4dc8d800c3592b4bd4d1d70a064d98dd4fe Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 22 Mar 2010 21:49:15 -0700 Subject: [PATCH] Improve switching to car mode, retain night mode option. Fiddle with how we go into car mode to try to ensure we get a clean transition. Also have the system take care of remembering the night mode setting so it will stay at what you want. Change-Id: Icb94fdd961c7a192f7707ec71544485a1ea12455 --- .../android/app/ActivityManagerNative.java | 49 +++++++++++++++++++ core/java/android/app/IActivityManager.java | 5 ++ core/java/android/provider/Settings.java | 11 ++++- .../android/server/UiModeManagerService.java | 48 ++++++++++++++---- .../server/am/ActivityManagerService.java | 31 ++++++++++-- 5 files changed, 128 insertions(+), 16 deletions(-) diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 596ca9de7ba4e..adadfebd7d330 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -168,6 +168,29 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case START_ACTIVITY_WITH_CONFIG_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + IBinder b = data.readStrongBinder(); + IApplicationThread app = ApplicationThreadNative.asInterface(b); + Intent intent = Intent.CREATOR.createFromParcel(data); + String resolvedType = data.readString(); + Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR); + int grantedMode = data.readInt(); + IBinder resultTo = data.readStrongBinder(); + String resultWho = data.readString(); + int requestCode = data.readInt(); + boolean onlyIfNeeded = data.readInt() != 0; + boolean debug = data.readInt() != 0; + Configuration config = Configuration.CREATOR.createFromParcel(data); + int result = startActivityWithConfig(app, intent, resolvedType, + grantedUriPermissions, grantedMode, resultTo, resultWho, + requestCode, onlyIfNeeded, debug, config); + reply.writeNoException(); + reply.writeInt(result); + return true; + } + case START_ACTIVITY_INTENT_SENDER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); @@ -1295,6 +1318,32 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return result; } + public int startActivityWithConfig(IApplicationThread caller, Intent intent, + String resolvedType, Uri[] grantedUriPermissions, int grantedMode, + IBinder resultTo, String resultWho, + int requestCode, boolean onlyIfNeeded, + boolean debug, Configuration config) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(caller != null ? caller.asBinder() : null); + intent.writeToParcel(data, 0); + data.writeString(resolvedType); + data.writeTypedArray(grantedUriPermissions, 0); + data.writeInt(grantedMode); + data.writeStrongBinder(resultTo); + data.writeString(resultWho); + data.writeInt(requestCode); + data.writeInt(onlyIfNeeded ? 1 : 0); + data.writeInt(debug ? 1 : 0); + config.writeToParcel(data, 0); + mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } public int startActivityIntentSender(IApplicationThread caller, IntentSender intent, Intent fillInIntent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 30feae1eeb8bd..ea0e9527044a4 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -88,6 +88,10 @@ public interface IActivityManager extends IInterface { Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) throws RemoteException; + public int startActivityWithConfig(IApplicationThread caller, + Intent intent, String resolvedType, Uri[] grantedUriPermissions, + int grantedMode, IBinder resultTo, String resultWho, int requestCode, + boolean onlyIfNeeded, boolean debug, Configuration newConfig) throws RemoteException; public int startActivityIntentSender(IApplicationThread caller, IntentSender intent, Intent fillInIntent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, @@ -503,4 +507,5 @@ public interface IActivityManager extends IInterface { int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103; int START_ACTIVITY_AND_WAIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+104; int WILL_ACTIVITY_BE_VISIBLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+105; + int START_ACTIVITY_WITH_CONFIG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+106; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 13f87803ffa5c..2ba38c23b581a 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3273,6 +3273,14 @@ public final class Settings { public static final int INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT = INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF; + /** + * The current night mode that has been selected by the user. Owned + * and controlled by UiModeManagerService. Constants are as per + * UiModeManager. + * @hide + */ + public static final String UI_NIGHT_MODE = "ui_night_mode"; + /** * @hide */ @@ -3299,7 +3307,8 @@ public final class Settings { MOUNT_PLAY_NOTIFICATION_SND, MOUNT_UMS_AUTOSTART, MOUNT_UMS_PROMPT, - MOUNT_UMS_NOTIFY_ENABLED + MOUNT_UMS_NOTIFY_ENABLED, + UI_NIGHT_MODE }; /** diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java index 5bd23f429ba63..4e506e7eea9b8 100644 --- a/services/java/com/android/server/UiModeManagerService.java +++ b/services/java/com/android/server/UiModeManagerService.java @@ -45,6 +45,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.provider.Settings; import android.text.format.DateUtils; import android.text.format.Time; import android.util.Slog; @@ -127,20 +128,39 @@ class UiModeManagerService extends IUiModeManager.Stub { category = null; } if (category != null) { + // This is the new activity that will serve as home while + // we are in care mode. intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(category); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + + // Now we are going to be careful about switching the + // configuration and starting the activity -- we need to + // do this in a specific order under control of the + // activity manager, to do it cleanly. So compute the + // new config, but don't set it yet, and let the + // activity manager take care of both the start and config + // change. + Configuration newConfig = null; + if (mHoldingConfiguration) { + updateConfigurationLocked(false); + newConfig = mConfiguration; + } try { + ActivityManagerNative.getDefault().startActivityWithConfig( + null, intent, null, null, 0, null, null, 0, false, false, + newConfig); mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { + mHoldingConfiguration = false; + } catch (RemoteException e) { Slog.w(TAG, e.getCause()); } } if (mHoldingConfiguration) { mHoldingConfiguration = false; - updateConfigurationLocked(); + updateConfigurationLocked(true); } } } @@ -275,6 +295,9 @@ class UiModeManagerService extends IUiModeManager.Stub { com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1); mDeskModeKeepsScreenOn = (context.getResources().getInteger( com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1); + + mNightMode = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO); } public void disableCarMode() { @@ -319,6 +342,10 @@ class UiModeManagerService extends IUiModeManager.Stub { } if (mNightMode != mode) { + long ident = Binder.clearCallingIdentity(); + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.UI_NIGHT_MODE, mode); + Binder.restoreCallingIdentity(ident); mNightMode = mode; updateLocked(); } @@ -360,7 +387,7 @@ class UiModeManagerService extends IUiModeManager.Stub { } } - final void updateConfigurationLocked() { + final void updateConfigurationLocked(boolean sendIt) { int uiMode = 0; if (mCarModeEnabled) { uiMode = Configuration.UI_MODE_TYPE_CAR; @@ -385,13 +412,14 @@ class UiModeManagerService extends IUiModeManager.Stub { if (!mHoldingConfiguration && uiMode != mSetUiMode) { mSetUiMode = uiMode; + mConfiguration.uiMode = uiMode; - try { - final IActivityManager am = ActivityManagerNative.getDefault(); - mConfiguration.uiMode = uiMode; - am.updateConfiguration(mConfiguration); - } catch (RemoteException e) { - Slog.w(TAG, "Failure communicating with activity manager", e); + if (sendIt) { + try { + ActivityManagerNative.getDefault().updateConfiguration(mConfiguration); + } catch (RemoteException e) { + Slog.w(TAG, "Failure communicating with activity manager", e); + } } } } @@ -447,7 +475,7 @@ class UiModeManagerService extends IUiModeManager.Stub { mHoldingConfiguration = true; } - updateConfigurationLocked(); + updateConfigurationLocked(true); // keep screen on when charging and in car mode boolean keepScreenOn = mCharging && diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7034c88ae2af2..f7340530a884b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3612,7 +3612,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, - boolean debug, WaitResult outResult) { + boolean debug, WaitResult outResult, Configuration config) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -3666,6 +3666,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, onlyIfNeeded, componentSpecified); + if (config != null) { + // If the caller also wants to switch to a new configuration, + // do so now. This allows a clean switch, as we are waiting + // for the current activity to pause (so we will not destroy + // it), and have not yet started the next activity. + enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, + "updateConfiguration()"); + updateConfigurationLocked(config, null); + } Binder.restoreCallingIdentity(origId); if (outResult != null) { @@ -3707,8 +3716,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) { - return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions, - grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null); + return startActivityMayWait(caller, intent, resolvedType, + grantedUriPermissions, grantedMode, resultTo, resultWho, + requestCode, onlyIfNeeded, debug, null, null); } public final WaitResult startActivityAndWait(IApplicationThread caller, @@ -3717,11 +3727,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) { WaitResult res = new WaitResult(); - startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions, - grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res); + startActivityMayWait(caller, intent, resolvedType, + grantedUriPermissions, grantedMode, resultTo, resultWho, + requestCode, onlyIfNeeded, debug, res, null); return res; } + public final int startActivityWithConfig(IApplicationThread caller, + Intent intent, String resolvedType, Uri[] grantedUriPermissions, + int grantedMode, IBinder resultTo, + String resultWho, int requestCode, boolean onlyIfNeeded, + boolean debug, Configuration config) { + return startActivityMayWait(caller, intent, resolvedType, + grantedUriPermissions, grantedMode, resultTo, resultWho, + requestCode, onlyIfNeeded, debug, null, config); + } + public int startActivityIntentSender(IApplicationThread caller, IntentSender intent, Intent fillInIntent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,