diff --git a/api/current.xml b/api/current.xml index 444b002ed4fec..5592759226a67 100644 --- a/api/current.xml +++ b/api/current.xml @@ -38899,6 +38899,17 @@ visibility="public" > + + The intent will have the following extra values: + * + *

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. */ @@ -2153,6 +2160,16 @@ public class Intent implements Parcelable, Cloneable { */ public static final int EXTRA_DOCK_STATE_CAR = 2; + /** + * Used as an int extra field in {@link android.content.Intent#ACTION_DOCK_EVENT} + * intents to request the physical dock state. Possible values are + * {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED}, + * {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or + * {@link android.content.Intent#EXTRA_DOCK_STATE_CAR}. + */ + public static final String EXTRA_PHYSICAL_DOCK_STATE = + "android.intent.extra.PHYSICAL_DOCK_STATE"; + /** * 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. diff --git a/core/java/com/android/internal/app/DisableCarModeActivity.java b/core/java/com/android/internal/app/DisableCarModeActivity.java new file mode 100644 index 0000000000000..95dc1f9d014b3 --- /dev/null +++ b/core/java/com/android/internal/app/DisableCarModeActivity.java @@ -0,0 +1,42 @@ +/* + * 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 com.android.internal.app; + +import android.app.Activity; +import android.app.IUiModeManager; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +public class DisableCarModeActivity extends Activity { + private static final String TAG = "DisableCarModeActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + IUiModeManager uiModeManager = IUiModeManager.Stub.asInterface( + ServiceManager.getService("uimode")); + uiModeManager.disableCarMode(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to disable car mode", e); + } + finish(); + } + +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a27d28f6138ac..333db05a10f4b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1252,6 +1252,10 @@ + + We\'ve encountered a problem turning off Tethering. Please try again. + + + Car mode enabled + Select to disable car mode. + diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index b566fb7eb8a58..4791718aad9d8 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -22,8 +22,10 @@ import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IUiModeManager; import android.app.KeyguardManager; -import android.app.StatusBarManager; +import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.StatusBarManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.ActivityNotFoundException; @@ -55,6 +57,8 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; +import com.android.internal.R; +import com.android.internal.app.DisableCarModeActivity; import com.android.internal.widget.LockPatternUtils; import java.io.FileNotFoundException; @@ -101,6 +105,7 @@ class DockObserver extends UEventObserver { private final Context mContext; private PowerManagerService mPowerManager; + private NotificationManager mNotificationManager; private KeyguardManager.KeyguardLock mKeyguardLock; private boolean mKeyguardDisabled; @@ -125,7 +130,8 @@ class DockObserver extends UEventObserver { // Launch a dock activity String category; - if (mCarModeEnabled || mDockState == Intent.EXTRA_DOCK_STATE_CAR) { + if (mCarModeEnabled) { + // Only launch car home when car mode is enabled. category = Intent.CATEGORY_CAR_DOCK; } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) { category = Intent.CATEGORY_DESK_DOCK; @@ -332,9 +338,13 @@ class DockObserver extends UEventObserver { 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 if (!mCarModeEnabled && mDockState == Intent.EXTRA_DOCK_STATE_CAR) { + // Pretend to be in DOCK_STATE_UNDOCKED. + intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); } else { intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState); } + intent.putExtra(Intent.EXTRA_PHYSICAL_DOCK_STATE, mDockState); intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled); // Check if this is Bluetooth Dock @@ -462,6 +472,52 @@ class DockObserver extends UEventObserver { } }; + private void adjustStatusBarCarMode() { + if (mStatusBarManager == null) { + mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE); + } + + // Fear not: StatusBarService manages a list of requests to disable + // features of the status bar; these are ORed together to form the + // active disabled list. So if (for example) the device is locked and + // the status bar should be totally disabled, the calls below will + // have no effect until the device is unlocked. + if (mStatusBarManager != null) { + long ident = Binder.clearCallingIdentity(); + mStatusBarManager.disable(mCarModeEnabled + ? StatusBarManager.DISABLE_NOTIFICATION_TICKER + : StatusBarManager.DISABLE_NONE); + Binder.restoreCallingIdentity(ident); + } + + if (mNotificationManager == null) { + mNotificationManager = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + } + + if (mNotificationManager != null) { + long ident = Binder.clearCallingIdentity(); + if (mCarModeEnabled) { + Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class); + + Notification n = new Notification(); + n.icon = R.drawable.stat_notify_car_mode; + n.defaults = Notification.DEFAULT_LIGHTS; + n.flags = Notification.FLAG_ONGOING_EVENT; + n.when = 0; + n.setLatestEventInfo( + mContext, + mContext.getString(R.string.car_mode_disable_notification_title), + mContext.getString(R.string.car_mode_disable_notification_message), + PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0)); + mNotificationManager.notify(0, n); + } else { + mNotificationManager.cancel(0); + } + Binder.restoreCallingIdentity(ident); + } + } + private void setCarMode(boolean enabled) throws RemoteException { mCarModeEnabled = enabled; if (enabled) { @@ -475,23 +531,7 @@ class DockObserver extends UEventObserver { setMode(Configuration.UI_MODE_TYPE_NORMAL, Configuration.UI_MODE_NIGHT_UNDEFINED); } - - if (mStatusBarManager == null) { - mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE); - } - - // Fear not: StatusBarService manages a list of requests to disable - // features of the status bar; these are ORed together to form the - // active disabled list. So if (for example) the device is locked and - // the status bar should be totally disabled, the calls below will - // have no effect until the device is unlocked. - if (mStatusBarManager != null) { - long ident = Binder.clearCallingIdentity(); - mStatusBarManager.disable(enabled - ? StatusBarManager.DISABLE_NOTIFICATION_TICKER - : StatusBarManager.DISABLE_NONE); - Binder.restoreCallingIdentity(ident); - } + adjustStatusBarCarMode(); } private void setMode(int modeType, int modeNight) throws RemoteException {