blob: 617b29da93a13ebeb436b73ab40f66850f8713e8 [file] [log] [blame]
Dianne Hackborn7299c412010-03-04 18:41:49 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.app.Activity;
20import android.app.ActivityManagerNative;
Dianne Hackborn7299c412010-03-04 18:41:49 -080021import android.app.IUiModeManager;
22import android.app.Notification;
23import android.app.NotificationManager;
24import android.app.PendingIntent;
25import android.app.StatusBarManager;
26import android.app.UiModeManager;
Dianne Hackbornf5c5d222010-04-09 13:14:48 -070027import android.content.ActivityNotFoundException;
Dianne Hackborn7299c412010-03-04 18:41:49 -080028import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.content.pm.PackageManager;
33import android.content.res.Configuration;
Mike Lockwoode29db6a2010-03-05 13:45:51 -050034import android.os.BatteryManager;
Dianne Hackborn7299c412010-03-04 18:41:49 -080035import android.os.Binder;
Dianne Hackborn7299c412010-03-04 18:41:49 -080036import android.os.Handler;
Mike Lockwoode29db6a2010-03-05 13:45:51 -050037import android.os.PowerManager;
Dianne Hackborn7299c412010-03-04 18:41:49 -080038import android.os.RemoteException;
39import android.os.ServiceManager;
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -070040import android.provider.Settings;
Dianne Hackborn7299c412010-03-04 18:41:49 -080041import android.util.Slog;
42
43import java.io.FileDescriptor;
44import java.io.PrintWriter;
45
46import com.android.internal.R;
47import com.android.internal.app.DisableCarModeActivity;
Jeff Brown2416e092012-08-21 22:12:20 -070048import com.android.server.TwilightService.TwilightState;
Dianne Hackborn7299c412010-03-04 18:41:49 -080049
50class UiModeManagerService extends IUiModeManager.Stub {
51 private static final String TAG = UiModeManager.class.getSimpleName();
52 private static final boolean LOG = false;
53
Daniel Sandler11ddf532011-11-16 11:10:03 -080054 // Enable launching of applications when entering the dock.
55 private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
John Spurlock960779d2012-05-29 14:37:05 -040056 private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
Daniel Sandler11ddf532011-11-16 11:10:03 -080057
Dianne Hackborn7299c412010-03-04 18:41:49 -080058 private final Context mContext;
Jeff Brown2416e092012-08-21 22:12:20 -070059 private final TwilightService mTwilightService;
60 private final Handler mHandler = new Handler();
Dianne Hackborn7299c412010-03-04 18:41:49 -080061
62 final Object mLock = new Object();
Bernd Holzheyba9ab182010-03-12 09:30:29 +010063
Dianne Hackborn7299c412010-03-04 18:41:49 -080064 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
65 private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Bernd Holzheyba9ab182010-03-12 09:30:29 +010066
Dianne Hackborn7299c412010-03-04 18:41:49 -080067 private int mNightMode = UiModeManager.MODE_NIGHT_NO;
68 private boolean mCarModeEnabled = false;
Mike Lockwoode29db6a2010-03-05 13:45:51 -050069 private boolean mCharging = false;
Joe Onorato44fcb832011-12-14 20:59:30 -080070 private final int mDefaultUiModeType;
Mike Lockwoode29db6a2010-03-05 13:45:51 -050071 private final boolean mCarModeKeepsScreenOn;
72 private final boolean mDeskModeKeepsScreenOn;
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -070073 private final boolean mTelevision;
Dianne Hackborn7299c412010-03-04 18:41:49 -080074
75 private boolean mComputedNightMode;
76 private int mCurUiMode = 0;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080077 private int mSetUiMode = 0;
Bernd Holzheyba9ab182010-03-12 09:30:29 +010078
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080079 private boolean mHoldingConfiguration = false;
Dianne Hackborn7299c412010-03-04 18:41:49 -080080 private Configuration mConfiguration = new Configuration();
Bernd Holzheyba9ab182010-03-12 09:30:29 +010081
Dianne Hackborn7299c412010-03-04 18:41:49 -080082 private boolean mSystemReady;
83
84 private NotificationManager mNotificationManager;
85
Dianne Hackborn7299c412010-03-04 18:41:49 -080086 private StatusBarManager mStatusBarManager;
Mike Lockwoode29db6a2010-03-05 13:45:51 -050087 private final PowerManager.WakeLock mWakeLock;
Dianne Hackborn7299c412010-03-04 18:41:49 -080088
Dianne Hackbornf5c5d222010-04-09 13:14:48 -070089 static Intent buildHomeIntent(String category) {
90 Intent intent = new Intent(Intent.ACTION_MAIN);
91 intent.addCategory(category);
92 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
93 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
94 return intent;
95 }
John Spurlock960779d2012-05-29 14:37:05 -040096
Dianne Hackborn7299c412010-03-04 18:41:49 -080097 // The broadcast receiver which receives the result of the ordered broadcast sent when
98 // the dock state changes. The original ordered broadcast is sent with an initial result
99 // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
100 // to RESULT_CANCELED, then the intent to start a dock app will not be sent.
101 private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
102 @Override
103 public void onReceive(Context context, Intent intent) {
104 if (getResultCode() != Activity.RESULT_OK) {
Daniel Sandler69a1da42011-11-04 15:08:30 -0400105 if (LOG) {
John Spurlock960779d2012-05-29 14:37:05 -0400106 Slog.v(TAG, "Handling broadcast result for action " + intent.getAction()
Daniel Sandler69a1da42011-11-04 15:08:30 -0400107 + ": canceled: " + getResultCode());
108 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800109 return;
110 }
111
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700112 final int enableFlags = intent.getIntExtra("enableFlags", 0);
113 final int disableFlags = intent.getIntExtra("disableFlags", 0);
John Spurlock960779d2012-05-29 14:37:05 -0400114
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800115 synchronized (mLock) {
116 // Launch a dock activity
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700117 String category = null;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800118 if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700119 // Only launch car home when car mode is enabled and the caller
120 // has asked us to switch to it.
Daniel Sandler11ddf532011-11-16 11:10:03 -0800121 if (ENABLE_LAUNCH_CAR_DOCK_APP
122 && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700123 category = Intent.CATEGORY_CAR_DOCK;
124 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800125 } else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(intent.getAction())) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700126 // Only launch car home when desk mode is enabled and the caller
127 // has asked us to switch to it. Currently re-using the car
128 // mode flag since we don't have a formal API for "desk mode".
Daniel Sandler11ddf532011-11-16 11:10:03 -0800129 if (ENABLE_LAUNCH_DESK_DOCK_APP
130 && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700131 category = Intent.CATEGORY_DESK_DOCK;
132 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800133 } else {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700134 // Launch the standard home app if requested.
135 if ((disableFlags&UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
136 category = Intent.CATEGORY_HOME;
137 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800138 }
Daniel Sandler69a1da42011-11-04 15:08:30 -0400139
140 if (LOG) {
141 Slog.v(TAG, String.format(
John Spurlock960779d2012-05-29 14:37:05 -0400142 "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s",
Daniel Sandler69a1da42011-11-04 15:08:30 -0400143 intent.getAction(), enableFlags, disableFlags, category));
144 }
John Spurlock960779d2012-05-29 14:37:05 -0400145
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800146 if (category != null) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700147 // This is the new activity that will serve as home while
148 // we are in care mode.
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700149 Intent homeIntent = buildHomeIntent(category);
John Spurlock960779d2012-05-29 14:37:05 -0400150
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700151 // Now we are going to be careful about switching the
152 // configuration and starting the activity -- we need to
153 // do this in a specific order under control of the
154 // activity manager, to do it cleanly. So compute the
155 // new config, but don't set it yet, and let the
156 // activity manager take care of both the start and config
157 // change.
158 Configuration newConfig = null;
159 if (mHoldingConfiguration) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700160 mHoldingConfiguration = false;
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700161 updateConfigurationLocked(false);
162 newConfig = mConfiguration;
163 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800164 try {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700165 ActivityManagerNative.getDefault().startActivityWithConfig(
Dianne Hackborna4972e92012-03-14 10:38:05 -0700166 null, homeIntent, null, null, null, 0, 0,
167 newConfig, null);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700168 mHoldingConfiguration = false;
169 } catch (RemoteException e) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800170 Slog.w(TAG, e.getCause());
171 }
172 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100173
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800174 if (mHoldingConfiguration) {
175 mHoldingConfiguration = false;
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700176 updateConfigurationLocked(true);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800177 }
178 }
179 }
180 };
181
Dianne Hackborn7299c412010-03-04 18:41:49 -0800182 private final BroadcastReceiver mDockModeReceiver = new BroadcastReceiver() {
183 @Override
184 public void onReceive(Context context, Intent intent) {
185 int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
186 Intent.EXTRA_DOCK_STATE_UNDOCKED);
187 updateDockState(state);
188 }
189 };
190
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500191 private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
192 @Override
193 public void onReceive(Context context, Intent intent) {
194 mCharging = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
195 synchronized (mLock) {
196 if (mSystemReady) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700197 updateLocked(0, 0);
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500198 }
199 }
200 }
201 };
202
Jeff Brown2416e092012-08-21 22:12:20 -0700203 private final TwilightService.TwilightListener mTwilightListener =
204 new TwilightService.TwilightListener() {
Dianne Hackborn57f45032010-06-17 15:49:33 -0700205 @Override
Jeff Brown2416e092012-08-21 22:12:20 -0700206 public void onTwilightStateChanged() {
207 updateTwilight();
Dianne Hackborn57f45032010-06-17 15:49:33 -0700208 }
209 };
210
Jeff Brown2416e092012-08-21 22:12:20 -0700211 public UiModeManagerService(Context context, TwilightService twilight) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800212 mContext = context;
Jeff Brown2416e092012-08-21 22:12:20 -0700213 mTwilightService = twilight;
Dianne Hackborn7299c412010-03-04 18:41:49 -0800214
215 ServiceManager.addService(Context.UI_MODE_SERVICE, this);
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100216
Dianne Hackborn7299c412010-03-04 18:41:49 -0800217 mContext.registerReceiver(mDockModeReceiver,
218 new IntentFilter(Intent.ACTION_DOCK_EVENT));
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500219 mContext.registerReceiver(mBatteryReceiver,
220 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
221
222 PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
223 mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800224
225 mConfiguration.setToDefaults();
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500226
Joe Onorato44fcb832011-12-14 20:59:30 -0800227 mDefaultUiModeType = context.getResources().getInteger(
228 com.android.internal.R.integer.config_defaultUiModeType);
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500229 mCarModeKeepsScreenOn = (context.getResources().getInteger(
230 com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
231 mDeskModeKeepsScreenOn = (context.getResources().getInteger(
232 com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700233 mTelevision = context.getPackageManager().hasSystemFeature(
234 PackageManager.FEATURE_TELEVISION);
235
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700236 mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
237 Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
Jeff Brown2416e092012-08-21 22:12:20 -0700238
239 mTwilightService.registerListener(mTwilightListener, mHandler);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800240 }
241
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700242 public void disableCarMode(int flags) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800243 synchronized (mLock) {
244 setCarModeLocked(false);
Mike Lockwood924e1642010-03-05 11:56:53 -0500245 if (mSystemReady) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700246 updateLocked(0, flags);
Mike Lockwood924e1642010-03-05 11:56:53 -0500247 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800248 }
249 }
250
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700251 public void enableCarMode(int flags) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800252 synchronized (mLock) {
253 setCarModeLocked(true);
Mike Lockwood924e1642010-03-05 11:56:53 -0500254 if (mSystemReady) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700255 updateLocked(flags, 0);
Mike Lockwood924e1642010-03-05 11:56:53 -0500256 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800257 }
258 }
259
260 public int getCurrentModeType() {
261 synchronized (mLock) {
262 return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
263 }
264 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100265
Dianne Hackborn7299c412010-03-04 18:41:49 -0800266 public void setNightMode(int mode) throws RemoteException {
267 synchronized (mLock) {
268 switch (mode) {
269 case UiModeManager.MODE_NIGHT_NO:
270 case UiModeManager.MODE_NIGHT_YES:
271 case UiModeManager.MODE_NIGHT_AUTO:
272 break;
273 default:
274 throw new IllegalArgumentException("Unknown mode: " + mode);
275 }
276 if (!isDoingNightMode()) {
277 return;
278 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100279
Dianne Hackborn7299c412010-03-04 18:41:49 -0800280 if (mNightMode != mode) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700281 long ident = Binder.clearCallingIdentity();
282 Settings.Secure.putInt(mContext.getContentResolver(),
283 Settings.Secure.UI_NIGHT_MODE, mode);
284 Binder.restoreCallingIdentity(ident);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800285 mNightMode = mode;
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700286 updateLocked(0, 0);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800287 }
288 }
289 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100290
Dianne Hackborn7299c412010-03-04 18:41:49 -0800291 public int getNightMode() throws RemoteException {
292 return mNightMode;
293 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100294
Dianne Hackborn7299c412010-03-04 18:41:49 -0800295 void systemReady() {
296 synchronized (mLock) {
297 mSystemReady = true;
298 mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
Jeff Brown2416e092012-08-21 22:12:20 -0700299 updateComputedNightModeLocked();
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700300 updateLocked(0, 0);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800301 }
302 }
303
304 boolean isDoingNightMode() {
305 return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
306 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100307
Dianne Hackborn7299c412010-03-04 18:41:49 -0800308 void setCarModeLocked(boolean enabled) {
309 if (mCarModeEnabled != enabled) {
310 mCarModeEnabled = enabled;
Dianne Hackborn7299c412010-03-04 18:41:49 -0800311 }
312 }
313
314 void updateDockState(int newState) {
315 synchronized (mLock) {
316 if (newState != mDockState) {
317 mDockState = newState;
Mike Lockwood924e1642010-03-05 11:56:53 -0500318 setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800319 if (mSystemReady) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700320 updateLocked(UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME, 0);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800321 }
322 }
323 }
324 }
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500325
Daniel Sandler69a1da42011-11-04 15:08:30 -0400326 final static boolean isDeskDockState(int state) {
327 switch (state) {
328 case Intent.EXTRA_DOCK_STATE_DESK:
329 case Intent.EXTRA_DOCK_STATE_LE_DESK:
330 case Intent.EXTRA_DOCK_STATE_HE_DESK:
331 return true;
332 default:
333 return false;
334 }
335 }
336
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700337 final void updateConfigurationLocked(boolean sendIt) {
Dianne Hackborn0cf2c8a2012-05-17 17:29:49 -0700338 int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION
339 : mDefaultUiModeType;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800340 if (mCarModeEnabled) {
341 uiMode = Configuration.UI_MODE_TYPE_CAR;
Daniel Sandler69a1da42011-11-04 15:08:30 -0400342 } else if (isDeskDockState(mDockState)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800343 uiMode = Configuration.UI_MODE_TYPE_DESK;
344 }
Dianne Hackborn9c9c5322010-03-30 23:12:22 -0700345 if (mCarModeEnabled) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800346 if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
Jeff Brown2416e092012-08-21 22:12:20 -0700347 updateComputedNightModeLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800348 uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
349 : Configuration.UI_MODE_NIGHT_NO;
350 } else {
351 uiMode |= mNightMode << 4;
352 }
353 } else {
354 // Disabling the car mode clears the night mode.
Daniel Sandler8daf2a42010-04-02 10:15:09 -0400355 uiMode = (uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | Configuration.UI_MODE_NIGHT_NO;
356 }
357
358 if (LOG) {
John Spurlock960779d2012-05-29 14:37:05 -0400359 Slog.d(TAG,
360 "updateConfigurationLocked: mDockState=" + mDockState
Daniel Sandler8daf2a42010-04-02 10:15:09 -0400361 + "; mCarMode=" + mCarModeEnabled
362 + "; mNightMode=" + mNightMode
363 + "; uiMode=" + uiMode);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800364 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100365
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800366 mCurUiMode = uiMode;
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100367
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800368 if (!mHoldingConfiguration && uiMode != mSetUiMode) {
369 mSetUiMode = uiMode;
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700370 mConfiguration.uiMode = uiMode;
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100371
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -0700372 if (sendIt) {
373 try {
374 ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
375 } catch (RemoteException e) {
376 Slog.w(TAG, "Failure communicating with activity manager", e);
377 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800378 }
379 }
380 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100381
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700382 final void updateLocked(int enableFlags, int disableFlags) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800383 long ident = Binder.clearCallingIdentity();
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100384
Dianne Hackborn7299c412010-03-04 18:41:49 -0800385 try {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800386 String action = null;
387 String oldAction = null;
388 if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
Tobias Haamel780b2602010-03-15 12:54:45 +0100389 adjustStatusBarCarModeLocked();
Dianne Hackborn7299c412010-03-04 18:41:49 -0800390 oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
Daniel Sandler69a1da42011-11-04 15:08:30 -0400391 } else if (isDeskDockState(mLastBroadcastState)) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800392 oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
393 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100394
Dianne Hackborn7299c412010-03-04 18:41:49 -0800395 if (mCarModeEnabled) {
396 if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
397 adjustStatusBarCarModeLocked();
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100398
Dianne Hackborn7299c412010-03-04 18:41:49 -0800399 if (oldAction != null) {
400 mContext.sendBroadcast(new Intent(oldAction));
401 }
402 mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
403 action = UiModeManager.ACTION_ENTER_CAR_MODE;
404 }
Daniel Sandler69a1da42011-11-04 15:08:30 -0400405 } else if (isDeskDockState(mDockState)) {
406 if (!isDeskDockState(mLastBroadcastState)) {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800407 if (oldAction != null) {
408 mContext.sendBroadcast(new Intent(oldAction));
409 }
Daniel Sandler69a1da42011-11-04 15:08:30 -0400410 mLastBroadcastState = mDockState;
Dianne Hackborn7299c412010-03-04 18:41:49 -0800411 action = UiModeManager.ACTION_ENTER_DESK_MODE;
412 }
413 } else {
Dianne Hackborn7299c412010-03-04 18:41:49 -0800414 mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
415 action = oldAction;
416 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100417
Dianne Hackborn7299c412010-03-04 18:41:49 -0800418 if (action != null) {
Daniel Sandler69a1da42011-11-04 15:08:30 -0400419 if (LOG) {
420 Slog.v(TAG, String.format(
421 "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
422 action, enableFlags, disableFlags));
423 }
424
Dianne Hackborn7299c412010-03-04 18:41:49 -0800425 // Send the ordered broadcast; the result receiver will receive after all
426 // broadcasts have been sent. If any broadcast receiver changes the result
427 // code from the initial value of RESULT_OK, then the result receiver will
428 // not launch the corresponding dock application. This gives apps a chance
429 // to override the behavior and stay in their app even when the device is
430 // placed into a dock.
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700431 Intent intent = new Intent(action);
432 intent.putExtra("enableFlags", enableFlags);
433 intent.putExtra("disableFlags", disableFlags);
434 mContext.sendOrderedBroadcast(intent, null,
Dianne Hackborn7299c412010-03-04 18:41:49 -0800435 mResultReceiver, null, Activity.RESULT_OK, null, null);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800436 // Attempting to make this transition a little more clean, we are going
437 // to hold off on doing a configuration change until we have finished
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700438 // the broadcast and started the home activity.
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800439 mHoldingConfiguration = true;
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700440 } else {
441 Intent homeIntent = null;
442 if (mCarModeEnabled) {
Daniel Sandler11ddf532011-11-16 11:10:03 -0800443 if (ENABLE_LAUNCH_CAR_DOCK_APP
444 && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700445 homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
446 }
Daniel Sandler69a1da42011-11-04 15:08:30 -0400447 } else if (isDeskDockState(mDockState)) {
Daniel Sandler11ddf532011-11-16 11:10:03 -0800448 if (ENABLE_LAUNCH_DESK_DOCK_APP
449 && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700450 homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
451 }
452 } else {
453 if ((disableFlags&UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
454 homeIntent = buildHomeIntent(Intent.CATEGORY_HOME);
455 }
456 }
Daniel Sandler69a1da42011-11-04 15:08:30 -0400457
458 if (LOG) {
459 Slog.v(TAG, "updateLocked: null action, mDockState="
460 + mDockState +", firing homeIntent: " + homeIntent);
461 }
462
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700463 if (homeIntent != null) {
464 try {
465 mContext.startActivity(homeIntent);
466 } catch (ActivityNotFoundException e) {
467 }
468 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800469 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100470
Dianne Hackbornf5c5d222010-04-09 13:14:48 -0700471 updateConfigurationLocked(true);
Mike Lockwoode29db6a2010-03-05 13:45:51 -0500472
473 // keep screen on when charging and in car mode
474 boolean keepScreenOn = mCharging &&
475 ((mCarModeEnabled && mCarModeKeepsScreenOn) ||
476 (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
477 if (keepScreenOn != mWakeLock.isHeld()) {
478 if (keepScreenOn) {
479 mWakeLock.acquire();
480 } else {
481 mWakeLock.release();
482 }
483 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800484 } finally {
485 Binder.restoreCallingIdentity(ident);
486 }
487 }
488
489 private void adjustStatusBarCarModeLocked() {
490 if (mStatusBarManager == null) {
491 mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
492 }
493
Joe Onorato089de882010-04-12 08:18:45 -0700494 // Fear not: StatusBarManagerService manages a list of requests to disable
Dianne Hackborn7299c412010-03-04 18:41:49 -0800495 // features of the status bar; these are ORed together to form the
496 // active disabled list. So if (for example) the device is locked and
497 // the status bar should be totally disabled, the calls below will
498 // have no effect until the device is unlocked.
499 if (mStatusBarManager != null) {
500 mStatusBarManager.disable(mCarModeEnabled
501 ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
502 : StatusBarManager.DISABLE_NONE);
503 }
504
505 if (mNotificationManager == null) {
506 mNotificationManager = (NotificationManager)
507 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
508 }
509
510 if (mNotificationManager != null) {
511 if (mCarModeEnabled) {
512 Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class);
513
514 Notification n = new Notification();
515 n.icon = R.drawable.stat_notify_car_mode;
516 n.defaults = Notification.DEFAULT_LIGHTS;
517 n.flags = Notification.FLAG_ONGOING_EVENT;
518 n.when = 0;
519 n.setLatestEventInfo(
520 mContext,
521 mContext.getString(R.string.car_mode_disable_notification_title),
522 mContext.getString(R.string.car_mode_disable_notification_message),
523 PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0));
524 mNotificationManager.notify(0, n);
525 } else {
526 mNotificationManager.cancel(0);
527 }
528 }
529 }
530
Jeff Brown2416e092012-08-21 22:12:20 -0700531 private void updateTwilight() {
532 synchronized (mLock) {
533 if (isDoingNightMode() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
534 updateComputedNightModeLocked();
535 updateLocked(0, 0);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800536 }
537 }
Jeff Brown2416e092012-08-21 22:12:20 -0700538 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800539
Jeff Brown2416e092012-08-21 22:12:20 -0700540 private void updateComputedNightModeLocked() {
541 TwilightState state = mTwilightService.getCurrentState();
542 if (state != null) {
543 mComputedNightMode = state.isNight();
Dianne Hackborn7299c412010-03-04 18:41:49 -0800544 }
Dianne Hackborn7299c412010-03-04 18:41:49 -0800545 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100546
Dianne Hackborn7299c412010-03-04 18:41:49 -0800547 @Override
548 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
549 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
550 != PackageManager.PERMISSION_GRANTED) {
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100551
Dianne Hackborn7299c412010-03-04 18:41:49 -0800552 pw.println("Permission Denial: can't dump uimode service from from pid="
553 + Binder.getCallingPid()
554 + ", uid=" + Binder.getCallingUid());
555 return;
556 }
Bernd Holzheyba9ab182010-03-12 09:30:29 +0100557
Dianne Hackborn7299c412010-03-04 18:41:49 -0800558 synchronized (mLock) {
559 pw.println("Current UI Mode Service state:");
560 pw.print(" mDockState="); pw.print(mDockState);
561 pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
562 pw.print(" mNightMode="); pw.print(mNightMode);
563 pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
564 pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
565 pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
Dianne Hackbornb8b11a02010-03-10 15:53:11 -0800566 pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
567 pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800568 pw.print(" mSystemReady="); pw.println(mSystemReady);
Jeff Brown2416e092012-08-21 22:12:20 -0700569 pw.print(" mTwilightService.getCurrentState()=");
570 pw.println(mTwilightService.getCurrentState());
Dianne Hackborn7299c412010-03-04 18:41:49 -0800571 }
572 }
573}