diff options
Diffstat (limited to 'services/java/com/android')
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); } } } |
