summaryrefslogtreecommitdiffstats
path: root/services/java/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android')
-rwxr-xr-xservices/java/com/android/server/BluetoothManagerService.java463
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java4
-rw-r--r--services/java/com/android/server/LocationManagerService.java185
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java26
-rw-r--r--services/java/com/android/server/ServiceWatcher.java85
-rw-r--r--services/java/com/android/server/WiredAccessoryManager.java2
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java16
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java1
-rw-r--r--services/java/com/android/server/am/ActiveServices.java31
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java119
-rw-r--r--services/java/com/android/server/am/BroadcastQueue.java50
-rw-r--r--services/java/com/android/server/am/BroadcastRecord.java10
-rw-r--r--services/java/com/android/server/display/DisplayDevice.java12
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java67
-rw-r--r--services/java/com/android/server/display/LocalDisplayAdapter.java14
-rw-r--r--services/java/com/android/server/location/GeocoderProxy.java9
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java5
-rw-r--r--services/java/com/android/server/location/LocationProviderInterface.java2
-rw-r--r--services/java/com/android/server/location/LocationProviderProxy.java14
-rw-r--r--services/java/com/android/server/location/MockProvider.java5
-rw-r--r--services/java/com/android/server/location/PassiveProvider.java5
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java12
-rw-r--r--services/java/com/android/server/power/DisplayBlanker.java25
-rw-r--r--services/java/com/android/server/power/DisplayPowerController.java8
-rw-r--r--services/java/com/android/server/power/DisplayPowerState.java16
-rw-r--r--services/java/com/android/server/power/PowerManagerService.java121
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java16
27 files changed, 990 insertions, 333 deletions
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index e7cd279..18182cd 100755
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -4,6 +4,7 @@
package com.android.server;
+import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
@@ -17,17 +18,21 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.os.Binder;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.Binder;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
private static final boolean DBG = true;
@@ -42,6 +47,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
//Maximum msec to wait for service restart
private static final int SERVICE_RESTART_TIME_MS = 200;
+ //Maximum msec to delay MESSAGE_USER_SWITCHED
+ private static final int USER_SWITCHED_TIME_MS = 200;
private static final int MESSAGE_ENABLE = 1;
private static final int MESSAGE_DISABLE = 2;
@@ -57,6 +64,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int MESSAGE_TIMEOUT_UNBIND =101;
private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
+ private static final int MESSAGE_USER_SWITCHED = 300;
private static final int MAX_SAVE_RETRIES=3;
private final Context mContext;
@@ -72,6 +80,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private boolean mBinding;
private boolean mUnbinding;
private boolean mQuietEnable = false;
+ private boolean mEnable;
+ private int mState;
+ private HandlerThread mThread;
+ private final BluetoothHandler mHandler;
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
@@ -106,23 +118,32 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
if (isAirplaneModeOn()) {
- // disable without persisting the setting
- handleDisable(false);
- } else {
- if (isBluetoothPersistedStateOn()) {
- // enable without persisting the setting
- handleEnable(false, false);
- }
+ // disable without persisting the setting
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE,
+ 0, 0));
+ } else if (isBluetoothPersistedStateOn()) {
+ // enable without persisting the setting
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
+ 0, 0));
}
+ } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED,
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
}
}
};
BluetoothManagerService(Context context) {
+ mThread = new HandlerThread("BluetoothManager");
+ mThread.start();
+ mHandler = new BluetoothHandler(mThread.getLooper());
+
mContext = context;
mBluetooth = null;
mBinding = false;
mUnbinding = false;
+ mEnable = false;
+ mState = BluetoothAdapter.STATE_OFF;
mAddress = null;
mName = null;
mContentResolver = context.getContentResolver();
@@ -130,6 +151,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
mContext.registerReceiver(mReceiver, filter);
boolean airplaneModeOn = isAirplaneModeOn();
@@ -139,7 +161,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (bluetoothOn) {
//Enable
if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
- enable();
+ enableHelper();
} else if (!isNameAndAddressSet()) {
//Sync the Bluetooth name and address from the Bluetooth Adapter
if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
@@ -251,6 +273,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
public boolean isEnabled() {
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"isEnabled(): not allowed for non-active user");
+ return false;
+ }
+
synchronized(mConnection) {
try {
return (mBluetooth != null && mBluetooth.isEnabled());
@@ -266,10 +293,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth +
" mBinding = " + mBinding);
}
- synchronized(mConnection) {
- if (mBinding) return;
- if (mConnection == null) mBinding = true;
- }
Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(msg);
}
@@ -277,21 +300,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
{
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
+
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"enableNoAutoConnect(): not allowed for non-active user");
+ return false;
+ }
+
if (DBG) {
Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding);
}
- if (Binder.getCallingUid() != android.os.Process.NFC_UID) {
+ if (Binder.getCallingUid() != Process.NFC_UID) {
throw new SecurityException("no permission to enable Bluetooth quietly");
}
- synchronized(mConnection) {
- if (mBinding) {
- Log.w(TAG,"enableNoAutoConnect(): binding in progress. Returning..");
- return true;
- }
- if (mConnection == null) mBinding = true;
- }
-
Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
msg.arg1=0; //No persist
msg.arg2=1; //Quiet mode
@@ -300,39 +321,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
public boolean enable() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- if (DBG) {
- Log.d(TAG,"enable(): mBluetooth =" + mBluetooth +
- " mBinding = " + mBinding);
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"enable(): not allowed for non-active user");
+ return false;
}
- synchronized(mConnection) {
- if (mBinding) {
- Log.w(TAG,"enable(): binding in progress. Returning..");
- return true;
- }
- if (mConnection == null) mBinding = true;
- }
-
- Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
- msg.arg1=1; //persist
- msg.arg2=0; //No Quiet Mode
- mHandler.sendMessage(msg);
- return true;
+ return enableHelper();
}
public boolean disable(boolean persist) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
+
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"disable(): not allowed for non-active user");
+ return false;
+ }
+
if (DBG) {
Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
" mBinding = " + mBinding);
}
- synchronized(mConnection) {
- if (mBluetooth == null) return false;
- }
Message msg = mHandler.obtainMessage(MESSAGE_DISABLE);
msg.arg1=(persist?1:0);
mHandler.sendMessage(msg);
@@ -348,13 +358,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
synchronized (mConnection) {
if (mUnbinding) return;
mUnbinding = true;
- if (mConnection != null) {
+ if (mBluetooth != null) {
if (!mConnection.isGetNameAddressOnly()) {
//Unregister callback object
try {
mBluetooth.unregisterCallback(mBluetoothCallback);
} catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothCallback",re);
+ Log.e(TAG, "Unable to unregister BluetoothCallback",re);
}
}
if (DBG) Log.d(TAG, "Sending unbind request.");
@@ -362,6 +372,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Unbind
mContext.unbindService(mConnection);
mUnbinding = false;
+ mBinding = false;
} else {
mUnbinding=false;
}
@@ -382,6 +393,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
/**
+ * Inform BluetoothAdapter instances that Adapter service is up
+ */
+ private void sendBluetoothServiceUpCallback() {
+ if (!mConnection.isGetNameAddressOnly()) {
+ if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks");
+ int n = mCallbacks.beginBroadcast();
+ Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
+ }
+ mCallbacks.finishBroadcast();
+ }
+ }
+ /**
* Inform BluetoothAdapter instances that Adapter service is down
*/
private void sendBluetoothServiceDownCallback() {
@@ -402,6 +431,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
public String getAddress() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
+
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"getAddress(): not allowed for non-active user");
+ return mAddress;
+ }
+
synchronized(mConnection) {
if (mBluetooth != null) {
try {
@@ -420,6 +455,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
public String getName() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
+
+ if (!checkIfCallerIsForegroundUser()) {
+ Log.w(TAG,"getName(): not allowed for non-active user");
+ return mName;
+ }
+
synchronized(mConnection) {
if (mBluetooth != null) {
try {
@@ -464,7 +505,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
- private final Handler mHandler = new Handler() {
+ private class BluetoothHandler extends Handler {
+ public BluetoothHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
if (DBG) Log.d (TAG, "Message: " + msg.what);
@@ -473,7 +518,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
synchronized(mConnection) {
//Start bind request
- if (mBluetooth == null) {
+ if ((mBluetooth == null) && (!mBinding)) {
if (DBG) Log.d(TAG, "Binding to service to get name and address");
mConnection.setGetNameAddressOnly(true);
//Start bind timeout and bind
@@ -484,11 +529,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
+ } else {
+ mBinding = true;
}
}
else {
Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
- mHandler.sendMessage(saveMsg);
+ saveMsg.arg1 = 0;
+ if (mBluetooth != null) {
+ mHandler.sendMessage(saveMsg);
+ } else {
+ // if enable is also called to bind the service
+ // wait for MESSAGE_BLUETOOTH_SERVICE_CONNECTED
+ mHandler.sendMessageDelayed(saveMsg, TIMEOUT_SAVE_MS);
+ }
}
}
break;
@@ -508,8 +562,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (name != null && address != null) {
storeNameAndAddress(name,address);
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
+ if (mConnection.isGetNameAddressOnly()) {
+ unbindAndFinish();
+ }
} else {
if (msg.arg1 < MAX_SAVE_RETRIES) {
Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
@@ -518,10 +573,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
} else {
Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
+ if (mConnection.isGetNameAddressOnly()) {
+ unbindAndFinish();
+ }
}
}
+ } else {
+ // rebind service by Request GET NAME AND ADDRESS
+ // if service is unbinded by disable or
+ // MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received
+ Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+ mHandler.sendMessage(getMsg);
}
}
break;
@@ -530,12 +592,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (DBG) {
Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
}
-
+ mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
+ mEnable = true;
handleEnable(msg.arg1 == 1, msg.arg2 ==1);
break;
case MESSAGE_DISABLE:
- handleDisable(msg.arg1 == 1);
+ mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
+ if (mEnable && mBluetooth != null) {
+ waitForOnOff(true, false);
+ mEnable = false;
+ handleDisable(msg.arg1 == 1);
+ waitForOnOff(false, false);
+ } else {
+ mEnable = false;
+ handleDisable(msg.arg1 == 1);
+ }
break;
case MESSAGE_REGISTER_ADAPTER:
@@ -580,27 +652,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Request GET NAME AND ADDRESS
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
- return;
+ if (!mEnable) return;
}
+ mConnection.setGetNameAddressOnly(false);
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Log.e(TAG, "Unable to register BluetoothCallback",re);
}
-
//Inform BluetoothAdapter instances that service is up
- int n = mCallbacks.beginBroadcast();
- Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
- for (int i=0; i <n;i++) {
+ sendBluetoothServiceUpCallback();
+
+ //Check if name and address is loaded if not get it first.
+ if (!isNameAndAddressSet()) {
try {
- mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
- }
+ storeNameAndAddress(mBluetooth.getName(),
+ mBluetooth.getAddress());
+ } catch (RemoteException e) {Log.e(TAG, "", e);};
}
- mCallbacks.finishBroadcast();
//Do enable request
try {
@@ -619,12 +690,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
Log.e(TAG,"Unable to call enable()",e);
}
}
+
+ if (!mEnable) {
+ waitForOnOff(true, false);
+ handleDisable(false);
+ waitForOnOff(false, false);
+ }
break;
}
case MESSAGE_TIMEOUT_BIND: {
Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
synchronized(mConnection) {
mBinding = false;
+ mEnable = false;
}
break;
}
@@ -633,51 +711,37 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
int prevState = msg.arg1;
int newState = msg.arg2;
if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
- if (prevState != newState) {
- //Notify all proxy objects first of adapter state change
- if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) {
- boolean isUp = (newState==BluetoothAdapter.STATE_ON);
- sendBluetoothStateCallback(isUp);
-
- //If Bluetooth is off, send service down event to proxy objects, and unbind
- if (!isUp) {
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
- }
- }
-
- //Send broadcast message to everyone else
- Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
- intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
- intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- BLUETOOTH_PERM);
- }
+ mState = newState;
+ bluetoothStateChangeHandler(prevState, newState);
break;
}
case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
{
- if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
- sendBluetoothServiceDownCallback();
-
- // Send BT state broadcast to update
- // the BT icon correctly
- Message stateChangeMsg = mHandler.obtainMessage(
- MESSAGE_BLUETOOTH_STATE_CHANGE);
- stateChangeMsg.arg1 = BluetoothAdapter.STATE_ON;
- stateChangeMsg.arg2 =
- BluetoothAdapter.STATE_TURNING_OFF;
- mHandler.sendMessage(stateChangeMsg);
+ Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
synchronized(mConnection) {
+ // if service is unbinded already, do nothing and return
+ if (mBluetooth == null) return;
mBluetooth = null;
}
- // Send a Bluetooth Restart message
- Message restartMsg = mHandler.obtainMessage(
- MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mHandler.sendMessageDelayed(restartMsg,
- SERVICE_RESTART_TIME_MS);
+
+ if (mEnable) {
+ mEnable = false;
+ // Send a Bluetooth Restart message
+ Message restartMsg = mHandler.obtainMessage(
+ MESSAGE_RESTART_BLUETOOTH_SERVICE);
+ mHandler.sendMessageDelayed(restartMsg,
+ SERVICE_RESTART_TIME_MS);
+ }
+
+ if (!mConnection.isGetNameAddressOnly()) {
+ sendBluetoothServiceDownCallback();
+
+ // Send BT state broadcast to update
+ // the BT icon correctly
+ bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+ BluetoothAdapter.STATE_TURNING_OFF);
+ mState = BluetoothAdapter.STATE_OFF;
+ }
break;
}
case MESSAGE_RESTART_BLUETOOTH_SERVICE:
@@ -687,6 +751,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
/* Enable without persisting the setting as
it doesnt change when IBluetooth
service restarts */
+ mEnable = true;
handleEnable(false, mQuietEnable);
break;
}
@@ -699,9 +764,66 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
break;
}
+
+ case MESSAGE_USER_SWITCHED:
+ {
+ if (DBG) {
+ Log.d(TAG, "MESSAGE_USER_SWITCHED");
+ }
+ mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+ /* disable and enable BT when detect a user switch */
+ if (mEnable && mBluetooth != null) {
+ synchronized (mConnection) {
+ if (mBluetooth != null) {
+ //Unregister callback object
+ try {
+ mBluetooth.unregisterCallback(mBluetoothCallback);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Unable to unregister",re);
+ }
+ }
+ }
+ mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
+
+ waitForOnOff(true, false);
+
+ bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
+
+ // disable
+ handleDisable(false);
+
+ waitForOnOff(false, true);
+
+ bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+ BluetoothAdapter.STATE_OFF);
+ mState = BluetoothAdapter.STATE_OFF;
+ sendBluetoothServiceDownCallback();
+ synchronized (mConnection) {
+ if (mBluetooth != null) {
+ mBluetooth = null;
+ //Unbind
+ mContext.unbindService(mConnection);
+ }
+ }
+ SystemClock.sleep(100);
+
+ // enable
+ handleEnable(false, mQuietEnable);
+ } else if (mBinding || mBluetooth != null) {
+ Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
+ userMsg.arg2 = 1 + msg.arg2;
+ // if user is switched when service is being binding
+ // delay sending MESSAGE_USER_SWITCHED
+ mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
+ if (DBG) {
+ Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
+ }
+ }
+ break;
+ }
}
}
- };
+ }
private void handleEnable(boolean persist, boolean quietMode) {
if (persist) {
@@ -711,18 +833,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mQuietEnable = quietMode;
synchronized(mConnection) {
- if (mBluetooth == null) {
+ if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
mConnection.setGetNameAddressOnly(false);
Intent i = new Intent(IBluetooth.class.getName());
- if (!mContext.bindService(i, mConnection, Context.BIND_AUTO_CREATE,
+ if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
UserHandle.USER_CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
+ } else {
+ mBinding = true;
}
- } else {
+ } else if (mBluetooth != null) {
+ if (mConnection.isGetNameAddressOnly()) {
+ // if GetNameAddressOnly is set, we can clear this flag,
+ // so the service won't be unbind
+ // after name and address are saved
+ mConnection.setGetNameAddressOnly(false);
+ //Register callback object
+ try {
+ mBluetooth.registerCallback(mBluetoothCallback);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Unable to register BluetoothCallback",re);
+ }
+ //Inform BluetoothAdapter instances that service is up
+ sendBluetoothServiceUpCallback();
+ }
+
//Check if name and address is loaded if not get it first.
if (!isNameAndAddressSet()) {
try {
@@ -751,12 +890,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
private void handleDisable(boolean persist) {
+ if (persist) {
+ persistBluetoothSetting(false);
+ }
+
synchronized(mConnection) {
- if (mBluetooth != null ) {
- if (persist) {
- persistBluetoothSetting(false);
- }
- mConnection.setGetNameAddressOnly(false);
+ // don't need to disable if GetNameAddressOnly is set,
+ // service will be unbinded after Name and Address are saved
+ if ((mBluetooth != null) && (!mConnection.isGetNameAddressOnly())) {
if (DBG) Log.d(TAG,"Sending off request.");
try {
@@ -769,4 +910,102 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
}
}
+
+ private boolean checkIfCallerIsForegroundUser() {
+ int foregroundUser;
+ int callingUser = UserHandle.getCallingUserId();
+ long callingIdentity = Binder.clearCallingIdentity();
+ boolean valid = false;
+ try {
+ foregroundUser = ActivityManager.getCurrentUser();
+ valid = (callingUser == foregroundUser);
+ if (DBG) {
+ Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+ + " callingUser=" + callingUser
+ + " foregroundUser=" + foregroundUser);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ return valid;
+ }
+
+ private boolean enableHelper() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ if (DBG) {
+ Log.d(TAG,"enable(): mBluetooth =" + mBluetooth +
+ " mBinding = " + mBinding);
+ }
+
+ Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+ msg.arg1=1; //persist
+ msg.arg2=0; //No Quiet Mode
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ private void bluetoothStateChangeHandler(int prevState, int newState) {
+ if (prevState != newState) {
+ //Notify all proxy objects first of adapter state change
+ if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) {
+ boolean isUp = (newState==BluetoothAdapter.STATE_ON);
+ sendBluetoothStateCallback(isUp);
+
+ //If Bluetooth is off, send service down event to proxy objects, and unbind
+ if (!isUp) {
+ //Only unbind with mEnable flag not set
+ //For race condition: disable and enable back-to-back
+ //Avoid unbind right after enable due to callback from disable
+ if ((!mEnable) && (mBluetooth != null)) {
+ sendBluetoothServiceDownCallback();
+ unbindAndFinish();
+ }
+ }
+ }
+
+ //Send broadcast message to everyone else
+ Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+ intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
+ intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ BLUETOOTH_PERM);
+ }
+ }
+
+ /**
+ * if on is true, wait for state become ON
+ * if off is true, wait for state become OFF
+ * if both on and off are false, wait for state not ON
+ */
+ private boolean waitForOnOff(boolean on, boolean off) {
+ int i = 0;
+ while (i < 10) {
+ synchronized(mConnection) {
+ try {
+ if (mBluetooth == null) break;
+ if (on) {
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
+ } else if (off) {
+ if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
+ } else {
+ if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getState()", e);
+ break;
+ }
+ }
+ if (on || off) {
+ SystemClock.sleep(300);
+ } else {
+ SystemClock.sleep(50);
+ }
+ i++;
+ }
+ Log.e(TAG,"waitForOnOff time out");
+ return false;
+ }
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index e4998e11..ffbfef6 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -900,7 +900,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
+ "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
+ " calling userId = " + userId + ", foreground user id = "
- + mSettings.getCurrentUserId() + ", calling uid = " + Binder.getCallingPid());
+ + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid());
}
if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
return true;
@@ -2673,6 +2673,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mSwitchingDialog.setCanceledOnTouchOutside(true);
mSwitchingDialog.getWindow().setType(
WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
+ mSwitchingDialog.getWindow().getAttributes().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
mSwitchingDialog.show();
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e73d599..c5016e6 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -226,7 +226,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
updateProvidersLocked();
}
}
- });
+ }, UserHandle.USER_ALL);
mPackageMonitor.register(mContext, Looper.myLooper(), true);
// listen for user change
@@ -289,7 +289,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
mContext,
LocationManager.NETWORK_PROVIDER,
NETWORK_LOCATION_SERVICE_ACTION,
- providerPackageNames, mLocationHandler);
+ providerPackageNames, mLocationHandler, mCurrentUserId);
if (networkProvider != null) {
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
mProxyProviders.add(networkProvider);
@@ -303,18 +303,20 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
mContext,
LocationManager.FUSED_PROVIDER,
FUSED_LOCATION_SERVICE_ACTION,
- providerPackageNames, mLocationHandler);
+ providerPackageNames, mLocationHandler, mCurrentUserId);
if (fusedLocationProvider != null) {
addProviderLocked(fusedLocationProvider);
mProxyProviders.add(fusedLocationProvider);
mEnabledProviders.add(fusedLocationProvider.getName());
+ mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
} else {
Slog.e(TAG, "no fused location provider found",
new IllegalStateException("Location service needs a fused location provider"));
}
// bind to geocoder provider
- mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames);
+ mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
+ mCurrentUserId);
if (mGeocodeProvider == null) {
Slog.e(TAG, "no geocoder provider found");
}
@@ -326,11 +328,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
*/
private void switchUser(int userId) {
mBlacklist.switchUser(userId);
- //Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this
synchronized (mLock) {
- // TODO: inform previous user's Receivers that they will no longer receive updates
+ mLastLocation.clear();
+ for (LocationProviderInterface p : mProviders) {
+ updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
+ p.switchUser(userId);
+ }
mCurrentUserId = userId;
- // TODO: inform new user's Receivers that they are back on the update train
+ updateProvidersLocked();
}
}
@@ -587,7 +592,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
- private boolean isAllowedBySettingsLocked(String provider) {
+ private boolean isAllowedBySettingsLocked(String provider, int userId) {
+ if (userId != mCurrentUserId) {
+ return false;
+ }
if (mEnabledProviders.contains(provider)) {
return true;
}
@@ -597,7 +605,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Use system settings
ContentResolver resolver = mContext.getContentResolver();
- return Settings.Secure.isLocationProviderEnabled(resolver, provider);
+ return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
}
/**
@@ -695,24 +703,30 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
@Override
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
ArrayList<String> out;
- synchronized (mLock) {
- out = new ArrayList<String>(mProviders.size());
- for (LocationProviderInterface provider : mProviders) {
- String name = provider.getName();
- if (LocationManager.FUSED_PROVIDER.equals(name)) {
- continue;
- }
- if (isAllowedProviderSafe(name)) {
- if (enabledOnly && !isAllowedBySettingsLocked(name)) {
+ int callingUserId = UserHandle.getCallingUserId();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ out = new ArrayList<String>(mProviders.size());
+ for (LocationProviderInterface provider : mProviders) {
+ String name = provider.getName();
+ if (LocationManager.FUSED_PROVIDER.equals(name)) {
continue;
}
- if (criteria != null && !LocationProvider.propertiesMeetCriteria(
- name, provider.getProperties(), criteria)) {
- continue;
+ if (isAllowedProviderSafe(name)) {
+ if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
+ continue;
+ }
+ if (criteria != null && !LocationProvider.propertiesMeetCriteria(
+ name, provider.getProperties(), criteria)) {
+ continue;
+ }
+ out.add(name);
}
- out.add(name);
}
}
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
if (D) Log.d(TAG, "getProviders()=" + out);
@@ -778,12 +792,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
LocationProviderInterface p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
- boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
+ boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
if (isEnabled && !shouldBeEnabled) {
- updateProviderListenersLocked(name, false);
+ updateProviderListenersLocked(name, false, mCurrentUserId);
changesMade = true;
} else if (!isEnabled && shouldBeEnabled) {
- updateProviderListenersLocked(name, true);
+ updateProviderListenersLocked(name, true, mCurrentUserId);
changesMade = true;
}
}
@@ -793,7 +807,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
}
- private void updateProviderListenersLocked(String provider, boolean enabled) {
+ private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
int listeners = 0;
LocationProviderInterface p = mProvidersByName.get(provider);
@@ -806,14 +820,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
final int N = records.size();
for (int i = 0; i < N; i++) {
UpdateRecord record = records.get(i);
- // Sends a notification message to the receiver
- if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
- if (deadReceivers == null) {
- deadReceivers = new ArrayList<Receiver>();
+ if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
+ // Sends a notification message to the receiver
+ if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList<Receiver>();
+ }
+ deadReceivers.add(record.mReceiver);
}
- deadReceivers.add(record.mReceiver);
+ listeners++;
}
- listeners++;
}
}
@@ -843,12 +859,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (records != null) {
for (UpdateRecord record : records) {
- LocationRequest locationRequest = record.mRequest;
-
- providerRequest.locationRequests.add(locationRequest);
- if (locationRequest.getInterval() < providerRequest.interval) {
- providerRequest.reportLocation = true;
- providerRequest.interval = locationRequest.getInterval();
+ if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
+ LocationRequest locationRequest = record.mRequest;
+ providerRequest.locationRequests.add(locationRequest);
+ if (locationRequest.getInterval() < providerRequest.interval) {
+ providerRequest.reportLocation = true;
+ providerRequest.interval = locationRequest.getInterval();
+ }
}
}
@@ -860,9 +877,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// under that threshold.
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
for (UpdateRecord record : records) {
- LocationRequest locationRequest = record.mRequest;
- if (locationRequest.getInterval() <= thresholdInterval) {
- worksource.add(record.mReceiver.mUid);
+ if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
+ LocationRequest locationRequest = record.mRequest;
+ if (locationRequest.getInterval() <= thresholdInterval) {
+ worksource.add(record.mReceiver.mUid);
+ }
}
}
}
@@ -1084,7 +1103,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
oldRecord.disposeLocked(false);
}
- boolean isProviderEnabled = isAllowedBySettingsLocked(name);
+ boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
if (isProviderEnabled) {
applyRequirementsLocked(name);
} else {
@@ -1141,7 +1160,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// update provider
for (String provider : providers) {
// If provider is already disabled, don't need to do anything
- if (!isAllowedBySettingsLocked(provider)) {
+ if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
continue;
}
@@ -1156,36 +1175,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
String perm = checkPermissionAndRequest(request);
checkPackageName(packageName);
- if (mBlacklist.isBlacklisted(packageName)) {
- if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
- packageName);
- return null;
- }
-
- synchronized (mLock) {
- // Figure out the provider. Either its explicitly request (deprecated API's),
- // or use the fused provider
- String name = request.getProvider();
- if (name == null) name = LocationManager.FUSED_PROVIDER;
- LocationProviderInterface provider = mProvidersByName.get(name);
- if (provider == null) return null;
-
- if (!isAllowedBySettingsLocked(name)) return null;
-
- Location location = mLastLocation.get(name);
- if (location == null) {
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (mBlacklist.isBlacklisted(packageName)) {
+ if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
+ packageName);
return null;
}
- if (ACCESS_FINE_LOCATION.equals(perm)) {
- return location;
- } else {
- Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
- if (noGPSLocation != null) {
- return mLocationFudger.getOrCreate(noGPSLocation);
+
+ synchronized (mLock) {
+ // Figure out the provider. Either its explicitly request (deprecated API's),
+ // or use the fused provider
+ String name = request.getProvider();
+ if (name == null) name = LocationManager.FUSED_PROVIDER;
+ LocationProviderInterface provider = mProvidersByName.get(name);
+ if (provider == null) return null;
+
+ if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
+
+ Location location = mLastLocation.get(name);
+ if (location == null) {
+ return null;
+ }
+ if (ACCESS_FINE_LOCATION.equals(perm)) {
+ return location;
+ } else {
+ Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ if (noGPSLocation != null) {
+ return mLocationFudger.getOrCreate(noGPSLocation);
+ }
}
}
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- return null;
}
@Override
@@ -1321,11 +1345,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
"\" provider requires ACCESS_FINE_LOCATION permission");
}
- synchronized (mLock) {
- LocationProviderInterface p = mProvidersByName.get(provider);
- if (p == null) return false;
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ LocationProviderInterface p = mProvidersByName.get(provider);
+ if (p == null) return false;
- return isAllowedBySettingsLocked(provider);
+ return isAllowedBySettingsLocked(provider, mCurrentUserId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -1461,6 +1490,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
+ int receiverUserId = UserHandle.getUserId(receiver.mUid);
+ if (receiverUserId != mCurrentUserId) {
+ if (D) {
+ Log.d(TAG, "skipping loc update for background user " + receiverUserId +
+ " (current user: " + mCurrentUserId + ", app: " +
+ receiver.mPackageName + ")");
+ }
+ continue;
+ }
+
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
receiver.mPackageName);
@@ -1551,7 +1590,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
synchronized (mLock) {
- if (isAllowedBySettingsLocked(provider)) {
+ if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
handleLocationChangedLocked(location, passive);
}
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 85b488c..09a606e 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -991,6 +991,14 @@ public class NotificationManagerService extends INotificationManager.Stub
| Notification.FLAG_NO_CLEAR;
}
+ final int currentUser;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ currentUser = ActivityManager.getCurrentUser();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
if (notification.icon != 0) {
final StatusBarNotification n = new StatusBarNotification(
pkg, id, tag, r.uid, r.initialPid, score, notification, user);
@@ -1015,7 +1023,10 @@ public class NotificationManagerService extends INotificationManager.Stub
Binder.restoreCallingIdentity(identity);
}
}
- sendAccessibilityEvent(notification, pkg);
+ // Send accessibility events only for the current user.
+ if (currentUser == userId) {
+ sendAccessibilityEvent(notification, pkg);
+ }
} else {
Slog.e(TAG, "Ignoring notification with icon==0: " + notification);
if (old != null && old.statusBarKey != null) {
@@ -1029,14 +1040,6 @@ public class NotificationManagerService extends INotificationManager.Stub
}
}
- final int currentUser;
- final long token = Binder.clearCallingIdentity();
- try {
- currentUser = ActivityManager.getCurrentUser();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
// If we're not supposed to beep, vibrate, etc. then don't.
if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
&& (!(old != null
@@ -1066,8 +1069,9 @@ public class NotificationManagerService extends INotificationManager.Stub
}
mSoundNotification = r;
// do not play notifications if stream volume is 0
- // (typically because ringer mode is silent).
- if (audioManager.getStreamVolume(audioStreamType) != 0) {
+ // (typically because ringer mode is silent) or if speech recognition is active.
+ if ((audioManager.getStreamVolume(audioStreamType) != 0)
+ && !audioManager.isSpeechRecognitionActive()) {
final long identity = Binder.clearCallingIdentity();
try {
final IRingtonePlayer player = mAudioService.getRingtonePlayer();
diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java
index e99949b..5598b0a 100644
--- a/services/java/com/android/server/ServiceWatcher.java
+++ b/services/java/com/android/server/ServiceWatcher.java
@@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.os.Handler;
import android.os.IBinder;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.content.PackageMonitor;
@@ -58,15 +59,17 @@ public class ServiceWatcher implements ServiceConnection {
private IBinder mBinder; // connected service
private String mPackageName; // current best package
private int mVersion; // current best version
+ private int mCurrentUserId;
public ServiceWatcher(Context context, String logTag, String action,
- List<String> initialPackageNames, Runnable newServiceWork, Handler handler) {
+ List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
mContext = context;
mTag = logTag;
mAction = action;
mPm = mContext.getPackageManager();
mNewServiceWork = newServiceWork;
mHandler = handler;
+ mCurrentUserId = userId;
mSignatureSets = new ArrayList<HashSet<Signature>>();
for (int i=0; i < initialPackageNames.size(); i++) {
@@ -85,9 +88,11 @@ public class ServiceWatcher implements ServiceConnection {
}
public boolean start() {
- if (!bindBestPackage(null)) return false;
+ synchronized (mLock) {
+ if (!bindBestPackageLocked(null)) return false;
+ }
- mPackageMonitor.register(mContext, null, true);
+ mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
return true;
}
@@ -98,13 +103,13 @@ public class ServiceWatcher implements ServiceConnection {
* is null.
* Return true if a new package was found to bind to.
*/
- private boolean bindBestPackage(String justCheckThisPackage) {
+ private boolean bindBestPackageLocked(String justCheckThisPackage) {
Intent intent = new Intent(mAction);
if (justCheckThisPackage != null) {
intent.setPackage(justCheckThisPackage);
}
- List<ResolveInfo> rInfos = mPm.queryIntentServices(new Intent(mAction),
- PackageManager.GET_META_DATA);
+ List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction),
+ PackageManager.GET_META_DATA, mCurrentUserId);
int bestVersion = Integer.MIN_VALUE;
String bestPackage = null;
for (ResolveInfo rInfo : rInfos) {
@@ -141,36 +146,32 @@ public class ServiceWatcher implements ServiceConnection {
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
if (bestPackage != null) {
- bindToPackage(bestPackage, bestVersion);
+ bindToPackageLocked(bestPackage, bestVersion);
return true;
}
return false;
}
- private void unbind() {
+ private void unbindLocked() {
String pkg;
- synchronized (mLock) {
- pkg = mPackageName;
- mPackageName = null;
- mVersion = Integer.MIN_VALUE;
- }
+ pkg = mPackageName;
+ mPackageName = null;
+ mVersion = Integer.MIN_VALUE;
if (pkg != null) {
if (D) Log.d(mTag, "unbinding " + pkg);
mContext.unbindService(this);
}
}
- private void bindToPackage(String packageName, int version) {
- unbind();
+ private void bindToPackageLocked(String packageName, int version) {
+ unbindLocked();
Intent intent = new Intent(mAction);
intent.setPackage(packageName);
- synchronized (mLock) {
- mPackageName = packageName;
- mVersion = version;
- }
+ mPackageName = packageName;
+ mVersion = version;
if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")");
mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
- | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE);
+ | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
}
private boolean isSignatureMatch(Signature[] signatures) {
@@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection {
*/
@Override
public void onPackageUpdateFinished(String packageName, int uid) {
- if (packageName.equals(mPackageName)) {
- // package updated, make sure to rebind
- unbind();
+ synchronized (mLock) {
+ if (packageName.equals(mPackageName)) {
+ // package updated, make sure to rebind
+ unbindLocked();
+ }
+ // check the updated package in case it is better
+ bindBestPackageLocked(packageName);
}
- // check the updated package in case it is better
- bindBestPackage(packageName);
}
@Override
public void onPackageAdded(String packageName, int uid) {
- if (packageName.equals(mPackageName)) {
- // package updated, make sure to rebind
- unbind();
+ synchronized (mLock) {
+ if (packageName.equals(mPackageName)) {
+ // package updated, make sure to rebind
+ unbindLocked();
+ }
+ // check the new package is case it is better
+ bindBestPackageLocked(packageName);
}
- // check the new package is case it is better
- bindBestPackage(packageName);
}
@Override
public void onPackageRemoved(String packageName, int uid) {
- if (packageName.equals(mPackageName)) {
- unbind();
- // the currently bound package was removed,
- // need to search for a new package
- bindBestPackage(null);
+ synchronized (mLock) {
+ if (packageName.equals(mPackageName)) {
+ unbindLocked();
+ // the currently bound package was removed,
+ // need to search for a new package
+ bindBestPackageLocked(null);
+ }
}
}
};
@@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection {
return mBinder;
}
}
+
+ public void switchUser(int userId) {
+ synchronized (mLock) {
+ unbindLocked();
+ mCurrentUserId = userId;
+ bindBestPackageLocked(null);
+ }
+ }
}
diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/java/com/android/server/WiredAccessoryManager.java
index 63e8895..d5c9c8f 100644
--- a/services/java/com/android/server/WiredAccessoryManager.java
+++ b/services/java/com/android/server/WiredAccessoryManager.java
@@ -152,7 +152,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
break;
}
- updateLocked(NAME_H2W, headset);
+ updateLocked(NAME_H2W, (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC)) | headset);
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3d77b3a..7c482f5 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -643,6 +643,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return mSecurityPolicy.mActiveWindowId;
}
+ void onTouchInteractionStart() {
+ mSecurityPolicy.onTouchInteractionStart();
+ }
+
void onTouchInteractionEnd() {
mSecurityPolicy.onTouchInteractionEnd();
}
@@ -2138,6 +2142,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
| AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
private int mActiveWindowId;
+ private boolean mTouchInteractionInProgress;
private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
final int eventType = event.getEventType();
@@ -2185,12 +2190,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
} break;
case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
- mActiveWindowId = windowId;
+ // Do not allow delayed hover events to confuse us
+ // which the active window is.
+ if (mTouchInteractionInProgress) {
+ mActiveWindowId = windowId;
+ }
} break;
}
}
+ public void onTouchInteractionStart() {
+ mTouchInteractionInProgress = true;
+ }
+
public void onTouchInteractionEnd() {
+ mTouchInteractionInProgress = false;
// We want to set the active window to be current immediately
// after the user has stopped touching the screen since if the
// user types with the IME he should get a feedback for the
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 2688776..dcf87350 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -398,6 +398,7 @@ class TouchExplorer implements EventStreamTransformation {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ mAms.onTouchInteractionStart();
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 7e3fdbd..35999ea 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -248,8 +248,9 @@ public class ActiveServices {
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
- if (!bringUpServiceLocked(r, service.getFlags(), false)) {
- return new ComponentName("!", "Service process is bad");
+ String error = bringUpServiceLocked(r, service.getFlags(), false);
+ if (error != null) {
+ return new ComponentName("!!", error);
}
return r.name;
}
@@ -518,7 +519,7 @@ public class ActiveServices {
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
- if (!bringUpServiceLocked(s, service.getFlags(), false)) {
+ if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
return 0;
}
}
@@ -964,19 +965,19 @@ public class ActiveServices {
return true;
}
- private final boolean bringUpServiceLocked(ServiceRecord r,
+ private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, false);
- return true;
+ return null;
}
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
- return true;
+ return null;
}
if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
@@ -988,12 +989,13 @@ public class ActiveServices {
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (mAm.mStartedUsers.get(r.userId) == null) {
- Slog.w(TAG, "Unable to launch app "
+ String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
- + r.intent.getIntent() + ": user " + r.userId + " is stopped");
+ + r.intent.getIntent() + ": user " + r.userId + " is stopped";
+ Slog.w(TAG, msg);
bringDownServiceLocked(r, true);
- return false;
+ return msg;
}
// Service is now being launched, its package can't be stopped.
@@ -1018,7 +1020,7 @@ public class ActiveServices {
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
- return true;
+ return null;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
@@ -1041,12 +1043,13 @@ public class ActiveServices {
if (app == null) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated)) == null) {
- Slog.w(TAG, "Unable to launch app "
+ String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
- + r.intent.getIntent() + ": process is bad");
+ + r.intent.getIntent() + ": process is bad";
+ Slog.w(TAG, msg);
bringDownServiceLocked(r, true);
- return false;
+ return msg;
}
if (isolated) {
r.isolatedProc = app;
@@ -1057,7 +1060,7 @@ public class ActiveServices {
mPendingServices.add(r);
}
- return true;
+ return null;
}
private final void requestServiceBindingsLocked(ServiceRecord r) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c2aa3a5..daed0a2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3585,7 +3585,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "Failed trying to unstop package "
+ packageName + ": " + e);
}
- if (isUserRunningLocked(user)) {
+ if (isUserRunningLocked(user, false)) {
forceStopPackageLocked(packageName, pkgUid);
}
}
@@ -3739,7 +3739,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private void forceStopUserLocked(int userId) {
forceStopPackageLocked(null, -1, false, false, true, false, userId);
Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -7904,6 +7905,19 @@ public final class ActivityManagerService extends ActivityManagerNative
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
+ intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
+ broadcastIntentLocked(null, null, intent,
+ null, new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+ throws RemoteException {
+ }
+ }, 0, null, null,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -8879,7 +8893,7 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println(" [-a] [-c] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
pw.println(" a[ctivities]: activity stack state");
- pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
+ pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
pw.println(" o[om]: out of memory management");
@@ -9338,6 +9352,12 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
pw.print(": "); uss.dump("", pw);
}
+ pw.print(" mStartedUserArray: [");
+ for (int i=0; i<mStartedUserArray.length; i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mStartedUserArray[i]);
+ }
+ pw.println("]");
pw.print(" mUserLru: [");
for (int i=0; i<mUserLru.size(); i++) {
if (i > 0) pw.print(", ");
@@ -9707,6 +9727,9 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean onlyHistory = false;
if ("history".equals(dumpPackage)) {
+ if (opti < args.length && "-s".equals(args[opti])) {
+ dumpAll = false;
+ }
onlyHistory = true;
dumpPackage = null;
}
@@ -14106,11 +14129,14 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
R.anim.screen_user_enter);
+ boolean needStart = false;
+
// If the user we are switching to is not currently started, then
// we need to start it now.
if (mStartedUsers.get(userId) == null) {
mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false));
updateStartedUserArrayLocked();
+ needStart = true;
}
mCurrentUserId = userId;
@@ -14134,10 +14160,14 @@ public final class ActivityManagerService extends ActivityManagerNative
// so we can just fairly silently bring the user back from
// the almost-dead.
uss.mState = UserStartedState.STATE_RUNNING;
+ updateStartedUserArrayLocked();
+ needStart = true;
} else if (uss.mState == UserStartedState.STATE_SHUTDOWN) {
// This means ACTION_SHUTDOWN has been sent, so we will
// need to treat this as a new boot of the user.
uss.mState = UserStartedState.STATE_BOOTING;
+ updateStartedUserArrayLocked();
+ needStart = true;
}
mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
@@ -14146,17 +14176,19 @@ public final class ActivityManagerService extends ActivityManagerNative
oldUserId, userId, uss));
mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
- Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID, userId);
+ if (needStart) {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null, null,
+ false, false, MY_PID, Process.SYSTEM_UID, userId);
+ }
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
if (userId != 0) {
- intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+ Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null,
new IIntentReceiver.Stub() {
@@ -14180,6 +14212,21 @@ public final class ActivityManagerService extends ActivityManagerNative
getUserManagerLocked().userForeground(userId);
sendUserSwitchBroadcastsLocked(oldUserId, userId);
+ if (needStart) {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ broadcastIntentLocked(null, null, intent,
+ null, new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+ throws RemoteException {
+ }
+ }, 0, null, null,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -14217,19 +14264,6 @@ public final class ActivityManagerService extends ActivityManagerNative
null, null, 0, null, null,
android.Manifest.permission.MANAGE_USERS,
false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
- intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
- broadcastIntentLocked(null, null, intent,
- null, new IIntentReceiver.Stub() {
- @Override
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
- }
- }, 0, null, null,
- android.Manifest.permission.INTERACT_ACROSS_USERS,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -14318,8 +14352,7 @@ public final class ActivityManagerService extends ActivityManagerNative
void finishUserSwitch(UserStartedState uss) {
synchronized (this) {
- if ((uss.mState == UserStartedState.STATE_BOOTING
- || uss.mState == UserStartedState.STATE_SHUTDOWN)
+ if (uss.mState == UserStartedState.STATE_BOOTING
&& mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
uss.mState = UserStartedState.STATE_RUNNING;
final int userId = uss.mHandle.getIdentifier();
@@ -14410,6 +14443,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (uss.mState != UserStartedState.STATE_STOPPING
&& uss.mState != UserStartedState.STATE_SHUTDOWN) {
uss.mState = UserStartedState.STATE_STOPPING;
+ updateStartedUserArrayLocked();
long ident = Binder.clearCallingIdentity();
try {
@@ -14514,7 +14548,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public boolean isUserRunning(int userId) {
+ public boolean isUserRunning(int userId, boolean orStopped) {
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: isUserRunning() from pid="
@@ -14525,13 +14559,19 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
synchronized (this) {
- return isUserRunningLocked(userId);
+ return isUserRunningLocked(userId, orStopped);
}
}
- boolean isUserRunningLocked(int userId) {
+ boolean isUserRunningLocked(int userId, boolean orStopped) {
UserStartedState state = mStartedUsers.get(userId);
- return state != null && state.mState != UserStartedState.STATE_STOPPING
+ if (state == null) {
+ return false;
+ }
+ if (orStopped) {
+ return true;
+ }
+ return state.mState != UserStartedState.STATE_STOPPING
&& state.mState != UserStartedState.STATE_SHUTDOWN;
}
@@ -14552,9 +14592,24 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private void updateStartedUserArrayLocked() {
- mStartedUserArray = new int[mStartedUsers.size()];
+ int num = 0;
for (int i=0; i<mStartedUsers.size(); i++) {
- mStartedUserArray[i] = mStartedUsers.keyAt(i);
+ UserStartedState uss = mStartedUsers.valueAt(i);
+ // This list does not include stopping users.
+ if (uss.mState != UserStartedState.STATE_STOPPING
+ && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+ num++;
+ }
+ }
+ mStartedUserArray = new int[num];
+ num = 0;
+ for (int i=0; i<mStartedUsers.size(); i++) {
+ UserStartedState uss = mStartedUsers.valueAt(i);
+ if (uss.mState != UserStartedState.STATE_STOPPING
+ && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+ mStartedUserArray[num] = mStartedUsers.keyAt(i);
+ num++;
+ }
}
}
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 95c22ec..f9630ae 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -54,6 +54,7 @@ public class BroadcastQueue {
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
static final int MAX_BROADCAST_HISTORY = 25;
+ static final int MAX_BROADCAST_SUMMARY_HISTORY = 100;
final ActivityManagerService mService;
@@ -93,6 +94,12 @@ public class BroadcastQueue {
= new BroadcastRecord[MAX_BROADCAST_HISTORY];
/**
+ * Summary of historical data of past broadcasts, for debugging.
+ */
+ final Intent[] mBroadcastSummaryHistory
+ = new Intent[MAX_BROADCAST_SUMMARY_HISTORY];
+
+ /**
* Set when we current have a BROADCAST_INTENT_MSG in flight.
*/
boolean mBroadcastsScheduled = false;
@@ -922,6 +929,9 @@ public class BroadcastQueue {
MAX_BROADCAST_HISTORY-1);
r.finishTime = SystemClock.uptimeMillis();
mBroadcastHistory[0] = r;
+ System.arraycopy(mBroadcastSummaryHistory, 0, mBroadcastSummaryHistory, 1,
+ MAX_BROADCAST_SUMMARY_HISTORY-1);
+ mBroadcastSummaryHistory[0] = r.intent;
}
final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
@@ -1006,8 +1016,9 @@ public class BroadcastQueue {
}
}
+ int i;
boolean printed = false;
- for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
+ for (i=0; i<MAX_BROADCAST_HISTORY; i++) {
BroadcastRecord r = mBroadcastHistory[i];
if (r == null) {
break;
@@ -1028,11 +1039,44 @@ public class BroadcastQueue {
pw.print(i); pw.println(":");
r.dump(pw, " ");
} else {
- if (i >= 50) {
+ pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
+ pw.print(" ");
+ pw.println(r.intent.toShortString(false, true, true, false));
+ Bundle bundle = r.intent.getExtras();
+ if (bundle != null) {
+ pw.print(" extras: "); pw.println(bundle.toString());
+ }
+ }
+ }
+
+ if (dumpPackage == null) {
+ if (dumpAll) {
+ i = 0;
+ printed = false;
+ }
+ for (; i<MAX_BROADCAST_SUMMARY_HISTORY; i++) {
+ Intent intent = mBroadcastSummaryHistory[i];
+ if (intent == null) {
+ break;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Historical broadcasts summary [" + mQueueName + "]:");
+ printed = true;
+ }
+ if (!dumpAll && i >= 50) {
pw.println(" ...");
break;
}
- pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
+ pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(intent.toShortString(false, true, true, false));
+ Bundle bundle = intent.getExtras();
+ if (bundle != null) {
+ pw.print(" extras: "); pw.println(bundle.toString());
+ }
}
}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index 85ec328..1cf5b9c 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -81,12 +81,10 @@ class BroadcastRecord extends Binder {
final long now = SystemClock.uptimeMillis();
pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
- pw.print(prefix); pw.println(intent);
- if (sticky) {
- Bundle bundle = intent.getExtras();
- if (bundle != null) {
- pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
- }
+ pw.print(prefix); pw.println(intent.toInsecureString());
+ Bundle bundle = intent.getExtras();
+ if (bundle != null) {
+ pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
}
pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
pw.print(callerApp != null ? callerApp.toShortString() : "null");
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index f5aa3d4..a3ab3c1 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -105,6 +105,18 @@ abstract class DisplayDevice {
}
/**
+ * Blanks the display, if supported.
+ */
+ public void blankLocked() {
+ }
+
+ /**
+ * Unblanks the display, if supported.
+ */
+ public void unblankLocked() {
+ }
+
+ /**
* Sets the display layer stack while in a transaction.
*/
public final void setLayerStackInTransactionLocked(int layerStack) {
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index b8c6cd5..0a42528 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -103,6 +103,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private static final int MSG_REQUEST_TRAVERSAL = 4;
private static final int MSG_UPDATE_VIEWPORT = 5;
+ private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
+ private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
+ private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
+
private final Context mContext;
private final boolean mHeadless;
private final DisplayManagerHandler mHandler;
@@ -141,6 +145,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
new SparseArray<LogicalDisplay>();
private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
+ // Set to true if all displays have been blanked by the power manager.
+ private int mAllDisplayBlankStateFromPowerManager;
+
// Set to true when there are pending display changes that have yet to be applied
// to the surface flinger state.
private boolean mPendingTraversal;
@@ -286,6 +293,40 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
/**
+ * Called by the power manager to blank all displays.
+ */
+ public void blankAllDisplaysFromPowerManager() {
+ synchronized (mSyncRoot) {
+ if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
+ mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
+
+ final int count = mDisplayDevices.size();
+ for (int i = 0; i < count; i++) {
+ DisplayDevice device = mDisplayDevices.get(i);
+ device.blankLocked();
+ }
+ }
+ }
+ }
+
+ /**
+ * Called by the power manager to unblank all displays.
+ */
+ public void unblankAllDisplaysFromPowerManager() {
+ synchronized (mSyncRoot) {
+ if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
+ mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
+
+ final int count = mDisplayDevices.size();
+ for (int i = 0; i < count; i++) {
+ DisplayDevice device = mDisplayDevices.get(i);
+ device.unblankLocked();
+ }
+ }
+ }
+ }
+
+ /**
* Returns information about the specified logical display.
*
* @param displayId The logical display id.
@@ -528,6 +569,17 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
mDisplayDevices.add(device);
addLogicalDisplayLocked(device);
scheduleTraversalLocked(false);
+
+ // Blank or unblank the display immediately to match the state requested
+ // by the power manager (if known).
+ switch (mAllDisplayBlankStateFromPowerManager) {
+ case DISPLAY_BLANK_STATE_BLANKED:
+ device.blankLocked();
+ break;
+ case DISPLAY_BLANK_STATE_UNBLANKED:
+ device.unblankLocked();
+ break;
+ }
}
}
@@ -788,9 +840,18 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
pw.println("DISPLAY MANAGER (dumpsys display)");
- pw.println(" mHeadless=" + mHeadless);
synchronized (mSyncRoot) {
+ pw.println(" mHeadless=" + mHeadless);
+ pw.println(" mOnlyCode=" + mOnlyCore);
+ pw.println(" mSafeMode=" + mSafeMode);
+ pw.println(" mPendingTraversal=" + mPendingTraversal);
+ pw.println(" mAllDisplayBlankStateFromPowerManager="
+ + mAllDisplayBlankStateFromPowerManager);
+ pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
+ pw.println(" mDefaultViewport=" + mDefaultViewport);
+ pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
+
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
@@ -817,10 +878,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
pw.println(" Display " + displayId + ":");
display.dumpLocked(ipw);
}
-
- pw.println();
- pw.println("Default viewport: " + mDefaultViewport);
- pw.println("External touch viewport: " + mExternalTouchViewport);
}
}
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index 679a67e..d780006 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -92,6 +92,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private DisplayDeviceInfo mInfo;
private boolean mHavePendingChanges;
+ private boolean mBlanked;
public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
PhysicalDisplayInfo phys) {
@@ -150,10 +151,23 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
@Override
+ public void blankLocked() {
+ mBlanked = true;
+ Surface.blankDisplay(getDisplayTokenLocked());
+ }
+
+ @Override
+ public void unblankLocked() {
+ mBlanked = false;
+ Surface.unblankDisplay(getDisplayTokenLocked());
+ }
+
+ @Override
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
pw.println("mPhys=" + mPhys);
+ pw.println("mBlanked=" + mBlanked);
}
}
diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java
index 7d030e9..f5cc59f 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -21,6 +21,7 @@ import android.location.Address;
import android.location.GeocoderParams;
import android.location.IGeocodeProvider;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import com.android.server.ServiceWatcher;
@@ -38,8 +39,8 @@ public class GeocoderProxy {
private final ServiceWatcher mServiceWatcher;
public static GeocoderProxy createAndBind(Context context,
- List<String> initialPackageNames) {
- GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames);
+ List<String> initialPackageNames, int userId) {
+ GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, userId);
if (proxy.bind()) {
return proxy;
} else {
@@ -47,11 +48,11 @@ public class GeocoderProxy {
}
}
- public GeocoderProxy(Context context, List<String> initialPackageNames) {
+ public GeocoderProxy(Context context, List<String> initialPackageNames, int userId) {
mContext = context;
mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
- null, null);
+ null, null, userId);
}
private boolean bind () {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index a254d74..c272da4 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -783,6 +783,11 @@ public class GpsLocationProvider implements LocationProviderInterface {
sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
}
+ @Override
+ public void switchUser(int userId) {
+ // nothing to do here
+ }
+
private void handleSetRequest(ProviderRequest request, WorkSource source) {
if (DEBUG) Log.d(TAG, "setRequest " + request);
diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/java/com/android/server/location/LocationProviderInterface.java
index 6f09232..80e71f1 100644
--- a/services/java/com/android/server/location/LocationProviderInterface.java
+++ b/services/java/com/android/server/location/LocationProviderInterface.java
@@ -38,6 +38,8 @@ public interface LocationProviderInterface {
public boolean isEnabled();
public void setRequest(ProviderRequest request, WorkSource source);
+ public void switchUser(int userId);
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args);
// --- deprecated (but still supported) ---
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java
index 7faf72c..dd2e71c 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -25,6 +25,7 @@ import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;
@@ -54,9 +55,9 @@ public class LocationProviderProxy implements LocationProviderInterface {
private WorkSource mWorksource = new WorkSource();
public static LocationProviderProxy createAndBind(Context context, String name, String action,
- List<String> initialPackageNames, Handler handler) {
+ List<String> initialPackageNames, Handler handler, int userId) {
LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
- initialPackageNames, handler);
+ initialPackageNames, handler, userId);
if (proxy.bind()) {
return proxy;
} else {
@@ -65,11 +66,11 @@ public class LocationProviderProxy implements LocationProviderInterface {
}
private LocationProviderProxy(Context context, String name, String action,
- List<String> initialPackageNames, Handler handler) {
+ List<String> initialPackageNames, Handler handler, int userId) {
mContext = context;
mName = name;
mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
- mNewServiceWork, handler);
+ mNewServiceWork, handler, userId);
}
private boolean bind () {
@@ -211,6 +212,11 @@ public class LocationProviderProxy implements LocationProviderInterface {
}
@Override
+ public void switchUser(int userId) {
+ mServiceWatcher.switchUser(userId);
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.append("REMOTE SERVICE");
pw.append(" name=").append(mName);
diff --git a/services/java/com/android/server/location/MockProvider.java b/services/java/com/android/server/location/MockProvider.java
index 36c43ff..1194cbc 100644
--- a/services/java/com/android/server/location/MockProvider.java
+++ b/services/java/com/android/server/location/MockProvider.java
@@ -156,6 +156,11 @@ public class MockProvider implements LocationProviderInterface {
public void setRequest(ProviderRequest request, WorkSource source) { }
@Override
+ public void switchUser(int userId) {
+ // nothing to do here
+ }
+
+ @Override
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java
index 71bae07..734c572 100644
--- a/services/java/com/android/server/location/PassiveProvider.java
+++ b/services/java/com/android/server/location/PassiveProvider.java
@@ -96,6 +96,11 @@ public class PassiveProvider implements LocationProviderInterface {
mReportLocation = request.reportLocation;
}
+ @Override
+ public void switchUser(int userId) {
+ // nothing to do here
+ }
+
public void updateLocation(Location location) {
if (mReportLocation) {
try {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 0600f5c..b8d7286 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -6374,12 +6374,22 @@ public class PackageManagerService extends IPackageManager.Stub {
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
+ /*
+ * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
+ * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
+ */
+ int userIdentifier = getUser().getIdentifier();
+ if (userIdentifier == UserHandle.USER_ALL
+ && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
+ userIdentifier = UserHandle.USER_OWNER;
+ }
+
/*
* Determine if we have any installed package verifiers. If we
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, getUser().getIdentifier());
+ : getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (requiredUid != -1 && isVerificationEnabled(flags)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
diff --git a/services/java/com/android/server/power/DisplayBlanker.java b/services/java/com/android/server/power/DisplayBlanker.java
new file mode 100644
index 0000000..6072053
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayBlanker.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 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.power;
+
+/**
+ * Blanks or unblanks all displays.
+ */
+interface DisplayBlanker {
+ public void blankAllDisplays();
+ public void unblankAllDisplays();
+}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index 82c3617..6a57372 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -159,6 +159,9 @@ final class DisplayPowerController {
// A suspend blocker.
private final SuspendBlocker mSuspendBlocker;
+ // The display blanker.
+ private final DisplayBlanker mDisplayBlanker;
+
// Our handler.
private final DisplayControllerHandler mHandler;
@@ -343,10 +346,12 @@ final class DisplayPowerController {
*/
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
LightsService lights, TwilightService twilight, SuspendBlocker suspendBlocker,
+ DisplayBlanker displayBlanker,
Callbacks callbacks, Handler callbackHandler) {
mHandler = new DisplayControllerHandler(looper);
mNotifier = notifier;
mSuspendBlocker = suspendBlocker;
+ mDisplayBlanker = displayBlanker;
mCallbacks = callbacks;
mCallbackHandler = callbackHandler;
@@ -520,7 +525,8 @@ final class DisplayPowerController {
new ElectronBeam(display),
new PhotonicModulator(executor,
mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
- mSuspendBlocker));
+ mSuspendBlocker),
+ mDisplayBlanker);
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/java/com/android/server/power/DisplayPowerState.java
index f6ce7a7..fdfcacc 100644
--- a/services/java/com/android/server/power/DisplayPowerState.java
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -51,7 +51,8 @@ final class DisplayPowerState {
private final Choreographer mChoreographer;
private final ElectronBeam mElectronBeam;
- private final PhotonicModulator mScreenBrightnessModulator;
+ private final PhotonicModulator mPhotonicModulator;
+ private final DisplayBlanker mDisplayBlanker;
private int mDirty;
private boolean mScreenOn;
@@ -61,10 +62,11 @@ final class DisplayPowerState {
private Runnable mCleanListener;
public DisplayPowerState(ElectronBeam electronBean,
- PhotonicModulator screenBrightnessModulator) {
+ PhotonicModulator photonicModulator, DisplayBlanker displayBlanker) {
mChoreographer = Choreographer.getInstance();
mElectronBeam = electronBean;
- mScreenBrightnessModulator = screenBrightnessModulator;
+ mPhotonicModulator = photonicModulator;
+ mDisplayBlanker = displayBlanker;
// At boot time, we know that the screen is on and the electron beam
// animation is not playing. We don't know the screen's brightness though,
@@ -238,8 +240,8 @@ final class DisplayPowerState {
private void apply() {
if (mDirty != 0) {
if ((mDirty & DIRTY_SCREEN_ON) != 0 && !mScreenOn) {
- mScreenBrightnessModulator.setBrightness(0, true /*sync*/);
- PowerManagerService.nativeSetScreenState(false);
+ mPhotonicModulator.setBrightness(0, true /*sync*/);
+ mDisplayBlanker.blankAllDisplays();
}
if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
@@ -247,12 +249,12 @@ final class DisplayPowerState {
}
if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
- PowerManagerService.nativeSetScreenState(true);
+ mDisplayBlanker.unblankAllDisplays();
}
if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0
&& mScreenOn) {
- mScreenBrightnessModulator.setBrightness(
+ mPhotonicModulator.setBrightness(
(int)(mScreenBrightness * mElectronBeamLevel), false /*sync*/);
}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index abbae5b..b76ad45 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -48,6 +48,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.SystemService;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
@@ -81,6 +82,8 @@ public final class PowerManagerService extends IPowerManager.Stub
private static final int MSG_SANDMAN = 2;
// Message: Sent when the screen on blocker is released.
private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
+ // Message: Sent to poll whether the boot animation has terminated.
+ private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4;
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -127,6 +130,7 @@ public final class PowerManagerService extends IPowerManager.Stub
private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
+ private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
// Summarizes the user activity state.
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
@@ -152,9 +156,16 @@ public final class PowerManagerService extends IPowerManager.Stub
// See point of use for more details.
private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
+ // The name of the boot animation service in init.rc.
+ private static final String BOOT_ANIMATION_SERVICE = "bootanim";
+
+ // Poll interval in milliseconds for watching boot animation finished.
+ private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
+
private Context mContext;
private LightsService mLightsService;
private BatteryService mBatteryService;
+ private DisplayManagerService mDisplayManagerService;
private IBatteryStats mBatteryStats;
private HandlerThread mHandlerThread;
private PowerManagerHandler mHandler;
@@ -230,6 +241,9 @@ public final class PowerManagerService extends IPowerManager.Stub
// screen is coming up.
private final ScreenOnBlockerImpl mScreenOnBlocker;
+ // The display blanker used to turn the screen on or off.
+ private final DisplayBlankerImpl mDisplayBlanker;
+
// True if systemReady() has been called.
private boolean mSystemReady;
@@ -319,14 +333,15 @@ public final class PowerManagerService extends IPowerManager.Stub
private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
private static native void nativeAcquireSuspendBlocker(String name);
private static native void nativeReleaseSuspendBlocker(String name);
-
- static native void nativeSetScreenState(boolean on);
+ private static native void nativeSetInteractive(boolean enable);
+ private static native void nativeSetAutoSuspend(boolean enable);
public PowerManagerService() {
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService");
mWakeLockSuspendBlocker.acquire();
mScreenOnBlocker = new ScreenOnBlockerImpl();
+ mDisplayBlanker = new DisplayBlankerImpl();
mHoldingWakeLockSuspendBlocker = true;
mWakefulness = WAKEFULNESS_AWAKE;
}
@@ -342,23 +357,24 @@ public final class PowerManagerService extends IPowerManager.Stub
public void init(Context context, LightsService ls,
ActivityManagerService am, BatteryService bs, IBatteryStats bss,
DisplayManagerService dm) {
- // Forcibly turn the screen on at boot so that it is in a known power state.
- // We do this in init() rather than in the constructor because setting the
- // screen state requires a call into surface flinger which then needs to call back
- // into the activity manager to check permissions. Unfortunately the
- // activity manager is not running when the constructor is called, so we
- // have to defer setting the screen state until this point.
- nativeSetScreenState(true);
-
mContext = context;
mLightsService = ls;
mBatteryService = bs;
mBatteryStats = bss;
+ mDisplayManagerService = dm;
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
Watchdog.getInstance().addMonitor(this);
+
+ // Forcibly turn the screen on at boot so that it is in a known power state.
+ // We do this in init() rather than in the constructor because setting the
+ // screen state requires a call into surface flinger which then needs to call back
+ // into the activity manager to check permissions. Unfortunately the
+ // activity manager is not running when the constructor is called, so we
+ // have to defer setting the screen state until this point.
+ mDisplayBlanker.unblankAllDisplays();
}
public void setPolicy(WindowManagerPolicy policy) {
@@ -388,7 +404,7 @@ public final class PowerManagerService extends IPowerManager.Stub
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
mContext, mNotifier, mLightsService, twilight,
createSuspendBlockerLocked("PowerManagerService.Display"),
- mDisplayPowerControllerCallbacks, mHandler);
+ mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
@@ -1166,16 +1182,25 @@ public final class PowerManagerService extends IPowerManager.Stub
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU
| WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
@@ -1333,7 +1358,7 @@ public final class PowerManagerService extends IPowerManager.Stub
private boolean isBeingKeptAwakeLocked() {
return mStayOn
|| mProximityPositive
- || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0
+ || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0;
}
@@ -1646,6 +1671,29 @@ public final class PowerManagerService extends IPowerManager.Stub
updatePowerStateLocked();
}
+ private void startWatchingForBootAnimationFinished() {
+ mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED);
+ }
+
+ private void checkIfBootAnimationFinished() {
+ if (DEBUG) {
+ Slog.d(TAG, "Check if boot animation finished...");
+ }
+
+ if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED,
+ BOOT_ANIMATION_POLL_INTERVAL);
+ return;
+ }
+
+ synchronized (mLock) {
+ if (!mBootCompleted) {
+ Slog.i(TAG, "Boot animation finished.");
+ handleBootCompletedLocked();
+ }
+ }
+ }
+
private void handleBootCompletedLocked() {
final long now = SystemClock.uptimeMillis();
mBootCompleted = true;
@@ -2106,6 +2154,9 @@ public final class PowerManagerService extends IPowerManager.Stub
pw.println();
pw.println("Screen On Blocker: " + mScreenOnBlocker);
+ pw.println();
+ pw.println("Display Blanker: " + mDisplayBlanker);
+
dpc = mDisplayPowerController;
}
@@ -2151,9 +2202,13 @@ public final class PowerManagerService extends IPowerManager.Stub
private final class BootCompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- synchronized (mLock) {
- handleBootCompletedLocked();
- }
+ // This is our early signal that the system thinks it has finished booting.
+ // However, the boot animation may still be running for a few more seconds
+ // since it is ultimately in charge of when it terminates.
+ // Defer transitioning into the boot completed state until the animation exits.
+ // We do this so that the screen does not start to dim prematurely before
+ // the user has actually had a chance to interact with the device.
+ startWatchingForBootAnimationFinished();
}
}
@@ -2208,6 +2263,9 @@ public final class PowerManagerService extends IPowerManager.Stub
case MSG_SCREEN_ON_BLOCKER_RELEASED:
handleScreenOnBlockerReleased();
break;
+ case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED:
+ checkIfBootAnimationFinished();
+ break;
}
}
}
@@ -2397,5 +2455,36 @@ public final class PowerManagerService extends IPowerManager.Stub
return "held=" + (mNestCount != 0) + ", mNestCount=" + mNestCount;
}
}
- };
+ }
+
+ private final class DisplayBlankerImpl implements DisplayBlanker {
+ private boolean mBlanked;
+
+ @Override
+ public void blankAllDisplays() {
+ synchronized (this) {
+ mBlanked = true;
+ mDisplayManagerService.blankAllDisplaysFromPowerManager();
+ nativeSetInteractive(false);
+ nativeSetAutoSuspend(true);
+ }
+ }
+
+ @Override
+ public void unblankAllDisplays() {
+ synchronized (this) {
+ nativeSetAutoSuspend(false);
+ nativeSetInteractive(true);
+ mDisplayManagerService.unblankAllDisplaysFromPowerManager();
+ mBlanked = false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ synchronized (this) {
+ return "blanked=" + mBlanked;
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 0db9f19..54f6deb 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -264,6 +264,9 @@ public class WindowManagerService extends IWindowManager.Stub
*/
static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
+ /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
+ static final int WINDOW_FREEZE_TIMEOUT_DURATION = 3000;
+
/**
* If true, the window manager will do its own custom freezing and general
* management of the screen during rotation.
@@ -5651,12 +5654,12 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void showStrictModeViolation(boolean on) {
if (mHeadless) return;
- mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, 0));
+ int pid = Binder.getCallingPid();
+ mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
}
- private void showStrictModeViolation(int arg) {
+ private void showStrictModeViolation(int arg, int pid) {
final boolean on = arg != 0;
- int pid = Binder.getCallingPid();
synchronized(mWindowMap) {
// Ignoring requests to enable the red border from clients
// which aren't on screen. (e.g. Broadcast Receivers in
@@ -6021,7 +6024,8 @@ public class WindowManagerService extends IWindowManager.Stub
mWindowsFreezingScreen = true;
mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
- mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000);
+ mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
+ WINDOW_FREEZE_TIMEOUT_DURATION);
mWaitingForConfig = true;
getDefaultDisplayContentLocked().layoutNeeded = true;
startFreezingDisplayLocked(inTransaction, 0, 0);
@@ -7646,7 +7650,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
case SHOW_STRICT_MODE_VIOLATION: {
- showStrictModeViolation(msg.arg1);
+ showStrictModeViolation(msg.arg1, msg.arg2);
break;
}
@@ -8383,7 +8387,7 @@ public class WindowManagerService extends IWindowManager.Stub
// when we first froze the display.
mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
mH.sendMessageDelayed(mH.obtainMessage(
- H.WINDOW_FREEZE_TIMEOUT), 2000);
+ H.WINDOW_FREEZE_TIMEOUT), WINDOW_FREEZE_TIMEOUT_DURATION);
}
}
}