diff options
| author | 2015-09-23 11:33:58 -0700 | |
|---|---|---|
| committer | 2015-11-13 13:11:52 -0800 | |
| commit | 1746369a6bcd1a7219e94366b3774bfdfff08fc6 (patch) | |
| tree | 4bf6d5a7c3760c40a3056f4056713f7cd6653497 | |
| parent | 51c28927686ad9b52c7fcff54210d2b55ff13e34 (diff) | |
allow locking UI mode and block launching car dock for automotive
- add config to lock UI mode change: When this is enabled,
request to change car mode will be ignored. Apps can check
the config using UiModeManager.isUiModeLocked()
- add config to lock day / night mode: When this is enabled,
apps cannot change day / night mode without having
MODIFY_DAY_NIGHT_MODE permission.
Apps can check the config using UiModeManager.isNightModeLocked()
- add config to disable car dock intent launch for home key
and mode change
- All new configs have default values which keeps the current behavior.
Car products should override the configs to get desirable behavior.
bug: 22700993
Change-Id: I351fc53163575d2f523c2d6e886befdb69a5a0c6
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 3 | ||||
| -rw-r--r-- | core/java/android/app/IUiModeManager.aidl | 10 | ||||
| -rw-r--r-- | core/java/android/app/UiModeManager.java | 31 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 7 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 16 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 3 | ||||
| -rw-r--r-- | services/core/java/com/android/server/UiModeManagerService.java | 54 | ||||
| -rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 14 |
9 files changed, 131 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index 96ecad617a91..ba8613725109 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5491,6 +5491,8 @@ package android.app { method public void enableCarMode(int); method public int getCurrentModeType(); method public int getNightMode(); + method public boolean isNightModeLocked(); + method public boolean isUiModeLocked(); method public void setNightMode(int); field public static java.lang.String ACTION_ENTER_CAR_MODE; field public static java.lang.String ACTION_ENTER_DESK_MODE; diff --git a/api/system-current.txt b/api/system-current.txt index 0605851f058d..888f347c9e5d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -131,6 +131,7 @@ package android { field public static final java.lang.String MODIFY_AUDIO_ROUTING = "android.permission.MODIFY_AUDIO_ROUTING"; field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS"; field public static final java.lang.String MODIFY_CELL_BROADCASTS = "android.permission.MODIFY_CELL_BROADCASTS"; + field public static final java.lang.String MODIFY_DAY_NIGHT_MODE = "android.permission.MODIFY_DAY_NIGHT_MODE"; field public static final java.lang.String MODIFY_NETWORK_ACCOUNTING = "android.permission.MODIFY_NETWORK_ACCOUNTING"; field public static final java.lang.String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS"; field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE"; @@ -5609,6 +5610,8 @@ package android.app { method public void enableCarMode(int); method public int getCurrentModeType(); method public int getNightMode(); + method public boolean isNightModeLocked(); + method public boolean isUiModeLocked(); method public void setNightMode(int); field public static java.lang.String ACTION_ENTER_CAR_MODE; field public static java.lang.String ACTION_ENTER_DESK_MODE; diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl index 7e9873e5f2f2..cae54b6c0611 100644 --- a/core/java/android/app/IUiModeManager.aidl +++ b/core/java/android/app/IUiModeManager.aidl @@ -51,4 +51,14 @@ interface IUiModeManager { * 2 for night, and 3 for automatic mode switching. */ int getNightMode(); + + /** + * Tells if UI mode is locked or not. + */ + boolean isUiModeLocked(); + + /** + * Tells if Night mode is locked or not. + */ + boolean isNightModeLocked(); } diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 0f6ce1227ca4..44164158c7b4 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -233,4 +233,35 @@ public class UiModeManager { } return -1; } + + /** + * @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode + * like {@link #enableCarMode(int)} will silently fail. + */ + public boolean isUiModeLocked() { + if (mService != null) { + try { + return mService.isUiModeLocked(); + } catch (RemoteException e) { + Log.e(TAG, "isUiModeLocked: RemoteException", e); + } + } + return true; + } + + /** + * @return If Night mode is locked or not. When Night mode is locked, changing Night mode + * is only allowed to privileged system components and normal application's call + * to change Night mode using {@link #setNightMode(int)} will silently fail. + */ + public boolean isNightModeLocked() { + if (mService != null) { + try { + return mService.isNightModeLocked(); + } catch (RemoteException e) { + Log.e(TAG, "isNightModeLocked: RemoteException", e); + } + } + return true; + } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 6bdf71bdba6f..9df0ecbe0680 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2693,6 +2693,13 @@ <permission android:name="android.permission.DISPATCH_NFC_MESSAGE" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows changing day / night mode when system is configured with + config_lockDayNightMode set to true. If requesting app does not have permission, + it will be ignored. + @hide --> + <permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE" + android:protectionLevel="signature|privileged" /> + <!-- The system process is explicitly the only one allowed to launch the confirmation UI for full backup/restore --> <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 9c75b7aa701b..315f7e2da62f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -716,6 +716,13 @@ <bool name="config_carDockEnablesAccelerometer">true</bool> + <!-- Control whether to launch Car dock home app when user presses home button or when + car dock intent is fired. + In mobile device, usually separate home app is expected in car mode, and this should be + enabled. But in environments like real car, default home app may be enough, and in that + case, this can be disabled (set to false). --> + <bool name="config_enableCarDockHomeLaunch">true</bool> + <!-- HDMI behavior --> <!-- The number of degrees to rotate the display when the device has HDMI connected @@ -733,6 +740,15 @@ Any other values will have surprising consequences. --> <integer name="config_defaultUiModeType">1</integer> + <!-- Control whether to lock UI mode to what is selected from config_defaultUiModeType. + Once UI mode is locked, applications cannot change it anymore. --> + <bool name="config_lockUiMode">false</bool> + + <!-- Control whether to lock day/night mode change from normal application. When it is + true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE + permission. --> + <bool name="config_lockDayNightMode">false</bool> + <!-- Control the default night mode to use when there is no other mode override set. One of the following values (see UiModeManager.java): 0 - MODE_NIGHT_AUTO diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6820c259a51a..dae5106515f0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1471,11 +1471,14 @@ <java-symbol type="bool" name="config_carDockEnablesAccelerometer" /> <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" /> <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" /> + <java-symbol type="bool" name="config_enableCarDockHomeLaunch" /> <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" /> <java-symbol type="bool" name="config_enableLockScreenRotation" /> <java-symbol type="bool" name="config_enableLockScreenTranslucentDecor" /> <java-symbol type="bool" name="config_enableTranslucentDecor" /> <java-symbol type="bool" name="config_lidControlsSleep" /> + <java-symbol type="bool" name="config_lockDayNightMode" /> + <java-symbol type="bool" name="config_lockUiMode" /> <java-symbol type="bool" name="config_reverseDefaultRotation" /> <java-symbol type="bool" name="config_showNavigationBar" /> <java-symbol type="bool" name="config_supportAutoRotation" /> diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 0b67ad81b379..6f713cdfebbe 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -57,7 +57,6 @@ final class UiModeManagerService extends SystemService { private static final boolean LOG = false; // Enable launching of applications when entering the dock. - private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true; private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true; final Object mLock = new Object(); @@ -76,6 +75,13 @@ final class UiModeManagerService extends SystemService { private boolean mComputedNightMode; private int mCarModeEnableFlags; + // flag set by resource, whether to enable Car dock launch when starting car mode. + private boolean mEnableCarDockLaunch = true; + // flag set by resource, whether to lock UI mode to the default one or not. + private boolean mUiModeLocked = false; + // flag set by resource, whether to night mode change for normal all or not. + private boolean mNightModeLocked = false; + int mCurUiMode = 0; private int mSetUiMode = 0; private boolean mHoldingConfiguration = false; @@ -176,6 +182,10 @@ final class UiModeManagerService extends SystemService { com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1); mDeskModeKeepsScreenOn = (res.getInteger( com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1); + mEnableCarDockLaunch = res.getBoolean( + com.android.internal.R.bool.config_enableCarDockHomeLaunch); + mUiModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockUiMode); + mNightModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockDayNightMode); final PackageManager pm = context.getPackageManager(); mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) @@ -199,6 +209,10 @@ final class UiModeManagerService extends SystemService { private final IBinder mService = new IUiModeManager.Stub() { @Override public void enableCarMode(int flags) { + if (isUiModeLocked()) { + Slog.e(TAG, "enableCarMode while UI mode is locked"); + return; + } final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -214,6 +228,10 @@ final class UiModeManagerService extends SystemService { @Override public void disableCarMode(int flags) { + if (isUiModeLocked()) { + Slog.e(TAG, "disableCarMode while UI mode is locked"); + return; + } final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -241,6 +259,13 @@ final class UiModeManagerService extends SystemService { @Override public void setNightMode(int mode) { + if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission( + android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) + != PackageManager.PERMISSION_GRANTED)) { + Slog.e(TAG, + "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission"); + return; + } switch (mode) { case UiModeManager.MODE_NIGHT_NO: case UiModeManager.MODE_NIGHT_YES: @@ -273,6 +298,20 @@ final class UiModeManagerService extends SystemService { } @Override + public boolean isUiModeLocked() { + synchronized (mLock) { + return mUiModeLocked; + } + } + + @Override + public boolean isNightModeLocked() { + synchronized (mLock) { + return mNightModeLocked; + } + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { @@ -293,10 +332,13 @@ final class UiModeManagerService extends SystemService { pw.print(" mDockState="); pw.print(mDockState); pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); pw.print(" mNightMode="); pw.print(mNightMode); + pw.print(" mNightModeLocked="); pw.print(mNightModeLocked); pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled); pw.print(" mComputedNightMode="); pw.print(mComputedNightMode); - pw.print(" mCarModeEnableFlags="); pw.println(mCarModeEnableFlags); + pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags); + pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch); pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode)); + pw.print(" mUiModeLocked="); pw.print(mUiModeLocked); pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration); pw.print(" mSystemReady="); pw.println(mSystemReady); @@ -356,7 +398,9 @@ final class UiModeManagerService extends SystemService { private void updateConfigurationLocked() { int uiMode = mDefaultUiModeType; - if (mTelevision) { + if (mUiModeLocked) { + // no-op, keeps default one + } else if (mTelevision) { uiMode = Configuration.UI_MODE_TYPE_TELEVISION; } else if (mWatch) { uiMode = Configuration.UI_MODE_TYPE_WATCH; @@ -460,7 +504,7 @@ final class UiModeManagerService extends SystemService { } else { String category = null; if (mCarModeEnabled) { - if (ENABLE_LAUNCH_CAR_DOCK_APP + if (mEnableCarDockLaunch && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) { category = Intent.CATEGORY_CAR_DOCK; } @@ -503,7 +547,7 @@ final class UiModeManagerService extends SystemService { if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) { // Only launch car home when car mode is enabled and the caller // has asked us to switch to it. - if (ENABLE_LAUNCH_CAR_DOCK_APP + if (mEnableCarDockLaunch && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) { category = Intent.CATEGORY_CAR_DOCK; } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 121ef21812a1..2ec2be18b2bb 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -159,8 +159,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final boolean SHOW_PROCESSES_ON_ALT_MENU = false; // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. - // No longer recommended for desk docks; still useful in car docks. - static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true; + // No longer recommended for desk docks; static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; static final int SHORT_PRESS_POWER_NOTHING = 0; @@ -317,6 +316,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { int[] mNavigationBarHeightForRotation = new int[4]; int[] mNavigationBarWidthForRotation = new int[4]; + // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. + // This is for car dock and this is updated from resource. + private boolean mEnableCarDockHomeCapture = true; + boolean mBootMessageNeedsHiding; KeyguardServiceDelegate mKeyguardDelegate; final Runnable mWindowManagerDrawCallback = new Runnable() { @@ -1399,6 +1402,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHomeIntent.addCategory(Intent.CATEGORY_HOME); mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + mEnableCarDockHomeCapture = context.getResources().getBoolean( + com.android.internal.R.bool.config_enableCarDockHomeLaunch); mCarDockIntent = new Intent(Intent.ACTION_MAIN, null); mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK); mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK @@ -6404,7 +6409,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { * true: * <ul> * <li>The device is not in either car mode or desk mode - * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false + * <li>The device is in car mode but mEnableCarDockHomeCapture is false * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME @@ -6418,7 +6423,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // is, when in car mode you should be taken to car home regardless // of whether we are actually in a car dock. if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { - if (ENABLE_CAR_DOCK_HOME_CAPTURE) { + if (mEnableCarDockHomeCapture) { intent = mCarDockIntent; } } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { @@ -6938,6 +6943,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); pw.print(" mDockMode="); pw.print(mDockMode); + pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); |