summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.xml11
-rw-r--r--core/java/android/app/IUiModeManager.aidl49
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/content/pm/ActivityInfo.java7
-rw-r--r--core/java/android/content/res/AssetManager.java2
-rw-r--r--core/java/android/content/res/Configuration.java51
-rw-r--r--core/java/android/content/res/Resources.java2
-rw-r--r--core/jni/android_util_AssetManager.cpp6
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--core/res/res/values/strings.xml6
-rw-r--r--include/utils/ResourceTypes.h85
-rw-r--r--services/java/com/android/server/DockObserver.java120
-rw-r--r--tools/aapt/AaptAssets.cpp100
-rw-r--r--tools/aapt/AaptAssets.h6
-rw-r--r--tools/aapt/Resource.cpp4
-rw-r--r--tools/aapt/ResourceTable.cpp12
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java3
18 files changed, 444 insertions, 39 deletions
diff --git a/Android.mk b/Android.mk
index 7fc121d..4ecf5bd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IStatusBar.aidl \
core/java/android/app/IThumbnailReceiver.aidl \
core/java/android/app/ITransientNotification.aidl \
+ core/java/android/app/IUiModeManager.aidl \
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
core/java/android/backup/IBackupManager.aidl \
diff --git a/api/current.xml b/api/current.xml
index ab5a114..b2a2bc1 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -38037,6 +38037,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_CAR_MODE_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.CAR_MODE_ENABLED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_CC"
type="java.lang.String"
transient="false"
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 @@ public class Intent implements Parcelable, Cloneable {
/**
* 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 class Intent implements Parcelable, Cloneable {
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 class ActivityInfo extends ComponentInfo
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 final class AssetManager {
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 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration
navigationHidden = o.navigationHidden;
orientation = o.orientation;
screenLayout = o.screenLayout;
+ uiMode = o.uiMode;
}
public String toString() {
@@ -217,6 +248,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
sb.append(orientation);
sb.append(" layout=");
sb.append(screenLayout);
+ sb.append(" uiMode=");
+ sb.append(uiMode);
sb.append('}');
return sb.toString();
}
@@ -237,6 +270,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
+ uiMode = UI_MODE_TYPE_NORMAL;
}
/** {@hide} */
@@ -317,6 +351,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
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 @@ public final class Configuration implements Parcelable, Comparable<Configuration
&& 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(navigationHidden);
dest.writeInt(orientation);
dest.writeInt(screenLayout);
+ dest.writeInt(uiMode);
}
public static final Parcelable.Creator<Configuration> CREATOR
@@ -477,6 +521,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
navigationHidden = source.readInt();
orientation = source.readInt();
screenLayout = source.readInt();
+ uiMode = source.readInt();
}
public int compareTo(Configuration that) {
@@ -510,6 +555,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
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 @@ public final class Configuration implements Parcelable, Comparable<Configuration
+ 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 @@ public class Resources {
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 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c
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 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c
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 @@ static JNINativeMethod gAssetManagerMethods[] = {
(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
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 6090f60..13ea27e 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -939,10 +939,23 @@ struct ResTable_config
SCREENLONG_YES = 0x20,
};
+ enum {
+ // uiMode bits for the mode type.
+ MASK_UI_MODE_TYPE = 0x0f,
+ UI_MODE_TYPE_NORMAL = 0x00,
+ UI_MODE_TYPE_CAR = 0x01,
+
+ // uiMode bits for the night switch.
+ MASK_UI_MODE_NIGHT = 0x30,
+ UI_MODE_NIGHT_ANY = 0x00,
+ UI_MODE_NIGHT_NO = 0x10,
+ UI_MODE_NIGHT_YES = 0x20,
+ };
+
union {
struct {
uint8_t screenLayout;
- uint8_t screenConfigPad0;
+ uint8_t uiMode;
uint8_t screenConfigPad1;
uint8_t screenConfigPad2;
};
@@ -996,6 +1009,8 @@ struct ResTable_config
diff = (int32_t)(version - o.version);
if (diff != 0) return diff;
diff = (int32_t)(screenLayout - o.screenLayout);
+ if (diff != 0) return diff;
+ diff = (int32_t)(uiMode - o.uiMode);
return (int)diff;
}
@@ -1014,7 +1029,8 @@ struct ResTable_config
CONFIG_DENSITY = 0x0100,
CONFIG_SCREEN_SIZE = 0x0200,
CONFIG_VERSION = 0x0400,
- CONFIG_SCREEN_LAYOUT = 0x0800
+ CONFIG_SCREEN_LAYOUT = 0x0800,
+ CONFIG_UI_MODE = 0x1000
};
// Compare two configuration, returning CONFIG_* flags set for each value
@@ -1034,6 +1050,7 @@ struct ResTable_config
if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
if (version != o.version) diffs |= CONFIG_VERSION;
if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
+ if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
return diffs;
}
@@ -1078,19 +1095,28 @@ struct ResTable_config
}
}
- if (screenType || o.screenType) {
- if (orientation != o.orientation) {
- if (!orientation) return false;
- if (!o.orientation) return true;
+ if (orientation != o.orientation) {
+ if (!orientation) return false;
+ if (!o.orientation) return true;
+ }
+
+ if (screenConfig || o.screenConfig) {
+ if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0) {
+ if (!(uiMode & MASK_UI_MODE_TYPE)) return false;
+ if (!(o.uiMode & MASK_UI_MODE_TYPE)) return true;
+ }
+ if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0) {
+ if (!(uiMode & MASK_UI_MODE_NIGHT)) return false;
+ if (!(o.uiMode & MASK_UI_MODE_NIGHT)) return true;
}
+ }
- // density is never 'more specific'
- // as the default just equals 160
+ // density is never 'more specific'
+ // as the default just equals 160
- if (touchscreen != o.touchscreen) {
- if (!touchscreen) return false;
- if (!o.touchscreen) return true;
- }
+ if (touchscreen != o.touchscreen) {
+ if (!touchscreen) return false;
+ if (!o.touchscreen) return true;
}
if (input || o.input) {
@@ -1186,11 +1212,22 @@ struct ResTable_config
}
}
- if (screenType || o.screenType) {
- if ((orientation != o.orientation) && requested->orientation) {
- return (orientation);
+ if ((orientation != o.orientation) && requested->orientation) {
+ return (orientation);
+ }
+
+ if (screenConfig || o.screenConfig) {
+ if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0
+ && (requested->uiMode & MASK_UI_MODE_TYPE)) {
+ return (uiMode & MASK_UI_MODE_TYPE);
+ }
+ if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0
+ && (requested->uiMode & MASK_UI_MODE_NIGHT)) {
+ return (uiMode & MASK_UI_MODE_NIGHT);
}
+ }
+ if (screenType || o.screenType) {
if (density != o.density) {
// density is tough. Any density is potentially useful
// because the system will scale it. Scaling down
@@ -1340,6 +1377,20 @@ struct ResTable_config
&& screenLong != setScreenLong) {
return false;
}
+
+ const int uiModeType = uiMode&MASK_UI_MODE_TYPE;
+ const int setUiModeType = settings.uiMode&MASK_UI_MODE_TYPE;
+ if (setUiModeType != 0 && uiModeType != 0
+ && uiModeType != setUiModeType) {
+ return false;
+ }
+
+ const int uiModeNight = uiMode&MASK_UI_MODE_NIGHT;
+ const int setUiModeNight = settings.uiMode&MASK_UI_MODE_NIGHT;
+ if (setUiModeNight != 0 && uiModeNight != 0
+ && uiModeNight != setUiModeNight) {
+ return false;
+ }
}
if (screenType != 0) {
if (settings.orientation != 0 && orientation != 0
@@ -1420,13 +1471,15 @@ struct ResTable_config
String8 toString() const {
char buf[200];
sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d "
- "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d vers=%d.%d",
+ "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d "
+ "ui=%d night=%d vers=%d.%d",
mcc, mnc,
language[0] ? language[0] : '-', language[1] ? language[1] : '-',
country[0] ? country[0] : '-', country[1] ? country[1] : '-',
orientation, touchscreen, density, keyboard, navigation, inputFlags,
screenWidth, screenHeight,
screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG,
+ uiMode&MASK_UI_MODE_TYPE, uiMode&MASK_UI_MODE_NIGHT,
sdkVersion, minorVersion);
return String8(buf);
}
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 363e93e..742a7d8 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -17,6 +17,9 @@
package com.android.server;
import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IUiModeManager;
import android.app.KeyguardManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -24,8 +27,12 @@ import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Binder;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UEventObserver;
import android.provider.Settings;
@@ -47,7 +54,13 @@ class DockObserver extends UEventObserver {
private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
+ public static final int MODE_NIGHT_AUTO = Configuration.UI_MODE_NIGHT_MASK >> 4;
+ public static final int MODE_NIGHT_NO = Configuration.UI_MODE_NIGHT_NO >> 4;
+ public static final int MODE_NIGHT_YES = Configuration.UI_MODE_NIGHT_YES >> 4;
+
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ private int mNightMode = MODE_NIGHT_NO;
+ private boolean mCarModeEnabled = false;
private boolean mSystemReady;
private final Context mContext;
@@ -71,16 +84,12 @@ class DockObserver extends UEventObserver {
// Launch a dock activity
String category;
- switch (mDockState) {
- case Intent.EXTRA_DOCK_STATE_CAR:
- category = Intent.CATEGORY_CAR_DOCK;
- break;
- case Intent.EXTRA_DOCK_STATE_DESK:
- category = Intent.CATEGORY_DESK_DOCK;
- break;
- default:
- category = null;
- break;
+ if (mCarModeEnabled || mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+ category = Intent.CATEGORY_CAR_DOCK;
+ } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+ category = Intent.CATEGORY_DESK_DOCK;
+ } else {
+ category = null;
}
if (category != null) {
intent = new Intent(Intent.ACTION_MAIN);
@@ -101,6 +110,9 @@ class DockObserver extends UEventObserver {
mPowerManager = pm;
mLockPatternUtils = new LockPatternUtils(context);
init(); // set initial status
+
+ ServiceManager.addService("uimode", mBinder);
+
startObserving(DOCK_UEVENT_MATCH);
}
@@ -116,6 +128,14 @@ class DockObserver extends UEventObserver {
if (newState != mDockState) {
int oldState = mDockState;
mDockState = newState;
+ boolean carModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+ if (mCarModeEnabled != carModeEnabled) {
+ try {
+ setCarMode(carModeEnabled);
+ } catch (RemoteException e1) {
+ Log.w(TAG, "Unable to change car mode.", e1);
+ }
+ }
if (mSystemReady) {
// Don't force screen on when undocking from the desk dock.
// The change in power state will do this anyway.
@@ -180,7 +200,13 @@ class DockObserver extends UEventObserver {
// Pack up the values and broadcast them to everyone
Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+ if (mCarModeEnabled && mDockState != Intent.EXTRA_DOCK_STATE_CAR) {
+ // Pretend to be in DOCK_STATE_CAR.
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_CAR);
+ } else {
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+ }
+ intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled);
// Check if this is Bluetooth Dock
String address = BluetoothService.readDockBluetoothAddress();
@@ -199,4 +225,76 @@ class DockObserver extends UEventObserver {
}
}
};
+
+ private void setCarMode(boolean enabled) throws RemoteException {
+ mCarModeEnabled = enabled;
+ if (enabled) {
+ setMode(Configuration.UI_MODE_TYPE_CAR, mNightMode);
+ } else {
+ // Disabling the car mode clears the night mode.
+ setMode(Configuration.UI_MODE_TYPE_NORMAL, MODE_NIGHT_NO);
+ }
+ }
+
+ private void setMode(int modeType, int modeNight) throws RemoteException {
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ Configuration config = am.getConfiguration();
+
+ if (config.uiMode != (modeType | modeNight)) {
+ config.uiMode = modeType | modeNight;
+ long ident = Binder.clearCallingIdentity();
+ am.updateConfiguration(config);
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void setNightMode(int mode) throws RemoteException {
+ mNightMode = mode;
+ switch (mode) {
+ case MODE_NIGHT_NO:
+ case MODE_NIGHT_YES:
+ setMode(Configuration.UI_MODE_TYPE_CAR, mode << 4);
+ break;
+ case MODE_NIGHT_AUTO:
+ // FIXME: not yet supported, this functionality will be
+ // added in a separate change.
+ break;
+ default:
+ setMode(Configuration.UI_MODE_TYPE_CAR, MODE_NIGHT_NO << 4);
+ break;
+ }
+ }
+
+ /**
+ * Wrapper class implementing the IUiModeManager interface.
+ */
+ private final IUiModeManager.Stub mBinder = new IUiModeManager.Stub() {
+
+ public void disableCarMode() throws RemoteException {
+ if (mCarModeEnabled) {
+ setCarMode(false);
+ update();
+ }
+ }
+
+ public void enableCarMode() throws RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ENABLE_CAR_MODE,
+ "Need ENABLE_CAR_MODE permission");
+ if (!mCarModeEnabled) {
+ setCarMode(true);
+ update();
+ }
+ }
+
+ public void setNightMode(int mode) throws RemoteException {
+ if (mCarModeEnabled) {
+ DockObserver.this.setNightMode(mode);
+ }
+ }
+
+ public int getNightMode() throws RemoteException {
+ return mNightMode;
+ }
+ };
}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index c346b90..663a33a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -163,6 +163,20 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
return 0;
}
+ // ui mode type
+ if (getUiModeTypeName(part.string(), &config)) {
+ *axis = AXIS_UIMODETYPE;
+ *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+ return 0;
+ }
+
+ // ui mode night
+ if (getUiModeNightName(part.string(), &config)) {
+ *axis = AXIS_UIMODENIGHT;
+ *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+ return 0;
+ }
+
// density
if (getDensityName(part.string(), &config)) {
*axis = AXIS_DENSITY;
@@ -229,6 +243,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
String8 touch, key, keysHidden, nav, navHidden, size, vers;
+ String8 uiModeType, uiModeNight;
const char *p = dir;
const char *q;
@@ -352,6 +367,32 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
//printf("not orientation: %s\n", part.string());
}
+ // ui mode type
+ if (getUiModeTypeName(part.string())) {
+ uiModeType = part;
+
+ index++;
+ if (index == N) {
+ goto success;
+ }
+ part = parts[index];
+ } else {
+ //printf("not ui mode type: %s\n", part.string());
+ }
+
+ // ui mode night
+ if (getUiModeNightName(part.string())) {
+ uiModeNight = part;
+
+ index++;
+ if (index == N) {
+ goto success;
+ }
+ part = parts[index];
+ } else {
+ //printf("not ui mode night: %s\n", part.string());
+ }
+
// density
if (getDensityName(part.string())) {
den = part;
@@ -463,6 +504,8 @@ success:
this->screenLayoutSize = layoutsize;
this->screenLayoutLong = layoutlong;
this->orientation = orient;
+ this->uiModeType = uiModeType;
+ this->uiModeNight = uiModeNight;
this->density = den;
this->touchscreen = touch;
this->keysHidden = keysHidden;
@@ -493,6 +536,10 @@ AaptGroupEntry::toString() const
s += ",";
s += this->orientation;
s += ",";
+ s += uiModeType;
+ s += ",";
+ s += uiModeNight;
+ s += ",";
s += density;
s += ",";
s += touchscreen;
@@ -539,6 +586,14 @@ AaptGroupEntry::toDirName(const String8& resType) const
s += "-";
s += orientation;
}
+ if (this->uiModeType != "") {
+ s += "-";
+ s += uiModeType;
+ }
+ if (this->uiModeNight != "") {
+ s += "-";
+ s += uiModeNight;
+ }
if (this->density != "") {
s += "-";
s += density;
@@ -759,6 +814,47 @@ bool AaptGroupEntry::getOrientationName(const char* name,
return false;
}
+bool AaptGroupEntry::getUiModeTypeName(const char* name,
+ ResTable_config* out)
+{
+ if (strcmp(name, kWildcardName) == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+ | ResTable_config::UI_MODE_TYPE_NORMAL;
+ return true;
+ } else if (strcmp(name, "car") == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+ | ResTable_config::UI_MODE_TYPE_CAR;
+ return true;
+ }
+
+ return false;
+}
+
+bool AaptGroupEntry::getUiModeNightName(const char* name,
+ ResTable_config* out)
+{
+ if (strcmp(name, kWildcardName) == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+ | ResTable_config::UI_MODE_NIGHT_ANY;
+ return true;
+ } else if (strcmp(name, "night") == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+ | ResTable_config::UI_MODE_NIGHT_YES;
+ return true;
+ } else if (strcmp(name, "notnight") == 0) {
+ if (out) out->uiMode =
+ (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+ | ResTable_config::UI_MODE_NIGHT_NO;
+ return true;
+ }
+
+ return false;
+}
+
bool AaptGroupEntry::getDensityName(const char* name,
ResTable_config* out)
{
@@ -1004,6 +1100,8 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const
if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
if (v == 0) v = orientation.compare(o.orientation);
+ if (v == 0) v = uiModeType.compare(o.uiModeType);
+ if (v == 0) v = uiModeNight.compare(o.uiModeNight);
if (v == 0) v = density.compare(o.density);
if (v == 0) v = touchscreen.compare(o.touchscreen);
if (v == 0) v = keysHidden.compare(o.keysHidden);
@@ -1025,6 +1123,8 @@ ResTable_config AaptGroupEntry::toParams() const
getScreenLayoutSizeName(screenLayoutSize.string(), &params);
getScreenLayoutLongName(screenLayoutLong.string(), &params);
getOrientationName(orientation.string(), &params);
+ getUiModeTypeName(uiModeType.string(), &params);
+ getUiModeNightName(uiModeNight.string(), &params);
getDensityName(density.string(), &params);
getTouchscreenName(touchscreen.string(), &params);
getKeysHiddenName(keysHidden.string(), &params);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 26500a3..9a848e4 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -33,6 +33,8 @@ enum {
AXIS_SCREENLAYOUTSIZE,
AXIS_SCREENLAYOUTLONG,
AXIS_ORIENTATION,
+ AXIS_UIMODETYPE,
+ AXIS_UIMODENIGHT,
AXIS_DENSITY,
AXIS_TOUCHSCREEN,
AXIS_KEYSHIDDEN,
@@ -61,6 +63,8 @@ public:
String8 screenLayoutSize;
String8 screenLayoutLong;
String8 orientation;
+ String8 uiModeType;
+ String8 uiModeNight;
String8 density;
String8 touchscreen;
String8 keysHidden;
@@ -80,6 +84,8 @@ public:
static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
static bool getOrientationName(const char* name, ResTable_config* out = NULL);
+ static bool getUiModeTypeName(const char* name, ResTable_config* out = NULL);
+ static bool getUiModeNightName(const char* name, ResTable_config* out = NULL);
static bool getDensityName(const char* name, ResTable_config* out = NULL);
static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 0d2ea60..88c5441 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -101,13 +101,13 @@ public:
String8 leaf(group->getLeaf());
mLeafName = String8(leaf);
mParams = file->getGroupEntry().toParams();
- NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
+ NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d ui=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
group->getPath().string(), mParams.mcc, mParams.mnc,
mParams.language[0] ? mParams.language[0] : '-',
mParams.language[1] ? mParams.language[1] : '-',
mParams.country[0] ? mParams.country[0] : '-',
mParams.country[1] ? mParams.country[1] : '-',
- mParams.orientation,
+ mParams.orientation, mParams.uiMode,
mParams.density, mParams.touchscreen, mParams.keyboard,
mParams.inputFlags, mParams.navigation));
mPath = "res";
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b682702..a389bfb 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2472,6 +2472,12 @@ ResourceFilter::match(const ResTable_config& config)
if (!match(AXIS_ORIENTATION, config.orientation)) {
return false;
}
+ if (!match(AXIS_UIMODETYPE, (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE))) {
+ return false;
+ }
+ if (!match(AXIS_UIMODENIGHT, (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT))) {
+ return false;
+ }
if (!match(AXIS_DENSITY, config.density)) {
return false;
}
@@ -2674,7 +2680,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
- "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+ "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
ti+1,
config.mcc, config.mnc,
config.language[0] ? config.language[0] : '-',
@@ -2682,6 +2688,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
config.country[0] ? config.country[0] : '-',
config.country[1] ? config.country[1] : '-',
config.orientation,
+ config.uiMode,
config.touchscreen,
config.density,
config.keyboard,
@@ -2711,7 +2718,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
tHeader->entriesStart = htodl(typeSize);
tHeader->config = config;
NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
- "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+ "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
ti+1,
tHeader->config.mcc, tHeader->config.mnc,
tHeader->config.language[0] ? tHeader->config.language[0] : '-',
@@ -2719,6 +2726,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
tHeader->config.country[0] ? tHeader->config.country[0] : '-',
tHeader->config.country[1] ? tHeader->config.country[1] : '-',
tHeader->config.orientation,
+ tHeader->config.uiMode,
tHeader->config.touchscreen,
tHeader->config.density,
tHeader->config.keyboard,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
index 6c1b5b3..43ff424 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
@@ -59,7 +59,7 @@ public class BridgeAssetManager extends AssetManager {
public 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 version) {
+ int screenLayout, int uiMode, int version) {
Configuration c = new Configuration();
c.mcc = mcc;
@@ -71,5 +71,6 @@ public class BridgeAssetManager extends AssetManager {
c.navigation = navigation;
c.orientation = orientation;
c.screenLayout = screenLayout;
+ c.uiMode = uiMode;
}
}