Introduce special UI modes for night and car usage.

The device mode is now called ui mode. Furthermore is the order of
precedence for the resources now in such a way that the ui mode needs
to be specified after the orientation and before the density.

The ui mode can be set, like it is done for the locale, as follows:

IActivityManager am = ActivityManagerNative.getDefault();
Configuration config = am.getConfiguration();
config.uiMode = Configuration.UI_MODE_TYPE_CAR | Configuration.UI_MODE_NIGHT_ANY;
am.updateConfiguration(config);

To allow users to disable the car mode and set the night mode the IUiModeManager
interface is used.

The automatic night mode switching will be added in a separate change.
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
new file mode 100644
index 0000000..6ac8a2a
--- /dev/null
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 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 android.app;
+
+/**
+ * Interface used to control special UI modes.
+ * @hide
+ */
+interface IUiModeManager {
+    /**
+     * Enables the car mode. Only the system can do this.
+     * @hide
+     */
+    void enableCarMode();
+
+    /**
+     * Disables the car mode.
+     */
+    void disableCarMode();
+
+    /**
+     * Sets the night mode.
+     * The mode can be one of:
+     *   1 - notnight mode
+     *   2 - night mode
+     *   3 - automatic mode switching
+     */
+    void setNightMode(int mode);
+
+    /**
+     * Gets the currently configured night mode.  Return 1 for notnight,
+     * 2 for night, and 3 for automatic mode switching.
+     */
+    int getNightMode();
+}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c32999f..e36eba9 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1816,7 +1816,9 @@
     /**
      * Broadcast Action:  A sticky broadcast indicating the phone was docked
      * or undocked.  Includes the extra
-     * field {@link #EXTRA_DOCK_STATE}, containing the current dock state.
+     * field {@link #EXTRA_DOCK_STATE}, containing the current dock state. It also
+     * includes the boolean extra field {@link #EXTRA_CAR_MODE_ENABLED}, indicating
+     * the state of the car mode.
      * This is intended for monitoring the current dock state.
      * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK}
      * or {@link #CATEGORY_DESK_DOCK} instead.
@@ -2152,6 +2154,12 @@
     public static final int EXTRA_DOCK_STATE_CAR = 2;
 
     /**
+     * Used as an boolean extra field in {@link android.content.Intent#ACTION_DOCK_EVENT}
+     * intents to indicate that the car mode is enabled or not.
+     */
+    public static final String EXTRA_CAR_MODE_ENABLED = "android.intent.extra.CAR_MODE_ENABLED";
+
+    /**
      * Boolean that can be supplied as meta-data with a dock activity, to
      * indicate that the dock should take over the home key when it is active.
      */
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index b94bb51..a13f7f9 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -251,6 +251,13 @@
     public static final int CONFIG_SCREEN_LAYOUT = 0x0100;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the ui mode. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     * @hide (UIMODE) Pending API council approval
+     */
+    public static final int CONFIG_UI_MODE = 0x0200;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configutation, but a higher-level value, so its
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 23a408b..7f9a5c6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -619,7 +619,7 @@
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int screenLayout, int majorVersion);
+            int screenLayout, int uiMode, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 1fe34b5..aa5f128 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -161,7 +161,37 @@
      * or {@link #ORIENTATION_SQUARE}.
      */
     public int orientation;
-    
+
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_MASK = 0x0f;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_NORMAL = 0x00;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_CAR = 0x01;
+
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_MASK = 0x30;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_NO = 0x10;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_YES = 0x20;
+
+    /**
+     * Bit mask of the ui mode.  Currently there are two fields:
+     * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
+     * device. They may be one of
+     * {@link #UI_MODE_TYPE_NORMAL} or {@link #UI_MODE_TYPE_CAR}.
+     *
+     * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
+     * is in a special mode. They may be one of
+     * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
+     *
+     * @hide (UIMODE) Pending API council approval
+     */
+    public int uiMode;
+
     /**
      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
      * for this object to be valid.  {@more}
@@ -189,6 +219,7 @@
         navigationHidden = o.navigationHidden;
         orientation = o.orientation;
         screenLayout = o.screenLayout;
+        uiMode = o.uiMode;
     }
 
     public String toString() {
@@ -217,6 +248,8 @@
         sb.append(orientation);
         sb.append(" layout=");
         sb.append(screenLayout);
+        sb.append(" uiMode=");
+        sb.append(uiMode);
         sb.append('}');
         return sb.toString();
     }
@@ -237,6 +270,7 @@
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
+        uiMode = UI_MODE_TYPE_NORMAL;
     }
 
     /** {@hide} */
@@ -317,6 +351,11 @@
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
             screenLayout = delta.screenLayout;
         }
