summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author keunyoung <keunyoung@google.com> 2015-09-23 11:33:58 -0700
committer keunyoung <keunyoung@google.com> 2015-11-13 13:11:52 -0800
commit1746369a6bcd1a7219e94366b3774bfdfff08fc6 (patch)
tree4bf6d5a7c3760c40a3056f4056713f7cd6653497
parent51c28927686ad9b52c7fcff54210d2b55ff13e34 (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.txt2
-rw-r--r--api/system-current.txt3
-rw-r--r--core/java/android/app/IUiModeManager.aidl10
-rw-r--r--core/java/android/app/UiModeManager.java31
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/values/config.xml16
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java54
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java14
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);