2010-03-04 18:41:49 -08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2008 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.server;
|
|
|
|
|
|
|
|
import android.app.Activity;
|
2012-09-26 01:30:41 -07:00
|
|
|
import android.app.ActivityManager;
|
2010-03-04 18:41:49 -08:00
|
|
|
import android.app.ActivityManagerNative;
|
|
|
|
import android.app.IUiModeManager;
|
|
|
|
import android.app.Notification;
|
|
|
|
import android.app.NotificationManager;
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.app.StatusBarManager;
|
|
|
|
import android.app.UiModeManager;
|
|
|
|
import android.content.BroadcastReceiver;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.IntentFilter;
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
import android.content.res.Configuration;
|
2010-03-05 13:45:51 -05:00
|
|
|
import android.os.BatteryManager;
|
2010-03-04 18:41:49 -08:00
|
|
|
import android.os.Binder;
|
|
|
|
import android.os.Handler;
|
2010-03-05 13:45:51 -05:00
|
|
|
import android.os.PowerManager;
|
2010-03-04 18:41:49 -08:00
|
|
|
import android.os.RemoteException;
|
|
|
|
import android.os.ServiceManager;
|
2012-10-05 14:42:56 -07:00
|
|
|
import android.os.SystemClock;
|
2012-08-29 18:32:08 -07:00
|
|
|
import android.os.UserHandle;
|
2010-03-22 21:49:15 -07:00
|
|
|
import android.provider.Settings;
|
2012-09-28 16:31:34 -07:00
|
|
|
import android.service.dreams.DreamService;
|
2012-09-26 01:30:41 -07:00
|
|
|
import android.service.dreams.IDreamManager;
|
2010-03-04 18:41:49 -08:00
|
|
|
import android.util.Slog;
|
|
|
|
|
|
|
|
import java.io.FileDescriptor;
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
|
|
|
import com.android.internal.R;
|
|
|
|
import com.android.internal.app.DisableCarModeActivity;
|
2012-08-21 22:12:20 -07:00
|
|
|
import com.android.server.TwilightService.TwilightState;
|
2010-03-04 18:41:49 -08:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
final class UiModeManagerService extends IUiModeManager.Stub {
|
2010-03-04 18:41:49 -08:00
|
|
|
private static final String TAG = UiModeManager.class.getSimpleName();
|
|
|
|
private static final boolean LOG = false;
|
|
|
|
|
2011-11-16 11:10:03 -08:00
|
|
|
// Enable launching of applications when entering the dock.
|
|
|
|
private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
|
2012-05-29 14:37:05 -04:00
|
|
|
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
|
2011-11-16 11:10:03 -08:00
|
|
|
|
2012-09-26 01:30:41 -07:00
|
|
|
private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
|
|
|
|
private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
|
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
private final Context mContext;
|
2012-08-21 22:12:20 -07:00
|
|
|
private final TwilightService mTwilightService;
|
|
|
|
private final Handler mHandler = new Handler();
|
2010-03-04 18:41:49 -08:00
|
|
|
|
|
|
|
final Object mLock = new Object();
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
|
|
|
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
|
|
|
|
private boolean mCarModeEnabled = false;
|
2010-03-05 13:45:51 -05:00
|
|
|
private boolean mCharging = false;
|
2011-12-14 20:59:30 -08:00
|
|
|
private final int mDefaultUiModeType;
|
2010-03-05 13:45:51 -05:00
|
|
|
private final boolean mCarModeKeepsScreenOn;
|
|
|
|
private final boolean mDeskModeKeepsScreenOn;
|
2012-05-17 17:29:49 -07:00
|
|
|
private final boolean mTelevision;
|
2010-03-04 18:41:49 -08:00
|
|
|
|
|
|
|
private boolean mComputedNightMode;
|
|
|
|
private int mCurUiMode = 0;
|
2010-03-10 15:53:11 -08:00
|
|
|
private int mSetUiMode = 0;
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-10 15:53:11 -08:00
|
|
|
private boolean mHoldingConfiguration = false;
|
2010-03-04 18:41:49 -08:00
|
|
|
private Configuration mConfiguration = new Configuration();
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
private boolean mSystemReady;
|
|
|
|
|
|
|
|
private NotificationManager mNotificationManager;
|
|
|
|
|
|
|
|
private StatusBarManager mStatusBarManager;
|
2012-10-05 14:42:56 -07:00
|
|
|
|
|
|
|
private final PowerManager mPowerManager;
|
2010-03-05 13:45:51 -05:00
|
|
|
private final PowerManager.WakeLock mWakeLock;
|
2010-03-04 18:41:49 -08:00
|
|
|
|
2010-04-09 13:14:48 -07:00
|
|
|
static Intent buildHomeIntent(String category) {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_MAIN);
|
|
|
|
intent.addCategory(category);
|
|
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
|
|
|
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
|
|
|
return intent;
|
|
|
|
}
|
2012-05-29 14:37:05 -04:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
// The broadcast receiver which receives the result of the ordered broadcast sent when
|
|
|
|
// the dock state changes. The original ordered broadcast is sent with an initial result
|
|
|
|
// code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
|
|
|
|
// to RESULT_CANCELED, then the intent to start a dock app will not be sent.
|
|
|
|
private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
if (getResultCode() != Activity.RESULT_OK) {
|
2011-11-04 15:08:30 -04:00
|
|
|
if (LOG) {
|
2012-05-29 14:37:05 -04:00
|
|
|
Slog.v(TAG, "Handling broadcast result for action " + intent.getAction()
|
2011-11-04 15:08:30 -04:00
|
|
|
+ ": canceled: " + getResultCode());
|
|
|
|
}
|
2010-03-04 18:41:49 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-26 01:30:41 -07:00
|
|
|
final int enableFlags = intent.getIntExtra("enableFlags", 0);
|
|
|
|
final int disableFlags = intent.getIntExtra("disableFlags", 0);
|
2010-03-10 15:53:11 -08:00
|
|
|
synchronized (mLock) {
|
2012-09-26 01:30:41 -07:00
|
|
|
updateAfterBroadcastLocked(intent.getAction(), enableFlags, disableFlags);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private final BroadcastReceiver mDockModeReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
|
|
|
|
Intent.EXTRA_DOCK_STATE_UNDOCKED);
|
|
|
|
updateDockState(state);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-05 13:45:51 -05:00
|
|
|
private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
mCharging = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
|
|
|
|
synchronized (mLock) {
|
|
|
|
if (mSystemReady) {
|
2010-04-09 13:14:48 -07:00
|
|
|
updateLocked(0, 0);
|
2010-03-05 13:45:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-21 22:12:20 -07:00
|
|
|
private final TwilightService.TwilightListener mTwilightListener =
|
|
|
|
new TwilightService.TwilightListener() {
|
2010-06-17 15:49:33 -07:00
|
|
|
@Override
|
2012-08-21 22:12:20 -07:00
|
|
|
public void onTwilightStateChanged() {
|
|
|
|
updateTwilight();
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-21 22:12:20 -07:00
|
|
|
public UiModeManagerService(Context context, TwilightService twilight) {
|
2010-03-04 18:41:49 -08:00
|
|
|
mContext = context;
|
2012-08-21 22:12:20 -07:00
|
|
|
mTwilightService = twilight;
|
2010-03-04 18:41:49 -08:00
|
|
|
|
|
|
|
ServiceManager.addService(Context.UI_MODE_SERVICE, this);
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
mContext.registerReceiver(mDockModeReceiver,
|
|
|
|
new IntentFilter(Intent.ACTION_DOCK_EVENT));
|
2010-03-05 13:45:51 -05:00
|
|
|
mContext.registerReceiver(mBatteryReceiver,
|
|
|
|
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
|
|
|
|
2012-10-05 14:42:56 -07:00
|
|
|
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
|
|
|
mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
|
2010-03-04 18:41:49 -08:00
|
|
|
|
|
|
|
mConfiguration.setToDefaults();
|
2010-03-05 13:45:51 -05:00
|
|
|
|
2011-12-14 20:59:30 -08:00
|
|
|
mDefaultUiModeType = context.getResources().getInteger(
|
|
|
|
com.android.internal.R.integer.config_defaultUiModeType);
|
2010-03-05 13:45:51 -05:00
|
|
|
mCarModeKeepsScreenOn = (context.getResources().getInteger(
|
|
|
|
com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
|
|
|
|
mDeskModeKeepsScreenOn = (context.getResources().getInteger(
|
|
|
|
com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
|
2012-05-17 17:29:49 -07:00
|
|
|
mTelevision = context.getPackageManager().hasSystemFeature(
|
|
|
|
PackageManager.FEATURE_TELEVISION);
|
|
|
|
|
2010-03-22 21:49:15 -07:00
|
|
|
mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
|
|
|
|
Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
|
2012-08-21 22:12:20 -07:00
|
|
|
|
|
|
|
mTwilightService.registerListener(mTwilightListener, mHandler);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
@Override // Binder call
|
2010-03-26 00:44:29 -07:00
|
|
|
public void disableCarMode(int flags) {
|
2012-10-11 13:35:42 -07:00
|
|
|
final long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
synchronized (mLock) {
|
|
|
|
setCarModeLocked(false);
|
|
|
|
if (mSystemReady) {
|
|
|
|
updateLocked(0, flags);
|
|
|
|
}
|
2010-03-05 11:56:53 -05:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
@Override // Binder call
|
2010-04-09 13:14:48 -07:00
|
|
|
public void enableCarMode(int flags) {
|
2012-10-11 13:35:42 -07:00
|
|
|
final long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
synchronized (mLock) {
|
|
|
|
setCarModeLocked(true);
|
|
|
|
if (mSystemReady) {
|
|
|
|
updateLocked(flags, 0);
|
|
|
|
}
|
2010-03-05 11:56:53 -05:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
@Override // Binder call
|
2010-03-04 18:41:49 -08:00
|
|
|
public int getCurrentModeType() {
|
2012-10-11 13:35:42 -07:00
|
|
|
final long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
synchronized (mLock) {
|
|
|
|
return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
@Override // Binder call
|
|
|
|
public void setNightMode(int mode) {
|
|
|
|
switch (mode) {
|
|
|
|
case UiModeManager.MODE_NIGHT_NO:
|
|
|
|
case UiModeManager.MODE_NIGHT_YES:
|
|
|
|
case UiModeManager.MODE_NIGHT_AUTO:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new IllegalArgumentException("Unknown mode: " + mode);
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
final long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
synchronized (mLock) {
|
|
|
|
if (isDoingNightModeLocked() && mNightMode != mode) {
|
|
|
|
Settings.Secure.putInt(mContext.getContentResolver(),
|
|
|
|
Settings.Secure.UI_NIGHT_MODE, mode);
|
|
|
|
mNightMode = mode;
|
|
|
|
updateLocked(0, 0);
|
|
|
|
}
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
@Override // Binder call
|
|
|
|
public int getNightMode() {
|
|
|
|
synchronized (mLock) {
|
|
|
|
return mNightMode;
|
|
|
|
}
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
void systemReady() {
|
|
|
|
synchronized (mLock) {
|
|
|
|
mSystemReady = true;
|
|
|
|
mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
|
2012-08-21 22:12:20 -07:00
|
|
|
updateComputedNightModeLocked();
|
2010-04-09 13:14:48 -07:00
|
|
|
updateLocked(0, 0);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private boolean isDoingNightModeLocked() {
|
2010-03-04 18:41:49 -08:00
|
|
|
return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private void setCarModeLocked(boolean enabled) {
|
2010-03-04 18:41:49 -08:00
|
|
|
if (mCarModeEnabled != enabled) {
|
|
|
|
mCarModeEnabled = enabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private void updateDockState(int newState) {
|
2010-03-04 18:41:49 -08:00
|
|
|
synchronized (mLock) {
|
|
|
|
if (newState != mDockState) {
|
|
|
|
mDockState = newState;
|
2010-03-05 11:56:53 -05:00
|
|
|
setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR);
|
2010-03-04 18:41:49 -08:00
|
|
|
if (mSystemReady) {
|
2010-04-09 13:14:48 -07:00
|
|
|
updateLocked(UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME, 0);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-05 13:45:51 -05:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private static boolean isDeskDockState(int state) {
|
2011-11-04 15:08:30 -04:00
|
|
|
switch (state) {
|
|
|
|
case Intent.EXTRA_DOCK_STATE_DESK:
|
|
|
|
case Intent.EXTRA_DOCK_STATE_LE_DESK:
|
|
|
|
case Intent.EXTRA_DOCK_STATE_HE_DESK:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private void updateConfigurationLocked() {
|
2012-09-26 01:30:41 -07:00
|
|
|
int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION : mDefaultUiModeType;
|
2010-03-10 15:53:11 -08:00
|
|
|
if (mCarModeEnabled) {
|
|
|
|
uiMode = Configuration.UI_MODE_TYPE_CAR;
|
2011-11-04 15:08:30 -04:00
|
|
|
} else if (isDeskDockState(mDockState)) {
|
2010-03-10 15:53:11 -08:00
|
|
|
uiMode = Configuration.UI_MODE_TYPE_DESK;
|
|
|
|
}
|
2010-03-30 23:12:22 -07:00
|
|
|
if (mCarModeEnabled) {
|
2010-03-10 15:53:11 -08:00
|
|
|
if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
|
2012-08-21 22:12:20 -07:00
|
|
|
updateComputedNightModeLocked();
|
2010-03-10 15:53:11 -08:00
|
|
|
uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
|
|
|
|
: Configuration.UI_MODE_NIGHT_NO;
|
2010-03-04 18:41:49 -08:00
|
|
|
} else {
|
2010-03-10 15:53:11 -08:00
|
|
|
uiMode |= mNightMode << 4;
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2010-03-10 15:53:11 -08:00
|
|
|
} else {
|
|
|
|
// Disabling the car mode clears the night mode.
|
2010-04-02 10:15:09 -04:00
|
|
|
uiMode = (uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | Configuration.UI_MODE_NIGHT_NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LOG) {
|
2012-05-29 14:37:05 -04:00
|
|
|
Slog.d(TAG,
|
|
|
|
"updateConfigurationLocked: mDockState=" + mDockState
|
2010-04-02 10:15:09 -04:00
|
|
|
+ "; mCarMode=" + mCarModeEnabled
|
|
|
|
+ "; mNightMode=" + mNightMode
|
|
|
|
+ "; uiMode=" + uiMode);
|
2010-03-10 15:53:11 -08:00
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-10 15:53:11 -08:00
|
|
|
mCurUiMode = uiMode;
|
2012-09-26 01:30:41 -07:00
|
|
|
if (!mHoldingConfiguration) {
|
2010-03-22 21:49:15 -07:00
|
|
|
mConfiguration.uiMode = uiMode;
|
2012-09-26 01:30:41 -07:00
|
|
|
}
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private void sendConfigurationLocked() {
|
2012-09-26 01:30:41 -07:00
|
|
|
if (mSetUiMode != mConfiguration.uiMode) {
|
|
|
|
mSetUiMode = mConfiguration.uiMode;
|
|
|
|
|
|
|
|
try {
|
|
|
|
ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
Slog.w(TAG, "Failure communicating with activity manager", e);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2010-03-10 15:53:11 -08:00
|
|
|
}
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private void updateLocked(int enableFlags, int disableFlags) {
|
|
|
|
String action = null;
|
|
|
|
String oldAction = null;
|
|
|
|
if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
|
|
|
|
adjustStatusBarCarModeLocked();
|
|
|
|
oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
|
|
|
|
} else if (isDeskDockState(mLastBroadcastState)) {
|
|
|
|
oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
if (mCarModeEnabled) {
|
|
|
|
if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
|
2010-03-15 12:54:45 +01:00
|
|
|
adjustStatusBarCarModeLocked();
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
if (oldAction != null) {
|
|
|
|
mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
|
|
|
|
action = UiModeManager.ACTION_ENTER_CAR_MODE;
|
|
|
|
}
|
|
|
|
} else if (isDeskDockState(mDockState)) {
|
|
|
|
if (!isDeskDockState(mLastBroadcastState)) {
|
|
|
|
if (oldAction != null) {
|
|
|
|
mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
mLastBroadcastState = mDockState;
|
|
|
|
action = UiModeManager.ACTION_ENTER_DESK_MODE;
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
} else {
|
|
|
|
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
|
|
|
action = oldAction;
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
if (action != null) {
|
|
|
|
if (LOG) {
|
|
|
|
Slog.v(TAG, String.format(
|
|
|
|
"updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
|
|
|
|
action, enableFlags, disableFlags));
|
|
|
|
}
|
2011-11-04 15:08:30 -04:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
// Send the ordered broadcast; the result receiver will receive after all
|
|
|
|
// broadcasts have been sent. If any broadcast receiver changes the result
|
|
|
|
// code from the initial value of RESULT_OK, then the result receiver will
|
|
|
|
// not launch the corresponding dock application. This gives apps a chance
|
|
|
|
// to override the behavior and stay in their app even when the device is
|
|
|
|
// placed into a dock.
|
|
|
|
Intent intent = new Intent(action);
|
|
|
|
intent.putExtra("enableFlags", enableFlags);
|
|
|
|
intent.putExtra("disableFlags", disableFlags);
|
|
|
|
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
|
|
|
|
mResultReceiver, null, Activity.RESULT_OK, null, null);
|
|
|
|
|
|
|
|
// Attempting to make this transition a little more clean, we are going
|
|
|
|
// to hold off on doing a configuration change until we have finished
|
|
|
|
// the broadcast and started the home activity.
|
|
|
|
mHoldingConfiguration = true;
|
|
|
|
updateConfigurationLocked();
|
|
|
|
} else {
|
|
|
|
String category = null;
|
|
|
|
if (mCarModeEnabled) {
|
|
|
|
if (ENABLE_LAUNCH_CAR_DOCK_APP
|
|
|
|
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_CAR_DOCK;
|
2010-04-09 13:14:48 -07:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
} else if (isDeskDockState(mDockState)) {
|
|
|
|
if (ENABLE_LAUNCH_DESK_DOCK_APP
|
|
|
|
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_DESK_DOCK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_HOME;
|
2011-11-04 15:08:30 -04:00
|
|
|
}
|
2012-10-11 13:35:42 -07:00
|
|
|
}
|
2011-11-04 15:08:30 -04:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
if (LOG) {
|
|
|
|
Slog.v(TAG, "updateLocked: null action, mDockState="
|
|
|
|
+ mDockState +", category=" + category);
|
2010-03-26 00:44:29 -07:00
|
|
|
}
|
2010-03-05 13:45:51 -05:00
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
sendConfigurationAndStartDreamOrDockAppLocked(category);
|
|
|
|
}
|
|
|
|
|
|
|
|
// keep screen on when charging and in car mode
|
|
|
|
boolean keepScreenOn = mCharging &&
|
|
|
|
((mCarModeEnabled && mCarModeKeepsScreenOn) ||
|
|
|
|
(mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
|
|
|
|
if (keepScreenOn != mWakeLock.isHeld()) {
|
|
|
|
if (keepScreenOn) {
|
|
|
|
mWakeLock.acquire();
|
|
|
|
} else {
|
|
|
|
mWakeLock.release();
|
2010-03-05 13:45:51 -05:00
|
|
|
}
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-26 01:30:41 -07:00
|
|
|
private void updateAfterBroadcastLocked(String action, int enableFlags, int disableFlags) {
|
|
|
|
// Launch a dock activity
|
|
|
|
String category = null;
|
|
|
|
if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
|
|
|
|
// Only launch car home when car mode is enabled and the caller
|
|
|
|
// has asked us to switch to it.
|
|
|
|
if (ENABLE_LAUNCH_CAR_DOCK_APP
|
|
|
|
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_CAR_DOCK;
|
|
|
|
}
|
|
|
|
} else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(action)) {
|
|
|
|
// Only launch car home when desk mode is enabled and the caller
|
|
|
|
// has asked us to switch to it. Currently re-using the car
|
|
|
|
// mode flag since we don't have a formal API for "desk mode".
|
|
|
|
if (ENABLE_LAUNCH_DESK_DOCK_APP
|
|
|
|
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_DESK_DOCK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Launch the standard home app if requested.
|
|
|
|
if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
|
|
|
|
category = Intent.CATEGORY_HOME;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LOG) {
|
|
|
|
Slog.v(TAG, String.format(
|
|
|
|
"Handling broadcast result for action %s: enable=0x%08x, disable=0x%08x, "
|
|
|
|
+ "category=%s",
|
|
|
|
action, enableFlags, disableFlags, category));
|
|
|
|
}
|
|
|
|
|
|
|
|
sendConfigurationAndStartDreamOrDockAppLocked(category);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void sendConfigurationAndStartDreamOrDockAppLocked(String category) {
|
|
|
|
// Update the configuration but don't send it yet.
|
|
|
|
mHoldingConfiguration = false;
|
|
|
|
updateConfigurationLocked();
|
|
|
|
|
|
|
|
// Start the dock app, if there is one.
|
|
|
|
boolean dockAppStarted = false;
|
|
|
|
if (category != null) {
|
|
|
|
// Now we are going to be careful about switching the
|
|
|
|
// configuration and starting the activity -- we need to
|
|
|
|
// do this in a specific order under control of the
|
|
|
|
// activity manager, to do it cleanly. So compute the
|
|
|
|
// new config, but don't set it yet, and let the
|
|
|
|
// activity manager take care of both the start and config
|
|
|
|
// change.
|
|
|
|
Intent homeIntent = buildHomeIntent(category);
|
|
|
|
try {
|
|
|
|
int result = ActivityManagerNative.getDefault().startActivityWithConfig(
|
|
|
|
null, homeIntent, null, null, null, 0, 0,
|
|
|
|
mConfiguration, null, UserHandle.USER_CURRENT);
|
|
|
|
if (result >= ActivityManager.START_SUCCESS) {
|
|
|
|
dockAppStarted = true;
|
|
|
|
} else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
|
|
|
|
Slog.e(TAG, "Could not start dock app: " + homeIntent
|
|
|
|
+ ", startActivityWithConfig result " + result);
|
|
|
|
}
|
|
|
|
} catch (RemoteException ex) {
|
|
|
|
Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the new configuration.
|
|
|
|
sendConfigurationLocked();
|
|
|
|
|
|
|
|
// If we did not start a dock app, then start dreaming if supported.
|
2012-09-26 18:57:48 -07:00
|
|
|
if (category != null && !dockAppStarted
|
2012-10-11 13:35:42 -07:00
|
|
|
&& isScreenSaverEnabledLocked() && isScreenSaverActivatedOnDockLocked()) {
|
2012-09-26 01:30:41 -07:00
|
|
|
Slog.i(TAG, "Activating dream while docked.");
|
|
|
|
try {
|
|
|
|
IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
|
2012-09-28 16:31:34 -07:00
|
|
|
ServiceManager.getService(DreamService.DREAM_SERVICE));
|
2012-10-05 14:42:56 -07:00
|
|
|
if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
|
|
|
|
// Wake up.
|
|
|
|
// The power manager will wake up the system when it starts receiving power
|
|
|
|
// but there is a race between that happening and the UI mode manager
|
|
|
|
// starting a dream. We want the system to already be awake
|
|
|
|
// by the time this happens. Otherwise the dream may not start.
|
|
|
|
mPowerManager.wakeUp(SystemClock.uptimeMillis());
|
|
|
|
|
|
|
|
// Dream.
|
|
|
|
dreamManagerService.dream();
|
|
|
|
}
|
2012-09-26 01:30:41 -07:00
|
|
|
} catch (RemoteException ex) {
|
|
|
|
Slog.e(TAG, "Could not start dream when docked.", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private boolean isScreenSaverEnabledLocked() {
|
2012-09-26 01:30:41 -07:00
|
|
|
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
|
|
|
Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
|
|
|
|
UserHandle.USER_CURRENT) != 0;
|
|
|
|
}
|
|
|
|
|
2012-10-11 13:35:42 -07:00
|
|
|
private boolean isScreenSaverActivatedOnDockLocked() {
|
2012-09-26 01:30:41 -07:00
|
|
|
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
|
|
|
|
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
|
|
|
|
DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
|
|
|
|
}
|
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
private void adjustStatusBarCarModeLocked() {
|
|
|
|
if (mStatusBarManager == null) {
|
2012-10-11 13:35:42 -07:00
|
|
|
mStatusBarManager = (StatusBarManager)
|
|
|
|
mContext.getSystemService(Context.STATUS_BAR_SERVICE);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
|
2010-04-12 08:18:45 -07:00
|
|
|
// Fear not: StatusBarManagerService manages a list of requests to disable
|
2010-03-04 18:41:49 -08:00
|
|
|
// 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) {
|
|
|
|
mStatusBarManager.disable(mCarModeEnabled
|
|
|
|
? StatusBarManager.DISABLE_NOTIFICATION_TICKER
|
|
|
|
: StatusBarManager.DISABLE_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNotificationManager == null) {
|
|
|
|
mNotificationManager = (NotificationManager)
|
|
|
|
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNotificationManager != null) {
|
|
|
|
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),
|
2012-09-23 17:08:57 -07:00
|
|
|
PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
|
|
|
|
null, UserHandle.CURRENT));
|
|
|
|
mNotificationManager.notifyAsUser(null,
|
|
|
|
R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
|
2010-03-04 18:41:49 -08:00
|
|
|
} else {
|
2012-09-23 17:08:57 -07:00
|
|
|
mNotificationManager.cancelAsUser(null,
|
|
|
|
R.string.car_mode_disable_notification_title, UserHandle.ALL);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-21 22:12:20 -07:00
|
|
|
private void updateTwilight() {
|
|
|
|
synchronized (mLock) {
|
2012-10-11 13:35:42 -07:00
|
|
|
if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
|
2012-08-21 22:12:20 -07:00
|
|
|
updateComputedNightModeLocked();
|
|
|
|
updateLocked(0, 0);
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
2012-08-21 22:12:20 -07:00
|
|
|
}
|
2010-03-04 18:41:49 -08:00
|
|
|
|
2012-08-21 22:12:20 -07:00
|
|
|
private void updateComputedNightModeLocked() {
|
|
|
|
TwilightState state = mTwilightService.getCurrentState();
|
|
|
|
if (state != null) {
|
|
|
|
mComputedNightMode = state.isNight();
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
@Override
|
|
|
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
|
|
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
|
|
|
!= PackageManager.PERMISSION_GRANTED) {
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
pw.println("Permission Denial: can't dump uimode service from from pid="
|
|
|
|
+ Binder.getCallingPid()
|
|
|
|
+ ", uid=" + Binder.getCallingUid());
|
|
|
|
return;
|
|
|
|
}
|
2010-03-12 09:30:29 +01:00
|
|
|
|
2010-03-04 18:41:49 -08:00
|
|
|
synchronized (mLock) {
|
|
|
|
pw.println("Current UI Mode Service state:");
|
|
|
|
pw.print(" mDockState="); pw.print(mDockState);
|
|
|
|
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
|
|
|
|
pw.print(" mNightMode="); pw.print(mNightMode);
|
|
|
|
pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
|
|
|
|
pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
|
|
|
|
pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
|
2010-03-10 15:53:11 -08:00
|
|
|
pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
|
|
|
|
pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
|
2010-03-04 18:41:49 -08:00
|
|
|
pw.print(" mSystemReady="); pw.println(mSystemReady);
|
2012-08-21 22:12:20 -07:00
|
|
|
pw.print(" mTwilightService.getCurrentState()=");
|
|
|
|
pw.println(mTwilightService.getCurrentState());
|
2010-03-04 18:41:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|