+        if (delta.uiMode != UI_MODE_TYPE_NORMAL
+                && uiMode != delta.uiMode) {
+            changed |= ActivityInfo.CONFIG_UI_MODE;
+            uiMode = delta.uiMode;
+        }
         
         return changed;
     }
@@ -393,6 +432,10 @@
                 && screenLayout != delta.screenLayout) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
+        if (delta.uiMode != UI_MODE_TYPE_NORMAL
+                && uiMode != delta.uiMode) {
+            changed |= ActivityInfo.CONFIG_UI_MODE;
+        }
         
         return changed;
     }
@@ -444,6 +487,7 @@
         dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
+        dest.writeInt(uiMode);
     }
 
     public static final Parcelable.Creator<Configuration> CREATOR
@@ -477,6 +521,7 @@
         navigationHidden = source.readInt();
         orientation = source.readInt();
         screenLayout = source.readInt();
+        uiMode = source.readInt();
     }
 
     public int compareTo(Configuration that) {
@@ -510,6 +555,8 @@
         n = this.orientation - that.orientation;
         if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
+        if (n != 0) return n;
+        n = this.uiMode - that.uiMode;
         //if (n != 0) return n;
         return n;
     }
@@ -533,6 +580,6 @@
                 + this.locale.hashCode() + this.touchscreen
                 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
                 + this.navigation + this.navigationHidden
-                + this.orientation + this.screenLayout;
+                + this.orientation + this.screenLayout + this.uiMode;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e4fc259..ae8e297 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1294,7 +1294,7 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
-                    mConfiguration.screenLayout, sSdkVersion);
+                    mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
             int N = mDrawableCache.size();
             if (DEBUG_CONFIG) {
                 Log.d(TAG, "Cleaning up drawables config changes: 0x"
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 2fff727..a82a21e 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -537,7 +537,8 @@
                                                           jint keyboard, jint keyboardHidden,
                                                           jint navigation,
                                                           jint screenWidth, jint screenHeight,
-                                                          jint screenLayout, jint sdkVersion)
+                                                          jint screenLayout, jint uiMode,
+                                                          jint sdkVersion)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
@@ -560,6 +561,7 @@
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
     config.screenLayout = (uint8_t)screenLayout;
+    config.uiMode = (uint8_t)uiMode;
     config.sdkVersion = (uint16_t)sdkVersion;
     config.minorVersion = 0;
     am->setConfiguration(config, locale8);
@@ -1614,7 +1616,7 @@
         (void*) android_content_AssetManager_setLocale },
     { "getLocales",      "()[Ljava/lang/String;",
         (void*) android_content_AssetManager_getLocales },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1ae736e..f5f5a27 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -564,6 +564,14 @@
         android:label="@string/permlab_changeConfiguration"
         android:description="@string/permdesc_changeConfiguration" />
 
+    <!-- Allows an application to enable the car mode.
+         @hide -->
+    <permission android:name="android.permission.ENABLE_CAR_MODE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_enableCarMode"
+        android:description="@string/permdesc_enableCarMode" />
+
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0a5c584..7f66111 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -462,6 +462,12 @@
         size.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_enableCarMode">enable car mode</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_enableCarMode">Allows an application to
+        enable the car mode.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_killBackgroundProcesses">kill background processes</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_killBackgroundProcesses">Allows an application to