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: Ic0e58f3428151e0b1c19a2e9a7d6ded32ff962a6
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index 7e9873e..cae54b6 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -51,4 +51,14 @@
      * 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 0f6ce12..4416415 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -233,4 +233,35 @@
         }
         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 9bbbdca..8a0477f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2712,6 +2712,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 d9e0472..caa20dc 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 3860f68..16c9db1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1476,11 +1476,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" />