diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | api/current.xml | 11 | ||||
-rw-r--r-- | core/java/android/app/IUiModeManager.aidl | 49 | ||||
-rw-r--r-- | core/java/android/content/Intent.java | 10 | ||||
-rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 7 | ||||
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 2 | ||||
-rw-r--r-- | core/java/android/content/res/Configuration.java | 51 | ||||
-rw-r--r-- | core/java/android/content/res/Resources.java | 2 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 6 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 8 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 6 | ||||
-rw-r--r-- | include/utils/ResourceTypes.h | 85 | ||||
-rw-r--r-- | services/java/com/android/server/DockObserver.java | 120 | ||||
-rw-r--r-- | tools/aapt/AaptAssets.cpp | 100 | ||||
-rw-r--r-- | tools/aapt/AaptAssets.h | 6 | ||||
-rw-r--r-- | tools/aapt/Resource.cpp | 4 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 12 | ||||
-rw-r--r-- | tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java | 3 |
18 files changed, 444 insertions, 39 deletions
@@ -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=""android.intent.extra.CAR_MODE_ENABLED"" + 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(), ¶ms); getScreenLayoutLongName(screenLayoutLong.string(), ¶ms); getOrientationName(orientation.string(), ¶ms); + getUiModeTypeName(uiModeType.string(), ¶ms); + getUiModeNightName(uiModeNight.string(), ¶ms); getDensityName(density.string(), ¶ms); getTouchscreenName(touchscreen.string(), ¶ms); getKeysHiddenName(keysHidden.string(), ¶ms); 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; } } |