From b4422d237f39921deaa51f410653658d2e3dc262 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Fri, 22 Nov 2013 08:25:26 -0800 Subject: Move some system services to separate directories Refactored the directory structure so that services can be optionally excluded. This is step 1. Will be followed by another change that makes it possible to remove services from the build. Change-Id: Ideacedfd34b5e213217ad3ff4ebb21c4a8e73f85 --- .../server/bluetooth/BluetoothManagerService.java | 1262 ++++++++++++++++++++ 1 file changed, 1262 insertions(+) create mode 100644 service/java/com/android/server/bluetooth/BluetoothManagerService.java (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java new file mode 100644 index 0000000000..546324a73e --- /dev/null +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -0,0 +1,1262 @@ +/* + * 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; + +import android.app.ActivityManager; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.IBluetooth; +import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothCallback; +import android.bluetooth.IBluetoothManager; +import android.bluetooth.IBluetoothManagerCallback; +import android.bluetooth.IBluetoothStateChangeCallback; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Handler; +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.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Log; +class BluetoothManagerService extends IBluetoothManager.Stub { + private static final String TAG = "BluetoothManagerService"; + private static final boolean DBG = true; + + private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; + private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; + private static final String EXTRA_ACTION="action"; + private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; + private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; + private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind + 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 wait for restart due to error + private static final int ERROR_RESTART_TIME_MS = 3000; + //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; + private static final int MESSAGE_REGISTER_ADAPTER = 20; + private static final int MESSAGE_UNREGISTER_ADAPTER = 21; + private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; + private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; + private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; + private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; + private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; + private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; + private static final int MESSAGE_TIMEOUT_BIND =100; + 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 static final int MAX_ERROR_RESTART_RETRIES=6; + + // Bluetooth persisted setting is off + private static final int BLUETOOTH_OFF=0; + // Bluetooth persisted setting is on + // and Airplane mode won't affect Bluetooth state at start up + private static final int BLUETOOTH_ON_BLUETOOTH=1; + // Bluetooth persisted setting is on + // but Airplane mode will affect Bluetooth state at start up + // and Airplane mode will have higher priority. + private static final int BLUETOOTH_ON_AIRPLANE=2; + + private static final int SERVICE_IBLUETOOTH = 1; + private static final int SERVICE_IBLUETOOTHGATT = 2; + + private final Context mContext; + + // Locks are not provided for mName and mAddress. + // They are accessed in handler or broadcast receiver, same thread context. + private String mAddress; + private String mName; + private final ContentResolver mContentResolver; + private final RemoteCallbackList mCallbacks; + private final RemoteCallbackList mStateChangeCallbacks; + private IBluetooth mBluetooth; + private IBluetoothGatt mBluetoothGatt; + private boolean mBinding; + private boolean mUnbinding; + // used inside handler thread + private boolean mQuietEnable = false; + // configuarion from external IBinder call which is used to + // synchronize with broadcast receiver. + private boolean mQuietEnableExternal; + // configuarion from external IBinder call which is used to + // synchronize with broadcast receiver. + private boolean mEnableExternal; + // used inside handler thread + private boolean mEnable; + private int mState; + private final BluetoothHandler mHandler; + private int mErrorRecoveryRetryCounter; + + private void registerForAirplaneMode(IntentFilter filter) { + final ContentResolver resolver = mContext.getContentResolver(); + final String airplaneModeRadios = Settings.Global.getString(resolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + final String toggleableRadios = Settings.Global.getString(resolver, + Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); + boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : + airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); + if (mIsAirplaneSensitive) { + filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + } + } + + private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { + @Override + public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { + Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); + mHandler.sendMessage(msg); + } + }; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { + String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); + if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName); + if (newName != null) { + storeNameAndAddress(newName, null); + } + } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { + synchronized(mReceiver) { + if (isBluetoothPersistedStateOn()) { + if (isAirplaneModeOn()) { + persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); + } else { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + } + if (isAirplaneModeOn()) { + // disable without persisting the setting + sendDisableMsg(); + } else if (mEnableExternal) { + // enable without persisting the setting + sendEnableMsg(mQuietEnableExternal); + } + } + } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); + } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + synchronized(mReceiver) { + if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { + //Enable + if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); + sendEnableMsg(mQuietEnableExternal); + } + } + + if (!isNameAndAddressSet()) { + //Sync the Bluetooth name and address from the Bluetooth Adapter + if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); + getNameAndAddress(); + } + } + } + }; + + BluetoothManagerService(Context context) { + mHandler = new BluetoothHandler(IoThread.get().getLooper()); + + mContext = context; + mBluetooth = null; + mBinding = false; + mUnbinding = false; + mEnable = false; + mState = BluetoothAdapter.STATE_OFF; + mQuietEnableExternal = false; + mEnableExternal = false; + mAddress = null; + mName = null; + mErrorRecoveryRetryCounter = 0; + mContentResolver = context.getContentResolver(); + mCallbacks = new RemoteCallbackList(); + mStateChangeCallbacks = new RemoteCallbackList(); + IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); + filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); + filter.addAction(Intent.ACTION_USER_SWITCHED); + registerForAirplaneMode(filter); + mContext.registerReceiver(mReceiver, filter); + loadStoredNameAndAddress(); + if (isBluetoothPersistedStateOn()) { + mEnableExternal = true; + } + } + + /** + * Returns true if airplane mode is currently on + */ + private final boolean isAirplaneModeOn() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; + } + + /** + * Returns true if the Bluetooth saved state is "on" + */ + private final boolean isBluetoothPersistedStateOn() { + return Settings.Global.getInt(mContentResolver, + Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; + } + + /** + * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH + */ + private final boolean isBluetoothPersistedStateOnBluetooth() { + return Settings.Global.getInt(mContentResolver, + Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; + } + + /** + * Save the Bluetooth on/off state + * + */ + private void persistBluetoothSetting(int value) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.BLUETOOTH_ON, + value); + } + + /** + * Returns true if the Bluetooth Adapter's name and address is + * locally cached + * @return + */ + private boolean isNameAndAddressSet() { + return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; + } + + /** + * Retrieve the Bluetooth Adapter's name and address and save it in + * in the local cache + */ + private void loadStoredNameAndAddress() { + if (DBG) Log.d(TAG, "Loading stored name and address"); + if (mContext.getResources().getBoolean + (com.android.internal.R.bool.config_bluetooth_address_validation) && + Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { + // if the valid flag is not set, don't load the address and name + if (DBG) Log.d(TAG, "invalid bluetooth name and address stored"); + return; + } + mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); + mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); + if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); + } + + /** + * Save the Bluetooth name and address in the persistent store. + * Only non-null values will be saved. + * @param name + * @param address + */ + private void storeNameAndAddress(String name, String address) { + if (name != null) { + Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); + mName = name; + if (DBG) Log.d(TAG,"Stored Bluetooth name: " + + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); + } + + if (address != null) { + Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); + mAddress=address; + if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); + } + + if ((name != null) && (address != null)) { + Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); + } + } + + public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ + Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); + msg.obj = callback; + mHandler.sendMessage(msg); + synchronized(mConnection) { + return mBluetooth; + } + } + + public void unregisterAdapter(IBluetoothManagerCallback callback) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, + "Need BLUETOOTH permission"); + Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); + msg.obj = callback; + mHandler.sendMessage(msg); + } + + public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, + "Need BLUETOOTH permission"); + Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); + msg.obj = callback; + mHandler.sendMessage(msg); + } + + public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, + "Need BLUETOOTH permission"); + Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); + msg.obj = callback; + mHandler.sendMessage(msg); + } + + public boolean isEnabled() { + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && + (!checkIfCallerIsForegroundUser())) { + Log.w(TAG,"isEnabled(): not allowed for non-active and non system user"); + return false; + } + + synchronized(mConnection) { + try { + return (mBluetooth != null && mBluetooth.isEnabled()); + } catch (RemoteException e) { + Log.e(TAG, "isEnabled()", e); + } + } + return false; + } + + public void getNameAndAddress() { + if (DBG) { + Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth + + " mBinding = " + mBinding); + } + Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); + mHandler.sendMessage(msg); + } + public boolean enableNoAutoConnect() + { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (DBG) { + Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding); + } + int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); + + if (callingAppId != Process.NFC_UID) { + throw new SecurityException("no permission to enable Bluetooth quietly"); + } + + synchronized(mReceiver) { + mQuietEnableExternal = true; + mEnableExternal = true; + sendEnableMsg(true); + } + return true; + + } + public boolean enable() { + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && + (!checkIfCallerIsForegroundUser())) { + Log.w(TAG,"enable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + if (DBG) { + Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding); + } + + synchronized(mReceiver) { + mQuietEnableExternal = false; + mEnableExternal = true; + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + Binder.restoreCallingIdentity(callingIdentity); + sendEnableMsg(false); + } + return true; + } + + public boolean disable(boolean persist) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); + + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && + (!checkIfCallerIsForegroundUser())) { + Log.w(TAG,"disable(): not allowed for non-active and non system user"); + return false; + } + + if (DBG) { + Log.d(TAG,"disable(): mBluetooth = " + mBluetooth + + " mBinding = " + mBinding); + } + + synchronized(mReceiver) { + if (persist) { + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); + persistBluetoothSetting(BLUETOOTH_OFF); + Binder.restoreCallingIdentity(callingIdentity); + } + mEnableExternal = false; + sendDisableMsg(); + } + return true; + } + + public void unbindAndFinish() { + if (DBG) { + Log.d(TAG,"unbindAndFinish(): " + mBluetooth + + " mBinding = " + mBinding); + } + + synchronized (mConnection) { + if (mUnbinding) return; + mUnbinding = true; + if (mBluetooth != null) { + if (!mConnection.isGetNameAddressOnly()) { + //Unregister callback object + try { + mBluetooth.unregisterCallback(mBluetoothCallback); + } catch (RemoteException re) { + Log.e(TAG, "Unable to unregister BluetoothCallback",re); + } + } + if (DBG) Log.d(TAG, "Sending unbind request."); + mBluetooth = null; + //Unbind + mContext.unbindService(mConnection); + mUnbinding = false; + mBinding = false; + } else { + mUnbinding=false; + } + } + } + + public IBluetoothGatt getBluetoothGatt() { + // sync protection + return mBluetoothGatt; + } + + private void sendBluetoothStateCallback(boolean isUp) { + int n = mStateChangeCallbacks.beginBroadcast(); + if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); + for (int i=0; i " + 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; + } + + private void sendDisableMsg() { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); + } + + private void sendEnableMsg(boolean quietMode) { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, + quietMode ? 1 : 0, 0)); + } + + private boolean canUnbindBluetoothService() { + synchronized(mConnection) { + //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 + //Only unbind with Bluetooth at OFF state + //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message + try { + if (mEnable || (mBluetooth == null)) return false; + if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; + return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); + } catch (RemoteException e) { + Log.e(TAG, "getState()", e); + } + } + return false; + } + + private void recoverBluetoothServiceFromError() { + Log.e(TAG,"recoverBluetoothServiceFromError"); + synchronized (mConnection) { + if (mBluetooth != null) { + //Unregister callback object + try { + mBluetooth.unregisterCallback(mBluetoothCallback); + } catch (RemoteException re) { + Log.e(TAG, "Unable to unregister",re); + } + } + } + + SystemClock.sleep(500); + + // disable + handleDisable(); + + waitForOnOff(false, true); + + sendBluetoothServiceDownCallback(); + synchronized (mConnection) { + if (mBluetooth != null) { + mBluetooth = null; + //Unbind + mContext.unbindService(mConnection); + } + } + + mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); + mState = BluetoothAdapter.STATE_OFF; + + mEnable = false; + + if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { + // Send a Bluetooth Restart message to reenable bluetooth + Message restartMsg = mHandler.obtainMessage( + MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); + } else { + // todo: notify user to power down and power up phone to make bluetooth work. + } + } +} -- cgit v1.2.3 From 7cc271a83d91f0893988d78b92d73ad3719c1502 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 25 Feb 2014 09:40:05 -0500 Subject: Tabs -> spaces in frameworks/base. Change-Id: I5a84e8e93ac99b5ed0212b37bf66efa5e53864be --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 546324a73e..0d6f548139 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1005,7 +1005,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_OFF; // enable handleEnable(mQuietEnable); - } else if (mBinding || mBluetooth != null) { + } 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 @@ -1014,7 +1014,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); } - } + } break; } } -- cgit v1.2.3 From 24fe135adce66ec47af8c7c5e3379e27ab71bf05 Mon Sep 17 00:00:00 2001 From: Natalie Silvanovich Date: Thu, 1 May 2014 16:12:23 -0700 Subject: Null checks in register/unregister BT Adapters Prevents system crash Bug: 13743852 Change-Id: I05bcb31fc8377866b93899a01c004d15e041f21f --- .../com/android/server/bluetooth/BluetoothManagerService.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0d6f548139..f22020f575 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -307,6 +307,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ + if (callback == null) { + Log.w(TAG, "Callback is null in registerAdapter"); + return null; + } Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); msg.obj = callback; mHandler.sendMessage(msg); @@ -316,6 +320,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public void unregisterAdapter(IBluetoothManagerCallback callback) { + if (callback == null) { + Log.w(TAG, "Callback is null in unregisterAdapter"); + return; + } mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); -- cgit v1.2.3 From 229d7fa1f8427ceacd3704e349b0f754b5a05f3a Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 2 May 2014 16:28:33 -0700 Subject: Bump up priority of system receiving BOOT_COMPLETED. Change-Id: I5166f88f11f781914312e867cb653c8ecbefa705 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0d6f548139..e2a8ca2b99 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -212,6 +212,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); registerForAirplaneMode(filter); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { -- cgit v1.2.3 From 8adda7c563ad656ab476249407744ec69ea3ecef Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Mon, 18 Aug 2014 15:31:57 +0200 Subject: Allow SystemUI to control Bluetooth for secondary users Bug: 15818610 Change-Id: I9eaeaffc73f7675957ed3cd6a896ea83a79d6cff --- .../android/server/bluetooth/BluetoothManagerService.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 07c904883f..7b64139e9c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -121,6 +121,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private int mState; private final BluetoothHandler mHandler; private int mErrorRecoveryRetryCounter; + private final int mSystemUiUid; private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); @@ -218,6 +219,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBluetoothPersistedStateOn()) { mEnableExternal = true; } + + int sysUiUid = -1; + try { + sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", + UserHandle.USER_OWNER); + } catch (PackageManager.NameNotFoundException e) { + Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); + } + mSystemUiUid = sysUiUid; } /** @@ -1118,7 +1128,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { foregroundUser = ActivityManager.getCurrentUser(); valid = (callingUser == foregroundUser) || - callingAppId == Process.NFC_UID; + callingAppId == Process.NFC_UID || + callingAppId == mSystemUiUid; if (DBG) { Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser -- cgit v1.2.3 From 5d9ea3f257b9c28e5bcf066d0448f47effed6cbf Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 10 Oct 2014 15:03:13 -0700 Subject: Fix issue #17829949: Don't kill Bluetooth service... ...even in extreme low memory condition Bind to Bluetooth with BIND_IMPORTANT, so that it is allowed to go to a higher oom adj level. Fix some problems when this is done from a system or persistent process, where this would go to a level that is *too* high. Instead, introduce a new oom adj level for it that is right below persistent. Change-Id: I002bcc4accc36c8579c4cda161be7d2fba21ba17 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 7b64139e9c..636228baae 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -663,7 +663,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); Intent i = new Intent(IBluetooth.class.getName()); if (!doBind(i, mConnection, - Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { + Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { mBinding = true; @@ -1050,7 +1051,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); mConnection.setGetNameAddressOnly(false); Intent i = new Intent(IBluetooth.class.getName()); - if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { + if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { mBinding = true; @@ -1153,7 +1155,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_BLUETOOTH_LE)) { Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE, UserHandle.CURRENT); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT); } } else { //If Bluetooth is off, send service down event to proxy objects, and unbind -- cgit v1.2.3 From c0b8ac0a09131e6ca6ad0efbe51e28dcfc0c8098 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Tue, 28 Oct 2014 14:06:28 -0700 Subject: Add dumpsys support for bluetooth Bug: 18159457 Change-Id: I8d3f7084a7b089c111fd622ff526630bfdfa7300 --- .../server/bluetooth/BluetoothManagerService.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 636228baae..ebdd386d1e 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -44,6 +44,10 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -1282,4 +1286,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // todo: notify user to power down and power up phone to make bluetooth work. } } + + @Override + public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + writer.println("enabled: " + mEnable); + writer.println("state: " + mState); + writer.println("address: " + mAddress); + writer.println("name: " + mName); + if (mBluetooth == null) { + writer.println("Bluetooth Service not connected"); + } else { + try { + writer.println(mBluetooth.dump()); + } catch (RemoteException re) { + writer.println("RemoteException while calling Bluetooth Service"); + } + } + } } -- cgit v1.2.3 From 3362fef6d2c0d5930592d83164d2009e7ccec43f Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Wed, 12 Nov 2014 15:57:54 +0000 Subject: Change the routing path of bluetooth headset connections. The HeadsetService is now bound directly by the BluetoothManagerService. The IBinder object related to the HeadsetService is then given back to the BluetoothHeadset and to the client app. This change makes the HeadsetService available for managed profile clients. Bug: 16968338 Change-Id: I016d1837e4f987c0fab1fc2c64cb06eb91b24d87 --- .../server/bluetooth/BluetoothManagerService.java | 229 +++++++++++++++++++++ 1 file changed, 229 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ebdd386d1e..3117a17175 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -18,11 +18,14 @@ package com.android.server; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothCallback; +import android.bluetooth.IBluetoothHeadset; import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; +import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -32,6 +35,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -42,12 +46,18 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Vector; + class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -67,6 +77,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int ERROR_RESTART_TIME_MS = 3000; //Maximum msec to delay MESSAGE_USER_SWITCHED private static final int USER_SWITCHED_TIME_MS = 200; + // Delay for the addProxy function in msec + private static final int ADD_PROXY_DELAY_MS = 100; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @@ -83,6 +95,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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 MESSAGE_ADD_PROXY_DELAYED = 400; + private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; private static final int MAX_SAVE_RETRIES=3; private static final int MAX_ERROR_RESTART_RETRIES=6; @@ -127,6 +141,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private int mErrorRecoveryRetryCounter; private final int mSystemUiUid; + // Save a ProfileServiceConnections object for each of the bound + // bluetooth profile services + private final Map mProfileServices = + new HashMap (); + private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); final String airplaneModeRadios = Settings.Global.getString(resolver, @@ -499,6 +518,187 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mBluetoothGatt; } + @Override + public boolean bindBluetoothProfileService(int bluetoothProfile, + IBluetoothProfileServiceConnection proxy) { + if (!mEnable) { + if (DBG) { + Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile + + ", while Bluetooth was disabled"); + } + return false; + } + synchronized (mProfileServices) { + ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); + if (psc == null) { + if (DBG) { + Log.d(TAG, "Creating new ProfileServiceConnections object for" + + " profile: " + bluetoothProfile); + } + Intent intent = null; + if (bluetoothProfile == BluetoothProfile.HEADSET) { + intent = new Intent(IBluetoothHeadset.class.getName()); + } else { + return false; + } + psc = new ProfileServiceConnections(intent); + mProfileServices.put(new Integer(bluetoothProfile), psc); + psc.bindService(); + } + } + + // Introducing a delay to give the client app time to prepare + Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); + addProxyMsg.arg1 = bluetoothProfile; + addProxyMsg.obj = proxy; + mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); + return true; + } + + @Override + public void unbindBluetoothProfileService(int bluetoothProfile, + IBluetoothProfileServiceConnection proxy) { + synchronized (mProfileServices) { + ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); + if (psc == null) { + return; + } + psc.removeProxy(proxy); + } + } + + private void unbindAllBluetoothProfileServices() { + synchronized (mProfileServices) { + for (Integer i : mProfileServices.keySet()) { + ProfileServiceConnections psc = mProfileServices.get(i); + mContext.unbindService(psc); + psc.removeAllProxies(); + } + mProfileServices.clear(); + } + } + + /** + * This class manages the clients connected to a given ProfileService + * and maintains the connection with that service. + */ + final private class ProfileServiceConnections implements ServiceConnection, + IBinder.DeathRecipient { + final RemoteCallbackList mProxies = + new RemoteCallbackList (); + IBinder mService; + ComponentName mClassName; + Intent mIntent; + + ProfileServiceConnections(Intent intent) { + mService = null; + mClassName = null; + mIntent = intent; + } + + private void bindService() { + if (mIntent != null && mService == null) { + if (!doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { + Log.w(TAG, "Unable to bind with intent: " + mIntent + + ". Triggering retry."); + } + Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); + msg.obj = this; + mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); + } + } + + private void addProxy(IBluetoothProfileServiceConnection proxy) { + mProxies.register(proxy); + if (mService != null) { + try{ + proxy.onServiceConnected(mClassName, mService); + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect to proxy", e); + } + } else { + if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { + Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); + msg.obj = this; + mHandler.sendMessage(msg); + } + } + } + + private void removeProxy(IBluetoothProfileServiceConnection proxy) { + if (proxy != null) { + if (mProxies.unregister(proxy)) { + try { + proxy.onServiceDisconnected(mClassName); + } catch (RemoteException e) { + Log.e(TAG, "Unable to disconnect proxy", e); + } + } + } else { + Log.w(TAG, "Trying to remove a null proxy"); + } + } + + private void removeAllProxies() { + onServiceDisconnected(mClassName); + mProxies.kill(); + } + + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + // remove timeout message + mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); + mService = service; + mClassName = className; + try { + mService.linkToDeath(this, 0); + } catch (RemoteException e) { + Log.e(TAG, "Unable to linkToDeath", e); + } + int n = mProxies.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mProxies.getBroadcastItem(i).onServiceConnected(className, service); + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect to proxy", e); + } + } + mProxies.finishBroadcast(); + } + + @Override + public void onServiceDisconnected(ComponentName className) { + if (mService == null) { + return; + } + mService.unlinkToDeath(this, 0); + mService = null; + mClassName = null; + int n = mProxies.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mProxies.getBroadcastItem(i).onServiceDisconnected(className); + } catch (RemoteException e) { + Log.e(TAG, "Unable to disconnect from proxy", e); + } + } + mProxies.finishBroadcast(); + } + + @Override + public void binderDied() { + if (DBG) { + Log.w(TAG, "Profile service for profile: " + mClassName + + " died."); + } + onServiceDisconnected(mClassName); + // Trigger rebind + Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); + msg.obj = this; + mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); + } + } + private void sendBluetoothStateCallback(boolean isUp) { int n = mStateChangeCallbacks.beginBroadcast(); if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); @@ -803,6 +1003,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; } + case MESSAGE_ADD_PROXY_DELAYED: + { + ProfileServiceConnections psc = mProfileServices.get( + new Integer(msg.arg1)); + if (psc == null) { + break; + } + IBluetoothProfileServiceConnection proxy = + (IBluetoothProfileServiceConnection) msg.obj; + psc.addProxy(proxy); + break; + } + case MESSAGE_BIND_PROFILE_SERVICE: + { + ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; + removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); + if (psc == null) { + break; + } + psc.bindService(); + break; + } case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); @@ -1005,6 +1227,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); } + unbindAllBluetoothProfileServices(); // disable handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close @@ -1129,16 +1352,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int callingUser = UserHandle.getCallingUserId(); int callingUid = Binder.getCallingUid(); long callingIdentity = Binder.clearCallingIdentity(); + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + UserInfo ui = um.getProfileParent(callingUser); + int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; int callingAppId = UserHandle.getAppId(callingUid); boolean valid = false; try { foregroundUser = ActivityManager.getCurrentUser(); valid = (callingUser == foregroundUser) || + parentUser == foregroundUser || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; if (DBG) { Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + + " parentUser=" + parentUser + " foregroundUser=" + foregroundUser); } } finally { @@ -1165,6 +1393,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else { //If Bluetooth is off, send service down event to proxy objects, and unbind if (!isUp && canUnbindBluetoothService()) { + unbindAllBluetoothProfileServices(); sendBluetoothServiceDownCallback(); unbindAndFinish(); } -- cgit v1.2.3 From 13fa7292d58381a19e7262a2e2fa9d11c5896c75 Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Tue, 9 Dec 2014 18:58:45 +0000 Subject: Only add successfully bound profile services to mProfileServices. This causes crashes on all devices that disable the BluetoothHeadset service when disabling bluetooth and thereby trying to unbind all services. Bug: 18669882 Change-Id: I48978a1556ead967c848c5bd9f6e001d38754b8d --- .../server/bluetooth/BluetoothManagerService.java | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 3117a17175..ca376fdfe9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -535,15 +535,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Log.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " + bluetoothProfile); } - Intent intent = null; - if (bluetoothProfile == BluetoothProfile.HEADSET) { - intent = new Intent(IBluetoothHeadset.class.getName()); - } else { - return false; - } + + if (bluetoothProfile != BluetoothProfile.HEADSET) return false; + + Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); + if (!psc.bindService()) return false; + mProfileServices.put(new Integer(bluetoothProfile), psc); - psc.bindService(); } } @@ -571,7 +570,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mProfileServices) { for (Integer i : mProfileServices.keySet()) { ProfileServiceConnections psc = mProfileServices.get(i); - mContext.unbindService(psc); + try { + mContext.unbindService(psc); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); + } psc.removeAllProxies(); } mProfileServices.clear(); @@ -596,16 +599,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mIntent = intent; } - private void bindService() { - if (mIntent != null && mService == null) { - if (!doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { - Log.w(TAG, "Unable to bind with intent: " + mIntent - + ". Triggering retry."); - } + private boolean bindService() { + if (mIntent != null && mService == null && + doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); msg.obj = this; mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); + return true; } + Log.w(TAG, "Unable to bind with intent: " + mIntent); + return false; } private void addProxy(IBluetoothProfileServiceConnection proxy) { -- cgit v1.2.3 From 0190837e14c10d1d79293c3ed1205d70a01cfc4b Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Thu, 18 Dec 2014 14:16:36 -0800 Subject: BluetoothManagerService: Enforce DUMP permission Bug: 18667272 Change-Id: If9a510aa7b5f22b9df1d8b33f0a18183040a8cf6 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ca376fdfe9..32a6a2faad 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1521,6 +1521,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + writer.println("enabled: " + mEnable); writer.println("state: " + mState); writer.println("address: " + mAddress); -- cgit v1.2.3 From a758133e0b011657977776b1c649915799112a45 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Sat, 28 Feb 2015 13:12:17 -0500 Subject: Remove unused imports in frameworks/base. Change-Id: I031443de83f93eb57a98863001826671b18f3b17 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 32a6a2faad..ef51ad62c1 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -55,8 +55,6 @@ import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; -import java.util.List; -import java.util.Vector; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; -- cgit v1.2.3 From 0bb7222b2b5c192004da0faedddb2b52bc0a5470 Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Fri, 5 Dec 2014 09:31:30 -0800 Subject: DO NOT MERGE ANYWHERE Bluetooth native dumpsys logging support (3/4) Bug: 18508263 Change-Id: I88f9c90dab8b0c825010c8617709449a3dd704b2 --- .../server/bluetooth/BluetoothManagerService.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 32a6a2faad..0c726f313d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -41,6 +41,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -51,6 +52,7 @@ import android.provider.Settings; import android.util.Log; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; @@ -1523,17 +1525,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - writer.println("enabled: " + mEnable); - writer.println("state: " + mState); - writer.println("address: " + mAddress); - writer.println("name: " + mName); + writer.println("Bluetooth Status"); + writer.println(" enabled: " + mEnable); + writer.println(" state: " + mState); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName + "\n"); + writer.flush(); + if (mBluetooth == null) { writer.println("Bluetooth Service not connected"); } else { try { - writer.println(mBluetooth.dump()); + ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd); + mBluetooth.dump(pfd); + pfd.close(); } catch (RemoteException re) { writer.println("RemoteException while calling Bluetooth Service"); + } catch (IOException re) { + writer.println("IOException attempting to dup() fd"); } } } -- cgit v1.2.3 From 5e8cdc7f00265c4adb2b22935eb28708fdbf29ae Mon Sep 17 00:00:00 2001 From: Nitin Arora Date: Mon, 2 Mar 2015 15:03:51 -0800 Subject: Bluetooth LE background operation mode (2/2) Changes include new framework APIs to enable and disable Bluetooth LE separately from Bluetooth Classic. Along with handling the new states in the Bluetooth manager service. Change-Id: Idf667981f48fcbcb6dfda1aa77ea8bab1b2361f0 --- .../server/bluetooth/BluetoothManagerService.java | 284 ++++++++++++++++++--- 1 file changed, 247 insertions(+), 37 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 32a6a2faad..46a4599dad 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -58,6 +58,7 @@ import java.util.Map; import java.util.List; import java.util.Vector; +import java.util.*; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -114,6 +115,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTHGATT = 2; private final Context mContext; + private static int mBleAppCount = 0; // Locks are not provided for mName and mAddress. // They are accessed in handler or broadcast receiver, same thread context. @@ -186,11 +188,40 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } } + + int st = BluetoothAdapter.STATE_OFF; + if (mBluetooth != null) { + try { + st = mBluetooth.getState(); + } catch (RemoteException e) { + Log.e(TAG,"Unable to call getState", e); + } + } + Log.d(TAG, "state" + st); + if (isAirplaneModeOn()) { - // disable without persisting the setting - sendDisableMsg(); + // Clear registered LE apps to force shut-off + synchronized (this) { + mBleAppCount = 0; + } + if (st == BluetoothAdapter.STATE_BLE_ON) { + //if state is BLE_ON make sure you trigger disableBLE part + try { + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + mEnableExternal = false; + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } else if (st == BluetoothAdapter.STATE_ON){ + // disable without persisting the setting + Log.d(TAG, "Calling disable"); + sendDisableMsg(); + } } else if (mEnableExternal) { // enable without persisting the setting + Log.d(TAG, "Calling enable"); sendEnableMsg(mQuietEnableExternal); } } @@ -205,12 +236,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(mQuietEnableExternal); } } - - if (!isNameAndAddressSet()) { - //Sync the Bluetooth name and address from the Bluetooth Adapter - if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); - } } } }; @@ -220,6 +245,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; mBluetooth = null; + mBluetoothGatt = null; mBinding = false; mUnbinding = false; mEnable = false; @@ -398,6 +424,133 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + class ClientDeathRecipient implements IBinder.DeathRecipient { + public void binderDied() { + if (DBG) Log.d(TAG, "Binder is dead - unregister Ble App"); + if (mBleAppCount > 0) --mBleAppCount; + + if (mBleAppCount == 0) { + if (DBG) Log.d(TAG, "Disabling LE only mode after application crash"); + try { + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } + } + } + + /** Internal death rec list */ + Map mBleApps = new HashMap(); + + public int updateBleAppCount(IBinder token, boolean enable) { + if (enable) { + ClientDeathRecipient r = mBleApps.get(token); + if (r == null) { + ClientDeathRecipient deathRec = new ClientDeathRecipient(); + try { + token.linkToDeath(deathRec, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("Wake lock is already dead."); + } + mBleApps.put(token, deathRec); + synchronized (this) { + ++mBleAppCount; + } + if (DBG) Log.d(TAG, "Registered for death Notification"); + } + + } else { + ClientDeathRecipient r = mBleApps.get(token); + if (r != null) { + try { + token.linkToDeath(r, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("Wake lock is already dead."); + } + mBleApps.remove(token); + synchronized (this) { + if (mBleAppCount > 0) --mBleAppCount; + } + if (DBG) Log.d(TAG, "Unregistered for death Notification"); + } + } + if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount); + if (mBleAppCount == 0 && mEnable) { + try { + if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { + if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable"); + mEnable = false; + } + } catch (RemoteException e) { + Log.e(TAG, "getState()", e); + } + } + return mBleAppCount; + } + + /** @hide*/ + public boolean isBleAppPresent() { + if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount); + return (mBleAppCount > 0); + } + + /** + * Action taken when GattService is turned off + */ + private void onBluetoothGattServiceUp() { + if (DBG) Log.d(TAG,"BluetoothGatt Service is Up"); + try{ + if (isBleAppPresent() == false && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mBluetooth.onLeServiceUp(); + + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + Binder.restoreCallingIdentity(callingIdentity); + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onServiceUp", e); + } + } + + /** + * Inform BluetoothAdapter instances that BREDR part is down + * and turn off all service and stack if no LE app needs it + */ + private void sendBrEdrDownCallback() { + if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks"); + int n = mCallbacks.beginBroadcast(); + + if (isBleAppPresent() == false) { + try { + mBluetooth.onBrEdrDown(); + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } + else{//need to stay at BLE ON. disconnect all Gatt connections + try{ + mBluetoothGatt.unregAll();//disconnectAll(); + } catch(RemoteException e) { + Log.e(TAG,"Unable to disconn all", e); + } + } + + Log.d(TAG,"Broadcasting onBrEdrDown() to " + n + " receivers."); + for (int i=0; i " + newState); + // Send broadcast message to everyone else + Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); + intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } + private void bluetoothStateChangeHandler(int prevState, int newState) { + boolean isStandardBroadcast = true; 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 (isUp) { - // connect to GattService - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_BLUETOOTH_LE)) { - Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, - UserHandle.CURRENT); - } - } else { - //If Bluetooth is off, send service down event to proxy objects, and unbind - if (!isUp && canUnbindBluetoothService()) { - unbindAllBluetoothProfileServices(); + if (newState == BluetoothAdapter.STATE_BLE_ON + || newState == BluetoothAdapter.STATE_OFF) { + boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF + && newState == BluetoothAdapter.STATE_BLE_ON); + + if (newState == BluetoothAdapter.STATE_OFF) { + // If Bluetooth is off, send service down event to proxy objects, and unbind + if (DBG) Log.d(TAG, "Bluetooth is complete turn off"); + if (canUnbindBluetoothService()) { + if (DBG) Log.d(TAG, "Good to unbind!"); sendBluetoothServiceDownCallback(); unbindAndFinish(); + sendBleStateChanged(prevState, newState); + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; } + + } else if (!intermediate_off) { + // connect to GattService + if (DBG) Log.d(TAG, "Bluetooth is in LE only mode"); + if (mBluetoothGatt != null) { + if (DBG) Log.d(TAG, "Calling BluetoothGattServiceUp"); + onBluetoothGattServiceUp(); + } else { + if (DBG) Log.d(TAG, "Binding Bluetooth GATT service"); + if (mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_BLUETOOTH_LE)) { + Intent i = new Intent(IBluetoothGatt.class.getName()); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); + } + } + sendBleStateChanged(prevState, newState); + //Don't broadcase this as std intent + isStandardBroadcast = false; + + } else if (intermediate_off){ + if (DBG) Log.d(TAG, "Intermediate off, back to LE only mode"); + // For LE only mode, broadcast as is + sendBleStateChanged(prevState, newState); + sendBluetoothStateCallback(false); // BT is OFF for general users + // Broadcast as STATE_OFF + newState = BluetoothAdapter.STATE_OFF; + sendBrEdrDownCallback(); } + } else if (newState == BluetoothAdapter.STATE_ON) { + boolean isUp = (newState==BluetoothAdapter.STATE_ON); + sendBluetoothStateCallback(isUp); + sendBleStateChanged(prevState, newState); + + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON + || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + sendBleStateChanged(prevState, newState); + isStandardBroadcast = false; + + } else if (newState == BluetoothAdapter.STATE_TURNING_ON + || newState == BluetoothAdapter.STATE_TURNING_OFF) { + sendBleStateChanged(prevState, newState); } - //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 (isStandardBroadcast) { + if (prevState == BluetoothAdapter.STATE_BLE_ON) { + // Show prevState of BLE_ON as OFF to standard users + prevState = BluetoothAdapter.STATE_OFF; + } + 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); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } } } -- cgit v1.2.3 From 7688f220e1dd3457c608aabf39ab900606a387a8 Mon Sep 17 00:00:00 2001 From: Nitin Arora Date: Mon, 2 Mar 2015 15:03:51 -0800 Subject: Bluetooth LE background operation mode (2/2) Changes include new framework APIs to enable and disable Bluetooth LE separately from Bluetooth Classic. Along with handling the new states in the Bluetooth manager service. Change-Id: Idf667981f48fcbcb6dfda1aa77ea8bab1b2361f0 --- .../server/bluetooth/BluetoothManagerService.java | 283 ++++++++++++++++++--- 1 file changed, 246 insertions(+), 37 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ef51ad62c1..3e5eee86a7 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -112,6 +112,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTHGATT = 2; private final Context mContext; + private static int mBleAppCount = 0; // Locks are not provided for mName and mAddress. // They are accessed in handler or broadcast receiver, same thread context. @@ -184,11 +185,40 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } } + + int st = BluetoothAdapter.STATE_OFF; + if (mBluetooth != null) { + try { + st = mBluetooth.getState(); + } catch (RemoteException e) { + Log.e(TAG,"Unable to call getState", e); + } + } + Log.d(TAG, "state" + st); + if (isAirplaneModeOn()) { - // disable without persisting the setting - sendDisableMsg(); + // Clear registered LE apps to force shut-off + synchronized (this) { + mBleAppCount = 0; + } + if (st == BluetoothAdapter.STATE_BLE_ON) { + //if state is BLE_ON make sure you trigger disableBLE part + try { + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + mEnableExternal = false; + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } else if (st == BluetoothAdapter.STATE_ON){ + // disable without persisting the setting + Log.d(TAG, "Calling disable"); + sendDisableMsg(); + } } else if (mEnableExternal) { // enable without persisting the setting + Log.d(TAG, "Calling enable"); sendEnableMsg(mQuietEnableExternal); } } @@ -203,12 +233,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(mQuietEnableExternal); } } - - if (!isNameAndAddressSet()) { - //Sync the Bluetooth name and address from the Bluetooth Adapter - if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); - } } } }; @@ -218,6 +242,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; mBluetooth = null; + mBluetoothGatt = null; mBinding = false; mUnbinding = false; mEnable = false; @@ -396,6 +421,133 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + class ClientDeathRecipient implements IBinder.DeathRecipient { + public void binderDied() { + if (DBG) Log.d(TAG, "Binder is dead - unregister Ble App"); + if (mBleAppCount > 0) --mBleAppCount; + + if (mBleAppCount == 0) { + if (DBG) Log.d(TAG, "Disabling LE only mode after application crash"); + try { + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } + } + } + + /** Internal death rec list */ + Map mBleApps = new HashMap(); + + public int updateBleAppCount(IBinder token, boolean enable) { + if (enable) { + ClientDeathRecipient r = mBleApps.get(token); + if (r == null) { + ClientDeathRecipient deathRec = new ClientDeathRecipient(); + try { + token.linkToDeath(deathRec, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("Wake lock is already dead."); + } + mBleApps.put(token, deathRec); + synchronized (this) { + ++mBleAppCount; + } + if (DBG) Log.d(TAG, "Registered for death Notification"); + } + + } else { + ClientDeathRecipient r = mBleApps.get(token); + if (r != null) { + try { + token.linkToDeath(r, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("Wake lock is already dead."); + } + mBleApps.remove(token); + synchronized (this) { + if (mBleAppCount > 0) --mBleAppCount; + } + if (DBG) Log.d(TAG, "Unregistered for death Notification"); + } + } + if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount); + if (mBleAppCount == 0 && mEnable) { + try { + if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { + if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable"); + mEnable = false; + } + } catch (RemoteException e) { + Log.e(TAG, "getState()", e); + } + } + return mBleAppCount; + } + + /** @hide*/ + public boolean isBleAppPresent() { + if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount); + return (mBleAppCount > 0); + } + + /** + * Action taken when GattService is turned off + */ + private void onBluetoothGattServiceUp() { + if (DBG) Log.d(TAG,"BluetoothGatt Service is Up"); + try{ + if (isBleAppPresent() == false && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mBluetooth.onLeServiceUp(); + + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + Binder.restoreCallingIdentity(callingIdentity); + } + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onServiceUp", e); + } + } + + /** + * Inform BluetoothAdapter instances that BREDR part is down + * and turn off all service and stack if no LE app needs it + */ + private void sendBrEdrDownCallback() { + if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks"); + int n = mCallbacks.beginBroadcast(); + + if (isBleAppPresent() == false) { + try { + mBluetooth.onBrEdrDown(); + } catch(RemoteException e) { + Log.e(TAG,"Unable to call onBrEdrDown", e); + } + } + else{//need to stay at BLE ON. disconnect all Gatt connections + try{ + mBluetoothGatt.unregAll();//disconnectAll(); + } catch(RemoteException e) { + Log.e(TAG,"Unable to disconn all", e); + } + } + + Log.d(TAG,"Broadcasting onBrEdrDown() to " + n + " receivers."); + for (int i=0; i " + newState); + // Send broadcast message to everyone else + Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); + intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); + intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } + private void bluetoothStateChangeHandler(int prevState, int newState) { + boolean isStandardBroadcast = true; 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 (isUp) { - // connect to GattService - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_BLUETOOTH_LE)) { - Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, - UserHandle.CURRENT); - } - } else { - //If Bluetooth is off, send service down event to proxy objects, and unbind - if (!isUp && canUnbindBluetoothService()) { - unbindAllBluetoothProfileServices(); + if (newState == BluetoothAdapter.STATE_BLE_ON + || newState == BluetoothAdapter.STATE_OFF) { + boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF + && newState == BluetoothAdapter.STATE_BLE_ON); + + if (newState == BluetoothAdapter.STATE_OFF) { + // If Bluetooth is off, send service down event to proxy objects, and unbind + if (DBG) Log.d(TAG, "Bluetooth is complete turn off"); + if (canUnbindBluetoothService()) { + if (DBG) Log.d(TAG, "Good to unbind!"); sendBluetoothServiceDownCallback(); unbindAndFinish(); + sendBleStateChanged(prevState, newState); + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; } + + } else if (!intermediate_off) { + // connect to GattService + if (DBG) Log.d(TAG, "Bluetooth is in LE only mode"); + if (mBluetoothGatt != null) { + if (DBG) Log.d(TAG, "Calling BluetoothGattServiceUp"); + onBluetoothGattServiceUp(); + } else { + if (DBG) Log.d(TAG, "Binding Bluetooth GATT service"); + if (mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_BLUETOOTH_LE)) { + Intent i = new Intent(IBluetoothGatt.class.getName()); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); + } + } + sendBleStateChanged(prevState, newState); + //Don't broadcase this as std intent + isStandardBroadcast = false; + + } else if (intermediate_off){ + if (DBG) Log.d(TAG, "Intermediate off, back to LE only mode"); + // For LE only mode, broadcast as is + sendBleStateChanged(prevState, newState); + sendBluetoothStateCallback(false); // BT is OFF for general users + // Broadcast as STATE_OFF + newState = BluetoothAdapter.STATE_OFF; + sendBrEdrDownCallback(); } + } else if (newState == BluetoothAdapter.STATE_ON) { + boolean isUp = (newState==BluetoothAdapter.STATE_ON); + sendBluetoothStateCallback(isUp); + sendBleStateChanged(prevState, newState); + + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON + || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + sendBleStateChanged(prevState, newState); + isStandardBroadcast = false; + + } else if (newState == BluetoothAdapter.STATE_TURNING_ON + || newState == BluetoothAdapter.STATE_TURNING_OFF) { + sendBleStateChanged(prevState, newState); } - //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 (isStandardBroadcast) { + if (prevState == BluetoothAdapter.STATE_BLE_ON) { + // Show prevState of BLE_ON as OFF to standard users + prevState = BluetoothAdapter.STATE_OFF; + } + 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); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } } } -- cgit v1.2.3 From 3acb7e832747b2a14dd7db79dfd47e6d6a5dd066 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Sun, 26 Apr 2015 17:04:29 -0700 Subject: Honor Ble scanning settings from Settings UI. Bug:20643039 Change-Id: Ib1465108e26b8537c9da1bfbb31a99d2e33da910 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ef82bb70ce..1019faa6d9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -48,6 +48,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import android.util.Log; import java.io.FileDescriptor; @@ -443,6 +444,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** Internal death rec list */ Map mBleApps = new HashMap(); + @Override + public boolean isBleScanAlwaysAvailable() { + try { + return (Settings.Global.getInt(mContentResolver, + Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; + } catch (SettingNotFoundException e) { + } + return false; + } + public int updateBleAppCount(IBinder token, boolean enable) { if (enable) { ClientDeathRecipient r = mBleApps.get(token); -- cgit v1.2.3 From 3abeb111cb4760d1df29eb6dbcb2734c6775e71b Mon Sep 17 00:00:00 2001 From: Nitin Arora Date: Wed, 29 Apr 2015 12:35:03 -0700 Subject: Bluetooth: Ensure Bluetooth interface handle is valid This change adds null checks to Bluetooth interface handle to prevent using null references when BluetoothService is not up. Also removed the callbacks for the intermediate state removed for now as they are not being used. Change-Id: I0e72ff4da467a8bcf5a4e5ac48d8558e7f308c7e --- .../server/bluetooth/BluetoothManagerService.java | 29 +++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 1019faa6d9..32b91d25fb 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -512,7 +512,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void onBluetoothGattServiceUp() { if (DBG) Log.d(TAG,"BluetoothGatt Service is Up"); try{ - if (isBleAppPresent() == false && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + if (isBleAppPresent() == false && mBluetooth != null + && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { mBluetooth.onLeServiceUp(); // waive WRITE_SECURE_SETTINGS permission check @@ -531,32 +532,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void sendBrEdrDownCallback() { if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks"); - int n = mCallbacks.beginBroadcast(); + + if(mBluetooth == null) { + Log.w(TAG, "Bluetooth handle is null"); + return; + } if (isBleAppPresent() == false) { try { mBluetooth.onBrEdrDown(); } catch(RemoteException e) { - Log.e(TAG,"Unable to call onBrEdrDown", e); + Log.e(TAG, "Call to onBrEdrDown() failed.", e); } - } - else{//need to stay at BLE ON. disconnect all Gatt connections + } else { + // Need to stay at BLE ON. Disconnect all Gatt connections try{ - mBluetoothGatt.unregAll();//disconnectAll(); + mBluetoothGatt.unregAll(); } catch(RemoteException e) { - Log.e(TAG,"Unable to disconn all", e); - } - } - - Log.d(TAG,"Broadcasting onBrEdrDown() to " + n + " receivers."); - for (int i=0; i Date: Fri, 5 Dec 2014 09:31:30 -0800 Subject: Bluetooth native dumpsys logging support (3/5) Bug: 18508263 Change-Id: I88f9c90dab8b0c825010c8617709449a3dd704b2 --- .../server/bluetooth/BluetoothManagerService.java | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 32b91d25fb..f5d27f952b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -41,6 +41,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -52,6 +53,7 @@ import android.provider.Settings.SettingNotFoundException; import android.util.Log; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; @@ -1737,17 +1739,32 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - writer.println("enabled: " + mEnable); - writer.println("state: " + mState); - writer.println("address: " + mAddress); - writer.println("name: " + mName); + writer.println("Bluetooth Status"); + writer.println(" enabled: " + mEnable); + writer.println(" state: " + mState); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName + "\n"); + writer.flush(); + if (mBluetooth == null) { writer.println("Bluetooth Service not connected"); } else { + ParcelFileDescriptor pfd = null; try { - writer.println(mBluetooth.dump()); + pfd = ParcelFileDescriptor.dup(fd); + mBluetooth.dump(pfd); } catch (RemoteException re) { writer.println("RemoteException while calling Bluetooth Service"); + } catch (IOException ioe) { + writer.println("IOException attempting to dup() fd"); + } finally { + if (pfd != null) { + try { + pfd.close(); + } catch (IOException ioe) { + writer.println("IOException attempting to close() fd"); + } + } } } } -- cgit v1.2.3 From 252a61970f78294b0d6d3d85c0dcdb9af7f588b4 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Tue, 12 May 2015 19:13:36 -0700 Subject: Do not report WiFi and Bluetooth MAC addresses - framework. As a part of the new runtime permissions work we are limiting the PII apps can access. BT and WiFi MAC addresses are PII and based on our research there is no valid use case for app dev to get these addresses aside of user tracking which we are trying to limit. bug:21078858 Change-Id: Ib48223b272c0fd4f5c36acc889d4f44df204b309 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f5d27f952b..c46fa76e89 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -16,6 +16,7 @@ package com.android.server; +import android.Manifest; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; @@ -909,16 +910,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks.finishBroadcast(); } } + public String getAddress() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, - "Need BLUETOOTH permission"); + "Need BLUETOOTH permission"); if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { + (!checkIfCallerIsForegroundUser())) { Log.w(TAG,"getAddress(): not allowed for non-active and non system user"); return null; } + if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS) + != PackageManager.PERMISSION_GRANTED) { + return BluetoothAdapter.DEFAULT_MAC_ADDRESS; + } + synchronized(mConnection) { if (mBluetooth != null) { try { -- cgit v1.2.3 From bd8268db5921a2826ca29ead948b1f1ae0b1c974 Mon Sep 17 00:00:00 2001 From: Nitin Arora Date: Thu, 7 May 2015 18:45:44 -0700 Subject: Bluetooth: Clear BLE always ON apps at Airplane mode This patch clears the container managing the Ble Always On apps while switching on, the airplane mode. The airplane mode will completely turn Off the Bleutooth Adapter from any state it is in. Change-Id: Ib28d39d85efe3aac37e3a53a4fb892099568c702 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c46fa76e89..66fd36fb0f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -205,6 +205,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Clear registered LE apps to force shut-off synchronized (this) { mBleAppCount = 0; + mBleApps.clear(); } if (st == BluetoothAdapter.STATE_BLE_ON) { //if state is BLE_ON make sure you trigger disableBLE part -- cgit v1.2.3 From 80c388b84556479872432be7a370df26829fe005 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Thu, 11 Jun 2015 17:50:29 -0700 Subject: Stops BLE scan when scan only mode is disabled. Bug: 21791070 Change-Id: I1137190f01fb3790b7dfbc409429414da44abe58 --- .../server/bluetooth/BluetoothManagerService.java | 66 ++++++++++++++++------ 1 file changed, 49 insertions(+), 17 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 66fd36fb0f..fbb6dc9bb9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -21,8 +21,8 @@ import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; -import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothCallback; +import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothHeadset; import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; @@ -37,6 +37,7 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.database.ContentObserver; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -56,11 +57,8 @@ import android.util.Log; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; - import java.util.HashMap; import java.util.Map; - -import java.util.*; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -259,6 +257,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mName = null; mErrorRecoveryRetryCounter = 0; mContentResolver = context.getContentResolver(); + // Observe BLE scan only mode settings change. + registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); @@ -458,6 +458,40 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + // Monitor change of BLE scan only mode settings. + private void registerForBleScanModeChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + if (!isBleScanAlwaysAvailable()) { + disableBleScanMode(); + clearBleApps(); + try { + if (mBluetooth != null) mBluetooth.onBrEdrDown(); + } catch (RemoteException e) { + Log.e(TAG, "error when disabling bluetooth", e); + } + } + } + }; + + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), + false, contentObserver); + } + + // Disable ble scan only mode. + private void disableBleScanMode() { + try { + if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { + if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable"); + mEnable = false; + } + } catch (RemoteException e) { + Log.e(TAG, "getState()", e); + } + } + public int updateBleAppCount(IBinder token, boolean enable) { if (enable) { ClientDeathRecipient r = mBleApps.get(token); @@ -478,11 +512,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else { ClientDeathRecipient r = mBleApps.get(token); if (r != null) { - try { - token.linkToDeath(r, 0); - } catch (RemoteException ex) { - throw new IllegalArgumentException("Wake lock is already dead."); - } + // Unregister death recipient as the app goes away. + token.unlinkToDeath(r, 0); mBleApps.remove(token); synchronized (this) { if (mBleAppCount > 0) --mBleAppCount; @@ -492,18 +523,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount); if (mBleAppCount == 0 && mEnable) { - try { - if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { - if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable"); - mEnable = false; - } - } catch (RemoteException e) { - Log.e(TAG, "getState()", e); - } + disableBleScanMode(); } return mBleAppCount; } + // Clear all apps using BLE scan only mode. + private void clearBleApps() { + synchronized (this) { + mBleApps.clear(); + mBleAppCount = 0; + } + } + /** @hide*/ public boolean isBleAppPresent() { if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount); -- cgit v1.2.3 From 07cc3918d5ca93587cea7af0b757221c5a942bb7 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Wed, 17 Jun 2015 17:01:23 -0700 Subject: Sync the Bluetooth name and address from the Bluetooth Adapter It looks like the synchronization of the Bluetooth name and address from the Bluetooth Adapter has been removed by the following commit without an explanation: Bluetooth LE background operation mode (2/2) As a result, the BluetoothManagerService.mAddress was always null. Bug: 20545952 Change-Id: I595f370e06e17b2c67ce511f793efdee7674598c --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index fbb6dc9bb9..f9f67144d8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -237,6 +237,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(mQuietEnableExternal); } } + + if (!isNameAndAddressSet()) { + // Sync the Bluetooth name and address from the Bluetooth Adapter + if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); + getNameAndAddress(); + } } } }; -- cgit v1.2.3 From 9d6dfbef00176de7d27467de745cb4b1c81d25e9 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Sat, 20 Jun 2015 22:55:04 -0700 Subject: Fetch the Bluetooth name and address without enabling the whole stack After factory reset and first bootup, fetching the Bluetooth device name and address is now done without explicitly enabling/disabling the whole Bluetooth stack. Apparently, enabling/disabling the whole stack during th first bootup was somehow holding the kernel wakelock without releasing it. Also, disable debug log messages for class BluetoothManagerService. Bug: 21949364 Change-Id: Iffc14f7969d05c1456159d1f4246c53fb5df0f7a --- .../server/bluetooth/BluetoothManagerService.java | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f9f67144d8..b33b10bc7a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -61,7 +61,7 @@ import java.util.HashMap; import java.util.Map; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; - private static final boolean DBG = true; + private static final boolean DBG = false; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; @@ -227,21 +227,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { + if (DBG) Log.d(TAG, "Bluetooth user switched"); mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + if (DBG) Log.d(TAG, "Bluetooth boot completed"); synchronized(mReceiver) { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { //Enable if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); } - } - - if (!isNameAndAddressSet()) { - // Sync the Bluetooth name and address from the Bluetooth Adapter - if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); + if (!isNameAndAddressSet()) { + // Sync the Bluetooth name and address from the + // Bluetooth Adapter + if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); + getNameAndAddress(); + } } } } @@ -1099,7 +1101,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { boolean unbind = false; if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); synchronized(mConnection) { - if (!mEnable && mBluetooth != null) { + if (!mEnable && mBluetooth != null && !mConnection.isGetNameAddressOnly()) { try { mBluetooth.enable(); } catch (RemoteException e) { @@ -1107,7 +1109,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } - if (mBluetooth != null) waitForOnOff(true, false); + if (mBluetooth != null && !mConnection.isGetNameAddressOnly()) waitForOnOff(true, false); synchronized(mConnection) { if (mBluetooth != null) { String name = null; @@ -1137,7 +1139,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } - if (!mEnable) { + if (!mEnable && !mConnection.isGetNameAddressOnly()) { try { mBluetooth.disable(); } catch (RemoteException e) { @@ -1152,7 +1154,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessage(getMsg); } } - if (!mEnable && mBluetooth != null) waitForOnOff(false, true); + if (!mEnable && mBluetooth != null && !mConnection.isGetNameAddressOnly()) { + waitForOnOff(false, true); + } if (unbind) { unbindAndFinish(); } -- cgit v1.2.3 From 5f1a96fb7a27d2f66a9c66a05d2945a864108df5 Mon Sep 17 00:00:00 2001 From: Sharvil Nanavati Date: Sat, 20 Jun 2015 12:05:52 -0700 Subject: Dump bonded Bluetooth devices in dumpsys. Change-Id: Ie509b0abc64cbc7813e9fe844ff4c05d8cb05f9d --- .../server/bluetooth/BluetoothManagerService.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0c726f313d..063144741b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothGatt; @@ -115,6 +116,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; + private static final String[] DEVICE_TYPE_NAMES = new String[] { + "???", + "BR/EDR", + "LE", + "DUAL" + }; + private final Context mContext; // Locks are not provided for mName and mAddress. @@ -1530,12 +1538,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" state: " + mState); writer.println(" address: " + mAddress); writer.println(" name: " + mName + "\n"); - writer.flush(); if (mBluetooth == null) { writer.println("Bluetooth Service not connected"); } else { try { + writer.println("Bonded devices:"); + for (BluetoothDevice device : mBluetooth.getBondedDevices()) { + writer.println(" " + device.getAddress() + + " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " + + device.getName()); + } + writer.flush(); + ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd); mBluetooth.dump(pfd); pfd.close(); -- cgit v1.2.3 From 1e7ac062da74127adf1a5e7a1f5fb74bb493fdeb Mon Sep 17 00:00:00 2001 From: Miao Chou Date: Fri, 26 Jun 2015 17:14:35 -0700 Subject: Add BluetoothService to reduce resuming time after reboot As a subclass of SystemService, BluetoothService wraps around BluetoothManagerService to unlock Auto-enabling Bluetooth earlier by overriding onBootPhase() and removes the need to wait for BOOT_COMPLETED message. Bug:21705209 Change-Id: I2acc41370a750d8416e11e662e06392326741d2c --- .../server/bluetooth/BluetoothManagerService.java | 49 ++++++++++++---------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 25f8872fa5..b9f62e6785 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -60,6 +60,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; + class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = false; @@ -234,25 +235,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(mQuietEnableExternal); } } - } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { - if (DBG) Log.d(TAG, "Bluetooth user switched"); - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, - intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); - } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { - if (DBG) Log.d(TAG, "Bluetooth boot completed"); - synchronized(mReceiver) { - if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { - //Enable - if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal); - } - if (!isNameAndAddressSet()) { - // Sync the Bluetooth name and address from the - // Bluetooth Adapter - if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); - } - } } } }; @@ -277,9 +259,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); - IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); - filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - filter.addAction(Intent.ACTION_USER_SWITCHED); + IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); registerForAirplaneMode(filter); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); @@ -789,6 +769,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + /** + * Send enable message and set adapter name and address. Called when the boot phase becomes + * PHASE_SYSTEM_SERVICES_READY. + */ + public void handleOnBootPhase() { + if (DBG) Log.d(TAG, "Bluetooth boot completed"); + if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { + if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); + sendEnableMsg(mQuietEnableExternal); + } + if (!isNameAndAddressSet()) { + // Sync the Bluetooth name and address from the Bluetooth Adapter + if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); + getNameAndAddress(); + } + } + + /** + * Called when switching to a different foreground user. + */ + public void handleOnSwitchUser(int userHandle) { + if (DBG) Log.d(TAG, "Bluetooth user switched"); + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0)); + } + /** * This class manages the clients connected to a given ProfileService * and maintains the connection with that service. -- cgit v1.2.3 From 62aa79cf68c9b3ee2fc16a38da14c1857a28d13c Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Thu, 30 Jul 2015 08:59:32 -0700 Subject: Bluetooth: Don't call beginBroadcast() while in a broadcast Block duplicate calls to beginBroadcast() and add try/finally to ensure finishBroadcast() is always called. Bug: 22800686 Change-Id: Ie8d4005f4cd50dd2544a2832773d72eab0015d92 --- .../server/bluetooth/BluetoothManagerService.java | 112 +++++++++++++-------- 1 file changed, 71 insertions(+), 41 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b9f62e6785..10a4cd1dae 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -805,6 +805,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { IBinder mService; ComponentName mClassName; Intent mIntent; + boolean mInvokingProxyCallbacks = false; ProfileServiceConnections(Intent intent) { mService = null; @@ -871,34 +872,54 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Log.e(TAG, "Unable to linkToDeath", e); } - int n = mProxies.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - mProxies.getBroadcastItem(i).onServiceConnected(className, service); - } catch (RemoteException e) { - Log.e(TAG, "Unable to connect to proxy", e); + + if (mInvokingProxyCallbacks) { + Log.e(TAG, "Proxy callbacks already in progress."); + return; + } + mInvokingProxyCallbacks = true; + + final int n = mProxies.beginBroadcast(); + try { + for (int i = 0; i < n; i++) { + try { + mProxies.getBroadcastItem(i).onServiceConnected(className, service); + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect to proxy", e); + } } + } finally { + mProxies.finishBroadcast(); + mInvokingProxyCallbacks = false; } - mProxies.finishBroadcast(); } @Override public void onServiceDisconnected(ComponentName className) { - if (mService == null) { - return; - } + if (mService == null) return; mService.unlinkToDeath(this, 0); mService = null; mClassName = null; - int n = mProxies.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - mProxies.getBroadcastItem(i).onServiceDisconnected(className); - } catch (RemoteException e) { - Log.e(TAG, "Unable to disconnect from proxy", e); + + if (mInvokingProxyCallbacks) { + Log.e(TAG, "Proxy callbacks already in progress."); + return; + } + mInvokingProxyCallbacks = true; + + final int n = mProxies.beginBroadcast(); + try { + for (int i = 0; i < n; i++) { + try { + mProxies.getBroadcastItem(i).onServiceDisconnected(className); + } catch (RemoteException e) { + Log.e(TAG, "Unable to disconnect from proxy", e); + } } + } finally { + mProxies.finishBroadcast(); + mInvokingProxyCallbacks = false; } - mProxies.finishBroadcast(); } @Override @@ -916,16 +937,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendBluetoothStateCallback(boolean isUp) { - int n = mStateChangeCallbacks.beginBroadcast(); - if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); - for (int i=0; i Date: Mon, 3 Aug 2015 17:44:47 -0700 Subject: Reset the pointer to the Bluetooth GATT service During error recovery, if the mBluetooth pointer is reset to null, reset the mBluetoothGatt pointer as well. Bug: 21756298 Change-Id: I26204ba47dd3c5465bb7de30cfa5dc0f07eee2fd --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 10a4cd1dae..50bd544a30 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1506,6 +1506,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Unbind mContext.unbindService(mConnection); } + mBluetoothGatt = null; } SystemClock.sleep(100); @@ -1811,6 +1812,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Unbind mContext.unbindService(mConnection); } + mBluetoothGatt = null; } mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); -- cgit v1.2.3 From 71bd291257152ddb6520b326b03526161b5885e3 Mon Sep 17 00:00:00 2001 From: Joe LaPenna Date: Fri, 4 Sep 2015 12:52:42 -0700 Subject: Do not wtf when the systemui is not present. Not all devices, like wearables actually have a system ui. BUG: 23822226 Change-Id: Ibc2d6c3b8db1de668b9cbced3efcec5a7a39f20b --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 50bd544a30..d5c4a41f07 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -273,7 +273,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", UserHandle.USER_OWNER); } catch (PackageManager.NameNotFoundException e) { - Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); + // Some platforms, such as wearables do not have a system ui. + Log.w(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = sysUiUid; } -- cgit v1.2.3 From 0b0bce04c28537744a927c4b8b34360587659ca3 Mon Sep 17 00:00:00 2001 From: Xiaohui Chen Date: Wed, 16 Sep 2015 09:56:14 -0700 Subject: Cleanup USER_OWNER in various services Bug: 19913735 Change-Id: I980370bab18e1b9ccf4043eed2b9fd721a940f72 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index d5c4a41f07..fd67b4148b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -271,7 +271,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int sysUiUid = -1; try { sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", - UserHandle.USER_OWNER); + UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Log.w(TAG, "Unable to resolve SystemUI's UID.", e); -- cgit v1.2.3 From c3ce4172e58781e13b80c04c7ae10fb6f9c336d9 Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Wed, 11 Nov 2015 21:43:26 -0800 Subject: Move Bluetooth startup to PHASE_ACTIVITY_MANAGER_READY For some reason BluetoothManagerService recently has been unable to bind to the BluetoothService, causing timeouts, which in turn could lead to Bluetooth not working immediately after boot. While refactoring that code, the "get name and address" code was also removed to make the startup sequence more transparent and easier to debug. Bug: 25597150 Change-Id: I62ffe4589a76ea8a6db75e3c7599f149db677ea3 --- .../server/bluetooth/BluetoothManagerService.java | 246 ++++----------------- 1 file changed, 44 insertions(+), 202 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index fd67b4148b..f329cff2c9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -95,8 +95,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; private static final int MESSAGE_TIMEOUT_BIND =100; 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 MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; @@ -587,15 +585,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - /** @hide*/ - public void getNameAndAddress() { - if (DBG) { - Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth + - " mBinding = " + mBinding); - } - Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); - mHandler.sendMessage(msg); - } public boolean enableNoAutoConnect() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, @@ -681,14 +670,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mUnbinding) return; mUnbinding = true; if (mBluetooth != null) { - if (!mConnection.isGetNameAddressOnly()) { - //Unregister callback object - try { - mBluetooth.unregisterCallback(mBluetoothCallback); - } catch (RemoteException re) { - Log.e(TAG, "Unable to unregister BluetoothCallback",re); - } + //Unregister callback object + try { + mBluetooth.unregisterCallback(mBluetoothCallback); + } catch (RemoteException re) { + Log.e(TAG, "Unable to unregister BluetoothCallback",re); } + if (DBG) Log.d(TAG, "Sending unbind request."); mBluetooth = null; //Unbind @@ -780,11 +768,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); } - if (!isNameAndAddressSet()) { - // Sync the Bluetooth name and address from the Bluetooth Adapter - if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); - } } /** @@ -957,42 +940,38 @@ 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"); - try { - int n = mCallbacks.beginBroadcast(); - Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); - for (int i=0; i Date: Wed, 6 Jan 2016 14:51:50 -0700 Subject: Consistent naming for PackageManager methods. When hidden PackageManager methods take a userId argument, they should be named explicitly with the "AsUser" suffix. This fixes several lagging examples so that we can pave the way to safely start passing flags to new methods without scary overloading. Also fix spacing issues in various logging statements. Change-Id: I1e42f7f66427410275df713bea04f6e0445fba28 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f329cff2c9..3c91423a5d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -268,7 +268,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int sysUiUid = -1; try { - sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", + sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. -- cgit v1.2.3 From 4c9ad00c777847f2fb1d00b870e8c6e573985b7f Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 7 Jan 2016 18:50:29 -0700 Subject: More progress on triaging PackageManager callers. Catch a bunch of simple cases where the PackageManager flags are obvious. Add the ability to use the MATCH_SYSTEM_ONLY flag on PackageInfo and ApplicationInfo queries. Re-examine recent tasks after a user is unlocked, since some of the activities may now be available and runnable. Bug: 26471205, 26253870 Change-Id: I989d9f8409070e5cae13202b47e2c7de85bf4a5b --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 3c91423a5d..c1a082b3cb 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -269,7 +269,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int sysUiUid = -1; try { sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", - UserHandle.USER_SYSTEM); + PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Log.w(TAG, "Unable to resolve SystemUI's UID.", e); -- cgit v1.2.3 From cb60d2763eca79aa11a8c3e7c47ca72e1dbf5594 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 12 Jan 2016 16:05:15 -0800 Subject: IBluetooth: remove dump(), support arguments Because IBluetooth is a Binder service, we don't need dump() to support dumpsys, just call the IBinder.dump(). Change-Id: Idcd48f758427b824e0b7eaafd091ba3fb2ff8993 (cherry picked from commit adbb3ff062e039b2552c6b5ded92e56346ac3934) --- .../server/bluetooth/BluetoothManagerService.java | 58 +++++----------------- 1 file changed, 13 insertions(+), 45 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c1a082b3cb..499b706a2b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -114,13 +114,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; - private static final String[] DEVICE_TYPE_NAMES = new String[] { - "???", - "BR/EDR", - "LE", - "DUAL" - }; - private final Context mContext; private static int mBleAppCount = 0; @@ -131,6 +124,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ContentResolver mContentResolver; private final RemoteCallbackList mCallbacks; private final RemoteCallbackList mStateChangeCallbacks; + private IBinder mBluetoothBinder; private IBluetooth mBluetooth; private IBluetoothGatt mBluetoothGatt; private boolean mBinding; @@ -242,6 +236,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; mBluetooth = null; + mBluetoothBinder = null; mBluetoothGatt = null; mBinding = false; mUnbinding = false; @@ -678,6 +673,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (DBG) Log.d(TAG, "Sending unbind request."); + mBluetoothBinder = null; mBluetooth = null; //Unbind mContext.unbindService(mConnection); @@ -1166,6 +1162,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); mBinding = false; + mBluetoothBinder = service; mBluetooth = IBluetooth.Stub.asInterface(service); try { @@ -1674,44 +1671,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } @Override - public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - - writer.println("Bluetooth Status"); - writer.println(" enabled: " + mEnable); - writer.println(" state: " + mState); - writer.println(" address: " + mAddress); - writer.println(" name: " + mName + "\n"); - writer.flush(); - - if (mBluetooth == null) { - writer.println("Bluetooth Service not connected"); - } else { - ParcelFileDescriptor pfd = null; - try { - writer.println("Bonded devices:"); - for (BluetoothDevice device : mBluetooth.getBondedDevices()) { - writer.println(" " + device.getAddress() + - " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " + - device.getName()); - } - writer.flush(); - - pfd = ParcelFileDescriptor.dup(fd); - mBluetooth.dump(pfd); - } catch (RemoteException re) { - writer.println("RemoteException while calling Bluetooth Service"); - } catch (IOException ioe) { - writer.println("IOException attempting to dup() fd"); - } finally { - if (pfd != null) { - try { - pfd.close(); - } catch (IOException ioe) { - writer.println("IOException attempting to close() fd"); - } - } - } + public void dump(FileDescriptor fd, PrintWriter writer, String args[]) { + if (mBluetoothBinder == null) { + writer.println("Bluetooth Service not connected"); + } else { + try { + mBluetoothBinder.dump(fd, args); + } catch (RemoteException re) { + writer.println("RemoteException while calling Bluetooth Service"); } + } } } -- cgit v1.2.3 From 224812b70c0dec6be960324c9c26b78494344d60 Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Wed, 17 Feb 2016 11:35:36 -0800 Subject: Restore DUMP permission check for BluetoothManagerService Bug: 27150536 Change-Id: I6e07f8f5f7476c6cd6dca79e2fb5e8c8412493ec --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 499b706a2b..6d0d9e9090 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1672,6 +1672,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter writer, String args[]) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); if (mBluetoothBinder == null) { writer.println("Bluetooth Service not connected"); } else { -- cgit v1.2.3 From fbbadd9530c38c0668486374b081fbea0adb1e61 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Tue, 23 Feb 2016 11:54:37 -0800 Subject: Suppress output for Protobuf data if Bluetooth is disabled If Bluetooth is disabled or there is some other error, don't print anything when extracting the Metrics-related data in Protobuf format. [Cherry-pick from AOSP] Bug: 27315491 Change-Id: Ic1ec5334fbf0b524909400f080e2eac3ec34edf4 --- .../server/bluetooth/BluetoothManagerService.java | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6d0d9e9090..8cfeb748cc 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1671,16 +1671,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } @Override - public void dump(FileDescriptor fd, PrintWriter writer, String args[]) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - if (mBluetoothBinder == null) { - writer.println("Bluetooth Service not connected"); - } else { - try { - mBluetoothBinder.dump(fd, args); - } catch (RemoteException re) { - writer.println("RemoteException while calling Bluetooth Service"); + public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + String errorMsg = null; + if (mBluetoothBinder == null) { + errorMsg = "Bluetooth Service not connected"; + } else { + try { + mBluetoothBinder.dump(fd, args); + } catch (RemoteException re) { + errorMsg = "RemoteException while calling Bluetooth Service"; + } + } + if (errorMsg != null) { + // Silently return if we are extracting metrics in Protobuf format + if ((args.length > 0) && args[0].startsWith("--proto")) + return; + writer.println(errorMsg); } - } } } -- cgit v1.2.3 From dfeaed13d9d1b6b90485307940cda666c1fbb4fc Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sat, 5 Mar 2016 14:29:13 -0700 Subject: Bluetooth should use Slog. It's in the system process, so whatever it has to say is probably important enough to stick around. Change-Id: Iaeca99d6b9c4881c53ab89216b5128e345a5ff0f --- .../server/bluetooth/BluetoothManagerService.java | 233 ++++++++++----------- 1 file changed, 115 insertions(+), 118 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8cfeb748cc..f65dbb67b2 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -19,7 +19,6 @@ package com.android.server; import android.Manifest; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothCallback; @@ -44,7 +43,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -53,10 +51,9 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; -import android.util.Log; +import android.util.Slog; import java.io.FileDescriptor; -import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; @@ -176,7 +173,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { String action = intent.getAction(); if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); - if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName); + if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); if (newName != null) { storeNameAndAddress(newName, null); } @@ -195,10 +192,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { st = mBluetooth.getState(); } catch (RemoteException e) { - Log.e(TAG,"Unable to call getState", e); + Slog.e(TAG,"Unable to call getState", e); } } - Log.d(TAG, "state" + st); + Slog.d(TAG, "state" + st); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off @@ -214,16 +211,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = false; } } catch(RemoteException e) { - Log.e(TAG,"Unable to call onBrEdrDown", e); + Slog.e(TAG,"Unable to call onBrEdrDown", e); } } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting - Log.d(TAG, "Calling disable"); + Slog.d(TAG, "Calling disable"); sendDisableMsg(); } } else if (mEnableExternal) { // enable without persisting the setting - Log.d(TAG, "Calling enable"); + Slog.d(TAG, "Calling enable"); sendEnableMsg(mQuietEnableExternal); } } @@ -267,7 +264,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. - Log.w(TAG, "Unable to resolve SystemUI's UID.", e); + Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = sysUiUid; } @@ -320,17 +317,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * in the local cache */ private void loadStoredNameAndAddress() { - if (DBG) Log.d(TAG, "Loading stored name and address"); + if (DBG) Slog.d(TAG, "Loading stored name and address"); if (mContext.getResources().getBoolean (com.android.internal.R.bool.config_bluetooth_address_validation) && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { // if the valid flag is not set, don't load the address and name - if (DBG) Log.d(TAG, "invalid bluetooth name and address stored"); + if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored"); return; } mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); - if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); + if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } /** @@ -343,14 +340,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (name != null) { Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); mName = name; - if (DBG) Log.d(TAG,"Stored Bluetooth name: " + + if (DBG) Slog.d(TAG,"Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); } if (address != null) { Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); mAddress=address; - if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + + if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); } @@ -361,7 +358,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ if (callback == null) { - Log.w(TAG, "Callback is null in registerAdapter"); + Slog.w(TAG, "Callback is null in registerAdapter"); return null; } Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); @@ -374,7 +371,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unregisterAdapter(IBluetoothManagerCallback callback) { if (callback == null) { - Log.w(TAG, "Callback is null in unregisterAdapter"); + Slog.w(TAG, "Callback is null in unregisterAdapter"); return; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, @@ -403,7 +400,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean isEnabled() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Log.w(TAG,"isEnabled(): not allowed for non-active and non system user"); + Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user"); return false; } @@ -411,7 +408,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { return (mBluetooth != null && mBluetooth.isEnabled()); } catch (RemoteException e) { - Log.e(TAG, "isEnabled()", e); + Slog.e(TAG, "isEnabled()", e); } } return false; @@ -419,17 +416,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { - if (DBG) Log.d(TAG, "Binder is dead - unregister Ble App"); + if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); if (mBleAppCount > 0) --mBleAppCount; if (mBleAppCount == 0) { - if (DBG) Log.d(TAG, "Disabling LE only mode after application crash"); + if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { if (mBluetooth != null) { mBluetooth.onBrEdrDown(); } } catch(RemoteException e) { - Log.e(TAG,"Unable to call onBrEdrDown", e); + Slog.e(TAG,"Unable to call onBrEdrDown", e); } } } @@ -459,7 +456,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { if (mBluetooth != null) mBluetooth.onBrEdrDown(); } catch (RemoteException e) { - Log.e(TAG, "error when disabling bluetooth", e); + Slog.e(TAG, "error when disabling bluetooth", e); } } } @@ -474,11 +471,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void disableBleScanMode() { try { if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { - if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable"); + if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); mEnable = false; } } catch (RemoteException e) { - Log.e(TAG, "getState()", e); + Slog.e(TAG, "getState()", e); } } @@ -496,7 +493,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (this) { ++mBleAppCount; } - if (DBG) Log.d(TAG, "Registered for death Notification"); + if (DBG) Slog.d(TAG, "Registered for death Notification"); } } else { @@ -508,10 +505,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (this) { if (mBleAppCount > 0) --mBleAppCount; } - if (DBG) Log.d(TAG, "Unregistered for death Notification"); + if (DBG) Slog.d(TAG, "Unregistered for death Notification"); } } - if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount); + if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); if (mBleAppCount == 0 && mEnable) { disableBleScanMode(); } @@ -528,7 +525,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** @hide*/ public boolean isBleAppPresent() { - if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount); + if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); return (mBleAppCount > 0); } @@ -536,7 +533,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Action taken when GattService is turned off */ private void onBluetoothGattServiceUp() { - if (DBG) Log.d(TAG,"BluetoothGatt Service is Up"); + if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); try{ if (isBleAppPresent() == false && mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { @@ -548,7 +545,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Binder.restoreCallingIdentity(callingIdentity); } } catch(RemoteException e) { - Log.e(TAG,"Unable to call onServiceUp", e); + Slog.e(TAG,"Unable to call onServiceUp", e); } } @@ -557,10 +554,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * and turn off all service and stack if no LE app needs it */ private void sendBrEdrDownCallback() { - if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks"); + if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); if(mBluetooth == null) { - Log.w(TAG, "Bluetooth handle is null"); + Slog.w(TAG, "Bluetooth handle is null"); return; } @@ -568,14 +565,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetooth.onBrEdrDown(); } catch(RemoteException e) { - Log.e(TAG, "Call to onBrEdrDown() failed.", e); + Slog.e(TAG, "Call to onBrEdrDown() failed.", e); } } else { // Need to stay at BLE ON. Disconnect all Gatt connections try{ mBluetoothGatt.unregAll(); } catch(RemoteException e) { - Log.e(TAG, "Unable to disconnect all apps.", e); + Slog.e(TAG, "Unable to disconnect all apps.", e); } } } @@ -586,7 +583,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { "Need BLUETOOTH ADMIN permission"); if (DBG) { - Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + + Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); @@ -606,14 +603,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean enable() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Log.w(TAG,"enable(): not allowed for non-active and non system user"); + Slog.w(TAG,"enable(): not allowed for non-active and non system user"); return false; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (DBG) { - Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + + Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } @@ -623,7 +620,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false); } - if (DBG) Log.d(TAG, "enable returning"); + if (DBG) Slog.d(TAG, "enable returning"); return true; } @@ -633,12 +630,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Log.w(TAG,"disable(): not allowed for non-active and non system user"); + Slog.w(TAG,"disable(): not allowed for non-active and non system user"); return false; } if (DBG) { - Log.d(TAG,"disable(): mBluetooth = " + mBluetooth + + Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding); } @@ -657,7 +654,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindAndFinish() { if (DBG) { - Log.d(TAG,"unbindAndFinish(): " + mBluetooth + + Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding); } @@ -669,10 +666,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetooth.unregisterCallback(mBluetoothCallback); } catch (RemoteException re) { - Log.e(TAG, "Unable to unregister BluetoothCallback",re); + Slog.e(TAG, "Unable to unregister BluetoothCallback",re); } - if (DBG) Log.d(TAG, "Sending unbind request."); + if (DBG) Slog.d(TAG, "Sending unbind request."); mBluetoothBinder = null; mBluetooth = null; //Unbind @@ -696,7 +693,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { IBluetoothProfileServiceConnection proxy) { if (!mEnable) { if (DBG) { - Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile + + Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + ", while Bluetooth was disabled"); } return false; @@ -705,7 +702,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); if (psc == null) { if (DBG) { - Log.d(TAG, "Creating new ProfileServiceConnections object for" + Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " + bluetoothProfile); } @@ -746,7 +743,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mContext.unbindService(psc); } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); + Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); } psc.removeAllProxies(); } @@ -759,9 +756,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * PHASE_SYSTEM_SERVICES_READY. */ public void handleOnBootPhase() { - if (DBG) Log.d(TAG, "Bluetooth boot completed"); + if (DBG) Slog.d(TAG, "Bluetooth boot completed"); if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { - if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); + if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); } } @@ -770,7 +767,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Called when switching to a different foreground user. */ public void handleOnSwitchUser(int userHandle) { - if (DBG) Log.d(TAG, "Bluetooth user switched"); + if (DBG) Slog.d(TAG, "Bluetooth user switched"); mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0)); } @@ -801,7 +798,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); return true; } - Log.w(TAG, "Unable to bind with intent: " + mIntent); + Slog.w(TAG, "Unable to bind with intent: " + mIntent); return false; } @@ -811,7 +808,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try{ proxy.onServiceConnected(mClassName, mService); } catch (RemoteException e) { - Log.e(TAG, "Unable to connect to proxy", e); + Slog.e(TAG, "Unable to connect to proxy", e); } } else { if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { @@ -828,11 +825,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { proxy.onServiceDisconnected(mClassName); } catch (RemoteException e) { - Log.e(TAG, "Unable to disconnect proxy", e); + Slog.e(TAG, "Unable to disconnect proxy", e); } } } else { - Log.w(TAG, "Trying to remove a null proxy"); + Slog.w(TAG, "Trying to remove a null proxy"); } } @@ -850,11 +847,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mService.linkToDeath(this, 0); } catch (RemoteException e) { - Log.e(TAG, "Unable to linkToDeath", e); + Slog.e(TAG, "Unable to linkToDeath", e); } if (mInvokingProxyCallbacks) { - Log.e(TAG, "Proxy callbacks already in progress."); + Slog.e(TAG, "Proxy callbacks already in progress."); return; } mInvokingProxyCallbacks = true; @@ -865,7 +862,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mProxies.getBroadcastItem(i).onServiceConnected(className, service); } catch (RemoteException e) { - Log.e(TAG, "Unable to connect to proxy", e); + Slog.e(TAG, "Unable to connect to proxy", e); } } } finally { @@ -882,7 +879,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mClassName = null; if (mInvokingProxyCallbacks) { - Log.e(TAG, "Proxy callbacks already in progress."); + Slog.e(TAG, "Proxy callbacks already in progress."); return; } mInvokingProxyCallbacks = true; @@ -893,7 +890,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mProxies.getBroadcastItem(i).onServiceDisconnected(className); } catch (RemoteException e) { - Log.e(TAG, "Unable to disconnect from proxy", e); + Slog.e(TAG, "Unable to disconnect from proxy", e); } } } finally { @@ -905,7 +902,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void binderDied() { if (DBG) { - Log.w(TAG, "Profile service for profile: " + mClassName + Slog.w(TAG, "Profile service for profile: " + mClassName + " died."); } onServiceDisconnected(mClassName); @@ -919,12 +916,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void sendBluetoothStateCallback(boolean isUp) { try { int n = mStateChangeCallbacks.beginBroadcast(); - if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); + if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); for (int i=0; i " + newState); + if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); // Send broadcast message to everyone else Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); @@ -1498,9 +1495,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newState == BluetoothAdapter.STATE_OFF) { // If Bluetooth is off, send service down event to proxy objects, and unbind - if (DBG) Log.d(TAG, "Bluetooth is complete turn off"); + if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); if (canUnbindBluetoothService()) { - if (DBG) Log.d(TAG, "Good to unbind!"); + if (DBG) Slog.d(TAG, "Good to unbind!"); sendBluetoothServiceDownCallback(); unbindAndFinish(); sendBleStateChanged(prevState, newState); @@ -1510,12 +1507,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (!intermediate_off) { // connect to GattService - if (DBG) Log.d(TAG, "Bluetooth is in LE only mode"); + if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); if (mBluetoothGatt != null) { - if (DBG) Log.d(TAG, "Calling BluetoothGattServiceUp"); + if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); onBluetoothGattServiceUp(); } else { - if (DBG) Log.d(TAG, "Binding Bluetooth GATT service"); + if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); if (mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_BLUETOOTH_LE)) { Intent i = new Intent(IBluetoothGatt.class.getName()); @@ -1527,7 +1524,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { isStandardBroadcast = false; } else if (intermediate_off){ - if (DBG) Log.d(TAG, "Intermediate off, back to LE only mode"); + if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); // For LE only mode, broadcast as is sendBleStateChanged(prevState, newState); sendBluetoothStateCallback(false); // BT is OFF for general users @@ -1583,7 +1580,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; } } catch (RemoteException e) { - Log.e(TAG, "getState()", e); + Slog.e(TAG, "getState()", e); break; } } @@ -1594,7 +1591,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } i++; } - Log.e(TAG,"waitForOnOff time out"); + Slog.e(TAG,"waitForOnOff time out"); return false; } @@ -1619,21 +1616,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); } catch (RemoteException e) { - Log.e(TAG, "getState()", e); + Slog.e(TAG, "getState()", e); } } return false; } private void recoverBluetoothServiceFromError() { - Log.e(TAG,"recoverBluetoothServiceFromError"); + Slog.e(TAG,"recoverBluetoothServiceFromError"); synchronized (mConnection) { if (mBluetooth != null) { //Unregister callback object try { mBluetooth.unregisterCallback(mBluetoothCallback); } catch (RemoteException re) { - Log.e(TAG, "Unable to unregister",re); + Slog.e(TAG, "Unable to unregister",re); } } } -- cgit v1.2.3 From b523d1ab94ce34a89f3e20e21932df4ba04846fb Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sat, 5 Mar 2016 14:42:58 -0700 Subject: Kick Bluetooth stack after user is unlocked. If Bluetooth was enabled at boot time, but the actual Bluetooth package wasn't encryption aware, we need to kick off another enabled pass once the user is unlocked. Bug: 27326711 Change-Id: I511c4fd8567792e5bc4d49fa95929fd87edd0fbf --- .../server/bluetooth/BluetoothManagerService.java | 45 ++++++++++++++++------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f65dbb67b2..e241a4aa99 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -89,14 +89,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; - private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; - private static final int MESSAGE_TIMEOUT_BIND =100; - private static final int MESSAGE_TIMEOUT_UNBIND =101; + private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; + private static final int MESSAGE_TIMEOUT_BIND = 100; + private static final int MESSAGE_TIMEOUT_UNBIND = 101; private static final int MESSAGE_USER_SWITCHED = 300; + private static final int MESSAGE_USER_UNLOCKED = 301; private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; - private static final int MAX_SAVE_RETRIES=3; - private static final int MAX_ERROR_RESTART_RETRIES=6; + private static final int MAX_SAVE_RETRIES = 3; + private static final int MAX_ERROR_RESTART_RETRIES = 6; // Bluetooth persisted setting is off private static final int BLUETOOTH_OFF=0; @@ -767,8 +768,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Called when switching to a different foreground user. */ public void handleOnSwitchUser(int userHandle) { - if (DBG) Slog.d(TAG, "Bluetooth user switched"); - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0)); + if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); + mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); + } + + /** + * Called when user is unlocked. + */ + public void handleOnUnlockUser(int userHandle) { + if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); + mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); } /** @@ -1308,12 +1317,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } - case MESSAGE_USER_SWITCHED: - { - if (DBG) { - Slog.d(TAG, "MESSAGE_USER_SWITCHED"); - } + case MESSAGE_USER_SWITCHED: { + if (DBG) Slog.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) { @@ -1381,6 +1388,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; } + case MESSAGE_USER_UNLOCKED: { + if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); + mHandler.removeMessages(MESSAGE_USER_SWITCHED); + + synchronized (mConnection) { + if (mEnable && !mBinding && (mBluetooth == null)) { + // We should be connected, but we gave up for some + // reason; maybe the Bluetooth service wasn't encryption + // aware, so try binding again. + if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); + handleEnable(mQuietEnable); + } + } + } } } } -- cgit v1.2.3 From c668f0ef9e9e9552076798acc5d014a4cfff925e Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Fri, 11 Mar 2016 13:47:20 -0800 Subject: Get adapter name and address on boot Bug: 25836009 Change-Id: I6fe68b116fcd736cd5736be68c97af3052351b33 --- .../android/server/bluetooth/BluetoothManagerService.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index e241a4aa99..799a763845 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -761,6 +761,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); + } else if (!isNameAndAddressSet()) { + if (DBG) Slog.d(TAG, "Getting adapter name and address"); + enable(); + waitForOnOff(true, false); + disable(true); } } @@ -1001,6 +1006,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } + // mAddress is accessed from outside. // It is alright without a lock. Here, bluetooth is off, no other thread is // changing mAddress @@ -1181,6 +1187,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG,"Unable to call configHciSnoopLog", e); } + if (!isNameAndAddressSet()) { + try { + storeNameAndAddress(mBluetooth.getName(), + mBluetooth.getAddress()); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to grab names", re); + } + } + //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); -- cgit v1.2.3 From d684c548283f89b8df6e2bd213b16b76053b5aa0 Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Thu, 31 Mar 2016 14:14:27 -0700 Subject: Get name and address without enabling Bluetooth Bug: 27665077 Change-Id: I2a06c1a65f22b2f9095a859f5bdd39d4626da165 --- .../server/bluetooth/BluetoothManagerService.java | 56 +++++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 799a763845..0a814ab579 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -92,6 +92,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; private static final int MESSAGE_TIMEOUT_BIND = 100; private static final int MESSAGE_TIMEOUT_UNBIND = 101; + private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; private static final int MESSAGE_USER_SWITCHED = 300; private static final int MESSAGE_USER_UNLOCKED = 301; private static final int MESSAGE_ADD_PROXY_DELAYED = 400; @@ -599,8 +600,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(true); } return true; - } + public boolean enable() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { @@ -763,9 +764,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendEnableMsg(mQuietEnableExternal); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); - enable(); - waitForOnOff(true, false); - disable(true); + Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); + mHandler.sendMessage(getMsg); } } @@ -1076,6 +1076,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); private class BluetoothHandler extends Handler { + boolean mGetNameAddressOnly = false; + public BluetoothHandler(Looper looper) { super(looper); } @@ -1084,6 +1086,37 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void handleMessage(Message msg) { if (DBG) Slog.d (TAG, "Message: " + msg.what); switch (msg.what) { + case MESSAGE_GET_NAME_AND_ADDRESS: + if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); + synchronized(mConnection) { + if ((mBluetooth == null) && (!mBinding)) { + if (DBG) Slog.d(TAG, "Binding to service to get name and address"); + mGetNameAddressOnly = true; + Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); + mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); + Intent i = new Intent(IBluetooth.class.getName()); + if (!doBind(i, mConnection, + Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT)) { + mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); + } else { + mBinding = true; + } + } else if (mBluetooth != null) { + try { + storeNameAndAddress(mBluetooth.getName(), + mBluetooth.getAddress()); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to grab names", re); + } + if (mGetNameAddressOnly && !mEnable) { + unbindAndFinish(); + } + mGetNameAddressOnly = false; + } + } + break; + case MESSAGE_ENABLE: if (DBG) { Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); @@ -1177,6 +1210,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothBinder = service; mBluetooth = IBluetooth.Stub.asInterface(service); + if (!isNameAndAddressSet()) { + Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); + mHandler.sendMessage(getMsg); + if (mGetNameAddressOnly) return; + } + try { boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); @@ -1187,15 +1226,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG,"Unable to call configHciSnoopLog", e); } - if (!isNameAndAddressSet()) { - try { - storeNameAndAddress(mBluetooth.getName(), - mBluetooth.getAddress()); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to grab names", re); - } - } - //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); -- cgit v1.2.3 From 292415fd2fca1ae537459a1a117f4650d6123564 Mon Sep 17 00:00:00 2001 From: Sanket Agarwal Date: Thu, 21 Apr 2016 14:10:55 -0700 Subject: While turning OFF do not honor ON requests. Native stack does not handle being put from OFF -> ON state without doing a complete cleanup. Hence instead of going from start -> ON -> OFF -> cleanup it goes start -> ON -> OFF ->ON -> ... usually leads to race conditions down the road in native. This patch is a workaround so that we can throw away the requests if we are in currently "turning off" phase. The side-effect would be that user will need to turn it ON again. The race happens when the turn OFF time is longer but usually it is found to be close to order of seconds hence the wait should be bounded. Bug: b/28318203 Change-Id: I14f6633f31311e5b561e1dcbc8a9d6d2a5dd6fdc --- .../android/server/bluetooth/BluetoothManagerService.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0a814ab579..5e8687a904 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -613,7 +613,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { "Need BLUETOOTH ADMIN permission"); if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + - " mBinding = " + mBinding); + " mBinding = " + mBinding + " mState = " + mState); + } + // We do not honor ON requests when the adapter is already turned ON or in the process of + // turning ON. + // As a protective mechanism to make sure that the native stack gets cleaned up properly + // before turning it back ON we ignore requests while the bluetooth is turning OFF. + // Bug: b/28318203 + if (mState == BluetoothAdapter.STATE_BLE_TURNING_OFF || + mState == BluetoothAdapter.STATE_TURNING_OFF || + mState == BluetoothAdapter.STATE_ON || + mState == BluetoothAdapter.STATE_BLE_ON || + mState == BluetoothAdapter.STATE_TURNING_ON || + mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { + return false; } synchronized(mReceiver) { -- cgit v1.2.3 From 6d126c81896c8956f36a162382815b121f3e2be1 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Sun, 22 May 2016 22:16:41 -0700 Subject: Reduced the impact of "synchronized" statements * Removed "synchronized" statements that are not needed * Replaced "synchronized" statements with Read/Write lock as appropriate. The lock protects the access to and the setting of BluetoothAdapter.mService and BluetoothManagerService.mBluetooth and associated state. Bug: 28734075 Bug: 28799467 Change-Id: I8f8281c505f0a1ae0add1e14a3caba1f5b2a98e4 --- .../server/bluetooth/BluetoothManagerService.java | 271 ++++++++++++--------- 1 file changed, 157 insertions(+), 114 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 5e8687a904..f30a126ba6 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -52,6 +52,7 @@ import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -126,6 +127,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private IBinder mBluetoothBinder; private IBluetooth mBluetooth; private IBluetoothGatt mBluetoothGatt; + private final ReentrantReadWriteLock mBluetoothLock = + new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; // used inside handler thread @@ -190,12 +193,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } int st = BluetoothAdapter.STATE_OFF; - if (mBluetooth != null) { - try { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { st = mBluetooth.getState(); - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call getState", e); } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + } finally { + mBluetoothLock.readLock().unlock(); } Slog.d(TAG, "state" + st); @@ -208,12 +214,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (st == BluetoothAdapter.STATE_BLE_ON) { //if state is BLE_ON make sure you trigger disableBLE part try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); mEnableExternal = false; } - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().lock(); } } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting @@ -366,9 +375,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); msg.obj = callback; mHandler.sendMessage(msg); - synchronized(mConnection) { - return mBluetooth; - } + + return mBluetooth; } public void unregisterAdapter(IBluetoothManagerCallback callback) { @@ -406,12 +414,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - synchronized(mConnection) { - try { - return (mBluetooth != null && mBluetooth.isEnabled()); - } catch (RemoteException e) { - Slog.e(TAG, "isEnabled()", e); - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.isEnabled(); + } catch (RemoteException e) { + Slog.e(TAG, "isEnabled()", e); + } finally { + mBluetoothLock.readLock().unlock(); } return false; } @@ -424,11 +433,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBleAppCount == 0) { if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); } - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } @@ -456,9 +468,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { disableBleScanMode(); clearBleApps(); try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) mBluetooth.onBrEdrDown(); } catch (RemoteException e) { Slog.e(TAG, "error when disabling bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } @@ -472,12 +487,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Disable ble scan only mode. private void disableBleScanMode() { try { + mBluetoothLock.writeLock().lock(); if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); mEnable = false; } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -536,7 +554,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void onBluetoothGattServiceUp() { if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); - try{ + try { + mBluetoothLock.readLock().lock(); if (isBleAppPresent() == false && mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { mBluetooth.onLeServiceUp(); @@ -546,8 +565,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); Binder.restoreCallingIdentity(callingIdentity); } - } catch(RemoteException e) { - Slog.e(TAG,"Unable to call onServiceUp", e); + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onServiceUp", e); + } finally { + mBluetoothLock.readLock().unlock(); } } @@ -558,22 +579,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void sendBrEdrDownCallback() { if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); - if(mBluetooth == null) { + if (mBluetooth == null) { Slog.w(TAG, "Bluetooth handle is null"); return; } if (isBleAppPresent() == false) { try { - mBluetooth.onBrEdrDown(); - } catch(RemoteException e) { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) mBluetooth.onBrEdrDown(); + } catch (RemoteException e) { Slog.e(TAG, "Call to onBrEdrDown() failed.", e); + } finally { + mBluetoothLock.readLock().unlock(); } } else { // Need to stay at BLE ON. Disconnect all Gatt connections - try{ + try { mBluetoothGatt.unregAll(); - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG, "Unable to disconnect all apps.", e); } } @@ -673,7 +697,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { " mBinding = " + mBinding); } - synchronized (mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (mUnbinding) return; mUnbinding = true; if (mBluetooth != null) { @@ -695,6 +720,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mUnbinding=false; } mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -1010,14 +1037,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return BluetoothAdapter.DEFAULT_MAC_ADDRESS; } - synchronized(mConnection) { - if (mBluetooth != null) { - try { - return mBluetooth.getAddress(); - } catch (RemoteException e) { - Slog.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); - } - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.getAddress(); + } catch (RemoteException e) { + Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); + } finally { + mBluetoothLock.readLock().unlock(); } // mAddress is accessed from outside. @@ -1036,15 +1062,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return null; } - synchronized(mConnection) { - if (mBluetooth != null) { - try { - return mBluetooth.getName(); - } catch (RemoteException e) { - Slog.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); - } - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.getName(); + } catch (RemoteException e) { + Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); + } finally { + mBluetoothLock.readLock().unlock(); } + // mName is accessed from outside. // It alright without a lock. Here, bluetooth is off, no other thread is // changing mName @@ -1101,7 +1127,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { switch (msg.what) { case MESSAGE_GET_NAME_AND_ADDRESS: if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { if (DBG) Slog.d(TAG, "Binding to service to get name and address"); mGetNameAddressOnly = true; @@ -1127,6 +1154,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mGetNameAddressOnly = false; } + } finally { + mBluetoothLock.writeLock().unlock(); } break; @@ -1209,7 +1238,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); IBinder service = (IBinder) msg.obj; - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); onBluetoothGattServiceUp(); @@ -1264,6 +1294,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Slog.e(TAG,"Unable to call enable()",e); } + } finally { + mBluetoothLock.writeLock().unlock(); } if (!mEnable) { @@ -1275,9 +1307,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_TIMEOUT_BIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); - synchronized(mConnection) { - mBinding = false; - } + mBluetoothLock.writeLock().lock(); + mBinding = false; + mBluetoothLock.writeLock().unlock(); + break; } case MESSAGE_BLUETOOTH_STATE_CHANGE: @@ -1312,7 +1345,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTH) { // if service is unbinded already, do nothing and return if (mBluetooth == null) break; @@ -1324,6 +1358,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); break; } + } finally { + mBluetoothLock.writeLock().unlock(); } if (mEnable) { @@ -1369,9 +1405,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_TIMEOUT_UNBIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); - synchronized(mConnection) { - mUnbinding = false; - } + mBluetoothLock.writeLock().lock(); + mUnbinding = false; + mBluetoothLock.writeLock().unlock(); break; } @@ -1381,15 +1417,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /* disable and enable BT when detect a user switch */ if (mEnable && mBluetooth != null) { - synchronized (mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - //Unregister callback object - try { - mBluetooth.unregisterCallback(mBluetoothCallback); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister",re); - } + mBluetooth.unregisterCallback(mBluetoothCallback); } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to unregister", re); + } finally { + mBluetoothLock.readLock().unlock(); } if (mState == BluetoothAdapter.STATE_TURNING_OFF) { @@ -1420,14 +1456,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); - synchronized (mConnection) { - if (mBluetooth != null) { - mBluetooth = null; - //Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; + + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); } + mBluetoothGatt = null; + mBluetoothLock.writeLock().unlock(); + SystemClock.sleep(100); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); @@ -1450,14 +1488,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); mHandler.removeMessages(MESSAGE_USER_SWITCHED); - synchronized (mConnection) { - if (mEnable && !mBinding && (mBluetooth == null)) { - // We should be connected, but we gave up for some - // reason; maybe the Bluetooth service wasn't encryption - // aware, so try binding again. - if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); - handleEnable(mQuietEnable); - } + if (mEnable && !mBinding && (mBluetooth == null)) { + // We should be connected, but we gave up for some + // reason; maybe the Bluetooth service wasn't encryption + // aware, so try binding again. + if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); + handleEnable(mQuietEnable); } } } @@ -1467,7 +1503,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void handleEnable(boolean quietMode) { mQuietEnable = quietMode; - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { //Start bind timeout and bind Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); @@ -1496,6 +1533,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG,"Unable to call enable()",e); } } + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -1510,18 +1549,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void handleDisable() { - synchronized(mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { if (DBG) Slog.d(TAG,"Sending off request."); - - try { - if(!mBluetooth.disable()) { - Slog.e(TAG,"IBluetooth.disable() returned false"); - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call disable()",e); + if (!mBluetooth.disable()) { + Slog.e(TAG,"IBluetooth.disable() returned false"); } } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call disable()",e); + } finally { + mBluetoothLock.readLock().unlock(); } } @@ -1648,20 +1687,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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) { - Slog.e(TAG, "getState()", e); - break; + try { + mBluetoothLock.readLock().lock(); + 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) { + Slog.e(TAG, "getState()", e); + break; + } finally { + mBluetoothLock.readLock().unlock(); } if (on || off) { SystemClock.sleep(300); @@ -1684,34 +1724,36 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean canUnbindBluetoothService() { - synchronized(mConnection) { + try { //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 //Only unbind with Bluetooth at OFF state //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message - try { - if (mEnable || (mBluetooth == null)) return false; - if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; - return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); - } catch (RemoteException e) { - Slog.e(TAG, "getState()", e); - } + mBluetoothLock.readLock().lock(); + if (mEnable || (mBluetooth == null)) return false; + if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; + return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.readLock().unlock(); } return false; } private void recoverBluetoothServiceFromError() { Slog.e(TAG,"recoverBluetoothServiceFromError"); - synchronized (mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { //Unregister callback object - try { - mBluetooth.unregisterCallback(mBluetoothCallback); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister",re); - } + mBluetooth.unregisterCallback(mBluetoothCallback); } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to unregister", re); + } finally { + mBluetoothLock.readLock().unlock(); } SystemClock.sleep(500); @@ -1722,14 +1764,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { waitForOnOff(false, true); sendBluetoothServiceDownCallback(); - synchronized (mConnection) { - if (mBluetooth != null) { - mBluetooth = null; - //Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; + + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); } + mBluetoothGatt = null; + mBluetoothLock.writeLock().unlock(); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; -- cgit v1.2.3 From 630c0a3a0748855515a6544da3380c12f83a619e Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Tue, 24 May 2016 15:28:41 -0700 Subject: Add missing "try ... finally" safeguards Safeguards for code protected by ReentrantReadWriteLock. Bug: 28734075 Bug: 28799467 Change-Id: Ib7f598a92e8df6bd855ca48cdd094c1c73a935f2 --- .../server/bluetooth/BluetoothManagerService.java | 34 +++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f30a126ba6..1f88be55ec 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1457,14 +1457,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); + } + mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } - mBluetoothGatt = null; - mBluetoothLock.writeLock().unlock(); SystemClock.sleep(100); @@ -1765,14 +1768,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothServiceDownCallback(); - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); + } + mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } - mBluetoothGatt = null; - mBluetoothLock.writeLock().unlock(); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; -- cgit v1.2.3 From 302a1abcdc87fe9b0f70137c8dd27c47d16cd975 Mon Sep 17 00:00:00 2001 From: Christine Hallstrom Date: Wed, 25 May 2016 15:49:08 -0700 Subject: Properly check if BT is off when shutting down radios Use BluetoothAdapter#getState() instead of BluetoothAdapter#isEnabled() when checking if Bluetooth has turned off, as isEnabled() is set to false early in the shutdown process and getState() provides a better indication of the state of BT. Bug: 27354612 Change-Id: Ic7828f0726491d49c9a14ba5d654b24f66743662 --- .../server/bluetooth/BluetoothManagerService.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 1f88be55ec..831ce01dac 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -425,6 +425,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + public int getState() { + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && + (!checkIfCallerIsForegroundUser())) { + Slog.w(TAG, "getState(): not allowed for non-active and non system user"); + return BluetoothAdapter.STATE_OFF; + } + + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.getState(); + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + return BluetoothAdapter.STATE_OFF; + } + class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); -- cgit v1.2.3 From a4201975ca287ca4d3640a3800e6d379a8f4f80a Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Wed, 1 Jun 2016 22:25:18 -0700 Subject: Delay handleEnable() until Bluetooth state is OFF During shutdown of the Bluetooth stack, if a request to enable Bluetooth is received, the request is processed immediately. As a result, we don't let the Bluetooth service to shutdown cleanly, and the Bluetooth process with the native backend doesn't go away. This creates various issues in the native backend stack. Now, after an enable request is received, if necessary we delay acting on it, until the Bluetooth state is OFF. Bug: 17723234 Change-Id: I55db4bbd4f45227aa49eae996dcc328f76557a9b --- .../server/bluetooth/BluetoothManagerService.java | 72 ++++++++++------------ 1 file changed, 31 insertions(+), 41 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 1f88be55ec..3eadb5ca73 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -639,19 +639,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + mState); } - // We do not honor ON requests when the adapter is already turned ON or in the process of - // turning ON. - // As a protective mechanism to make sure that the native stack gets cleaned up properly - // before turning it back ON we ignore requests while the bluetooth is turning OFF. - // Bug: b/28318203 - if (mState == BluetoothAdapter.STATE_BLE_TURNING_OFF || - mState == BluetoothAdapter.STATE_TURNING_OFF || - mState == BluetoothAdapter.STATE_ON || - mState == BluetoothAdapter.STATE_BLE_ON || - mState == BluetoothAdapter.STATE_TURNING_ON || - mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { - return false; - } synchronized(mReceiver) { mQuietEnableExternal = false; @@ -701,6 +688,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().lock(); if (mUnbinding) return; mUnbinding = true; + mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); if (mBluetooth != null) { //Unregister callback object try { @@ -1165,7 +1153,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; - handleEnable(msg.arg1 == 1); + if (mBluetooth == null) { + handleEnable(msg.arg1 == 1); + } else { + // + // We need to wait until transitioned to STATE_OFF and + // the previous Bluetooth process has exited. The + // waiting period has three components: + // (a) Wait until the local state is STATE_OFF. This + // is accomplished by "waitForOnOff(false, true)". + // (b) Wait until the STATE_OFF state is updated to + // all components. + // (c) Wait until the Bluetooth process exits, and + // ActivityManager detects it. + // The waiting for (b) and (c) is accomplished by + // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE + // message. On slower devices, that delay needs to be + // on the order of (2 * SERVICE_RESTART_TIME_MS). + // + waitForOnOff(false, true); + mQuietEnable = (msg.arg1 == 1); + Message restartMsg = mHandler.obtainMessage( + MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, + 2 * SERVICE_RESTART_TIME_MS); + } break; case MESSAGE_DISABLE: @@ -1617,14 +1629,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newState == BluetoothAdapter.STATE_OFF) { // If Bluetooth is off, send service down event to proxy objects, and unbind if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); - if (canUnbindBluetoothService()) { - if (DBG) Slog.d(TAG, "Good to unbind!"); - sendBluetoothServiceDownCallback(); - unbindAndFinish(); - sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; - } + sendBluetoothServiceDownCallback(); + unbindAndFinish(); + sendBleStateChanged(prevState, newState); + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; } else if (!intermediate_off) { // connect to GattService @@ -1726,25 +1735,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { quietMode ? 1 : 0, 0)); } - private boolean canUnbindBluetoothService() { - try { - //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 - //Only unbind with Bluetooth at OFF state - //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message - mBluetoothLock.readLock().lock(); - if (mEnable || (mBluetooth == null)) return false; - if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; - return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); - } catch (RemoteException e) { - Slog.e(TAG, "getState()", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - return false; - } - private void recoverBluetoothServiceFromError() { Slog.e(TAG,"recoverBluetoothServiceFromError"); try { -- cgit v1.2.3 From c5ad1f87b25822ff086c75f5c165d131db0251da Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Thu, 9 Jun 2016 12:58:07 -0700 Subject: Unlock mBluetoothLock.readLock() instead of double-locking it Bug: 29011117 Change-Id: Ie9e359c3ee079c2cecc33f11cfff7c0dc6406be1 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 3eadb5ca73..9154b8eced 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -222,7 +222,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Slog.e(TAG,"Unable to call onBrEdrDown", e); } finally { - mBluetoothLock.readLock().lock(); + mBluetoothLock.readLock().unlock(); } } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting -- cgit v1.2.3 From 20f11b34f738d5586e0ad6b1cd50bbe4239de58d Mon Sep 17 00:00:00 2001 From: Calvin On Date: Wed, 15 Jun 2016 17:58:23 -0700 Subject: Fix race with BT disable in BLE_ON_STATE This will restart the BT stack when it detects a transition into OFF state while the user enable flag (mEnable) is set. Bug: 29363429 Change-Id: I9839119b34c4694ad92e96240c6989008b2f8d52 --- .../server/bluetooth/BluetoothManagerService.java | 59 +++++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 9154b8eced..59e4f28496 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1153,8 +1153,27 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; + + // Use service interface to get the exact state + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + int state = mBluetooth.getState(); + if (state == BluetoothAdapter.STATE_BLE_ON) { + Slog.w(TAG, "BT is in BLE_ON State"); + mBluetooth.onLeServiceUp(); + break; + } + } + } catch (RemoteException e) { + Slog.e(TAG, "", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + + mQuietEnable = (msg.arg1 == 1); if (mBluetooth == null) { - handleEnable(msg.arg1 == 1); + handleEnable(mQuietEnable); } else { // // We need to wait until transitioned to STATE_OFF and @@ -1172,7 +1191,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // on the order of (2 * SERVICE_RESTART_TIME_MS). // waitForOnOff(false, true); - mQuietEnable = (msg.arg1 == 1); Message restartMsg = mHandler.obtainMessage( MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, @@ -1335,17 +1353,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // handle error state transition case from TURNING_ON to OFF // unbind and rebind bluetooth service and enable bluetooth if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_OFF) && - (mBluetooth != null) && mEnable) { + (newState == BluetoothAdapter.STATE_OFF) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(); } if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_BLE_ON) && - (mBluetooth != null) && mEnable) { + (newState == BluetoothAdapter.STATE_BLE_ON) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(); } + // If we tried to enable BT while BT was in the process of shutting down, + // wait for the BT process to fully tear down and then force a restart + // here. This is a bit of a hack (b/29363429). + if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && + (newState == BluetoothAdapter.STATE_OFF)) { + if (mEnable) { + Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); + waitForOnOff(false, true); + Message restartMsg = mHandler.obtainMessage( + MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); + } + } if (newState == BluetoothAdapter.STATE_ON || - newState == BluetoothAdapter.STATE_BLE_ON) { + newState == BluetoothAdapter.STATE_BLE_ON) { // bluetooth is working, reset the counter if (mErrorRecoveryRetryCounter != 0) { Slog.w(TAG, "bluetooth is recovered from error"); @@ -1388,7 +1419,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Send BT state broadcast to update // the BT icon correctly if ((mState == BluetoothAdapter.STATE_TURNING_ON) || - (mState == BluetoothAdapter.STATE_ON)) { + (mState == BluetoothAdapter.STATE_ON)) { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); mState = BluetoothAdapter.STATE_TURNING_OFF; @@ -1621,8 +1652,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { boolean isStandardBroadcast = true; if (prevState != newState) { //Notify all proxy objects first of adapter state change - if (newState == BluetoothAdapter.STATE_BLE_ON - || newState == BluetoothAdapter.STATE_OFF) { + if (newState == BluetoothAdapter.STATE_BLE_ON || + newState == BluetoothAdapter.STATE_OFF) { boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF && newState == BluetoothAdapter.STATE_BLE_ON); @@ -1667,13 +1698,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothStateCallback(isUp); sendBleStateChanged(prevState, newState); - } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON - || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || + newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { sendBleStateChanged(prevState, newState); isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_TURNING_ON - || newState == BluetoothAdapter.STATE_TURNING_OFF) { + } else if (newState == BluetoothAdapter.STATE_TURNING_ON || + newState == BluetoothAdapter.STATE_TURNING_OFF) { sendBleStateChanged(prevState, newState); } -- cgit v1.2.3 From 3ad02fff15ef49d705caab6836d76067c489389f Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Mon, 27 Jun 2016 15:25:18 -0700 Subject: Add extra waiting when switching users If disabling Bluetooth times out, wait for an additional amount of time to ensure the process is shut down completely before attempting to restart. Bug: 29738770 Change-Id: I43dec35a1e03d12cb07863babea97d55baa32528 --- .../android/server/bluetooth/BluetoothManagerService.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 59e4f28496..172025b383 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -61,7 +61,7 @@ import java.util.Map; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; - private static final boolean DBG = false; + private static final boolean DBG = true; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; @@ -1494,7 +1494,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); - waitForOnOff(false, true); + boolean didDisableTimeout = !waitForOnOff(false, true); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); @@ -1512,7 +1512,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().unlock(); } - SystemClock.sleep(100); + // + // If disabling Bluetooth times out, wait for an + // additional amount of time to ensure the process is + // shut down completely before attempting to restart. + // + if (didDisableTimeout) { + SystemClock.sleep(3000); + } else { + SystemClock.sleep(100); + } mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; -- cgit v1.2.3 From 1fff3cdf4b1e4fc7920a5b76d4ae92eb6824325d Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Wed, 29 Jun 2016 17:31:44 -0700 Subject: Add Bluetooth toggle prompts - framework If permission review is enabled toggling bluetoth on or off results in a user prompt to collect consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. Also added a configuration resource which controls whether permission review mode is enabled. By default it is not and an OEM can change this via an overlay. For now we also keep the old mechanism to toggle review mode via a build property which is still used and will be removed when clients have transitioned. bug:28715749 Change-Id: I94c5828ad6c8aa6b363622a26ff9da4fc2e2fac7 --- .../server/bluetooth/BluetoothManagerService.java | 83 ++++++++++++++++++---- 1 file changed, 69 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8c5887f7a5..8b243e7f75 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -35,10 +35,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -151,6 +153,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final Map mProfileServices = new HashMap (); + private final boolean mPermissionReviewRequired; + private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); final String airplaneModeRadios = Settings.Global.getString(resolver, @@ -243,6 +247,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler = new BluetoothHandler(IoThread.get().getLooper()); mContext = context; + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); + mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -644,15 +653,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean enable() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"enable(): not allowed for non-active and non system user"); - return false; + public boolean enable(String packageName) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "enable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (!isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; + } } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + mState); @@ -668,14 +688,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean disable(boolean persist) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); + public boolean disable(String packageName, boolean persist) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"disable(): not allowed for non-active and non system user"); - return false; + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "disable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; + } } if (DBG) { @@ -696,6 +726,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + try { + // Validate the package only if we are going to use it + ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, + PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (applicationInfo.uid != callingUid) { + throw new SecurityException("Package " + callingUid + + " not in uid " + callingUid); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RemoteException(e.getMessage()); + } + return false; + } + public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + -- cgit v1.2.3 From ab0fd3594f0fe45cffceb360e022302a51cecfee Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Wed, 17 Aug 2016 11:46:34 -0700 Subject: Remove permission review build property - framework Change-Id: Ifcfd436f2d57a6006ef804292d2875434e4669da --- .../android/server/bluetooth/BluetoothManagerService.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8b243e7f75..9d880202f7 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -28,6 +28,7 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -248,8 +249,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED - || context.getResources().getBoolean( + mPermissionReviewRequired = context.getResources().getBoolean( com.android.internal.R.bool.config_permissionReviewRequired); mBluetooth = null; @@ -742,7 +742,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Legacy apps in permission review mode trigger a user prompt if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { Intent intent = new Intent(intentAction); - mContext.startActivity(intent); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + // Shouldn't happen + Slog.e(TAG, "Intent to handle action " + intentAction + " missing"); + return false; + } return true; } } catch (PackageManager.NameNotFoundException e) { -- cgit v1.2.3 From 6fca269639472d8daaedc426ed2f788940f09445 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Thu, 1 Sep 2016 16:32:13 -0700 Subject: Update Bluetooth toggle UI to UX spec - framework Change-Id: Iaaf9d3801a721f15ad7019bca59f235e4de3e2a7 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 9d880202f7..a789157a8e 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -742,6 +742,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Legacy apps in permission review mode trigger a user prompt if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { Intent intent = new Intent(intentAction); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); try { -- cgit v1.2.3 From a6088d9e03f849c2ff4ace740ccecf1aef7dd7cc Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Tue, 6 Sep 2016 18:03:10 -0700 Subject: Enable Bluetooth by default Bug: 29446913 Change-Id: I6d42810cb3f99617b886f6c643f8c66c42c1d017 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8c5887f7a5..89fdfaf305 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -293,7 +293,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private final boolean isBluetoothPersistedStateOn() { return Settings.Global.getInt(mContentResolver, - Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; + Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) != BLUETOOTH_OFF; } /** @@ -301,7 +301,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private final boolean isBluetoothPersistedStateOnBluetooth() { return Settings.Global.getInt(mContentResolver, - Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; + Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; } /** -- cgit v1.2.3 From 4cd9a26c6c408c3532cb49fc38fe182bc7a0b7fa Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Wed, 21 Sep 2016 17:28:11 -0700 Subject: Removed MESSAGE_BIND_PROFILE_SERVICE messages on unbind Add a missing call to remove all MESSAGE_BIND_PROFILE_SERVICE message when unbinding and finishing. Bug: 31442739 Test: manual, and "frameworks/base/core/tests/bluetoothtests" unit tests Change-Id: I7e9a8f79a38d4eb8ab8b53be04650226fc72732e (cherry picked from commit 2bbe13ebccb163c03fd6e74c4450dfd3a43b3984) --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 89fdfaf305..0f8db2e656 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -707,6 +707,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mUnbinding) return; mUnbinding = true; mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); + mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); if (mBluetooth != null) { //Unregister callback object try { -- cgit v1.2.3 From 5e3d34a070cbaa7ea142fc51960fc5bb3c0888d5 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Wed, 21 Sep 2016 17:28:11 -0700 Subject: Removed MESSAGE_BIND_PROFILE_SERVICE messages on unbind Add a missing call to remove all MESSAGE_BIND_PROFILE_SERVICE message when unbinding and finishing. Bug: 31442739 Test: manual, and "frameworks/base/core/tests/bluetoothtests" unit tests Change-Id: I7e9a8f79a38d4eb8ab8b53be04650226fc72732e --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 172025b383..6575a2a86c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -689,6 +689,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mUnbinding) return; mUnbinding = true; mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); + mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); if (mBluetooth != null) { //Unregister callback object try { -- cgit v1.2.3 From c816f2eeba24e185baf977bb5b82227d23257aca Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 18 Oct 2016 10:04:24 -0700 Subject: Bluetooth: More logging of bluetooth service state Bug: 32140251 Bug: 32140271 Bug: 32060415 Change-Id: I50faa184551748023ea5a573646a75293f553d16 --- .../android/server/bluetooth/BluetoothManagerService.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0f8db2e656..6757fcce43 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -203,7 +203,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - Slog.d(TAG, "state" + st); + Slog.d(TAG, "Airplane Mode change - current state: " + st); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off @@ -266,6 +266,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { + if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); mEnableExternal = true; } @@ -292,8 +293,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Returns true if the Bluetooth saved state is "on" */ private final boolean isBluetoothPersistedStateOn() { - return Settings.Global.getInt(mContentResolver, - Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) != BLUETOOTH_OFF; + int state = Settings.Global.getInt(mContentResolver, + Settings.Global.BLUETOOTH_ON, -1); + if (DBG) Slog.d(TAG, "Bluetooth persisted state: " + state); + return state != BLUETOOTH_OFF; } /** @@ -309,6 +312,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * */ private void persistBluetoothSetting(int value) { + if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); @@ -1366,7 +1370,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { { int prevState = msg.arg1; int newState = msg.arg2; - if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); + if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState =" + newState); mState = newState; bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF @@ -1678,6 +1682,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; + if (DBG) Slog.d(TAG, "bluetoothStateChangeHandler: " + prevState + " -> " + newState); if (prevState != newState) { //Notify all proxy objects first of adapter state change if (newState == BluetoothAdapter.STATE_BLE_ON || -- cgit v1.2.3 From 167b3c5e922186f5d4a6a63c737401c5f2051193 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 25 Oct 2016 10:47:51 -0700 Subject: Bluetooth: prevent enabling BLE in airplane mode Enabling BLE in airplane mode puts BluetoothManagerService in an unexpected state which causes Bluetooth to be on when airplane mode is disabled. Also fixes a bug where a crash of a BLE client would trigger a restart into ON mode. Test: SL4A BleBackgroundScanTest:test_airplane_mode_disables_ble Bug: 32140251 Bug: 32140271 Bug: 32369494 Change-Id: Ie65157e65c3a1ca914f567a7a0c631175d1e5835 (cherry picked from commit bd93b7b3dc6141cef6236cf0ca7dcc5acf5bfeed) --- .../com/android/server/bluetooth/BluetoothManagerService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6757fcce43..52be811fad 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -217,6 +217,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); + mEnable = false; mEnableExternal = false; } } catch (RemoteException e) { @@ -449,14 +450,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { - if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); + if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); if (mBleAppCount > 0) --mBleAppCount; if (mBleAppCount == 0) { if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { + if (mBluetooth != null && + mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; mBluetooth.onBrEdrDown(); } } catch (RemoteException e) { @@ -473,6 +476,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean isBleScanAlwaysAvailable() { + if (isAirplaneModeOn() && !mEnable) { + return false; + } try { return (Settings.Global.getInt(mContentResolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; -- cgit v1.2.3 From acb832d29d97138cfb925f00a2efd527ff912cac Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Wed, 29 Jun 2016 17:31:44 -0700 Subject: Add Bluetooth toggle prompts - framework If permission review is enabled toggling bluetoth on or off results in a user prompt to collect consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. Also added a configuration resource which controls whether permission review mode is enabled. By default it is not and an OEM can change this via an overlay. For now we also keep the old mechanism to toggle review mode via a build property which is still used and will be removed when clients have transitioned. bug:28715749 Change-Id: I94c5828ad6c8aa6b363622a26ff9da4fc2e2fac7 (cherry picked from commit 1fff3cdf4b1e4fc7920a5b76d4ae92eb6824325d) --- .../server/bluetooth/BluetoothManagerService.java | 83 ++++++++++++++++++---- 1 file changed, 69 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6575a2a86c..7875cb86ee 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -35,10 +35,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -151,6 +153,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final Map mProfileServices = new HashMap (); + private final boolean mPermissionReviewRequired; + private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); final String airplaneModeRadios = Settings.Global.getString(resolver, @@ -243,6 +247,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler = new BluetoothHandler(IoThread.get().getLooper()); mContext = context; + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); + mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -626,15 +635,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean enable() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"enable(): not allowed for non-active and non system user"); - return false; + public boolean enable(String packageName) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "enable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (!isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; + } } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + mState); @@ -650,14 +670,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean disable(boolean persist) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); + public boolean disable(String packageName, boolean persist) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"disable(): not allowed for non-active and non system user"); - return false; + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "disable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; + } } if (DBG) { @@ -678,6 +708,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + try { + // Validate the package only if we are going to use it + ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, + PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (applicationInfo.uid != callingUid) { + throw new SecurityException("Package " + callingUid + + " not in uid " + callingUid); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RemoteException(e.getMessage()); + } + return false; + } + public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + -- cgit v1.2.3 From 257f8fe85e626e8741ae626228214c2c34390aea Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 25 Oct 2016 10:47:51 -0700 Subject: Bluetooth: prevent enabling BLE in airplane mode Enabling BLE in airplane mode puts BluetoothManagerService in an unexpected state which causes Bluetooth to be on when airplane mode is disabled. Also fixes a bug where a crash of a BLE client would trigger a restart into ON mode. Test: SL4A BleBackgroundScanTest:test_airplane_mode_disables_ble Bug: 32140251 Bug: 32140271 Bug: 32369494 Change-Id: Ie65157e65c3a1ca914f567a7a0c631175d1e5835 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 7875cb86ee..2a5b1946b9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -221,6 +221,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); + mEnable = false; mEnableExternal = false; } } catch (RemoteException e) { @@ -436,14 +437,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { - if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); + if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); if (mBleAppCount > 0) --mBleAppCount; if (mBleAppCount == 0) { if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { + if (mBluetooth != null && + mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; mBluetooth.onBrEdrDown(); } } catch (RemoteException e) { @@ -460,6 +463,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean isBleScanAlwaysAvailable() { + if (isAirplaneModeOn() && !mEnable) { + return false; + } try { return (Settings.Global.getInt(mContentResolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; -- cgit v1.2.3 From 73458a81e89e0f1955f326d8d29e710a9b4eb746 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 4 Nov 2016 11:23:46 -0600 Subject: Detect non-oneway calls leaving system_server. To protect system stability, any Binder calls leaving the system_server must carefully be performed using FLAG_ONEWAY (or the 'oneway' verb in AIDL) which prevents the call from blocking indefinitely on the remote process. In this CL, the system_server uses the new Binder.setWarnOnBlocking() method to enable detection by default for all remote Binder interfaces. It can also use Binder.allowBlocking() to allow blocking calls on certain remote interfaces that have been determined to be safe. This CL adds the 'oneway' verb to several interfaces and methods where it should have been added, and marks a handful of system ContentProviders as being safe to call into. Also, we assume that any services obtained from ServiceManager are part of the core OS, and are okay to make blocking calls to. Test: builds, boots, runs with minimal logs triggered Bug: 32715088 Change-Id: Ide476e120cb40436a94b7faf7615c943d691f4c0 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6456048485..9b3fac3d66 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1364,7 +1364,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { - mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); + mBluetoothGatt = IBluetoothGatt.Stub + .asInterface(Binder.allowBlocking(service)); onBluetoothGattServiceUp(); break; } // else must be SERVICE_IBLUETOOTH @@ -1374,7 +1375,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBinding = false; mBluetoothBinder = service; - mBluetooth = IBluetooth.Stub.asInterface(service); + mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service)); if (!isNameAndAddressSet()) { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); -- cgit v1.2.3 From 66ed856126f6c78f3e3e61ccdf2ff0881d67966c Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Wed, 9 Nov 2016 12:01:24 -0800 Subject: Bluetooth: BLE app tracking fixes Simplify tracking registered BLE Apps and clear the state when we try to recover bluetooth from starting to ON. Test: enable and disable bluetooth an LE-only app running Bug: 32609235 Change-Id: I3233bf8402a3c8fc4886ef21b1e9411bc78d4e2c --- .../server/bluetooth/BluetoothManagerService.java | 96 +++++++++++----------- 1 file changed, 46 insertions(+), 50 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 2a5b1946b9..5b365983f0 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -58,6 +58,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap; import java.util.Map; @@ -117,7 +118,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTHGATT = 2; private final Context mContext; - private static int mBleAppCount = 0; // Locks are not provided for mName and mAddress. // They are accessed in handler or broadcast receiver, same thread context. @@ -211,10 +211,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off - synchronized (this) { - mBleAppCount = 0; - mBleApps.clear(); - } + clearBleApps(); if (st == BluetoothAdapter.STATE_BLE_ON) { //if state is BLE_ON make sure you trigger disableBLE part try { @@ -438,28 +435,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); - if (mBleAppCount > 0) --mBleAppCount; - - if (mBleAppCount == 0) { - if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null && - mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { - mEnable = false; - mBluetooth.onBrEdrDown(); - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); + if (isBleAppPresent()) { + // Nothing to do, another app is here. + return; + } + if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null && + mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; + mBluetooth.onBrEdrDown(); } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } /** Internal death rec list */ - Map mBleApps = new HashMap(); + Map mBleApps = new ConcurrentHashMap(); @Override public boolean isBleScanAlwaysAvailable() { @@ -479,17 +476,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { ContentObserver contentObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange) { - if (!isBleScanAlwaysAvailable()) { - disableBleScanMode(); - clearBleApps(); - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) mBluetooth.onBrEdrDown(); - } catch (RemoteException e) { - Slog.e(TAG, "error when disabling bluetooth", e); - } finally { - mBluetoothLock.readLock().unlock(); - } + if (isBleScanAlwaysAvailable()) { + // Nothing to do + return; + } + // BLE scan is not available. + disableBleScanMode(); + clearBleApps(); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) mBluetooth.onBrEdrDown(); + } catch (RemoteException e) { + Slog.e(TAG, "error when disabling bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); } } }; @@ -525,9 +525,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { throw new IllegalArgumentException("Wake lock is already dead."); } mBleApps.put(token, deathRec); - synchronized (this) { - ++mBleAppCount; - } if (DBG) Slog.d(TAG, "Registered for death Notification"); } @@ -537,31 +534,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Unregister death recipient as the app goes away. token.unlinkToDeath(r, 0); mBleApps.remove(token); - synchronized (this) { - if (mBleAppCount > 0) --mBleAppCount; - } if (DBG) Slog.d(TAG, "Unregistered for death Notification"); } } - if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); - if (mBleAppCount == 0 && mEnable) { + int appCount = mBleApps.size(); + if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); + if (appCount == 0 && mEnable) { disableBleScanMode(); } - return mBleAppCount; + return appCount; } // Clear all apps using BLE scan only mode. private void clearBleApps() { - synchronized (this) { - mBleApps.clear(); - mBleAppCount = 0; - } + mBleApps.clear(); } /** @hide*/ public boolean isBleAppPresent() { - if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); - return (mBleAppCount > 0); + if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); + return mBleApps.size() > 0; } /** @@ -1417,12 +1409,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { - recoverBluetoothServiceFromError(); + recoverBluetoothServiceFromError(false); } if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { - recoverBluetoothServiceFromError(); + recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, // wait for the BT process to fully tear down and then force a restart @@ -1837,7 +1829,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { quietMode ? 1 : 0, 0)); } - private void recoverBluetoothServiceFromError() { + private void recoverBluetoothServiceFromError(boolean clearBle) { Slog.e(TAG,"recoverBluetoothServiceFromError"); try { mBluetoothLock.readLock().lock(); @@ -1875,6 +1867,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; + if (clearBle) { + clearBleApps(); + } + mEnable = false; if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { -- cgit v1.2.3 From cb9f281e420c261efb59ede7289c4334f3a440d4 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Wed, 9 Nov 2016 12:01:24 -0800 Subject: Bluetooth: BLE app tracking fixes Simplify tracking registered BLE Apps and clear the state when we try to recover bluetooth from starting to ON. Test: enable and disable bluetooth an LE-only app running Bug: 32609235 Change-Id: I3233bf8402a3c8fc4886ef21b1e9411bc78d4e2c --- .../server/bluetooth/BluetoothManagerService.java | 96 +++++++++++----------- 1 file changed, 46 insertions(+), 50 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 52be811fad..7bf8c743c8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -56,6 +56,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap; import java.util.Map; @@ -115,7 +116,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTHGATT = 2; private final Context mContext; - private static int mBleAppCount = 0; // Locks are not provided for mName and mAddress. // They are accessed in handler or broadcast receiver, same thread context. @@ -207,10 +207,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off - synchronized (this) { - mBleAppCount = 0; - mBleApps.clear(); - } + clearBleApps(); if (st == BluetoothAdapter.STATE_BLE_ON) { //if state is BLE_ON make sure you trigger disableBLE part try { @@ -451,28 +448,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { public void binderDied() { if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); - if (mBleAppCount > 0) --mBleAppCount; - - if (mBleAppCount == 0) { - if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null && - mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { - mEnable = false; - mBluetooth.onBrEdrDown(); - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); + if (isBleAppPresent()) { + // Nothing to do, another app is here. + return; + } + if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null && + mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; + mBluetooth.onBrEdrDown(); } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } /** Internal death rec list */ - Map mBleApps = new HashMap(); + Map mBleApps = new ConcurrentHashMap(); @Override public boolean isBleScanAlwaysAvailable() { @@ -492,17 +489,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { ContentObserver contentObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange) { - if (!isBleScanAlwaysAvailable()) { - disableBleScanMode(); - clearBleApps(); - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) mBluetooth.onBrEdrDown(); - } catch (RemoteException e) { - Slog.e(TAG, "error when disabling bluetooth", e); - } finally { - mBluetoothLock.readLock().unlock(); - } + if (isBleScanAlwaysAvailable()) { + // Nothing to do + return; + } + // BLE scan is not available. + disableBleScanMode(); + clearBleApps(); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) mBluetooth.onBrEdrDown(); + } catch (RemoteException e) { + Slog.e(TAG, "error when disabling bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); } } }; @@ -538,9 +538,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { throw new IllegalArgumentException("Wake lock is already dead."); } mBleApps.put(token, deathRec); - synchronized (this) { - ++mBleAppCount; - } if (DBG) Slog.d(TAG, "Registered for death Notification"); } @@ -550,31 +547,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Unregister death recipient as the app goes away. token.unlinkToDeath(r, 0); mBleApps.remove(token); - synchronized (this) { - if (mBleAppCount > 0) --mBleAppCount; - } if (DBG) Slog.d(TAG, "Unregistered for death Notification"); } } - if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount); - if (mBleAppCount == 0 && mEnable) { + int appCount = mBleApps.size(); + if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); + if (appCount == 0 && mEnable) { disableBleScanMode(); } - return mBleAppCount; + return appCount; } // Clear all apps using BLE scan only mode. private void clearBleApps() { - synchronized (this) { - mBleApps.clear(); - mBleAppCount = 0; - } + mBleApps.clear(); } /** @hide*/ public boolean isBleAppPresent() { - if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount); - return (mBleAppCount > 0); + if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); + return mBleApps.size() > 0; } /** @@ -1384,12 +1376,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { - recoverBluetoothServiceFromError(); + recoverBluetoothServiceFromError(false); } if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { - recoverBluetoothServiceFromError(); + recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, // wait for the BT process to fully tear down and then force a restart @@ -1805,7 +1797,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { quietMode ? 1 : 0, 0)); } - private void recoverBluetoothServiceFromError() { + private void recoverBluetoothServiceFromError(boolean clearBle) { Slog.e(TAG,"recoverBluetoothServiceFromError"); try { mBluetoothLock.readLock().lock(); @@ -1843,6 +1835,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; + if (clearBle) { + clearBleApps(); + } + mEnable = false; if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { -- cgit v1.2.3 From 5682fb80c9c84e215def90b2204ff25d2a6ba87b Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Wed, 29 Jun 2016 17:31:44 -0700 Subject: Add Bluetooth toggle prompts - framework If permission review is enabled toggling bluetoth on or off results in a user prompt to collect consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. Also added a configuration resource which controls whether permission review mode is enabled. By default it is not and an OEM can change this via an overlay. For now we also keep the old mechanism to toggle review mode via a build property which is still used and will be removed when clients have transitioned. bug:28715749 Change-Id: I94c5828ad6c8aa6b363622a26ff9da4fc2e2fac7 --- .../server/bluetooth/BluetoothManagerService.java | 83 ++++++++++++++++++---- 1 file changed, 69 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 52be811fad..a3af5c6430 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -35,10 +35,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -151,6 +153,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final Map mProfileServices = new HashMap (); + private final boolean mPermissionReviewRequired; + private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); final String airplaneModeRadios = Settings.Global.getString(resolver, @@ -244,6 +248,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler = new BluetoothHandler(IoThread.get().getLooper()); mContext = context; + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); + mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -654,15 +663,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean enable() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"enable(): not allowed for non-active and non system user"); - return false; + public boolean enable(String packageName) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "enable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (!isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; + } } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + mState); @@ -678,14 +698,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean disable(boolean persist) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); + public boolean disable(String packageName, boolean persist) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"disable(): not allowed for non-active and non system user"); - return false; + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "disable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; + } } if (DBG) { @@ -706,6 +736,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + try { + // Validate the package only if we are going to use it + ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, + PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (applicationInfo.uid != callingUid) { + throw new SecurityException("Package " + callingUid + + " not in uid " + callingUid); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RemoteException(e.getMessage()); + } + return false; + } + public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + -- cgit v1.2.3 From cea5b6c7bda3e3695c67e585e1e507351fabaa03 Mon Sep 17 00:00:00 2001 From: Lenka Trochtova Date: Fri, 2 Dec 2016 12:19:39 +0100 Subject: Introduce a new user restriction for disallowing Bluetooth. Only the device owner will be able to set the restriction and the restriction will prevent usage of Bluetooth on the entire device - i.e. in all the users. Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.UserRestrictionsTest Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Bug: 32895300 Merged-In: I2875cf178cb16eca1965d0ba965d1cd3d8db2ad5 Change-Id: I2875cf178cb16eca1965d0ba965d1cd3d8db2ad5 --- .../server/bluetooth/BluetoothManagerService.java | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index aa6afdfba0..75b2dd494b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -39,6 +39,7 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -49,6 +50,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.os.UserManagerInternal; +import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; @@ -172,6 +175,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final UserRestrictionsListener mUserRestrictionsListener = + new UserRestrictionsListener() { + @Override + public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, + Bundle prevRestrictions) { + final boolean bluetoothDisallowed = + newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + if ((mEnable || mEnableExternal) && bluetoothDisallowed) { + disable(true); + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -621,6 +637,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean enableNoAutoConnect() { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); + } + return false; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); @@ -643,6 +666,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable() { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG,"enable(): not enabling - bluetooth disallowed"); + } + return false; + } + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Slog.w(TAG,"enable(): not allowed for non-active and non system user"); @@ -804,6 +834,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ public void handleOnBootPhase() { if (DBG) Slog.d(TAG, "Bluetooth boot completed"); + UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); + if (isBluetoothDisallowed()) { + return; + } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); @@ -1846,6 +1882,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private boolean isBluetoothDisallowed() { + long callingIdentity = Binder.clearCallingIdentity(); + try { + return mContext.getSystemService(UserManager.class) + .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); -- cgit v1.2.3 From 7d22b5dd649d59644a1fab5cbe86a2f32f9500b3 Mon Sep 17 00:00:00 2001 From: Lenka Trochtova Date: Fri, 2 Dec 2016 12:19:39 +0100 Subject: Introduce a new user restriction for disallowing Bluetooth. Only the device owner will be able to set the restriction and the restriction will prevent usage of Bluetooth on the entire device - i.e. in all the users. Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.UserRestrictionsTest Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Bug: 32895300 Change-Id: I2875cf178cb16eca1965d0ba965d1cd3d8db2ad5 --- .../server/bluetooth/BluetoothManagerService.java | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f7068cf3fb..b0c560353d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -42,6 +42,7 @@ import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -52,6 +53,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.os.UserManagerInternal; +import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; @@ -177,6 +180,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final UserRestrictionsListener mUserRestrictionsListener = + new UserRestrictionsListener() { + @Override + public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, + Bundle prevRestrictions) { + final boolean bluetoothDisallowed = + newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + if ((mEnable || mEnableExternal) && bluetoothDisallowed) { + try { + disable(null, true); + } catch (RemoteException e) { + Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener", + e); + } + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -634,6 +655,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean enableNoAutoConnect() { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); + } + return false; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); @@ -659,6 +687,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { final int callingUid = Binder.getCallingUid(); final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG,"enable(): not enabling - bluetooth disallowed"); + } + return false; + } + if (!callerSystem) { if (!checkIfCallerIsForegroundUser()) { Slog.w(TAG, "enable(): not allowed for non-active and non system user"); @@ -872,6 +907,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ public void handleOnBootPhase() { if (DBG) Slog.d(TAG, "Bluetooth boot completed"); + UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); + if (isBluetoothDisallowed()) { + return; + } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); @@ -1916,6 +1957,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private boolean isBluetoothDisallowed() { + long callingIdentity = Binder.clearCallingIdentity(); + try { + return mContext.getSystemService(UserManager.class) + .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); -- cgit v1.2.3 From 45b8ffba5f29180a91f0d13429135d8a608419e6 Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Wed, 29 Jun 2016 17:31:44 -0700 Subject: DO NOT MERGE Add Bluetooth toggle prompts - framework If permission review is enabled toggling bluetoth on or off results in a user prompt to collect consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. Also added a configuration resource which controls whether permission review mode is enabled. By default it is not and an OEM can change this via an overlay. For now we also keep the old mechanism to toggle review mode via a build property which is still used and will be removed when clients have transitioned. bug:28715749 Change-Id: I77bca2305f9d0f20034b2c8fc5b58e0565d5e617 --- .../server/bluetooth/BluetoothManagerService.java | 90 ++++++++++++++++++---- 1 file changed, 75 insertions(+), 15 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 75b2dd494b..5cf9eead5d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -35,11 +35,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; import android.os.Bundle; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -154,6 +156,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final Map mProfileServices = new HashMap (); + private final boolean mPermissionReviewRequired; + private void registerForAirplaneMode(IntentFilter filter) { final ContentResolver resolver = mContext.getContentResolver(); final String airplaneModeRadios = Settings.Global.getString(resolver, @@ -183,7 +187,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { final boolean bluetoothDisallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); if ((mEnable || mEnableExternal) && bluetoothDisallowed) { - disable(true); + try { + disable("android.os.UserManagerInternal", true); + } catch (RemoteException e) { + // Shouldn't happen: startConsentUiIfNeeded not called + // when from system. + } } } }; @@ -257,6 +266,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler = new BluetoothHandler(IoThread.get().getLooper()); mContext = context; + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); + mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -665,7 +679,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean enable() { + public boolean enable(String packageName) throws RemoteException { if (isBluetoothDisallowed()) { if (DBG) { Slog.d(TAG,"enable(): not enabling - bluetooth disallowed"); @@ -673,14 +687,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"enable(): not allowed for non-active and non system user"); - return false; + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "enable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (!isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; + } } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + mState); @@ -696,14 +721,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean disable(boolean persist) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); + public boolean disable(String packageName, boolean persist) throws RemoteException { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"disable(): not allowed for non-active and non system user"); - return false; + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "disable(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); + + if (isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; + } } if (DBG) { @@ -724,6 +759,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + try { + // Validate the package only if we are going to use it + ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, + PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (applicationInfo.uid != callingUid) { + throw new SecurityException("Package " + callingUid + + " not in uid " + callingUid); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RemoteException(e.getMessage()); + } + return false; + } + public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + -- cgit v1.2.3 From f46373a3b2c3218fa95b0cb4cb8fd9c2c605df16 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 13 Dec 2016 10:51:02 -0800 Subject: Bluetooth: log message improvements Some log improvements: - Reduce logspam - Use names for states in logs instead of numbers - Be more consistent with messages Also remove some commented out dead code. Test: run on phone, observe more useful logs Change-Id: I32163278e148be144c03d4e8aaf0eb761226c94c --- .../server/bluetooth/BluetoothManagerService.java | 239 ++++++++++----------- 1 file changed, 118 insertions(+), 121 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 5cf9eead5d..417531217b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -104,6 +104,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_USER_UNLOCKED = 301; private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; + private static final int MAX_SAVE_RETRIES = 3; private static final int MAX_ERROR_RESTART_RETRIES = 6; @@ -228,7 +229,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - Slog.d(TAG, "state" + st); + Slog.d(TAG, "State " + BluetoothAdapter.nameForState(st)); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off @@ -422,6 +423,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (callback == null) { + Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); + return; + } Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; mHandler.sendMessage(msg); @@ -430,6 +435,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (callback == null) { + Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); + return; + } Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; mHandler.sendMessage(msg); @@ -456,7 +465,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public int getState() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG, "getState(): not allowed for non-active and non system user"); + Slog.w(TAG, "getState(): report OFF for non-active and non system user"); return BluetoothAdapter.STATE_OFF; } @@ -708,7 +717,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + - " mBinding = " + mBinding + " mState = " + mState); + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); } synchronized(mReceiver) { @@ -787,7 +797,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + - " mBinding = " + mBinding); + " mBinding = " + mBinding + " mUnbinding = " + mUnbinding); } try { @@ -803,16 +813,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException re) { Slog.e(TAG, "Unable to unregister BluetoothCallback",re); } - - if (DBG) Slog.d(TAG, "Sending unbind request."); mBluetoothBinder = null; mBluetooth = null; - //Unbind mContext.unbindService(mConnection); mUnbinding = false; mBinding = false; } else { - mUnbinding=false; + mUnbinding = false; } mBluetoothGatt = null; } finally { @@ -1088,7 +1095,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { - if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); try { int n = mCallbacks.beginBroadcast(); Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); @@ -1107,7 +1113,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { - if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); try { int n = mCallbacks.beginBroadcast(); Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); @@ -1179,34 +1184,33 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private class BluetoothServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, IBinder service) { - if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); + public void onServiceConnected(ComponentName componentName, IBinder service) { + String name = componentName.getClassName(); + if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); - // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { - if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { + if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; - // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { - } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { + } else if (name.equals("com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { - Slog.e(TAG, "Unknown service connected: " + className.getClassName()); + Slog.e(TAG, "Unknown service connected: " + name); return; } msg.obj = service; mHandler.sendMessage(msg); } - public void onServiceDisconnected(ComponentName className) { - // Called if we unexpected disconnected. - if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + - className.getClassName()); + public void onServiceDisconnected(ComponentName componentName) { + // Called if we unexpectedly disconnect. + String name = componentName.getClassName(); + if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); - if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { + if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; - } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { + } else if (name.equals("com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { - Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); + Slog.e(TAG, "Unknown service disconnected: " + name); return; } mHandler.sendMessage(msg); @@ -1224,7 +1228,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void handleMessage(Message msg) { - if (DBG) Slog.d (TAG, "Message: " + msg.what); switch (msg.what) { case MESSAGE_GET_NAME_AND_ADDRESS: if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); @@ -1262,7 +1265,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_ENABLE: if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1312,6 +1315,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_DISABLE: + if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { waitForOnOff(true, false); @@ -1327,31 +1331,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_REGISTER_ADAPTER: { IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - boolean added = mCallbacks.register(callback); - Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); - } + mCallbacks.register(callback); break; + } case MESSAGE_UNREGISTER_ADAPTER: { IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - boolean removed = mCallbacks.unregister(callback); - Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); + mCallbacks.unregister(callback); break; } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - if (callback != null) { - mStateChangeCallbacks.register(callback); - } + mStateChangeCallbacks.register(callback); break; } case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - if (callback != null) { - mStateChangeCallbacks.unregister(callback); - } + mStateChangeCallbacks.unregister(callback); break; } case MESSAGE_ADD_PROXY_DELAYED: @@ -1424,13 +1422,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Do enable request try { if (mQuietEnable == false) { - if(!mBluetooth.enable()) { + if (!mBluetooth.enable()) { Slog.e(TAG,"IBluetooth.enable() returned false"); } - } - else - { - if(!mBluetooth.enableNoAutoConnect()) { + } else { + if (!mBluetooth.enableNoAutoConnect()) { Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); } } @@ -1448,19 +1444,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; } - case MESSAGE_TIMEOUT_BIND: { - Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); - mBluetoothLock.writeLock().lock(); - mBinding = false; - mBluetoothLock.writeLock().unlock(); - - break; - } case MESSAGE_BLUETOOTH_STATE_CHANGE: { int prevState = msg.arg1; int newState = msg.arg2; - if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); + if (DBG) { + Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } mState = newState; bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF @@ -1500,7 +1491,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { - Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); + Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); try { mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTH) { @@ -1511,7 +1502,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothGatt = null; break; } else { - Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); + Slog.e(TAG, "Unknown argument for service disconnect!"); break; } } finally { @@ -1548,8 +1539,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_RESTART_BLUETOOTH_SERVICE: { - Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" - +" Restart IBluetooth service"); + Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); /* Enable without persisting the setting as it doesnt change when IBluetooth service restarts */ @@ -1557,7 +1547,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { handleEnable(mQuietEnable); break; } - + case MESSAGE_TIMEOUT_BIND: { + Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); + mBluetoothLock.writeLock().lock(); + mBinding = false; + mBluetoothLock.writeLock().unlock(); + break; + } case MESSAGE_TIMEOUT_UNBIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); @@ -1643,11 +1639,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } 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 + // if user is switched when service is binding retry after a delay mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); if (DBG) { - Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); + Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2); } } break; @@ -1748,7 +1743,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { parentUser == foregroundUser || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; - if (DBG) { + if (DBG && !valid) { Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + " parentUser=" + parentUser @@ -1761,7 +1756,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendBleStateChanged(int prevState, int newState) { - if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); + if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + + " > " + BluetoothAdapter.nameForState(newState)); // Send broadcast message to everyone else Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); @@ -1772,75 +1768,76 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; - if (prevState != newState) { - //Notify all proxy objects first of adapter state change - if (newState == BluetoothAdapter.STATE_BLE_ON || - newState == BluetoothAdapter.STATE_OFF) { - boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF - && newState == BluetoothAdapter.STATE_BLE_ON); - - if (newState == BluetoothAdapter.STATE_OFF) { - // If Bluetooth is off, send service down event to proxy objects, and unbind - if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); - sendBluetoothServiceDownCallback(); - unbindAndFinish(); - sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; - - } else if (!intermediate_off) { - // connect to GattService - if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); - if (mBluetoothGatt != null) { - if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); - onBluetoothGattServiceUp(); - } else { - if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_BLUETOOTH_LE)) { - Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); - } - } - sendBleStateChanged(prevState, newState); - //Don't broadcase this as std intent - isStandardBroadcast = false; - - } else if (intermediate_off){ - if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); - // For LE only mode, broadcast as is - sendBleStateChanged(prevState, newState); - sendBluetoothStateCallback(false); // BT is OFF for general users - // Broadcast as STATE_OFF - newState = BluetoothAdapter.STATE_OFF; - sendBrEdrDownCallback(); - } - } else if (newState == BluetoothAdapter.STATE_ON) { - boolean isUp = (newState==BluetoothAdapter.STATE_ON); - sendBluetoothStateCallback(isUp); + if (prevState == newState) { // No change. Nothing to do. + return; + } + // Notify all proxy objects first of adapter state change + if (newState == BluetoothAdapter.STATE_BLE_ON || + newState == BluetoothAdapter.STATE_OFF) { + boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF + && newState == BluetoothAdapter.STATE_BLE_ON); + + if (newState == BluetoothAdapter.STATE_OFF) { + // If Bluetooth is off, send service down event to proxy objects, and unbind + if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down"); + sendBluetoothServiceDownCallback(); + unbindAndFinish(); sendBleStateChanged(prevState, newState); + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || - newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + } else if (!intermediate_off) { + // connect to GattService + if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); + if (mBluetoothGatt != null) { + if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); + onBluetoothGattServiceUp(); + } else { + if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); + if (mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_BLUETOOTH_LE)) { + Intent i = new Intent(IBluetoothGatt.class.getName()); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); + } + } sendBleStateChanged(prevState, newState); + //Don't broadcase this as std intent isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_TURNING_ON || - newState == BluetoothAdapter.STATE_TURNING_OFF) { + } else if (intermediate_off) { + if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); + // For LE only mode, broadcast as is sendBleStateChanged(prevState, newState); + sendBluetoothStateCallback(false); // BT is OFF for general users + // Broadcast as STATE_OFF + newState = BluetoothAdapter.STATE_OFF; + sendBrEdrDownCallback(); } + } else if (newState == BluetoothAdapter.STATE_ON) { + boolean isUp = (newState == BluetoothAdapter.STATE_ON); + sendBluetoothStateCallback(isUp); + sendBleStateChanged(prevState, newState); - if (isStandardBroadcast) { - if (prevState == BluetoothAdapter.STATE_BLE_ON) { - // Show prevState of BLE_ON as OFF to standard users - prevState = BluetoothAdapter.STATE_OFF; - } - 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); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || + newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + sendBleStateChanged(prevState, newState); + isStandardBroadcast = false; + + } else if (newState == BluetoothAdapter.STATE_TURNING_ON || + newState == BluetoothAdapter.STATE_TURNING_OFF) { + sendBleStateChanged(prevState, newState); + } + + if (isStandardBroadcast) { + if (prevState == BluetoothAdapter.STATE_BLE_ON) { + // Show prevState of BLE_ON as OFF to standard users + prevState = BluetoothAdapter.STATE_OFF; } + 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); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } } -- cgit v1.2.3 From fbccc787db465e1fac9f23a068811862a44c1171 Mon Sep 17 00:00:00 2001 From: Ivan Podogov Date: Mon, 5 Dec 2016 16:46:52 +0000 Subject: In permission review mode, always request user's consent to toggle BT. Bug: 33155221 Change-Id: Ic1ed987bbaf282892a2aef354a8ca0add2c829ba --- .../server/bluetooth/BluetoothManagerService.java | 24 ++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index a3af5c6430..bfbd8cb38d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -676,9 +676,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + if (!isEnabled() && mPermissionReviewRequired) { + startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE); return false; } } @@ -711,9 +710,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + if (isEnabled() && mPermissionReviewRequired) { + startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE); return false; } } @@ -736,8 +734,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, - int callingUid, String intentAction) throws RemoteException { + private void startConsentUi(String packageName, int callingUid, String intentAction) + throws RemoteException { try { // Validate the package only if we are going to use it ApplicationInfo applicationInfo = mContext.getPackageManager() @@ -749,16 +747,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " not in uid " + callingUid); } - // Legacy apps in permission review mode trigger a user prompt - if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - Intent intent = new Intent(intentAction); - mContext.startActivity(intent); - return true; - } + // Permission review mode, trigger a user prompt + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); } catch (PackageManager.NameNotFoundException e) { throw new RemoteException(e.getMessage()); } - return false; } public void unbindAndFinish() { -- cgit v1.2.3 From 84109761aacb89103670e871d28e1bb8478843a7 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 13 Dec 2016 10:51:02 -0800 Subject: Bluetooth: log message improvements Some log improvements: - Reduce logspam - Use names for states in logs instead of numbers - Be more consistent with messages Also remove some commented out dead code. Test: run on phone, observe more useful logs Change-Id: I32163278e148be144c03d4e8aaf0eb761226c94c --- .../server/bluetooth/BluetoothManagerService.java | 240 ++++++++++----------- 1 file changed, 118 insertions(+), 122 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index dbb8e0f44b..b2e38d8675 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -101,6 +101,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_USER_UNLOCKED = 301; private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; + private static final int MAX_SAVE_RETRIES = 3; private static final int MAX_ERROR_RESTART_RETRIES = 6; @@ -207,7 +208,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - Slog.d(TAG, "Airplane Mode change - current state: " + st); + Slog.d(TAG, "State " + BluetoothAdapter.nameForState(st)); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off @@ -405,6 +406,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (callback == null) { + Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); + return; + } Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; mHandler.sendMessage(msg); @@ -413,6 +418,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (callback == null) { + Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); + return; + } Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; mHandler.sendMessage(msg); @@ -439,7 +448,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public int getState() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG, "getState(): not allowed for non-active and non system user"); + Slog.w(TAG, "getState(): report OFF for non-active and non system user"); return BluetoothAdapter.STATE_OFF; } @@ -677,7 +686,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + - " mBinding = " + mBinding + " mState = " + mState); + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); } synchronized(mReceiver) { @@ -756,7 +766,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindAndFinish() { if (DBG) { Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + - " mBinding = " + mBinding); + " mBinding = " + mBinding + " mUnbinding = " + mUnbinding); } try { @@ -772,16 +782,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException re) { Slog.e(TAG, "Unable to unregister BluetoothCallback",re); } - - if (DBG) Slog.d(TAG, "Sending unbind request."); mBluetoothBinder = null; mBluetooth = null; - //Unbind mContext.unbindService(mConnection); mUnbinding = false; mBinding = false; } else { - mUnbinding=false; + mUnbinding = false; } mBluetoothGatt = null; } finally { @@ -1051,7 +1058,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { - if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks"); try { int n = mCallbacks.beginBroadcast(); Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); @@ -1070,7 +1076,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { - if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks"); try { int n = mCallbacks.beginBroadcast(); Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); @@ -1142,34 +1147,33 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private class BluetoothServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, IBinder service) { - if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); + public void onServiceConnected(ComponentName componentName, IBinder service) { + String name = componentName.getClassName(); + if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); - // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { - if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { + if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; - // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { - } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { + } else if (name.equals("com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { - Slog.e(TAG, "Unknown service connected: " + className.getClassName()); + Slog.e(TAG, "Unknown service connected: " + name); return; } msg.obj = service; mHandler.sendMessage(msg); } - public void onServiceDisconnected(ComponentName className) { - // Called if we unexpected disconnected. - if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + - className.getClassName()); + public void onServiceDisconnected(ComponentName componentName) { + // Called if we unexpectedly disconnect. + String name = componentName.getClassName(); + if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); - if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { + if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; - } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { + } else if (name.equals("com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { - Slog.e(TAG, "Unknown service disconnected: " + className.getClassName()); + Slog.e(TAG, "Unknown service disconnected: " + name); return; } mHandler.sendMessage(msg); @@ -1187,7 +1191,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void handleMessage(Message msg) { - if (DBG) Slog.d (TAG, "Message: " + msg.what); switch (msg.what) { case MESSAGE_GET_NAME_AND_ADDRESS: if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); @@ -1225,7 +1228,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_ENABLE: if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1275,6 +1278,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_DISABLE: + if (DBG) Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { waitForOnOff(true, false); @@ -1290,31 +1294,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_REGISTER_ADAPTER: { IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - boolean added = mCallbacks.register(callback); - Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); - } + mCallbacks.register(callback); break; + } case MESSAGE_UNREGISTER_ADAPTER: { IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - boolean removed = mCallbacks.unregister(callback); - Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); + mCallbacks.unregister(callback); break; } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - if (callback != null) { - mStateChangeCallbacks.register(callback); - } + mStateChangeCallbacks.register(callback); break; } case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - if (callback != null) { - mStateChangeCallbacks.unregister(callback); - } + mStateChangeCallbacks.unregister(callback); break; } case MESSAGE_ADD_PROXY_DELAYED: @@ -1387,13 +1385,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Do enable request try { if (mQuietEnable == false) { - if(!mBluetooth.enable()) { + if (!mBluetooth.enable()) { Slog.e(TAG,"IBluetooth.enable() returned false"); } - } - else - { - if(!mBluetooth.enableNoAutoConnect()) { + } else { + if (!mBluetooth.enableNoAutoConnect()) { Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); } } @@ -1411,19 +1407,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; } - case MESSAGE_TIMEOUT_BIND: { - Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); - mBluetoothLock.writeLock().lock(); - mBinding = false; - mBluetoothLock.writeLock().unlock(); - - break; - } case MESSAGE_BLUETOOTH_STATE_CHANGE: { int prevState = msg.arg1; int newState = msg.arg2; - if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState =" + newState); + if (DBG) { + Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } mState = newState; bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF @@ -1463,7 +1454,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { - Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); + Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); try { mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTH) { @@ -1474,7 +1465,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothGatt = null; break; } else { - Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); + Slog.e(TAG, "Unknown argument for service disconnect!"); break; } } finally { @@ -1511,8 +1502,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_RESTART_BLUETOOTH_SERVICE: { - Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" - +" Restart IBluetooth service"); + Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); /* Enable without persisting the setting as it doesnt change when IBluetooth service restarts */ @@ -1520,7 +1510,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { handleEnable(mQuietEnable); break; } - + case MESSAGE_TIMEOUT_BIND: { + Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); + mBluetoothLock.writeLock().lock(); + mBinding = false; + mBluetoothLock.writeLock().unlock(); + break; + } case MESSAGE_TIMEOUT_UNBIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); @@ -1606,11 +1602,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } 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 + // if user is switched when service is binding retry after a delay mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); if (DBG) { - Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); + Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2); } } break; @@ -1711,7 +1706,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { parentUser == foregroundUser || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; - if (DBG) { + if (DBG && !valid) { Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + " parentUser=" + parentUser @@ -1724,7 +1719,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendBleStateChanged(int prevState, int newState) { - if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState); + if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + + " > " + BluetoothAdapter.nameForState(newState)); // Send broadcast message to everyone else Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); @@ -1735,76 +1731,76 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; - if (DBG) Slog.d(TAG, "bluetoothStateChangeHandler: " + prevState + " -> " + newState); - if (prevState != newState) { - //Notify all proxy objects first of adapter state change - if (newState == BluetoothAdapter.STATE_BLE_ON || - newState == BluetoothAdapter.STATE_OFF) { - boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF - && newState == BluetoothAdapter.STATE_BLE_ON); - - if (newState == BluetoothAdapter.STATE_OFF) { - // If Bluetooth is off, send service down event to proxy objects, and unbind - if (DBG) Slog.d(TAG, "Bluetooth is complete turn off"); - sendBluetoothServiceDownCallback(); - unbindAndFinish(); - sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; - - } else if (!intermediate_off) { - // connect to GattService - if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); - if (mBluetoothGatt != null) { - if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); - onBluetoothGattServiceUp(); - } else { - if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_BLUETOOTH_LE)) { - Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); - } - } - sendBleStateChanged(prevState, newState); - //Don't broadcase this as std intent - isStandardBroadcast = false; - - } else if (intermediate_off){ - if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); - // For LE only mode, broadcast as is - sendBleStateChanged(prevState, newState); - sendBluetoothStateCallback(false); // BT is OFF for general users - // Broadcast as STATE_OFF - newState = BluetoothAdapter.STATE_OFF; - sendBrEdrDownCallback(); - } - } else if (newState == BluetoothAdapter.STATE_ON) { - boolean isUp = (newState==BluetoothAdapter.STATE_ON); - sendBluetoothStateCallback(isUp); + if (prevState == newState) { // No change. Nothing to do. + return; + } + // Notify all proxy objects first of adapter state change + if (newState == BluetoothAdapter.STATE_BLE_ON || + newState == BluetoothAdapter.STATE_OFF) { + boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF + && newState == BluetoothAdapter.STATE_BLE_ON); + + if (newState == BluetoothAdapter.STATE_OFF) { + // If Bluetooth is off, send service down event to proxy objects, and unbind + if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down"); + sendBluetoothServiceDownCallback(); + unbindAndFinish(); sendBleStateChanged(prevState, newState); + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || - newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + } else if (!intermediate_off) { + // connect to GattService + if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); + if (mBluetoothGatt != null) { + if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); + onBluetoothGattServiceUp(); + } else { + if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); + if (mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_BLUETOOTH_LE)) { + Intent i = new Intent(IBluetoothGatt.class.getName()); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); + } + } sendBleStateChanged(prevState, newState); + //Don't broadcase this as std intent isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_TURNING_ON || - newState == BluetoothAdapter.STATE_TURNING_OFF) { + } else if (intermediate_off) { + if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); + // For LE only mode, broadcast as is sendBleStateChanged(prevState, newState); + sendBluetoothStateCallback(false); // BT is OFF for general users + // Broadcast as STATE_OFF + newState = BluetoothAdapter.STATE_OFF; + sendBrEdrDownCallback(); } + } else if (newState == BluetoothAdapter.STATE_ON) { + boolean isUp = (newState == BluetoothAdapter.STATE_ON); + sendBluetoothStateCallback(isUp); + sendBleStateChanged(prevState, newState); - if (isStandardBroadcast) { - if (prevState == BluetoothAdapter.STATE_BLE_ON) { - // Show prevState of BLE_ON as OFF to standard users - prevState = BluetoothAdapter.STATE_OFF; - } - 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); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || + newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + sendBleStateChanged(prevState, newState); + isStandardBroadcast = false; + + } else if (newState == BluetoothAdapter.STATE_TURNING_ON || + newState == BluetoothAdapter.STATE_TURNING_OFF) { + sendBleStateChanged(prevState, newState); + } + + if (isStandardBroadcast) { + if (prevState == BluetoothAdapter.STATE_BLE_ON) { + // Show prevState of BLE_ON as OFF to standard users + prevState = BluetoothAdapter.STATE_OFF; } + 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); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } } -- cgit v1.2.3 From b5776f141a07450d29e4558083ce2bb1e087c381 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Thu, 15 Dec 2016 13:51:30 -0800 Subject: Bluetooth: fix issues re-enabling after crash When Bluetooth crashes, sometimes an LE app restarts it before ActivityManager gets a chance. In this case, the Bluetooth manager would assume the state should be LE only and did not continue to fully enabled. Luckily in this case the persisted system state is also ON. Use the persisted state as information about whether we should be fully enabled. Test: basic sanity check, forced crash of BT Bug: 33632976 Change-Id: I546d7abccb82a26fcca2eb70d6d7c76e9510404e --- .../server/bluetooth/BluetoothManagerService.java | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b2e38d8675..9b21208391 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -317,13 +317,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Save the Bluetooth on/off state - * */ private void persistBluetoothSetting(int value) { if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value); + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); + Binder.restoreCallingIdentity(callingIdentity); } /** @@ -588,20 +590,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } /** - * Action taken when GattService is turned off + * Action taken when GattService is turned on */ private void onBluetoothGattServiceUp() { if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); try { mBluetoothLock.readLock().lock(); - if (isBleAppPresent() == false && mBluetooth != null - && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + if (mBluetooth == null) { + if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); + return; + } + int st = mBluetooth.getState(); + if (st != BluetoothAdapter.STATE_BLE_ON) { + if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + + BluetoothAdapter.nameForState(st)); + return; + } + if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { + // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); - - // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - Binder.restoreCallingIdentity(callingIdentity); } } catch (RemoteException e) { Slog.e(TAG,"Unable to call onServiceUp", e); @@ -727,10 +735,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized(mReceiver) { if (persist) { - // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_OFF); - Binder.restoreCallingIdentity(callingIdentity); } mEnableExternal = false; sendDisableMsg(); -- cgit v1.2.3 From 0e22d63c17545b97edb4b8181204d7676c047efd Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Thu, 15 Dec 2016 13:51:30 -0800 Subject: Bluetooth: fix issues re-enabling after crash When Bluetooth crashes, sometimes an LE app restarts it before ActivityManager gets a chance. In this case, the Bluetooth manager would assume the state should be LE only and did not continue to fully enabled. Luckily in this case the persisted system state is also ON. Use the persisted state as information about whether we should be fully enabled. Test: basic sanity check, forced crash of BT Bug: 33632976 Change-Id: I546d7abccb82a26fcca2eb70d6d7c76e9510404e --- .../server/bluetooth/BluetoothManagerService.java | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 417531217b..1035ac8f7c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -335,12 +335,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Save the Bluetooth on/off state - * */ private void persistBluetoothSetting(int value) { + if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value); + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); + Binder.restoreCallingIdentity(callingIdentity); } /** @@ -605,20 +608,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } /** - * Action taken when GattService is turned off + * Action taken when GattService is turned on */ private void onBluetoothGattServiceUp() { if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); try { mBluetoothLock.readLock().lock(); - if (isBleAppPresent() == false && mBluetooth != null - && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + if (mBluetooth == null) { + if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); + return; + } + int st = mBluetooth.getState(); + if (st != BluetoothAdapter.STATE_BLE_ON) { + if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + + BluetoothAdapter.nameForState(st)); + return; + } + if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { + // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); - - // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - Binder.restoreCallingIdentity(callingIdentity); } } catch (RemoteException e) { Slog.e(TAG,"Unable to call onServiceUp", e); @@ -758,10 +767,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized(mReceiver) { if (persist) { - // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_OFF); - Binder.restoreCallingIdentity(callingIdentity); } mEnableExternal = false; sendDisableMsg(); -- cgit v1.2.3 From dd034c272c56955594f8a779a1f8b4ced8d4b41f Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 20 Dec 2016 11:21:12 -0800 Subject: Bluetooth: persist state when turning on from BLE Test: in BLE_ON state, turn to full on, reboot phone Bug: 33777496 Change-Id: I246d6ff0dcb81d66aa915ef443040d6fc3c98310 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 1035ac8f7c..86bbca7d07 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1282,8 +1282,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth != null) { int state = mBluetooth.getState(); if (state == BluetoothAdapter.STATE_BLE_ON) { - Slog.w(TAG, "BT is in BLE_ON State"); + Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); mBluetooth.onLeServiceUp(); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); break; } } -- cgit v1.2.3 From c5fdfc6d368ba26bc8b1a2fb4fb67c4e78c6b263 Mon Sep 17 00:00:00 2001 From: Ivan Podogov Date: Mon, 5 Dec 2016 16:46:52 +0000 Subject: In permission review mode, always request user's consent to toggle BT. Bug: 33155221 Test: Manual: flash the watch, check that the consent UI was displayed in both apps (the one with CompileSDK=21 and TargetSDK=21, and the one with CompileSDK=25 and TargetSDK=25). Change-Id: Ic1ed987bbaf282892a2aef354a8ca0add2c829ba --- .../server/bluetooth/BluetoothManagerService.java | 24 ++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 86bbca7d07..36ef3e9f04 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -717,9 +717,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + if (!isEnabled() && mPermissionReviewRequired) { + startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE); return false; } } @@ -753,9 +752,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + if (isEnabled() && mPermissionReviewRequired) { + startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE); return false; } } @@ -775,8 +773,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, - int callingUid, String intentAction) throws RemoteException { + private void startConsentUi(String packageName, int callingUid, String intentAction) + throws RemoteException { try { // Validate the package only if we are going to use it ApplicationInfo applicationInfo = mContext.getPackageManager() @@ -788,16 +786,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " not in uid " + callingUid); } - // Legacy apps in permission review mode trigger a user prompt - if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - Intent intent = new Intent(intentAction); - mContext.startActivity(intent); - return true; - } + // Permission review mode, trigger a user prompt + Intent intent = new Intent(intentAction); + mContext.startActivity(intent); } catch (PackageManager.NameNotFoundException e) { throw new RemoteException(e.getMessage()); } - return false; } public void unbindAndFinish() { -- cgit v1.2.3 From 6eb20469015829978b820ba63bc0d064e36d3697 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Wed, 28 Dec 2016 14:13:21 -0800 Subject: Bluetooth: track enabling in dumpsys Move basic state dumpsys to here from AdapterService. Track which apps are enabling and disabling Bluetooth, including BLE apps, and show the apps in the dumpsys logs. Test: start phone and enable/disable, take bug report Bug: 33692282 Change-Id: I6ea62ebdcfd7873d0be1bb5c5c520bbce3737a40 --- .../server/bluetooth/BluetoothManagerService.java | 174 +++++++++++++++------ 1 file changed, 125 insertions(+), 49 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 36ef3e9f04..adc59de87f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -57,14 +57,16 @@ import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; + class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -137,16 +139,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub { new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + // used inside handler thread private boolean mQuietEnable = false; - // configuarion from external IBinder call which is used to + private boolean mEnable; + + /** + * Used for tracking apps that enabled / disabled Bluetooth. + */ + private class ActiveLog { + private String mPackageName; + private boolean mEnable; + private long mTimestamp; + + public ActiveLog(String packageName, boolean enable, long timestamp) { + mPackageName = packageName; + mEnable = enable; + mTimestamp = timestamp; + } + + public long getTime() { + return mTimestamp; + } + + public String toString() { + return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) + + (mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName; + } + + } + + private LinkedList mActiveLogs; + + // configuration from external IBinder call which is used to // synchronize with broadcast receiver. private boolean mQuietEnableExternal; - // configuarion from external IBinder call which is used to - // synchronize with broadcast receiver. private boolean mEnableExternal; - // used inside handler thread - private boolean mEnable; + + // Map of apps registered to keep BLE scanning on. + private Map mBleApps = new ConcurrentHashMap(); + private int mState; private final BluetoothHandler mHandler; private int mErrorRecoveryRetryCounter; @@ -172,7 +204,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { + private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); @@ -251,12 +283,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting Slog.d(TAG, "Calling disable"); - sendDisableMsg(); + sendDisableMsg("airplane mode"); } } else if (mEnableExternal) { // enable without persisting the setting Slog.d(TAG, "Calling enable"); - sendEnableMsg(mQuietEnableExternal); + sendEnableMsg(mQuietEnableExternal, "airplane mode"); } } } @@ -272,6 +304,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { || context.getResources().getBoolean( com.android.internal.R.bool.config_permissionReviewRequired); + mActiveLogs = new LinkedList(); mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -298,15 +331,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = true; } - int sysUiUid = -1; + int systemUiUid = -1; try { - sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", + systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); } - mSystemUiUid = sysUiUid; + mSystemUiUid = systemUiUid; } /** @@ -484,8 +517,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } class ClientDeathRecipient implements IBinder.DeathRecipient { + private String mPackageName; + + public ClientDeathRecipient(String packageName) { + mPackageName = packageName; + } + public void binderDied() { - if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); + if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName); if (isBleAppPresent()) { // Nothing to do, another app is here. return; @@ -504,10 +543,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } } - } - /** Internal death rec list */ - Map mBleApps = new ConcurrentHashMap(); + public String getPackageName() { + return mPackageName; + } + } @Override public boolean isBleScanAlwaysAvailable() { @@ -565,28 +605,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable) { - if (enable) { - ClientDeathRecipient r = mBleApps.get(token); - if (r == null) { - ClientDeathRecipient deathRec = new ClientDeathRecipient(); - try { - token.linkToDeath(deathRec, 0); - } catch (RemoteException ex) { - throw new IllegalArgumentException("Wake lock is already dead."); - } - mBleApps.put(token, deathRec); - if (DBG) Slog.d(TAG, "Registered for death Notification"); - } - - } else { - ClientDeathRecipient r = mBleApps.get(token); - if (r != null) { - // Unregister death recipient as the app goes away. - token.unlinkToDeath(r, 0); - mBleApps.remove(token); - if (DBG) Slog.d(TAG, "Unregistered for death Notification"); + public int updateBleAppCount(IBinder token, boolean enable, String packageName) { + ClientDeathRecipient r = mBleApps.get(token); + if (r == null && enable) { + ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); + try { + token.linkToDeath(deathRec, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!"); } + mBleApps.put(token, deathRec); + if (DBG) Slog.d(TAG, "Registered for death of " + packageName); + } else if (!enable && r != null) { + // Unregister death recipient as the app goes away. + token.unlinkToDeath(r, 0); + mBleApps.remove(token); + if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName); } int appCount = mBleApps.size(); if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); @@ -601,7 +635,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBleApps.clear(); } - /** @hide*/ + /** @hide */ public boolean isBleAppPresent() { if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); return mBleApps.size() > 0; @@ -667,7 +701,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public boolean enableNoAutoConnect() + public boolean enableNoAutoConnect(String packageName) { if (isBluetoothDisallowed()) { if (DBG) { @@ -692,7 +726,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized(mReceiver) { mQuietEnableExternal = true; mEnableExternal = true; - sendEnableMsg(true); + sendEnableMsg(true, packageName); } return true; } @@ -724,7 +758,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (DBG) { - Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + + Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + BluetoothAdapter.nameForState(mState)); } @@ -733,7 +767,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false); + sendEnableMsg(false, packageName); } if (DBG) Slog.d(TAG, "enable returning"); return true; @@ -768,7 +802,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_OFF); } mEnableExternal = false; - sendDisableMsg(); + sendDisableMsg(packageName); } return true; } @@ -909,7 +943,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal); + sendEnableMsg(mQuietEnableExternal, "system boot"); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); @@ -1877,13 +1911,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - private void sendDisableMsg() { + private void sendDisableMsg(String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); + addActiveLog(packageName, false); } - private void sendEnableMsg(boolean quietMode) { + private void sendEnableMsg(boolean quietMode, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); + addActiveLog(packageName, true); + } + + private void addActiveLog(String packageName, boolean enable) { + synchronized (mActiveLogs) { + if (mActiveLogs.size() > 10) { + mActiveLogs.remove(); + } + mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis())); + } } private void recoverBluetoothServiceFromError(boolean clearBle) { @@ -1954,19 +1999,50 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); String errorMsg = null; + + boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); + + if (!protoOut) { + writer.println("Bluetooth Status"); + writer.println(" enabled: " + isEnabled()); + writer.println(" state: " + BluetoothAdapter.nameForState(mState)); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName); + if (mEnable) { + long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime(); + String onDurationString = String.format("%02d:%02d:%02d.%03d", + (int)(onDuration / (1000 * 60 * 60)), + (int)((onDuration / (1000 * 60)) % 60), + (int)((onDuration / 1000) % 60), + (int)(onDuration % 1000)); + writer.println(" time since enabled: " + onDurationString + "\n"); + } + + writer.println("Enable log:"); + for (ActiveLog log : mActiveLogs) { + writer.println(log); + } + + writer.println("\n" + mBleApps.size() + " BLE Apps registered:"); + for (ClientDeathRecipient app : mBleApps.values()) { + writer.println(app.getPackageName()); + } + + writer.flush(); + } + if (mBluetoothBinder == null) { errorMsg = "Bluetooth Service not connected"; } else { try { mBluetoothBinder.dump(fd, args); } catch (RemoteException re) { - errorMsg = "RemoteException while calling Bluetooth Service"; + errorMsg = "RemoteException while dumping Bluetooth Service"; } } if (errorMsg != null) { // Silently return if we are extracting metrics in Protobuf format - if ((args.length > 0) && args[0].startsWith("--proto")) - return; + if (protoOut) return; writer.println(errorMsg); } } -- cgit v1.2.3 From ad5a1691081dc51857ab92d84bbcca287ad71da3 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Tue, 3 Jan 2017 11:37:38 -0800 Subject: Bluetooth: don't output dumpsys info twice Dumpsys info was printed in the "Application Services" section as well as the bluetooth_manager section. Add an argument to print so it prints from here, and doesn't in the other section. Test: run a bugreport, check in "APP SERVICES" section Bug: 29356402 Change-Id: I8adedaeac54c9a538c581459654dbdf96361e046 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index adc59de87f..4f43eac8b3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2029,6 +2029,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } writer.flush(); + if (args.length == 0) { + // Add arg to produce output + args = new String[1]; + args[0] = "--print"; + } } if (mBluetoothBinder == null) { -- cgit v1.2.3 From 093c05a8fd1f1b8bfa55fd4add02ab7af41875c3 Mon Sep 17 00:00:00 2001 From: Lenka Trochtova Date: Mon, 9 Jan 2017 19:48:51 +0100 Subject: Don't offer the BT sharing option to the user if BT is disallowed. Disable BluetoothOppLauncherActivity component if the UserManager#BLUETOOTH_DISALLOWED user restriction is set. Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Bug: 32895060 Change-Id: I4316843b2858aefa750f12a8a0e940424aa21a10 --- .../server/bluetooth/BluetoothManagerService.java | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 4f43eac8b3..f2e1fb6781 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -217,6 +217,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { + if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH) + && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) { + // The relevant restriction has not changed - do nothing. + return; + } final boolean bluetoothDisallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); if ((mEnable || mEnableExternal) && bluetoothDisallowed) { @@ -227,6 +232,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // when from system. } } + updateOppLauncherComponentState(bluetoothDisallowed); } }; @@ -938,7 +944,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); - if (isBluetoothDisallowed()) { + final boolean isBluetoothDisallowed = isBluetoothDisallowed(); + updateOppLauncherComponentState(isBluetoothDisallowed); + if (isBluetoothDisallowed) { return; } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { @@ -1995,6 +2003,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + /** + * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not + * offered to the user if Bluetooth is disallowed. Puts the component to its default state if + * Bluetooth is not disallowed. + * + * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user + * restriction was set. + */ + private void updateOppLauncherComponentState(boolean bluetoothDisallowed) { + final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", + "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); + final int newState = bluetoothDisallowed + ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED + : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; + mContext.getPackageManager() + .setComponentEnabledSetting(oppLauncherComponent, newState, 0); + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); -- cgit v1.2.3 From 2e05346f152c08fc6089bfdb387e7a363471cb98 Mon Sep 17 00:00:00 2001 From: Shijian Li Date: Wed, 11 Jan 2017 17:32:12 +0000 Subject: Sync the startConsentUiIfNeeded logics to master. We are missing the package name when starting the activity now. Bug: 34216066 Change-Id: Ic8c8576ce2c65bc554bbf4794e169838c2ccbbe1 --- .../server/bluetooth/BluetoothManagerService.java | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index bfbd8cb38d..d767c462c6 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -28,6 +28,7 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -676,8 +677,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired) { - startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE); + if (!isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_ENABLE)) { return false; } } @@ -710,8 +712,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired) { - startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE); + if (isEnabled() && mPermissionReviewRequired + && startConsentUiIfNeeded(packageName, callingUid, + BluetoothAdapter.ACTION_REQUEST_DISABLE)) { return false; } } @@ -734,8 +737,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private void startConsentUi(String packageName, int callingUid, String intentAction) - throws RemoteException { + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { try { // Validate the package only if we are going to use it ApplicationInfo applicationInfo = mContext.getPackageManager() @@ -747,9 +750,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " not in uid " + callingUid); } - // Permission review mode, trigger a user prompt Intent intent = new Intent(intentAction); - mContext.startActivity(intent); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + // Shouldn't happen + Slog.e(TAG, "Intent to handle action " + intentAction + " missing"); + return false; + } + return true; } catch (PackageManager.NameNotFoundException e) { throw new RemoteException(e.getMessage()); } -- cgit v1.2.3 From 4fcee874c9a959ac473a77764a9279a2d82521ed Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Thu, 12 Jan 2017 15:56:39 +0000 Subject: Revert "Don't offer the BT sharing option to the user if BT is disallowed." Causes boot loop issue: 02-15 02:31:59.785 770 770 E System : Caused by: java.lang.IllegalArgumentException: Unknown component: com.android.bluetooth/com.android.bluetooth.opp.BluetoothOppLauncherActivity 02-15 02:31:59.785 770 770 E System : .at com.android.server.pm.PackageManagerService.setEnabledSetting(PackageManagerService.java:18500) 02-15 02:31:59.785 770 770 E System : .at com.android.server.pm.PackageManagerService.setComponentEnabledSetting(PackageManagerService.java:18461) 02-15 02:31:59.785 770 770 E System : .at android.app.ApplicationPackageManager.setComponentEnabledSetting(ApplicationPackageManager.java:2129) 02-15 02:31:59.785 770 770 E System : .at com.android.server.BluetoothManagerService.updateOppLauncherComponentState(BluetoothManagerService.java:2036) This reverts commit 093c05a8fd1f1b8bfa55fd4add02ab7af41875c3. Change-Id: Ia079bb2fcc91bb5979a3840ab50b9d9ddda1cf24 --- .../server/bluetooth/BluetoothManagerService.java | 28 +--------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f2e1fb6781..4f43eac8b3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -217,11 +217,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { - if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH) - && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) { - // The relevant restriction has not changed - do nothing. - return; - } final boolean bluetoothDisallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); if ((mEnable || mEnableExternal) && bluetoothDisallowed) { @@ -232,7 +227,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // when from system. } } - updateOppLauncherComponentState(bluetoothDisallowed); } }; @@ -944,9 +938,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); - final boolean isBluetoothDisallowed = isBluetoothDisallowed(); - updateOppLauncherComponentState(isBluetoothDisallowed); - if (isBluetoothDisallowed) { + if (isBluetoothDisallowed()) { return; } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { @@ -2003,24 +1995,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - /** - * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not - * offered to the user if Bluetooth is disallowed. Puts the component to its default state if - * Bluetooth is not disallowed. - * - * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user - * restriction was set. - */ - private void updateOppLauncherComponentState(boolean bluetoothDisallowed) { - final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", - "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); - final int newState = bluetoothDisallowed - ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED - : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; - mContext.getPackageManager() - .setComponentEnabledSetting(oppLauncherComponent, newState, 0); - } - @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); -- cgit v1.2.3 From af9d9d4cf965c352a4bf41da53d13cf6fcf47bf3 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Wed, 18 Jan 2017 09:37:52 -0800 Subject: Bluetooth: fix indentation, formatting in dumpsys Before ====== Enable log: 01-17 09:43:18 Enabled by com.android.systemui 01-18 07:13:10 Disabled by com.andorid.systemui 1 BLE Apps registered: com.google.android.gms After ===== Enable log: 02-06 07:49:07 Enabled by system boot 02-06 07:49:35 Disabled by com.andorid.systemui 1 BLE App registered: com.google.android.gms Test: run bugreport, see differences in dumpsys Change-Id: I6086f7f97c1fcbdb860d70d9516fd5bf630a9f5e --- .../server/bluetooth/BluetoothManagerService.java | 27 +++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 4f43eac8b3..6e578b94d7 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2018,21 +2018,32 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" time since enabled: " + onDurationString + "\n"); } - writer.println("Enable log:"); - for (ActiveLog log : mActiveLogs) { - writer.println(log); + if (mActiveLogs.size() == 0) { + writer.println("Bluetooth never enabled!"); + } else { + writer.println("Enable log:"); + for (ActiveLog log : mActiveLogs) { + writer.println(" " + log); + } } - writer.println("\n" + mBleApps.size() + " BLE Apps registered:"); + String bleAppString = "No BLE Apps registered."; + if (mBleApps.size() == 1) { + bleAppString = "1 BLE App registered:"; + } else if (mBleApps.size() > 1) { + bleAppString = mBleApps.size() + " BLE Apps registered:"; + } + writer.println("\n" + bleAppString); for (ClientDeathRecipient app : mBleApps.values()) { - writer.println(app.getPackageName()); + writer.println(" " + app.getPackageName()); } + writer.println(""); writer.flush(); if (args.length == 0) { - // Add arg to produce output - args = new String[1]; - args[0] = "--print"; + // Add arg to produce output + args = new String[1]; + args[0] = "--print"; } } -- cgit v1.2.3 From 5e992dbcf18128d45f2d0e8602678ccf8c0903c7 Mon Sep 17 00:00:00 2001 From: Lenka Trochtova Date: Tue, 17 Jan 2017 10:35:49 +0100 Subject: Don't offer the BT sharing option to the user if BT is disallowed. Disable BluetoothOppLauncherActivity component if the UserManager#BLUETOOTH_DISALLOWED user restriction is set. Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases --test com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Bug: 32895060 Bug: 34239380 Change-Id: I3467c82881896f276f542583bb50807b5e27276b --- .../server/bluetooth/BluetoothManagerService.java | 39 +++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6e578b94d7..3b3ce073e0 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -49,6 +49,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -58,6 +59,8 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import com.android.server.pm.PackageManagerService; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.concurrent.ConcurrentHashMap; @@ -217,6 +220,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { + if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH) + && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) { + // The relevant restriction has not changed - do nothing. + return; + } final boolean bluetoothDisallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); if ((mEnable || mEnableExternal) && bluetoothDisallowed) { @@ -227,6 +235,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // when from system. } } + updateOppLauncherComponentState(bluetoothDisallowed); } }; @@ -938,7 +947,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); - if (isBluetoothDisallowed()) { + final boolean isBluetoothDisallowed = isBluetoothDisallowed(); + PackageManagerService packageManagerService = + (PackageManagerService) ServiceManager.getService("package"); + if (packageManagerService != null && !packageManagerService.isOnlyCoreApps()) { + updateOppLauncherComponentState(isBluetoothDisallowed); + } + if (isBluetoothDisallowed) { return; } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { @@ -1995,6 +2010,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + /** + * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not + * offered to the user if Bluetooth is disallowed. Puts the component to its default state if + * Bluetooth is not disallowed. + * + * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user + * restriction was set. + */ + private void updateOppLauncherComponentState(boolean bluetoothDisallowed) { + final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", + "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); + final int newState = bluetoothDisallowed + ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED + : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; + try { + mContext.getPackageManager() + .setComponentEnabledSetting(oppLauncherComponent, newState, 0); + } catch (Exception e) { + // The component was not found, do nothing. + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); -- cgit v1.2.3 From 2e57588a3beaf78cdd0269e2bb89d2ea1f22603c Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Fri, 24 Feb 2017 11:06:33 -0800 Subject: Bluetooth: fix enable log: display 24h time Test: adb bugreport at 1pm, observe 13:xx:yy instead of 01:xx:yy Change-Id: I172dcc63f0f43563ec692349a9434f63c55eac25 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 3b3ce073e0..66576b5b86 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -166,7 +166,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public String toString() { - return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) + + return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName; } -- cgit v1.2.3 From 391254850acb75735fc18f3e38ff20020d9acab6 Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Wed, 22 Feb 2017 12:23:15 -0800 Subject: Bluetooth: Use content observer for airplane mode We are making this switch as the airplane mode switch intent is going away. Fix: 35256299 Test: Toggle Airplane Mode Change-Id: I3b1e5bbdf689b0db98cfbb0ab377198d34f0ba05 --- .../server/bluetooth/BluetoothManagerService.java | 135 +++++++++++---------- 1 file changed, 68 insertions(+), 67 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index e8df38bb96..82d86ffd95 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -82,6 +82,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_SYSTEM_BOOT = "system boot"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save //Maximum msec to wait for service restart @@ -195,19 +197,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final boolean mPermissionReviewRequired; - private void registerForAirplaneMode(IntentFilter filter) { - final ContentResolver resolver = mContext.getContentResolver(); - final String airplaneModeRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_RADIOS); - final String toggleableRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); - boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : - airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); - if (mIsAirplaneSensitive) { - filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - } - } - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { @@ -240,6 +229,62 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { + @Override + public void onChange(boolean unused) { + synchronized(this) { + if (isBluetoothPersistedStateOn()) { + if (isAirplaneModeOn()) { + persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); + } else { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + } + + int st = BluetoothAdapter.STATE_OFF; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + st = mBluetooth.getState(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + return; + } finally { + mBluetoothLock.readLock().unlock(); + } + + Slog.d(TAG, "Airplane Mode change - current state: " + + BluetoothAdapter.nameForState(st)); + + if (isAirplaneModeOn()) { + // Clear registered LE apps to force shut-off + clearBleApps(); + + // If state is BLE_ON make sure we trigger disableBLE + if (st == BluetoothAdapter.STATE_BLE_ON) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + mEnable = false; + mEnableExternal = false; + } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + } else if (st == BluetoothAdapter.STATE_ON){ + sendDisableMsg(REASON_AIRPLANE_MODE); + } + } else if (mEnableExternal) { + sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE); + } + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -250,58 +295,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newName != null) { storeNameAndAddress(newName, null); } - } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { - synchronized(mReceiver) { - if (isBluetoothPersistedStateOn()) { - if (isAirplaneModeOn()) { - persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); - } else { - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - } - } - - int st = BluetoothAdapter.STATE_OFF; - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - st = mBluetooth.getState(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call getState", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - Slog.d(TAG, "Airplane Mode change - current state: " + - BluetoothAdapter.nameForState(st)); - - if (isAirplaneModeOn()) { - // Clear registered LE apps to force shut-off - clearBleApps(); - if (st == BluetoothAdapter.STATE_BLE_ON) { - //if state is BLE_ON make sure you trigger disableBLE part - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - mBluetooth.onBrEdrDown(); - mEnable = false; - mEnableExternal = false; - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - } else if (st == BluetoothAdapter.STATE_ON){ - // disable without persisting the setting - Slog.d(TAG, "Calling disable"); - sendDisableMsg("airplane mode"); - } - } else if (mEnableExternal) { - // enable without persisting the setting - Slog.d(TAG, "Calling enable"); - sendEnableMsg(mQuietEnableExternal, "airplane mode"); - } - } } } }; @@ -333,7 +326,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - registerForAirplaneMode(filter); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); @@ -342,6 +334,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = true; } + String airplaneModeRadios = Settings.Global.getString(mContentResolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + if (airplaneModeRadios == null || + airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), + true, mAirplaneModeObserver); + } + int systemUiUid = -1; try { systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", @@ -973,7 +974,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal, "system boot"); + sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); -- cgit v1.2.3 From 335e25c4291e90d490da28f8df15b96cf07fafb7 Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Wed, 22 Feb 2017 12:23:15 -0800 Subject: Bluetooth: Use content observer for airplane mode We are making this switch as the airplane mode switch intent is going away. Fix: 35256299 Test: Toggle Airplane Mode Change-Id: I3b1e5bbdf689b0db98cfbb0ab377198d34f0ba05 --- .../server/bluetooth/BluetoothManagerService.java | 134 +++++++++++---------- 1 file changed, 68 insertions(+), 66 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 66576b5b86..aff98edf58 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -81,6 +81,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_SYSTEM_BOOT = "system boot"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save //Maximum msec to wait for service restart @@ -194,19 +196,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final boolean mPermissionReviewRequired; - private void registerForAirplaneMode(IntentFilter filter) { - final ContentResolver resolver = mContext.getContentResolver(); - final String airplaneModeRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_RADIOS); - final String toggleableRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); - boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : - airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); - if (mIsAirplaneSensitive) { - filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - } - } - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { @@ -239,6 +228,62 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { + @Override + public void onChange(boolean unused) { + synchronized(this) { + if (isBluetoothPersistedStateOn()) { + if (isAirplaneModeOn()) { + persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); + } else { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + } + + int st = BluetoothAdapter.STATE_OFF; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + st = mBluetooth.getState(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + return; + } finally { + mBluetoothLock.readLock().unlock(); + } + + Slog.d(TAG, "Airplane Mode change - current state: " + + BluetoothAdapter.nameForState(st)); + + if (isAirplaneModeOn()) { + // Clear registered LE apps to force shut-off + clearBleApps(); + + // If state is BLE_ON make sure we trigger disableBLE + if (st == BluetoothAdapter.STATE_BLE_ON) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + mEnable = false; + mEnableExternal = false; + } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + } else if (st == BluetoothAdapter.STATE_ON){ + sendDisableMsg(REASON_AIRPLANE_MODE); + } + } else if (mEnableExternal) { + sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE); + } + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -249,57 +294,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newName != null) { storeNameAndAddress(newName, null); } - } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { - synchronized(mReceiver) { - if (isBluetoothPersistedStateOn()) { - if (isAirplaneModeOn()) { - persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); - } else { - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - } - } - - int st = BluetoothAdapter.STATE_OFF; - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - st = mBluetooth.getState(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call getState", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - Slog.d(TAG, "State " + BluetoothAdapter.nameForState(st)); - - if (isAirplaneModeOn()) { - // Clear registered LE apps to force shut-off - clearBleApps(); - if (st == BluetoothAdapter.STATE_BLE_ON) { - //if state is BLE_ON make sure you trigger disableBLE part - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - mBluetooth.onBrEdrDown(); - mEnable = false; - mEnableExternal = false; - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - } else if (st == BluetoothAdapter.STATE_ON){ - // disable without persisting the setting - Slog.d(TAG, "Calling disable"); - sendDisableMsg("airplane mode"); - } - } else if (mEnableExternal) { - // enable without persisting the setting - Slog.d(TAG, "Calling enable"); - sendEnableMsg(mQuietEnableExternal, "airplane mode"); - } - } } } }; @@ -332,7 +326,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - registerForAirplaneMode(filter); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); @@ -340,6 +333,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = true; } + String airplaneModeRadios = Settings.Global.getString(mContentResolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + if (airplaneModeRadios == null || + airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), + true, mAirplaneModeObserver); + } + int systemUiUid = -1; try { systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", @@ -958,7 +960,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal, "system boot"); + sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); -- cgit v1.2.3 From ae076ee2c3cf6db8ef980110952426bb73fa98d6 Mon Sep 17 00:00:00 2001 From: Martin Brabham Date: Mon, 27 Feb 2017 16:55:07 -0800 Subject: BluetoothManagerService: continue teardown when BLE apps registered When the adapter is toggled off; when there are BLE apps registered, a request is sent to unregister all of the BLE apps. Upon unregister each app will call through to this function via a callback. When this gets called if the ble app count is 0, we can disable everything. I am keeping track of the flag so that we know explicitly where we are coming from. Bug: 34707848 Test: Compile Change-Id: I9a8322a6fa918e7b410770894c257ec9f7d8d1f5 --- .../server/bluetooth/BluetoothManagerService.java | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index aff98edf58..5e9cf74818 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -638,6 +638,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (appCount == 0 && mEnable) { disableBleScanMode(); } + if (appCount == 0 && !mEnableExternal) { + sendBrEdrDownCallback(); + } return appCount; } @@ -693,7 +696,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } - if (isBleAppPresent() == false) { + if (isBleAppPresent()) { + // Need to stay at BLE ON. Disconnect all Gatt connections + try { + mBluetoothGatt.unregAll(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to disconnect all apps.", e); + } + } else { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) mBluetooth.onBrEdrDown(); @@ -702,14 +712,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - } else { - // Need to stay at BLE ON. Disconnect all Gatt connections - try { - mBluetoothGatt.unregAll(); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to disconnect all apps.", e); - } } + } public boolean enableNoAutoConnect(String packageName) -- cgit v1.2.3 From 90dd95ea51affa3517bf52a71b097fefb5867ae5 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Thu, 16 Mar 2017 18:10:59 -0700 Subject: Bluetooth: log unexpected crashes and restarts Add some reasons to the log when: - the Bluetooth stack crashes underneath us - user switches - we automatically restart List every instance of the stack crashing underneath us in the dumpsys. Clean up some unused constants. Test: notice a Bluetooth crash, adb bugreport Change-Id: I79195f0a574de1bf48a976d31c64084d3ce2e14a --- .../server/bluetooth/BluetoothManagerService.java | 47 +++++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 5e9cf74818..c7c133daa9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -76,15 +76,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; - private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; - private static final String EXTRA_ACTION="action"; + private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + + private static final int ACTIVE_LOG_MAX_SIZE = 20; + private static final int CRASH_LOG_MAX_SIZE = 100; private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_RESTARTED = "automatic restart"; + private static final String REASON_START_CRASH = "turn-on crash"; private static final String REASON_SYSTEM_BOOT = "system boot"; + private static final String REASON_UNEXPECTED = "unexpected crash"; + private static final String REASON_USER_SWITCH = "user switch"; + private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind - 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 wait for restart due to error @@ -149,6 +155,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mQuietEnable = false; private boolean mEnable; + private CharSequence timeToLog(long timestamp) { + return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp); + } + /** * Used for tracking apps that enabled / disabled Bluetooth. */ @@ -168,13 +178,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public String toString() { - return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) + - (mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName; + return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by " + + mPackageName; } } private LinkedList mActiveLogs; + private LinkedList mCrashTimestamps; + private int mCrashes; // configuration from external IBinder call which is used to // synchronize with broadcast receiver. @@ -308,6 +320,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { com.android.internal.R.bool.config_permissionReviewRequired); mActiveLogs = new LinkedList(); + mCrashTimestamps = new LinkedList(); + mCrashes = 0; mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -1565,6 +1579,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().unlock(); } + // log the unexpected crash + addCrashLog(); + addActiveLog(REASON_UNEXPECTED, false); if (mEnable) { mEnable = false; // Send a Bluetooth Restart message @@ -1600,6 +1617,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { it doesnt change when IBluetooth service restarts */ mEnable = true; + addActiveLog(REASON_RESTARTED, true); handleEnable(mQuietEnable); break; } @@ -1654,6 +1672,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { unbindAllBluetoothProfileServices(); // disable + addActiveLog(REASON_USER_SWITCH, false); handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, @@ -1691,6 +1710,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; // enable + addActiveLog(REASON_USER_SWITCH, true); handleEnable(mQuietEnable); } else if (mBinding || mBluetooth != null) { Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); @@ -1945,13 +1965,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void addActiveLog(String packageName, boolean enable) { synchronized (mActiveLogs) { - if (mActiveLogs.size() > 10) { + if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { mActiveLogs.remove(); } mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis())); } } + private void addCrashLog() { + synchronized (mCrashTimestamps) { + if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst(); + mCrashTimestamps.add(System.currentTimeMillis()); + mCrashes++; + } + } + private void recoverBluetoothServiceFromError(boolean clearBle) { Slog.e(TAG,"recoverBluetoothServiceFromError"); try { @@ -1969,6 +1997,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { SystemClock.sleep(500); // disable + addActiveLog(REASON_START_CRASH, false); handleDisable(); waitForOnOff(false, true); @@ -2070,6 +2099,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); + if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); + for (Long time : mCrashTimestamps) { + writer.println(" " + timeToLog(time.longValue())); + } + String bleAppString = "No BLE Apps registered."; if (mBleApps.size() == 1) { bleAppString = "1 BLE App registered:"; -- cgit v1.2.3 From a24e8db434d06e563d0aff77c77e5c7c02848d58 Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Wed, 22 Feb 2017 12:23:15 -0800 Subject: Bluetooth: Use content observer for airplane mode We are making this switch as the airplane mode switch intent is going away. Fix: 35256299 Test: Toggle Airplane Mode Change-Id: I3b1e5bbdf689b0db98cfbb0ab377198d34f0ba05 --- .../server/bluetooth/BluetoothManagerService.java | 135 +++++++++++---------- 1 file changed, 68 insertions(+), 67 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index afb4c07563..421e4a1c8d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -82,6 +82,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_SYSTEM_BOOT = "system boot"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save //Maximum msec to wait for service restart @@ -195,19 +197,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final boolean mPermissionReviewRequired; - private void registerForAirplaneMode(IntentFilter filter) { - final ContentResolver resolver = mContext.getContentResolver(); - final String airplaneModeRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_RADIOS); - final String toggleableRadios = Settings.Global.getString(resolver, - Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); - boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : - airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); - if (mIsAirplaneSensitive) { - filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - } - } - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { @@ -240,6 +229,62 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { + @Override + public void onChange(boolean unused) { + synchronized(this) { + if (isBluetoothPersistedStateOn()) { + if (isAirplaneModeOn()) { + persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); + } else { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + } + + int st = BluetoothAdapter.STATE_OFF; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + st = mBluetooth.getState(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + return; + } finally { + mBluetoothLock.readLock().unlock(); + } + + Slog.d(TAG, "Airplane Mode change - current state: " + + BluetoothAdapter.nameForState(st)); + + if (isAirplaneModeOn()) { + // Clear registered LE apps to force shut-off + clearBleApps(); + + // If state is BLE_ON make sure we trigger disableBLE + if (st == BluetoothAdapter.STATE_BLE_ON) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + mEnable = false; + mEnableExternal = false; + } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + } else if (st == BluetoothAdapter.STATE_ON){ + sendDisableMsg(REASON_AIRPLANE_MODE); + } + } else if (mEnableExternal) { + sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE); + } + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -250,58 +295,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newName != null) { storeNameAndAddress(newName, null); } - } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { - synchronized(mReceiver) { - if (isBluetoothPersistedStateOn()) { - if (isAirplaneModeOn()) { - persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); - } else { - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - } - } - - int st = BluetoothAdapter.STATE_OFF; - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - st = mBluetooth.getState(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call getState", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - Slog.d(TAG, "Airplane Mode change - current state: " + - BluetoothAdapter.nameForState(st)); - - if (isAirplaneModeOn()) { - // Clear registered LE apps to force shut-off - clearBleApps(); - if (st == BluetoothAdapter.STATE_BLE_ON) { - //if state is BLE_ON make sure you trigger disableBLE part - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - mBluetooth.onBrEdrDown(); - mEnable = false; - mEnableExternal = false; - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - } else if (st == BluetoothAdapter.STATE_ON){ - // disable without persisting the setting - Slog.d(TAG, "Calling disable"); - sendDisableMsg("airplane mode"); - } - } else if (mEnableExternal) { - // enable without persisting the setting - Slog.d(TAG, "Calling enable"); - sendEnableMsg(mQuietEnableExternal, "airplane mode"); - } - } } } }; @@ -334,7 +327,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - registerForAirplaneMode(filter); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); @@ -343,6 +335,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = true; } + String airplaneModeRadios = Settings.Global.getString(mContentResolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + if (airplaneModeRadios == null || + airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), + true, mAirplaneModeObserver); + } + int systemUiUid = -1; try { systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", @@ -978,7 +979,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal, "system boot"); + sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); -- cgit v1.2.3 From dec018bb591c81f99b581c274230c0313c487038 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 31 Mar 2017 14:08:23 -0600 Subject: Consistent dump() permission checking. This change introduces new methods on DumpUtils that can check if the caller has DUMP and/or PACKAGE_USAGE_STATS access. It then moves all existing dump() methods to use these checks so that we emit consistent error messages. Test: cts-tradefed run commandAndExit cts-dev -m CtsSecurityTestCases -t android.security.cts.ServicePermissionsTest Bug: 32806790 Change-Id: Iaff6b9506818ee082b1e169c89ebe1001b3bfeca --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 58e86318e8..6c4895c91f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -60,6 +60,7 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import com.android.internal.util.DumpUtils; import com.android.server.pm.PackageManagerService; import java.io.FileDescriptor; @@ -2084,7 +2085,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; String errorMsg = null; boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); -- cgit v1.2.3 From cf3818675f65d8c1901b3d33eab5db1cabb74ea7 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Mon, 17 Apr 2017 22:35:45 -0700 Subject: Allow the Bluetooth MAC address to be updated asynchronously (2/3) There are intermittent issues where either the returned Bluetooth MAC address to Java framework is uninitialized or this address update arrives too late. This fix will do 2 things: (1) Returns error when MAC address is unavailable in the native code. (2) Updates the MAC address later by adding a new broadcast event. Test: Check address for these cases: factory reset, system reboot, and Bluetooth re-enable. Bug: 36709382 Change-Id: I09720193e38fdf9139e1bb146f8e1847e2b65b1a (cherry picked from commit ad4d1d8e28618546953e75d4983335631feb6f2a) --- .../com/android/server/bluetooth/BluetoothManagerService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6c4895c91f..6c18b260e1 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -308,6 +308,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newName != null) { storeNameAndAddress(newName, null); } + } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) { + String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS); + if (newAddress != null) { + if (DBG) Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress); + storeNameAndAddress(null, newAddress); + } else { + if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found"); + } } } }; @@ -343,6 +351,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); + filter = new IntentFilter(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); -- cgit v1.2.3 From 78488ad15a35a9333cbb156eecce9557cba52a01 Mon Sep 17 00:00:00 2001 From: Pavel Grafov Date: Tue, 28 Mar 2017 13:44:04 +0100 Subject: Introduce DISALLOW_BLUETOOTH_SHARING. When this restriction is enforced Bluetooth sharing option should not be present when the user tries to share something. Previously this was handled by explicitly disabling bluetooth sharing activity during managed provisioning, now this code is to be removed (see topic CLs) and the same behavior should be achieved by setting this restriction for profile owners by default. In Bluetooth: 1) Don't check restrictions on boot, it is invoked anyway through the listener during boot. 2) Ignore when the restriction is "changed" from true to true - i think it was the initial intent in that condition. 3) Disable the component for a particular user and not always the system user. This is something that has to be fixed in O I think since currently in secondary user the bluetooth itself gets disabled but the sharing thing still shows up. In DPMS: 1) Now ActiveAdmin for PO also contains a set of restrictions applied by default. 2) Now all ActiveAdmins for POs are loaded quite early. That shouldn't have huge impact though. Bug: 36249732 Test: run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testBluetoothSharingRestriction Test: run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Test: runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java Change-Id: I78c4ffbd503c4a10138e8c0862a9f206f24c5631 Merged-in: I78c4ffbd503c4a10138e8c0862a9f206f24c5631 (cherry picked from commit 7f4ad75218bdd3f1bdf9022a146147eae032cc0c) --- .../server/bluetooth/BluetoothManagerService.java | 57 ++++++++++------------ 1 file changed, 27 insertions(+), 30 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 6c18b260e1..18b4571ca3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import android.Manifest; import android.app.ActivityManager; +import android.app.AppGlobals; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; @@ -37,11 +38,11 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -50,7 +51,6 @@ import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -61,15 +61,15 @@ import android.provider.Settings.SettingNotFoundException; import android.util.Slog; import com.android.internal.util.DumpUtils; -import com.android.server.pm.PackageManagerService; +import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; class BluetoothManagerService extends IBluetoothManager.Stub { @@ -120,7 +120,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; - private static final int MAX_SAVE_RETRIES = 3; private static final int MAX_ERROR_RESTART_RETRIES = 6; // Bluetooth persisted setting is off @@ -223,22 +222,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { - if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH) - && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) { - // The relevant restriction has not changed - do nothing. - return; + if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, + UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) { + return; // No relevant changes, nothing to do. } - final boolean bluetoothDisallowed = - newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); - if ((mEnable || mEnableExternal) && bluetoothDisallowed) { + + final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + + // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the + // system user, so we only look at the system user. + if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) { try { - disable(null, true); + disable(null /* packageName */, true /* persist */); } catch (RemoteException e) { - Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener", - e); + Slog.w(TAG, "Exception when disabling Bluetooth", e); } } - updateOppLauncherComponentState(bluetoothDisallowed); + final boolean sharingDisallowed = disallowed + || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING); + updateOppLauncherComponentState(userId, sharingDisallowed); } }; @@ -994,11 +996,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); final boolean isBluetoothDisallowed = isBluetoothDisallowed(); - PackageManagerService packageManagerService = - (PackageManagerService) ServiceManager.getService("package"); - if (packageManagerService != null && !packageManagerService.isOnlyCoreApps()) { - updateOppLauncherComponentState(isBluetoothDisallowed); - } if (isBluetoothDisallowed) { return; } @@ -2074,21 +2071,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not - * offered to the user if Bluetooth is disallowed. Puts the component to its default state if - * Bluetooth is not disallowed. + * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default + * state if Bluetooth is not disallowed. * - * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user - * restriction was set. + * @param userId user to disable bluetooth sharing for. + * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed. */ - private void updateOppLauncherComponentState(boolean bluetoothDisallowed) { + private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) { final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); - final int newState = bluetoothDisallowed + final int newState = bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; try { - mContext.getPackageManager() - .setComponentEnabledSetting(oppLauncherComponent, newState, 0); + final IPackageManager imp = AppGlobals.getPackageManager(); + imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId); } catch (Exception e) { // The component was not found, do nothing. } -- cgit v1.2.3 From 777463136a672ee1bd56332204317f8732a9160c Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Mon, 17 Apr 2017 20:42:22 -0700 Subject: Limit btsnoop file size (3/9) Limit btsnoop file size by rotating between snoop files. The rotation occurrs when a fixed number of packets have been logged and will start overwriting the older file. Bug: 35998031 Test: Enable snoop logs from developer options and let logs get large Change-Id: I40d5da4c1b1c9b45908e5790d130f1c5e804c773 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 18b4571ca3..c785fb91e8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1494,16 +1494,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mGetNameAddressOnly) return; } - try { - boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, - Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); - if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { - Slog.e(TAG,"IBluetooth.configHciSnoopLog return false"); - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call configHciSnoopLog", e); - } - //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); -- cgit v1.2.3 From a87b1d276beacf1b05b17a6d0be2f0e330fb0157 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Mon, 1 May 2017 21:27:31 -0700 Subject: Add Save and Restore of BluetoothOn setting This change will automatically save the Bluetooth On setting when the user chooses to backup the phone settings into the cloud. This setting is restored by the Setup Wizard (SUW) when configuring the phone and this change will enable or disable the Bluetooth based on this restored setting. Bug: 35657817 Test: Manual test with Sailfish Change-Id: Ie4518593af63f96f8c363f98941ca5260a3ec4bb (cherry picked from commit 767f05feea67e642a76bd3e2e7633a8f5273f077) --- .../server/bluetooth/BluetoothManagerService.java | 49 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c785fb91e8..b65f54ecbd 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -91,6 +91,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String REASON_SYSTEM_BOOT = "system boot"; private static final String REASON_UNEXPECTED = "unexpected crash"; private static final String REASON_USER_SWITCH = "user switch"; + private static final String REASON_RESTORE_USER_SETTING = "restore user setting"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind //Maximum msec to wait for service restart @@ -119,6 +120,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_USER_UNLOCKED = 301; private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; + private static final int MESSAGE_RESTORE_USER_SETTING = 500; + + private static final int RESTORE_SETTING_TO_ON = 1; + private static final int RESTORE_SETTING_TO_OFF = 0; private static final int MAX_ERROR_RESTART_RETRIES = 6; @@ -318,6 +323,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else { if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found"); } + } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { + final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); + if (Settings.Global.BLUETOOTH_ON.equals(name)) { + // The Bluetooth On state may be changed during system restore. + final String prevValue = intent.getStringExtra( + Intent.EXTRA_SETTING_PREVIOUS_VALUE); + final String newValue = intent.getStringExtra( + Intent.EXTRA_SETTING_NEW_VALUE); + + if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + + prevValue + ", newValue=" + newValue); + + if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) { + Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING, + newValue.equals("0") ? + RESTORE_SETTING_TO_OFF : + RESTORE_SETTING_TO_ON, 0); + mHandler.sendMessage(msg); + } + } } } }; @@ -350,12 +375,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); - IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - mContext.registerReceiver(mReceiver, filter); - filter = new IntentFilter(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); + + IntentFilter filter = new IntentFilter(); + filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); + filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); + filter.addAction(Intent.ACTION_SETTING_RESTORED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); + loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); @@ -1421,6 +1448,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; + case MESSAGE_RESTORE_USER_SETTING: + try { + if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { + if (DBG) Slog.d(TAG, "Restore Bluetooth state to disabled"); + disable(REASON_RESTORE_USER_SETTING, true); + } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { + if (DBG) Slog.d(TAG, "Restore Bluetooth state to enabled"); + enable(REASON_RESTORE_USER_SETTING); + } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to change Bluetooth On setting", e); + } + break; + case MESSAGE_REGISTER_ADAPTER: { IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; -- cgit v1.2.3 From bfadc5c8040cc7b08a196ebaf02c1700d252476b Mon Sep 17 00:00:00 2001 From: Ram Periathiruvadi Date: Wed, 3 May 2017 19:11:20 -0700 Subject: Fix for Bluetooth not restarting on User Switch The flag that keeps track of the Bluetooth adapter status(mEnable) is not guarded correctly and could go out of sync with the adapter status. This causes User Switch handling to not function correctly since it checks for the status of the mEnable flag before restarting Bluetooth. This fix queries the Bluetooth Adapter for the status instead of using the mEnable flag. Bug: b/37648701 Test: Tested switching users multiple times in both phone and carkit. Also tested pairing and connection for sanity. Change-Id: I17facecf8e1de90df11c11d5b0a184f48a0356e4 (cherry picked from commit 7d1203a2f4fdbafe26d33421c3cdd83f07a5fba8) --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b65f54ecbd..61057dd254 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1697,7 +1697,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_USER_SWITCHED); /* disable and enable BT when detect a user switch */ - if (mEnable && mBluetooth != null) { + if (mBluetooth != null && isEnabled()) { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { @@ -1766,6 +1766,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_OFF; // enable addActiveLog(REASON_USER_SWITCH, true); + // mEnable flag could have been reset on disableBLE. Reenable it. + mEnable = true; handleEnable(mQuietEnable); } else if (mBinding || mBluetooth != null) { Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); -- cgit v1.2.3 From bcac61c17129d70e26354655e56c9bca5a1a3c75 Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Thu, 29 Jun 2017 03:12:02 -0700 Subject: Send disable messages when Bluetooth is disallowed Bug: 63021124 Test: cts-tradefed run commandAndExit cts \ -m CtsDevicePolicyManagerTestCases \ -t com.android.cts.devicepolicy.DeviceOwnerTest#testBluetoothRestriction Change-Id: I0ef538a4d0f0632ce303b29595ac1cab3b7d29ce --- .../server/bluetooth/BluetoothManagerService.java | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 61057dd254..75206e48aa 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -86,6 +86,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int ACTIVE_LOG_MAX_SIZE = 20; private static final int CRASH_LOG_MAX_SIZE = 100; private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_DISALLOWED = "disallowed by system"; + private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system"; private static final String REASON_RESTARTED = "automatic restart"; private static final String REASON_START_CRASH = "turn-on crash"; private static final String REASON_SYSTEM_BOOT = "system boot"; @@ -227,25 +229,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { - if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, - UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) { - return; // No relevant changes, nothing to do. - } - final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, + UserManager.DISALLOW_BLUETOOTH_SHARING)) { + updateOppLauncherComponentState(userId, newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH_SHARING)); + } - // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the - // system user, so we only look at the system user. - if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) { - try { - disable(null /* packageName */, true /* persist */); - } catch (RemoteException e) { - Slog.w(TAG, "Exception when disabling Bluetooth", e); + // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. + if (userId == UserHandle.USER_SYSTEM && + UserRestrictionsUtils.restrictionsChanged( + prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { + if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH)) { + updateOppLauncherComponentState(userId, true); // Sharing disallowed + sendDisableMsg(REASON_DISALLOWED); + } else { + updateOppLauncherComponentState(userId, newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH_SHARING)); } } - final boolean sharingDisallowed = disallowed - || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING); - updateOppLauncherComponentState(userId, sharingDisallowed); } }; @@ -2118,7 +2121,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; try { final IPackageManager imp = AppGlobals.getPackageManager(); - imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId); + imp.setComponentEnabledSetting(oppLauncherComponent, newState, + PackageManager.DONT_KILL_APP, userId); } catch (Exception e) { // The component was not found, do nothing. } -- cgit v1.2.3 From 8d93c73ed99a732c75caf65d5a44bb3090dbb027 Mon Sep 17 00:00:00 2001 From: Marie Janssen Date: Mon, 26 Jun 2017 07:21:03 -0700 Subject: Bluetooth: Use elapsed real time for calculating onDuration The system time can change after boot. Using elapsed real time avoids this problem. Test: start factory reset device, adb shell dumpsys bluetooth_manager Change-Id: Ieea2a2bc8b4bcb375897e609275207b6c3eccdce Fixes: 62985817 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 75206e48aa..c34c30cf6e 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -195,6 +195,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private LinkedList mActiveLogs; private LinkedList mCrashTimestamps; private int mCrashes; + private long mLastEnabledTime; // configuration from external IBinder call which is used to // synchronize with broadcast receiver. @@ -2021,6 +2022,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); addActiveLog(packageName, true); + mLastEnabledTime = SystemClock.elapsedRealtime(); } private void addActiveLog(String packageName, boolean enable) { @@ -2142,7 +2144,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" address: " + mAddress); writer.println(" name: " + mName); if (mEnable) { - long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime(); + long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; String onDurationString = String.format("%02d:%02d:%02d.%03d", (int)(onDuration / (1000 * 60 * 60)), (int)((onDuration / (1000 * 60)) % 60), -- cgit v1.2.3 From fb76dc36ad7aba5124b4ef08eeba44acaf4332c3 Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Mon, 10 Apr 2017 13:49:13 -0700 Subject: Bluetooth: Pre-pend empty line for dumpsys section headers Test: manual Change-Id: I2daa5c985e5504606edd9ff558bd5b92af7a7240 --- .../server/bluetooth/BluetoothManagerService.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c34c30cf6e..04279a31d2 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2150,31 +2150,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { (int)((onDuration / (1000 * 60)) % 60), (int)((onDuration / 1000) % 60), (int)(onDuration % 1000)); - writer.println(" time since enabled: " + onDurationString + "\n"); + writer.println(" time since enabled: " + onDurationString); } if (mActiveLogs.size() == 0) { - writer.println("Bluetooth never enabled!"); + writer.println("\nBluetooth never enabled!"); } else { - writer.println("Enable log:"); + writer.println("\nEnable log:"); for (ActiveLog log : mActiveLogs) { writer.println(" " + log); } } - writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); + writer.println("\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); for (Long time : mCrashTimestamps) { writer.println(" " + timeToLog(time.longValue())); } - String bleAppString = "No BLE Apps registered."; - if (mBleApps.size() == 1) { - bleAppString = "1 BLE App registered:"; - } else if (mBleApps.size() > 1) { - bleAppString = mBleApps.size() + " BLE Apps registered:"; - } - writer.println("\n" + bleAppString); + writer.println("\n" + mBleApps.size() + " BLE app" + + (mBleApps.size() == 1 ? "" : "s") + "registered"); for (ClientDeathRecipient app : mBleApps.values()) { writer.println(" " + app.getPackageName()); } -- cgit v1.2.3 From bbb0d40a3e8998eaa705943b68e10daec27d8613 Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Mon, 27 Nov 2017 16:42:11 -0800 Subject: Auto-format BluetoothManagerService.java Test: build Change-Id: If97c454a8e5aff34c4f8550f7ade3da413a200b7 --- .../server/bluetooth/BluetoothManagerService.java | 822 ++++++++++++--------- 1 file changed, 464 insertions(+), 358 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 04279a31d2..763a4e4945 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -67,6 +67,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; import java.util.LinkedList; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -79,15 +80,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; - private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; - private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; - private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; + private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address"; + private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name"; private static final int ACTIVE_LOG_MAX_SIZE = 20; private static final int CRASH_LOG_MAX_SIZE = 100; private static final String REASON_AIRPLANE_MODE = "airplane mode"; private static final String REASON_DISALLOWED = "disallowed by system"; - private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system"; private static final String REASON_RESTARTED = "automatic restart"; private static final String REASON_START_CRASH = "turn-on crash"; private static final String REASON_SYSTEM_BOOT = "system boot"; @@ -130,14 +130,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MAX_ERROR_RESTART_RETRIES = 6; // Bluetooth persisted setting is off - private static final int BLUETOOTH_OFF=0; + private static final int BLUETOOTH_OFF = 0; // Bluetooth persisted setting is on // and Airplane mode won't affect Bluetooth state at start up - private static final int BLUETOOTH_ON_BLUETOOTH=1; + private static final int BLUETOOTH_ON_BLUETOOTH = 1; // Bluetooth persisted setting is on // but Airplane mode will affect Bluetooth state at start up // and Airplane mode will have higher priority. - private static final int BLUETOOTH_ON_AIRPLANE=2; + private static final int BLUETOOTH_ON_AIRPLANE = 2; private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; @@ -154,8 +154,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private IBinder mBluetoothBinder; private IBluetooth mBluetooth; private IBluetoothGatt mBluetoothGatt; - private final ReentrantReadWriteLock mBluetoothLock = - new ReentrantReadWriteLock(); + private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; @@ -175,7 +174,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mEnable; private long mTimestamp; - public ActiveLog(String packageName, boolean enable, long timestamp) { + ActiveLog(String packageName, boolean enable, long timestamp) { mPackageName = packageName; mEnable = enable; mTimestamp = timestamp; @@ -186,8 +185,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public String toString() { - return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by " - + mPackageName; + return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by " + + mPackageName; } } @@ -203,7 +202,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mEnableExternal; // Map of apps registered to keep BLE scanning on. - private Map mBleApps = new ConcurrentHashMap(); + private Map mBleApps = + new ConcurrentHashMap(); private int mState; private final BluetoothHandler mHandler; @@ -212,51 +212,52 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Save a ProfileServiceConnections object for each of the bound // bluetooth profile services - private final Map mProfileServices = - new HashMap (); + private final Map mProfileServices = + new HashMap(); private final boolean mPermissionReviewRequired; private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override - public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { - Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); + public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { + Message msg = + mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState); mHandler.sendMessage(msg); } }; private final UserRestrictionsListener mUserRestrictionsListener = new UserRestrictionsListener() { - @Override - public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, - Bundle prevRestrictions) { - - if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, - UserManager.DISALLOW_BLUETOOTH_SHARING)) { - updateOppLauncherComponentState(userId, newRestrictions.getBoolean( - UserManager.DISALLOW_BLUETOOTH_SHARING)); - } - - // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. - if (userId == UserHandle.USER_SYSTEM && - UserRestrictionsUtils.restrictionsChanged( - prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { - if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( - UserManager.DISALLOW_BLUETOOTH)) { - updateOppLauncherComponentState(userId, true); // Sharing disallowed - sendDisableMsg(REASON_DISALLOWED); - } else { - updateOppLauncherComponentState(userId, newRestrictions.getBoolean( - UserManager.DISALLOW_BLUETOOTH_SHARING)); + @Override + public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, + Bundle prevRestrictions) { + + if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, + UserManager.DISALLOW_BLUETOOTH_SHARING)) { + updateOppLauncherComponentState(userId, + newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING)); + } + + // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. + if (userId == UserHandle.USER_SYSTEM + && UserRestrictionsUtils.restrictionsChanged(prevRestrictions, + newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { + if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH)) { + updateOppLauncherComponentState(userId, true); // Sharing disallowed + sendDisableMsg(REASON_DISALLOWED); + } else { + updateOppLauncherComponentState(userId, newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH_SHARING)); + } + } } - } - } - }; + }; private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { @Override public void onChange(boolean unused) { - synchronized(this) { + synchronized (this) { if (isBluetoothPersistedStateOn()) { if (isAirplaneModeOn()) { persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); @@ -278,8 +279,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - Slog.d(TAG, "Airplane Mode change - current state: " + - BluetoothAdapter.nameForState(st)); + Slog.d(TAG, + "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( + st)); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off @@ -295,11 +297,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = false; } } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); + Slog.e(TAG, "Unable to call onBrEdrDown", e); } finally { mBluetoothLock.readLock().unlock(); } - } else if (st == BluetoothAdapter.STATE_ON){ + } else if (st == BluetoothAdapter.STATE_ON) { sendDisableMsg(REASON_AIRPLANE_MODE); } } else if (mEnableExternal) { @@ -315,35 +317,42 @@ class BluetoothManagerService extends IBluetoothManager.Stub { String action = intent.getAction(); if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); - if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); + if (DBG) { + Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); + } if (newName != null) { storeNameAndAddress(newName, null); } } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) { String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS); if (newAddress != null) { - if (DBG) Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress); + if (DBG) { + Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress); + } storeNameAndAddress(null, newAddress); } else { - if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found"); + if (DBG) { + Slog.e(TAG, "No Bluetooth Adapter address parameter found"); + } } } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); if (Settings.Global.BLUETOOTH_ON.equals(name)) { // The Bluetooth On state may be changed during system restore. - final String prevValue = intent.getStringExtra( - Intent.EXTRA_SETTING_PREVIOUS_VALUE); - final String newValue = intent.getStringExtra( - Intent.EXTRA_SETTING_NEW_VALUE); + final String prevValue = + intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE); + final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); - if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + - prevValue + ", newValue=" + newValue); + if (DBG) { + Slog.d(TAG, + "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue + + ", newValue=" + newValue); + } if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) { Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING, - newValue.equals("0") ? - RESTORE_SETTING_TO_OFF : - RESTORE_SETTING_TO_ON, 0); + newValue.equals("0") ? RESTORE_SETTING_TO_OFF + : RESTORE_SETTING_TO_ON, 0); mHandler.sendMessage(msg); } } @@ -356,8 +365,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mPermissionReviewRequired = context.getResources().getBoolean( - com.android.internal.R.bool.config_permissionReviewRequired); + mPermissionReviewRequired = context.getResources() + .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired); mActiveLogs = new LinkedList(); mCrashTimestamps = new LinkedList(); @@ -389,23 +398,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { - if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); + if (DBG) { + Slog.d(TAG, "Startup: Bluetooth persisted state is ON."); + } mEnableExternal = true; } - String airplaneModeRadios = Settings.Global.getString(mContentResolver, - Settings.Global.AIRPLANE_MODE_RADIOS); - if (airplaneModeRadios == null || - airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { + String airplaneModeRadios = + Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS); + if (airplaneModeRadios == null || airplaneModeRadios.contains( + Settings.Global.RADIO_BLUETOOTH)) { mContentResolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), - true, mAirplaneModeObserver); + Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, + mAirplaneModeObserver); } int systemUiUid = -1; try { - systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", - PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); + systemUiUid = mContext.getPackageManager() + .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, + UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); @@ -416,7 +428,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Returns true if airplane mode is currently on */ - private final boolean isAirplaneModeOn() { + private boolean isAirplaneModeOn() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 1; } @@ -424,31 +436,32 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Returns true if the Bluetooth saved state is "on" */ - private final boolean isBluetoothPersistedStateOn() { - int state = Settings.Global.getInt(mContentResolver, - Settings.Global.BLUETOOTH_ON, -1); - if (DBG) Slog.d(TAG, "Bluetooth persisted state: " + state); + private boolean isBluetoothPersistedStateOn() { + int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); + if (DBG) { + Slog.d(TAG, "Bluetooth persisted state: " + state); + } return state != BLUETOOTH_OFF; } /** * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH */ - private final boolean isBluetoothPersistedStateOnBluetooth() { - return Settings.Global.getInt(mContentResolver, - Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; + private boolean isBluetoothPersistedStateOnBluetooth() { + return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, + BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; } /** * Save the Bluetooth on/off state */ private void persistBluetoothSetting(int value) { - if (DBG) Slog.d(TAG, "Persisting Bluetooth Setting: " + value); + if (DBG) { + Slog.d(TAG, "Persisting Bluetooth Setting: " + value); + } // waive WRITE_SECURE_SETTINGS permission check long callingIdentity = Binder.clearCallingIdentity(); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.BLUETOOTH_ON, - value); + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); Binder.restoreCallingIdentity(callingIdentity); } @@ -458,7 +471,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * @return */ private boolean isNameAndAddressSet() { - return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; + return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0; } /** @@ -466,17 +479,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * in the local cache */ private void loadStoredNameAndAddress() { - if (DBG) Slog.d(TAG, "Loading stored name and address"); - if (mContext.getResources().getBoolean - (com.android.internal.R.bool.config_bluetooth_address_validation) && - Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { + if (DBG) { + Slog.d(TAG, "Loading stored name and address"); + } + if (mContext.getResources() + .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation) + && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) + == 0) { // if the valid flag is not set, don't load the address and name - if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored"); + if (DBG) { + Slog.d(TAG, "invalid bluetooth name and address stored"); + } return; } mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); - if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); + if (DBG) { + Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); + } } /** @@ -489,15 +509,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (name != null) { Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); mName = name; - if (DBG) Slog.d(TAG,"Stored Bluetooth name: " + - Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); + if (DBG) { + Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver, + SECURE_SETTINGS_BLUETOOTH_NAME)); + } } if (address != null) { Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); - mAddress=address; - if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " + - Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); + mAddress = address; + if (DBG) { + Slog.d(TAG, + "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver, + SECURE_SETTINGS_BLUETOOTH_ADDRESS)); + } } if ((name != null) && (address != null)) { @@ -505,7 +530,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ + public IBluetooth registerAdapter(IBluetoothManagerCallback callback) { if (callback == null) { Slog.w(TAG, "Callback is null in registerAdapter"); return null; @@ -522,19 +547,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in unregisterAdapter"); return; } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, - "Need BLUETOOTH permission"); + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); msg.obj = callback; mHandler.sendMessage(msg); } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, - "Need BLUETOOTH permission"); + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (callback == null) { - Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); - return; + Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); + return; } Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; @@ -542,11 +565,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, - "Need BLUETOOTH permission"); + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (callback == null) { - Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); - return; + Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); + return; } Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); msg.obj = callback; @@ -554,15 +576,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean isEnabled() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user"); + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { + Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user"); return false; } try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) return mBluetooth.isEnabled(); + if (mBluetooth != null) { + return mBluetooth.isEnabled(); + } } catch (RemoteException e) { Slog.e(TAG, "isEnabled()", e); } finally { @@ -572,15 +595,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public int getState() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && - (!checkIfCallerIsForegroundUser())) { + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Slog.w(TAG, "getState(): report OFF for non-active and non system user"); return BluetoothAdapter.STATE_OFF; } try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) return mBluetooth.getState(); + if (mBluetooth != null) { + return mBluetooth.getState(); + } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); } finally { @@ -592,26 +616,29 @@ class BluetoothManagerService extends IBluetoothManager.Stub { class ClientDeathRecipient implements IBinder.DeathRecipient { private String mPackageName; - public ClientDeathRecipient(String packageName) { + ClientDeathRecipient(String packageName) { mPackageName = packageName; } public void binderDied() { - if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName); + if (DBG) { + Slog.d(TAG, "Binder is dead - unregister " + mPackageName); + } if (isBleAppPresent()) { - // Nothing to do, another app is here. - return; + // Nothing to do, another app is here. + return; + } + if (DBG) { + Slog.d(TAG, "Disabling LE only mode after application crash"); } - if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null && - mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + if (mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { mEnable = false; mBluetooth.onBrEdrDown(); } } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onBrEdrDown", e); + Slog.e(TAG, "Unable to call onBrEdrDown", e); } finally { mBluetoothLock.readLock().unlock(); } @@ -641,15 +668,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onChange(boolean selfChange) { if (isBleScanAlwaysAvailable()) { - // Nothing to do - return; + // Nothing to do + return; } // BLE scan is not available. disableBleScanMode(); clearBleApps(); try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) mBluetooth.onBrEdrDown(); + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + } } catch (RemoteException e) { Slog.e(TAG, "error when disabling bluetooth", e); } finally { @@ -659,8 +688,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { }; mContentResolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), - false, contentObserver); + Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false, + contentObserver); } // Disable ble scan only mode. @@ -668,7 +697,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { - if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); + if (DBG) { + Slog.d(TAG, "Reseting the mEnable flag for clean disable"); + } mEnable = false; } } catch (RemoteException e) { @@ -688,15 +719,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!"); } mBleApps.put(token, deathRec); - if (DBG) Slog.d(TAG, "Registered for death of " + packageName); + if (DBG) { + Slog.d(TAG, "Registered for death of " + packageName); + } } else if (!enable && r != null) { // Unregister death recipient as the app goes away. token.unlinkToDeath(r, 0); mBleApps.remove(token); - if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName); + if (DBG) { + Slog.d(TAG, "Unregistered for death of " + packageName); + } } int appCount = mBleApps.size(); - if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); + if (DBG) { + Slog.d(TAG, appCount + " registered Ble Apps"); + } if (appCount == 0 && mEnable) { disableBleScanMode(); } @@ -713,7 +750,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** @hide */ public boolean isBleAppPresent() { - if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); + if (DBG) { + Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); + } return mBleApps.size() > 0; } @@ -721,17 +760,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Action taken when GattService is turned on */ private void onBluetoothGattServiceUp() { - if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); + if (DBG) { + Slog.d(TAG, "BluetoothGatt Service is Up"); + } try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { - if (DBG) Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); + if (DBG) { + Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); + } return; } int st = mBluetooth.getState(); if (st != BluetoothAdapter.STATE_BLE_ON) { - if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + - BluetoothAdapter.nameForState(st)); + if (DBG) { + Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + + BluetoothAdapter.nameForState(st)); + } return; } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { @@ -740,7 +785,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } } catch (RemoteException e) { - Slog.e(TAG,"Unable to call onServiceUp", e); + Slog.e(TAG, "Unable to call onServiceUp", e); } finally { mBluetoothLock.readLock().unlock(); } @@ -751,7 +796,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * and turn off all service and stack if no LE app needs it */ private void sendBrEdrDownCallback() { - if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); + if (DBG) { + Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks"); + } if (mBluetooth == null) { Slog.w(TAG, "Bluetooth handle is null"); @@ -768,7 +815,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else { try { mBluetoothLock.readLock().lock(); - if (mBluetooth != null) mBluetooth.onBrEdrDown(); + if (mBluetooth != null) { + mBluetooth.onBrEdrDown(); + } } catch (RemoteException e) { Slog.e(TAG, "Call to onBrEdrDown() failed.", e); } finally { @@ -778,8 +827,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } - public boolean enableNoAutoConnect(String packageName) - { + public boolean enableNoAutoConnect(String packageName) { if (isBluetoothDisallowed()) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); @@ -788,11 +836,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); + "Need BLUETOOTH ADMIN permission"); if (DBG) { - Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + - " mBinding = " + mBinding); + Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + + mBinding); } int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); @@ -800,7 +848,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { throw new SecurityException("no permission to enable Bluetooth quietly"); } - synchronized(mReceiver) { + synchronized (mReceiver) { mQuietEnableExternal = true; mEnableExternal = true; sendEnableMsg(true, packageName); @@ -814,7 +862,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBluetoothDisallowed()) { if (DBG) { - Slog.d(TAG,"enable(): not enabling - bluetooth disallowed"); + Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } return false; } @@ -828,26 +876,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { return false; } } if (DBG) { - Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth + - " mBinding = " + mBinding + " mState = " + - BluetoothAdapter.nameForState(mState)); + Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = " + + mBinding + " mState = " + BluetoothAdapter.nameForState(mState)); } - synchronized(mReceiver) { + synchronized (mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false, packageName); } - if (DBG) Slog.d(TAG, "enable returning"); + if (DBG) { + Slog.d(TAG, "enable returning"); + } return true; } @@ -864,19 +912,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired - && startConsentUiIfNeeded(packageName, callingUid, - BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + if (isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { return false; } } if (DBG) { - Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth + - " mBinding = " + mBinding); + Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding); } - synchronized(mReceiver) { + synchronized (mReceiver) { if (persist) { persistBluetoothSetting(BLUETOOTH_OFF); } @@ -886,8 +932,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, - int callingUid, String intentAction) throws RemoteException { + private boolean startConsentUiIfNeeded(String packageName, int callingUid, String intentAction) + throws RemoteException { try { // Validate the package only if we are going to use it ApplicationInfo applicationInfo = mContext.getPackageManager() @@ -895,14 +941,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid)); if (applicationInfo.uid != callingUid) { - throw new SecurityException("Package " + callingUid - + " not in uid " + callingUid); + throw new SecurityException("Package " + callingUid + " not in uid " + callingUid); } Intent intent = new Intent(intentAction); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.setFlags( + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); try { mContext.startActivity(intent); } catch (ActivityNotFoundException e) { @@ -918,13 +963,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindAndFinish() { if (DBG) { - Slog.d(TAG,"unbindAndFinish(): " + mBluetooth + - " mBinding = " + mBinding + " mUnbinding = " + mUnbinding); + Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding + + " mUnbinding = " + mUnbinding); } try { mBluetoothLock.writeLock().lock(); - if (mUnbinding) return; + if (mUnbinding) { + return; + } mUnbinding = true; mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE); @@ -933,7 +980,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetooth.unregisterCallback(mBluetoothCallback); } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister BluetoothCallback",re); + Slog.e(TAG, "Unable to unregister BluetoothCallback", re); } mBluetoothBinder = null; mBluetooth = null; @@ -959,8 +1006,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { IBluetoothProfileServiceConnection proxy) { if (!mEnable) { if (DBG) { - Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + - ", while Bluetooth was disabled"); + Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + + ", while Bluetooth was disabled"); } return false; } @@ -968,15 +1015,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); if (psc == null) { if (DBG) { - Slog.d(TAG, "Creating new ProfileServiceConnections object for" - + " profile: " + bluetoothProfile); + Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " + + bluetoothProfile); } - if (bluetoothProfile != BluetoothProfile.HEADSET) return false; + if (bluetoothProfile != BluetoothProfile.HEADSET) { + return false; + } Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); - if (!psc.bindService()) return false; + if (!psc.bindService()) { + return false; + } mProfileServices.put(new Integer(bluetoothProfile), psc); } @@ -1022,7 +1073,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * PHASE_SYSTEM_SERVICES_READY. */ public void handleOnBootPhase() { - if (DBG) Slog.d(TAG, "Bluetooth boot completed"); + if (DBG) { + Slog.d(TAG, "Bluetooth boot completed"); + } UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); @@ -1031,10 +1084,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { - if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); + if (DBG) { + Slog.d(TAG, "Auto-enabling Bluetooth."); + } sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT); } else if (!isNameAndAddressSet()) { - if (DBG) Slog.d(TAG, "Getting adapter name and address"); + if (DBG) { + Slog.d(TAG, "Getting adapter name and address"); + } Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); } @@ -1044,7 +1101,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Called when switching to a different foreground user. */ public void handleOnSwitchUser(int userHandle) { - if (DBG) Slog.d(TAG, "User " + userHandle + " switched"); + if (DBG) { + Slog.d(TAG, "User " + userHandle + " switched"); + } mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget(); } @@ -1052,7 +1111,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Called when user is unlocked. */ public void handleOnUnlockUser(int userHandle) { - if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked"); + if (DBG) { + Slog.d(TAG, "User " + userHandle + " unlocked"); + } mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget(); } @@ -1060,10 +1121,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * This class manages the clients connected to a given ProfileService * and maintains the connection with that service. */ - final private class ProfileServiceConnections implements ServiceConnection, - IBinder.DeathRecipient { + private final class ProfileServiceConnections + implements ServiceConnection, IBinder.DeathRecipient { final RemoteCallbackList mProxies = - new RemoteCallbackList (); + new RemoteCallbackList(); IBinder mService; ComponentName mClassName; Intent mIntent; @@ -1076,8 +1137,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean bindService() { - if (mIntent != null && mService == null && - doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { + if (mIntent != null && mService == null && doBind(mIntent, this, 0, + UserHandle.CURRENT_OR_SELF)) { Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); msg.obj = this; mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); @@ -1090,7 +1151,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void addProxy(IBluetoothProfileServiceConnection proxy) { mProxies.register(proxy); if (mService != null) { - try{ + try { proxy.onServiceConnected(mClassName, mService); } catch (RemoteException e) { Slog.e(TAG, "Unable to connect to proxy", e); @@ -1158,7 +1219,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onServiceDisconnected(ComponentName className) { - if (mService == null) return; + if (mService == null) { + return; + } mService.unlinkToDeath(this, 0); mService = null; mClassName = null; @@ -1187,8 +1250,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void binderDied() { if (DBG) { - Slog.w(TAG, "Profile service for profile: " + mClassName - + " died."); + Slog.w(TAG, "Profile service for profile: " + mClassName + " died."); } onServiceDisconnected(mClassName); // Trigger rebind @@ -1201,12 +1263,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void sendBluetoothStateCallback(boolean isUp) { try { int n = mStateChangeCallbacks.beginBroadcast(); - if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); - for (int i=0; i " + - BluetoothAdapter.nameForState(newState)); + Slog.d(TAG, + "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState( + prevState) + " > " + BluetoothAdapter.nameForState( + newState)); } mState = newState; bluetoothStateChangeHandler(prevState, newState); // handle error state transition case from TURNING_ON to OFF // unbind and rebind bluetooth service and enable bluetooth - if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_OFF) && - (mBluetooth != null) && mEnable) { + if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState + == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(false); } - if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_BLE_ON) && - (mBluetooth != null) && mEnable) { + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState + == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, // wait for the BT process to fully tear down and then force a restart // here. This is a bit of a hack (b/29363429). - if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && - (newState == BluetoothAdapter.STATE_OFF)) { + if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState + == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); waitForOnOff(false, true); - Message restartMsg = mHandler.obtainMessage( - MESSAGE_RESTART_BLUETOOTH_SERVICE); + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); } } - if (newState == BluetoothAdapter.STATE_ON || - newState == BluetoothAdapter.STATE_BLE_ON) { + if (newState == BluetoothAdapter.STATE_ON + || newState == BluetoothAdapter.STATE_BLE_ON) { // bluetooth is working, reset the counter if (mErrorRecoveryRetryCounter != 0) { Slog.w(TAG, "bluetooth is recovered from error"); @@ -1618,14 +1695,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } break; } - case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: - { + case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")"); try { mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTH) { // if service is unbinded already, do nothing and return - if (mBluetooth == null) break; + if (mBluetooth == null) { + break; + } mBluetooth = null; } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = null; @@ -1644,33 +1722,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mEnable) { mEnable = false; // Send a Bluetooth Restart message - Message restartMsg = mHandler.obtainMessage( - MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, - SERVICE_RESTART_TIME_MS); + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, SERVICE_RESTART_TIME_MS); } sendBluetoothServiceDownCallback(); // Send BT state broadcast to update // the BT icon correctly - if ((mState == BluetoothAdapter.STATE_TURNING_ON) || - (mState == BluetoothAdapter.STATE_ON)) { + if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState + == BluetoothAdapter.STATE_ON)) { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, - BluetoothAdapter.STATE_TURNING_OFF); + BluetoothAdapter.STATE_TURNING_OFF); mState = BluetoothAdapter.STATE_TURNING_OFF; } if (mState == BluetoothAdapter.STATE_TURNING_OFF) { bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, - BluetoothAdapter.STATE_OFF); + BluetoothAdapter.STATE_OFF); } mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; break; } - case MESSAGE_RESTART_BLUETOOTH_SERVICE: - { + case MESSAGE_RESTART_BLUETOOTH_SERVICE: { Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); /* Enable without persisting the setting as it doesnt change when IBluetooth @@ -1687,8 +1763,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().unlock(); break; } - case MESSAGE_TIMEOUT_UNBIND: - { + case MESSAGE_TIMEOUT_UNBIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); mBluetoothLock.writeLock().lock(); mUnbinding = false; @@ -1697,7 +1772,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_USER_SWITCHED: { - if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED"); + if (DBG) { + Slog.d(TAG, "MESSAGE_USER_SWITCHED"); + } mHandler.removeMessages(MESSAGE_USER_SWITCHED); /* disable and enable BT when detect a user switch */ @@ -1735,12 +1812,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, - BluetoothAdapter.STATE_TURNING_OFF); + BluetoothAdapter.STATE_TURNING_OFF); boolean didDisableTimeout = !waitForOnOff(false, true); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, - BluetoothAdapter.STATE_OFF); + BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); try { @@ -1785,14 +1862,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } case MESSAGE_USER_UNLOCKED: { - if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); + if (DBG) { + Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); + } mHandler.removeMessages(MESSAGE_USER_SWITCHED); if (mEnable && !mBinding && (mBluetooth == null)) { // We should be connected, but we gave up for some // reason; maybe the Bluetooth service wasn't encryption // aware, so try binding again. - if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); + if (DBG) { + Slog.d(TAG, "Enabled but not bound; retrying after unlock"); + } handleEnable(mQuietEnable); } } @@ -1807,10 +1888,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { //Start bind timeout and bind - Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); - mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); + Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); + mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); Intent i = new Intent(IBluetooth.class.getName()); - if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { @@ -1820,17 +1901,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Enable bluetooth try { if (!mQuietEnable) { - if(!mBluetooth.enable()) { - Slog.e(TAG,"IBluetooth.enable() returned false"); + if (!mBluetooth.enable()) { + Slog.e(TAG, "IBluetooth.enable() returned false"); } - } - else { - if(!mBluetooth.enableNoAutoConnect()) { - Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); + } else { + if (!mBluetooth.enableNoAutoConnect()) { + Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false"); } } } catch (RemoteException e) { - Slog.e(TAG,"Unable to call enable()",e); + Slog.e(TAG, "Unable to call enable()", e); } } } finally { @@ -1852,13 +1932,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - if (DBG) Slog.d(TAG,"Sending off request."); + if (DBG) { + Slog.d(TAG, "Sending off request."); + } if (!mBluetooth.disable()) { - Slog.e(TAG,"IBluetooth.disable() returned false"); + Slog.e(TAG, "IBluetooth.disable() returned false"); } } } catch (RemoteException e) { - Slog.e(TAG,"Unable to call disable()",e); + Slog.e(TAG, "Unable to call disable()", e); } finally { mBluetoothLock.readLock().unlock(); } @@ -1876,15 +1958,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { boolean valid = false; try { foregroundUser = ActivityManager.getCurrentUser(); - valid = (callingUser == foregroundUser) || - parentUser == foregroundUser || - callingAppId == Process.NFC_UID || - callingAppId == mSystemUiUid; + valid = (callingUser == foregroundUser) || parentUser == foregroundUser + || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; if (DBG && !valid) { - Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid - + " callingUser=" + callingUser - + " parentUser=" + parentUser - + " foregroundUser=" + foregroundUser); + Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + + callingUser + " parentUser=" + parentUser + " foregroundUser=" + + foregroundUser); } } finally { Binder.restoreCallingIdentity(callingIdentity); @@ -1893,8 +1972,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendBleStateChanged(int prevState, int newState) { - if (DBG) Slog.d(TAG,"Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + - " > " + BluetoothAdapter.nameForState(newState)); + if (DBG) { + Slog.d(TAG, + "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } // Send broadcast message to everyone else Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); @@ -1909,14 +1991,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } // Notify all proxy objects first of adapter state change - if (newState == BluetoothAdapter.STATE_BLE_ON || - newState == BluetoothAdapter.STATE_OFF) { + if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) { boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF - && newState == BluetoothAdapter.STATE_BLE_ON); + && newState == BluetoothAdapter.STATE_BLE_ON); if (newState == BluetoothAdapter.STATE_OFF) { // If Bluetooth is off, send service down event to proxy objects, and unbind - if (DBG) Slog.d(TAG, "Bluetooth is complete send Service Down"); + if (DBG) { + Slog.d(TAG, "Bluetooth is complete send Service Down"); + } sendBluetoothServiceDownCallback(); unbindAndFinish(); sendBleStateChanged(prevState, newState); @@ -1925,16 +2008,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (!intermediate_off) { // connect to GattService - if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode"); + if (DBG) { + Slog.d(TAG, "Bluetooth is in LE only mode"); + } if (mBluetoothGatt != null) { - if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp"); + if (DBG) { + Slog.d(TAG, "Calling BluetoothGattServiceUp"); + } onBluetoothGattServiceUp(); } else { - if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service"); - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_BLUETOOTH_LE)) { + if (DBG) { + Slog.d(TAG, "Binding Bluetooth GATT service"); + } + if (mContext.getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT); } } sendBleStateChanged(prevState, newState); @@ -1942,7 +2032,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { isStandardBroadcast = false; } else if (intermediate_off) { - if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode"); + if (DBG) { + Slog.d(TAG, "Intermediate off, back to LE only mode"); + } // For LE only mode, broadcast as is sendBleStateChanged(prevState, newState); sendBluetoothStateCallback(false); // BT is OFF for general users @@ -1955,13 +2047,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothStateCallback(isUp); sendBleStateChanged(prevState, newState); - } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON || - newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) { + } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON + || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { sendBleStateChanged(prevState, newState); isStandardBroadcast = false; - } else if (newState == BluetoothAdapter.STATE_TURNING_ON || - newState == BluetoothAdapter.STATE_TURNING_OFF) { + } else if (newState == BluetoothAdapter.STATE_TURNING_ON + || newState == BluetoothAdapter.STATE_TURNING_OFF) { sendBleStateChanged(prevState, newState); } @@ -1988,13 +2080,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { while (i < 10) { try { mBluetoothLock.readLock().lock(); - if (mBluetooth == null) break; + if (mBluetooth == null) { + break; + } if (on) { - if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) { + return true; + } } else if (off) { - if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) { + return true; + } } else { - if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; + if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) { + return true; + } } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); @@ -2009,7 +2109,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } i++; } - Slog.e(TAG,"waitForOnOff time out"); + Slog.e(TAG, "waitForOnOff time out"); return false; } @@ -2019,8 +2119,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendEnableMsg(boolean quietMode, String packageName) { - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, - quietMode ? 1 : 0, 0)); + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); addActiveLog(packageName, true); mLastEnabledTime = SystemClock.elapsedRealtime(); } @@ -2035,15 +2134,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void addCrashLog() { - synchronized (mCrashTimestamps) { - if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst(); - mCrashTimestamps.add(System.currentTimeMillis()); - mCrashes++; - } + synchronized (mCrashTimestamps) { + if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) { + mCrashTimestamps.removeFirst(); + } + mCrashTimestamps.add(System.currentTimeMillis()); + mCrashes++; + } } private void recoverBluetoothServiceFromError(boolean clearBle) { - Slog.e(TAG,"recoverBluetoothServiceFromError"); + Slog.e(TAG, "recoverBluetoothServiceFromError"); try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { @@ -2082,15 +2183,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_OFF; if (clearBle) { - clearBleApps(); + clearBleApps(); } mEnable = false; if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { // Send a Bluetooth Restart message to reenable bluetooth - Message restartMsg = mHandler.obtainMessage( - MESSAGE_RESTART_BLUETOOTH_SERVICE); + Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); } else { // todo: notify user to power down and power up phone to make bluetooth work. @@ -2118,9 +2218,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) { final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth", "com.android.bluetooth.opp.BluetoothOppLauncherActivity"); - final int newState = bluetoothSharingDisallowed - ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED - : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; + final int newState = + bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED + : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; try { final IPackageManager imp = AppGlobals.getPackageManager(); imp.setComponentEnabledSetting(oppLauncherComponent, newState, @@ -2132,7 +2232,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; + if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { + return; + } String errorMsg = null; boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); @@ -2145,11 +2247,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" name: " + mName); if (mEnable) { long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; - String onDurationString = String.format("%02d:%02d:%02d.%03d", - (int)(onDuration / (1000 * 60 * 60)), - (int)((onDuration / (1000 * 60)) % 60), - (int)((onDuration / 1000) % 60), - (int)(onDuration % 1000)); + String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", + (int) (onDuration / (1000 * 60 * 60)), + (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), + (int) (onDuration % 1000)); writer.println(" time since enabled: " + onDurationString); } @@ -2162,14 +2263,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - writer.println("\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); - if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); + writer.println( + "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); + if (mCrashes == CRASH_LOG_MAX_SIZE) { + writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); + } for (Long time : mCrashTimestamps) { - writer.println(" " + timeToLog(time.longValue())); + writer.println(" " + timeToLog(time)); } - writer.println("\n" + mBleApps.size() + " BLE app" + - (mBleApps.size() == 1 ? "" : "s") + "registered"); + writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") + + "registered"); for (ClientDeathRecipient app : mBleApps.values()) { writer.println(" " + app.getPackageName()); } @@ -2194,7 +2298,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (errorMsg != null) { // Silently return if we are extracting metrics in Protobuf format - if (protoOut) return; + if (protoOut) { + return; + } writer.println(errorMsg); } } -- cgit v1.2.3 From 6fa8f5a5e2d566b2d3d3f7de6b79c4137f76ec9a Mon Sep 17 00:00:00 2001 From: Jack He Date: Fri, 8 Dec 2017 12:21:37 -0800 Subject: Bluetooth: Fix boolean logic in quiet mode enable * Change If97c454a8e5aff34c4f8550f7ade3da413a200b7 introduced a bug that flipped the logic of quiet mode enable in the handler for MESSAGE_BLUETOOTH_SERVICE_CONNECTED, causing quiet mode to be enabled when toggling from Settings and system UI. Bug: 70395489 Test: make, toggle bluetooth on/off Change-Id: I405fb462783df0d52d9ce84d2ebe959e56a1aa30 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 763a4e4945..d9713a517a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1628,7 +1628,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Do enable request try { - if (mQuietEnable) { + if (!mQuietEnable) { if (!mBluetooth.enable()) { Slog.e(TAG, "IBluetooth.enable() returned false"); } -- cgit v1.2.3 From 500febee6219c4509c06d11c11758915556be02f Mon Sep 17 00:00:00 2001 From: Arthur Hsu Date: Thu, 11 Jan 2018 16:46:22 -0800 Subject: Skip SystemUI check in BluetoothServiceManager if noHome. When device is configured with config_noHomeScreen, there will be no SystemUI. Checking SystemUI UID is meaningless. Bug: 62413935 69965109 Test: On sailfish, logcat shows expected SystemUI UID by default Change-Id: Iaccc0f10cb82da454077056824c3f6eea6a37c4e --- .../android/server/bluetooth/BluetoothManagerService.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index d9713a517a..337406d58f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -60,6 +60,7 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import com.android.internal.R; import com.android.internal.util.DumpUtils; import com.android.server.pm.UserRestrictionsUtils; @@ -415,9 +416,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int systemUiUid = -1; try { - systemUiUid = mContext.getPackageManager() - .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, - UserHandle.USER_SYSTEM); + // Check if device is configured with no home screen, which implies no SystemUI. + boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen); + if (!noHome) { + systemUiUid = mContext.getPackageManager() + .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, + UserHandle.USER_SYSTEM); + } + Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid)); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); -- cgit v1.2.3 From aa8b0f1d512e618dd39a647246073e27bf2f7b84 Mon Sep 17 00:00:00 2001 From: Arthur Hsu Date: Thu, 11 Jan 2018 11:05:11 -0800 Subject: Add config_supportBluetoothPersistedState. Add a config to indicate whether a device supports Bluetooth persisted state and defaulted to true. In ARC++, Bluetooth adapter state can be out-of-sync from its container if the user changes it before the container being available. When set to false, this config prevents Android to auto start the Bluetooth. ARC++ will set this to false and sync Bluetooth state later with Android. Related CL is ag/931281 Bug: 62413625, 69965109 Test: On sailfish, Bluetooth on/off correctly and state persisted across reboot Change-Id: Ie298929eb6b882108a12e8b95f61e3c9f8eb63ea --- .../com/android/server/bluetooth/BluetoothManagerService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 337406d58f..20777901a3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -439,10 +439,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Settings.Global.AIRPLANE_MODE_ON, 0) == 1; } + private boolean supportBluetoothPersistedState() { + return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState); + } + /** * Returns true if the Bluetooth saved state is "on" */ private boolean isBluetoothPersistedStateOn() { + if (!supportBluetoothPersistedState()) { + return false; + } int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); if (DBG) { Slog.d(TAG, "Bluetooth persisted state: " + state); @@ -454,6 +461,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH */ private boolean isBluetoothPersistedStateOnBluetooth() { + if (!supportBluetoothPersistedState()) { + return false; + } return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH; } -- cgit v1.2.3 From 2b6bd69eeb4f5d51632b54513c3363c6bb1f9e3a Mon Sep 17 00:00:00 2001 From: baisheng Date: Thu, 25 Jan 2018 18:07:24 +0800 Subject: Add dedicated signature permissions to platform manifest and shell manifest which could enable/disable BT and Wifi state on watch Skip Bluetooth consent UI if running on shell, also fix a typo in log message. Test: Manual test running `adb root; adb shell service call bluetooth_manager 6` and see if BT is on without consent UI. Bug: 69872231 Change-Id: Ie513794a7fc13041259fd84734bfc651495ba5cf --- .../server/bluetooth/BluetoothManagerService.java | 30 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 20777901a3..55ad8cc9bc 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -948,8 +948,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, int callingUid, String intentAction) - throws RemoteException { + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + if (checkBluetoothPermissionWhenPermissionReviewRequired()) { + return false; + } try { // Validate the package only if we are going to use it ApplicationInfo applicationInfo = mContext.getPackageManager() @@ -957,7 +960,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid)); if (applicationInfo.uid != callingUid) { - throw new SecurityException("Package " + callingUid + " not in uid " + callingUid); + throw new SecurityException("Package " + packageName + + " not in uid " + callingUid); } Intent intent = new Intent(intentAction); @@ -977,6 +981,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + /** + * Check if the caller must still pass permission check or if the caller is exempted + * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check. + * + * Commands from some callers may be exempted from triggering the consent UI when + * enabling bluetooth. This exemption is checked via the + * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip + * the consent UI where it may otherwise be required. + * + * @hide + */ + private boolean checkBluetoothPermissionWhenPermissionReviewRequired() { + if (!mPermissionReviewRequired) { + return false; + } + int result = mContext.checkCallingPermission( + android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED); + return result == PackageManager.PERMISSION_GRANTED; + } + public void unbindAndFinish() { if (DBG) { Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding -- cgit v1.2.3 From f2f77ed3ada721e23e636f07648a254584f7c979 Mon Sep 17 00:00:00 2001 From: Jack He Date: Fri, 2 Mar 2018 13:08:36 -0800 Subject: Bluetooth: Separate enable and disable Reasons from package name * Reasons to enable or disable Bluetooth should be in a separate namespace away from package names that initiated the enable or disable * Delcare reason code in android/bluetooth/enums.proto as EnableDisableReasonEnum and use these reason code together with package names to log Bluetooth enable and disable events * When reason is ENABLE_DISABLE_REASON_APPLICATION_REQUEST, the external package name is the real reason why Bluetooth is enabled or disabled * Change START_CRASH to START_ERROR since it represents a disable event when Bluetooth failed to start * Change UNEXPECTED_CRASH to CRASH since no crash is expected * Add getEnableDisableReasonString() method to covert reason code to human readable strings in dumpsys output Bug: 74090881 Test: Toggle Bluetooth, airplane mode, BLE scanning Change-Id: I06aa413e2a0a5f016c87759a1b694ef643c9cdee (cherry picked from commit 0dbe66460fa2a5ebb05ca757e58141c213038bc1) --- .../server/bluetooth/BluetoothManagerService.java | 145 +++++++++++++-------- 1 file changed, 89 insertions(+), 56 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 55ad8cc9bc..02b1380715 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -21,6 +21,7 @@ import android.app.ActivityManager; import android.app.AppGlobals; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothGatt; @@ -87,14 +88,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int ACTIVE_LOG_MAX_SIZE = 20; private static final int CRASH_LOG_MAX_SIZE = 100; - private static final String REASON_AIRPLANE_MODE = "airplane mode"; - private static final String REASON_DISALLOWED = "disallowed by system"; - private static final String REASON_RESTARTED = "automatic restart"; - private static final String REASON_START_CRASH = "turn-on crash"; - private static final String REASON_SYSTEM_BOOT = "system boot"; - private static final String REASON_UNEXPECTED = "unexpected crash"; - private static final String REASON_USER_SWITCH = "user switch"; - private static final String REASON_RESTORE_USER_SETTING = "restore user setting"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind //Maximum msec to wait for service restart @@ -163,7 +156,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mQuietEnable = false; private boolean mEnable; - private CharSequence timeToLog(long timestamp) { + private static CharSequence timeToLog(long timestamp) { return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp); } @@ -171,29 +164,27 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Used for tracking apps that enabled / disabled Bluetooth. */ private class ActiveLog { + private int mReason; private String mPackageName; private boolean mEnable; private long mTimestamp; - ActiveLog(String packageName, boolean enable, long timestamp) { + ActiveLog(int reason, String packageName, boolean enable, long timestamp) { + mReason = reason; mPackageName = packageName; mEnable = enable; mTimestamp = timestamp; } - public long getTime() { - return mTimestamp; - } - public String toString() { - return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + " by " - + mPackageName; + return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ") + + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName; } } - private LinkedList mActiveLogs; - private LinkedList mCrashTimestamps; + private final LinkedList mActiveLogs = new LinkedList<>(); + private final LinkedList mCrashTimestamps = new LinkedList<>(); private int mCrashes; private long mLastEnabledTime; @@ -213,8 +204,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Save a ProfileServiceConnections object for each of the bound // bluetooth profile services - private final Map mProfileServices = - new HashMap(); + private final Map mProfileServices = new HashMap<>(); private final boolean mPermissionReviewRequired; @@ -246,7 +236,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( UserManager.DISALLOW_BLUETOOTH)) { updateOppLauncherComponentState(userId, true); // Sharing disallowed - sendDisableMsg(REASON_DISALLOWED); + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, + mContext.getPackageName()); } else { updateOppLauncherComponentState(userId, newRestrictions.getBoolean( UserManager.DISALLOW_BLUETOOTH_SHARING)); @@ -303,10 +294,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } } else if (st == BluetoothAdapter.STATE_ON) { - sendDisableMsg(REASON_AIRPLANE_MODE); + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName()); } } else if (mEnableExternal) { - sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE); + sendEnableMsg(mQuietEnableExternal, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName()); } } } @@ -369,8 +363,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mPermissionReviewRequired = context.getResources() .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired); - mActiveLogs = new LinkedList(); - mCrashTimestamps = new LinkedList(); mCrashes = 0; mBluetooth = null; mBluetoothBinder = null; @@ -671,8 +663,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } try { - return (Settings.Global.getInt(mContentResolver, - Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0; + return Settings.Global.getInt(mContentResolver, + Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0; } catch (SettingNotFoundException e) { } return false; @@ -867,7 +859,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mReceiver) { mQuietEnableExternal = true; mEnableExternal = true; - sendEnableMsg(true, packageName); + sendEnableMsg(true, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); } return true; } @@ -907,7 +900,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false, packageName); + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); } if (DBG) { Slog.d(TAG, "enable returning"); @@ -943,7 +937,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_OFF); } mEnableExternal = false; - sendDisableMsg(packageName); + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName); } return true; } @@ -1127,7 +1122,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, "Auto-enabling Bluetooth."); } - sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT); + sendEnableMsg(mQuietEnableExternal, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT, + mContext.getPackageName()); } else if (!isNameAndAddressSet()) { if (DBG) { Slog.d(TAG, "Getting adapter name and address"); @@ -1569,20 +1566,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_RESTORE_USER_SETTING: - try { - if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { - if (DBG) { - Slog.d(TAG, "Restore Bluetooth state to disabled"); - } - disable(REASON_RESTORE_USER_SETTING, true); - } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { - if (DBG) { - Slog.d(TAG, "Restore Bluetooth state to enabled"); - } - enable(REASON_RESTORE_USER_SETTING); + if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { + if (DBG) { + Slog.d(TAG, "Restore Bluetooth state to disabled"); } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to change Bluetooth On setting", e); + persistBluetoothSetting(BLUETOOTH_OFF); + mEnableExternal = false; + sendDisableMsg( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, + mContext.getPackageName()); + } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) { + if (DBG) { + Slog.d(TAG, "Restore Bluetooth state to enabled"); + } + mQuietEnableExternal = false; + mEnableExternal = true; + // waive WRITE_SECURE_SETTINGS permission check + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING, + mContext.getPackageName()); } break; @@ -1609,7 +1611,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } case MESSAGE_ADD_PROXY_DELAYED: { - ProfileServiceConnections psc = mProfileServices.get(new Integer(msg.arg1)); + ProfileServiceConnections psc = mProfileServices.get(msg.arg1); if (psc == null) { break; } @@ -1758,7 +1760,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // log the unexpected crash addCrashLog(); - addActiveLog(REASON_UNEXPECTED, false); + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH, + mContext.getPackageName(), false); if (mEnable) { mEnable = false; // Send a Bluetooth Restart message @@ -1792,7 +1795,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { it doesnt change when IBluetooth service restarts */ mEnable = true; - addActiveLog(REASON_RESTARTED, true); + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, + mContext.getPackageName(), true); handleEnable(mQuietEnable); break; } @@ -1848,7 +1852,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { unbindAllBluetoothProfileServices(); // disable - addActiveLog(REASON_USER_SWITCH, false); + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, + mContext.getPackageName(), false); handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, @@ -1886,7 +1891,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; // enable - addActiveLog(REASON_USER_SWITCH, true); + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, + mContext.getPackageName(), true); // mEnable flag could have been reset on disableBLE. Reenable it. mEnable = true; handleEnable(mQuietEnable); @@ -2153,23 +2159,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - private void sendDisableMsg(String packageName) { + private void sendDisableMsg(int reason, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); - addActiveLog(packageName, false); + addActiveLog(reason, packageName, false); } - private void sendEnableMsg(boolean quietMode, String packageName) { + private void sendEnableMsg(boolean quietMode, int reason, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); - addActiveLog(packageName, true); + addActiveLog(reason, packageName, true); mLastEnabledTime = SystemClock.elapsedRealtime(); } - private void addActiveLog(String packageName, boolean enable) { + private void addActiveLog(int reason, String packageName, boolean enable) { synchronized (mActiveLogs) { if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { mActiveLogs.remove(); } - mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis())); + mActiveLogs.add( + new ActiveLog(reason, packageName, enable, System.currentTimeMillis())); } } @@ -2200,7 +2207,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { SystemClock.sleep(500); // disable - addActiveLog(REASON_START_CRASH, false); + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR, + mContext.getPackageName(), false); handleDisable(); waitForOnOff(false, true); @@ -2344,4 +2352,29 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(errorMsg); } } + + private static String getEnableDisableReasonString(int reason) { + switch (reason) { + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST: + return "APPLICATION_REQUEST"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE: + return "AIRPLANE_MODE"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED: + return "DISALLOWED"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED: + return "RESTARTED"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR: + return "START_ERROR"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT: + return "SYSTEM_BOOT"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH: + return "CRASH"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH: + return "USER_SWITCH"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: + return "RESTORE_USER_SETTING"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: + default: return "UNKNOWN[" + reason + "]"; + } + } } -- cgit v1.2.3 From c0e13903ac135023d9b8d25c2c78e1a2d421c99f Mon Sep 17 00:00:00 2001 From: Tej Singh Date: Thu, 22 Mar 2018 18:30:31 +0000 Subject: Logging: Bluetooth Enabled Logs bluetooth enabled state changed atom. Note: this is cherry picked from aosp: go/aog/647319. Bug: b/72320489 Bug: b/74457175 Test: verified logs appear in adb logcat -b stats Merged-In: Iab9bac487d845db0ba70b2622679523604b4944e Change-Id: Iab9bac487d845db0ba70b2622679523604b4944e --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 02b1380715..7f2e0b8123 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -60,6 +60,7 @@ import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import android.util.StatsLog; import com.android.internal.R; import com.android.internal.util.DumpUtils; @@ -2178,6 +2179,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mActiveLogs.add( new ActiveLog(reason, packageName, enable, System.currentTimeMillis())); } + + int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : + StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; + StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, + Binder.getCallingUid(), null, state, reason, packageName); } private void addCrashLog() { -- cgit v1.2.3 From 451a6825f5b217e2504d39d9a3281b7b17f01b59 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Mon, 19 Mar 2018 13:06:45 -0700 Subject: Remove BLE App entry from mBleApps list when App died When a registered BLE App unexpectedly dies, its entry in mBleApps list needs to be cleanup/removed. Test: Manual test by repeatedly killing the gms core process. Bug: 74076974 Change-Id: I2dc86b782dd6b07017a360a0b709504f0a375969 (cherry picked from commit 73a1651446c400ecd1b07f2f7f448d68406517f7) --- .../com/android/server/bluetooth/BluetoothManagerService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 02b1380715..ae56cb9268 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -632,6 +632,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, "Binder is dead - unregister " + mPackageName); } + + for (Map.Entry entry : mBleApps.entrySet()) { + IBinder token = entry.getKey(); + ClientDeathRecipient deathRec = entry.getValue(); + if (deathRec.equals(this)) { + mBleApps.remove(token); + break; + } + } + if (isBleAppPresent()) { // Nothing to do, another app is here. return; -- cgit v1.2.3 From 4f16d04b2bf85488a5d8df94d222882d3911af7f Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Tue, 20 Mar 2018 16:54:27 -0700 Subject: Calls unlinkToDeath in binderDied to deregister When a registered BLE App unexpectedly dies and the binderDied callback is called, the unlinkToDeath is called to remove linkage. Also, refactor code to use an existing function. Test: Manual test by repeatedly killing the gms core process. Bug: 74076974 Change-Id: If47a534ecafe7fceae14f8cf8526987cabd279cd (cherry picked from commit 699f42e24658b74f4b869b10633e9f31a7a9d7a8) --- .../server/bluetooth/BluetoothManagerService.java | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ae56cb9268..216794139c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -637,29 +637,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { IBinder token = entry.getKey(); ClientDeathRecipient deathRec = entry.getValue(); if (deathRec.equals(this)) { - mBleApps.remove(token); + updateBleAppCount(token, false, mPackageName); break; } } - - if (isBleAppPresent()) { - // Nothing to do, another app is here. - return; - } - if (DBG) { - Slog.d(TAG, "Disabling LE only mode after application crash"); - } - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { - mEnable = false; - mBluetooth.onBrEdrDown(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); - } } public String getPackageName() { -- cgit v1.2.3 From 450cadc996bbf7d9fee6eba48b24cdd7e68b1f0b Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Mon, 23 Apr 2018 11:17:17 -0700 Subject: BluetoothManagerService: Add dumpsys logs for BLE_ON -> OFF Add dumpsys logs for state transition from BLE_ON to OFF. This can be either from location settings off or airplane mode enabled. Test: manual Bug: 74090881 Change-Id: I1f6cfe691b359591af60c3be2e015bec5d3859e8 (cherry picked from commit 917f4b332e2c21f074e5f50bf598ff36d77f2945) --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8d10cfaaf9..2c0e97eae5 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -285,6 +285,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName(), false); mBluetooth.onBrEdrDown(); mEnable = false; mEnableExternal = false; @@ -677,6 +680,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + mContext.getPackageName(), false); mBluetooth.onBrEdrDown(); } } catch (RemoteException e) { -- cgit v1.2.3 From c89a9862ad53312de78f1b695feb6351bf56868f Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Fri, 11 May 2018 08:47:24 -0700 Subject: BluetoothManager: Continue when BLE not supported Bluetooth should turn on completely (without GATT) when the chip does not support Bluetooth Low Energy. Bug: 77495521 Test: Remove vendor/etc/permissions/android.hardware.bluetooth_le.xml Reboot Toggle Bluetooth Change-Id: I9314ee473b4a5a158196bab3037b1452247ba466 (cherry picked from commit 5123ebd75647d3e67487de69cd0381f325a0adc9) --- .../server/bluetooth/BluetoothManagerService.java | 37 +++++++--------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8d10cfaaf9..2a573b7f9d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -757,26 +757,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } /** - * Action taken when GattService is turned on + * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on. */ - private void onBluetoothGattServiceUp() { + private void continueFromBleOnState() { if (DBG) { - Slog.d(TAG, "BluetoothGatt Service is Up"); + Slog.d(TAG, "continueFromBleOnState()"); } try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { - if (DBG) { - Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!"); - } - return; - } - int st = mBluetooth.getState(); - if (st != BluetoothAdapter.STATE_BLE_ON) { - if (DBG) { - Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " - + BluetoothAdapter.nameForState(st)); - } + Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { @@ -1632,7 +1622,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service)); - onBluetoothGattServiceUp(); + continueFromBleOnState(); break; } // else must be SERVICE_IBLUETOOTH @@ -2049,21 +2039,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, "Bluetooth is in LE only mode"); } - if (mBluetoothGatt != null) { - if (DBG) { - Slog.d(TAG, "Calling BluetoothGattServiceUp"); - } - onBluetoothGattServiceUp(); + if (mBluetoothGatt != null || !mContext.getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + continueFromBleOnState(); } else { if (DBG) { Slog.d(TAG, "Binding Bluetooth GATT service"); } - if (mContext.getPackageManager() - .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { - Intent i = new Intent(IBluetoothGatt.class.getName()); - doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, - UserHandle.CURRENT); - } + Intent i = new Intent(IBluetoothGatt.class.getName()); + doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, + UserHandle.CURRENT); } sendBleStateChanged(prevState, newState); //Don't broadcase this as std intent -- cgit v1.2.3 From dea97b7e14979a37cf247b9204a7681b41a1f819 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Tue, 19 Jun 2018 08:48:10 -0700 Subject: Add Feature Flag for Hearing Aid Profile Using the Settings App-Developer Options-Feature Flag, allow the user to enable or disable the Hearing Aid Profile. Test: Manual testing using Settings App Change-Id: I58a9d339941e235242c443c85b6f4194b5a296c9 --- .../android/server/bluetooth/BluetoothManagerService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index aa426d3cd3..78b738500a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -53,12 +53,16 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.text.TextUtils; +import android.util.FeatureFlagUtils; +import android.util.Log; import android.util.Slog; import android.util.StatsLog; @@ -386,6 +390,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); + // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils + boolean isHearingAidEnabled; + String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS); + if (!TextUtils.isEmpty(value)) { + isHearingAidEnabled = Boolean.parseBoolean(value); + Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); + FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled); + } + IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); -- cgit v1.2.3 From c2342ac2d02119ac502e9cf427958409bc2b61a6 Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Wed, 18 Jul 2018 15:41:24 -0700 Subject: Always review permissions before mProfileServices = new HashMap<>(); - private final boolean mPermissionReviewRequired; + private final boolean mWirelessConsentRequired; private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override @@ -368,8 +368,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mPermissionReviewRequired = context.getResources() - .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired); + mWirelessConsentRequired = context.getResources() + .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired); mCrashes = 0; mBluetooth = null; @@ -885,7 +885,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { return false; } @@ -922,7 +922,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { return false; } @@ -945,7 +945,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean startConsentUiIfNeeded(String packageName, int callingUid, String intentAction) throws RemoteException { - if (checkBluetoothPermissionWhenPermissionReviewRequired()) { + if (checkBluetoothPermissionWhenWirelessConsentRequired()) { return false; } try { @@ -978,21 +978,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Check if the caller must still pass permission check or if the caller is exempted - * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check. + * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check. * * Commands from some callers may be exempted from triggering the consent UI when * enabling bluetooth. This exemption is checked via the - * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip + * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip * the consent UI where it may otherwise be required. * * @hide */ - private boolean checkBluetoothPermissionWhenPermissionReviewRequired() { - if (!mPermissionReviewRequired) { - return false; - } + private boolean checkBluetoothPermissionWhenWirelessConsentRequired() { int result = mContext.checkCallingPermission( - android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED); + android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED); return result == PackageManager.PERMISSION_GRANTED; } -- cgit v1.2.3 From 2d006b8a24d6ac043ece40c4dcff0cf3ab61323c Mon Sep 17 00:00:00 2001 From: jonerlin Date: Thu, 9 Aug 2018 16:39:43 +0800 Subject: AdapterService: Only bind HeadsetService in ON state. * there will be an endless loop to call doBind and cause many connectionRecords of HeadsetService while binding HeadsetService in BLE_ON state. * allow to bind HeadsetService only when BT state is ON Bug: 111730478 Test: Keep device in BLE_ON state -> kill com.android.phone process -> As time goes on, adb shell dumpsys activity services to check the connectionRecords of HeadsetService will not become more and more Change-Id: I5f66d015b8aa3c94c7e887ef033213af74235b4a --- .../server/bluetooth/BluetoothManagerService.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index aa426d3cd3..99e0056254 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1161,6 +1161,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean bindService() { + int state = BluetoothAdapter.STATE_OFF; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + state = mBluetooth.getState(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + return false; + } finally { + mBluetoothLock.readLock().unlock(); + } + + if (!mEnable || state != BluetoothAdapter.STATE_ON) { + if (DBG) { + Slog.d(TAG, "Unable to bindService while Bluetooth is disabled"); + } + return false; + } + if (mIntent != null && mService == null && doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); -- cgit v1.2.3 From 2a2cd5db7bc3924c92fe75f53f8b848b1a6a3a86 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Tue, 19 Jun 2018 08:48:10 -0700 Subject: Add Feature Flag for Hearing Aid Profile Using the Settings App-Developer Options-Feature Flag, allow the user to enable or disable the Hearing Aid Profile. Bug: 116317072 Bug: 116044083 Test: Manual testing using Settings App Change-Id: I58a9d339941e235242c443c85b6f4194b5a296c9 Merged-In: I58a9d339941e235242c443c85b6f4194b5a296c9 (cherry picked from commit dea97b7e14979a37cf247b9204a7681b41a1f819) --- .../android/server/bluetooth/BluetoothManagerService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 99e0056254..49de4b1577 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -53,12 +53,16 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.text.TextUtils; +import android.util.FeatureFlagUtils; +import android.util.Log; import android.util.Slog; import android.util.StatsLog; @@ -386,6 +390,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); + // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils + boolean isHearingAidEnabled; + String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS); + if (!TextUtils.isEmpty(value)) { + isHearingAidEnabled = Boolean.parseBoolean(value); + Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); + FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled); + } + IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); -- cgit v1.2.3 From 4554d5a132649aad6f14e224d3c9e29e73f23985 Mon Sep 17 00:00:00 2001 From: Chienyuan Date: Tue, 18 Dec 2018 10:40:25 +0800 Subject: BluetoothManagerService: catch NoSuchElementException for unlinkToDeath linkToDeath fail will cause NoSuchElementException when following unlinkToDeath, add try catch to handle it. Bug: 121104808 Test: build pass Change-Id: Idc4959331841946e2fc099bdc0fab7c753caf369 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 49de4b1577..555e89947a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -76,6 +76,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.Locale; import java.util.Map; +import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -1279,7 +1280,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mService == null) { return; } - mService.unlinkToDeath(this, 0); + try { + mService.unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + Log.e(TAG, "error unlinking to death", e); + } mService = null; mClassName = null; -- cgit v1.2.3 From 14c2b631b9b7a974f23c1492a19b2a68e32446db Mon Sep 17 00:00:00 2001 From: Rene Mayrhofer Date: Wed, 28 Nov 2018 11:32:40 -0800 Subject: Enable airplane mode when booting in safe mode Make it possible to boot in airplane mode when it was not turned on before shutdown/reboot, either for situations where this is required by regulation or to work around problems in normal boot. When safe mode is engaged (Vol-Down), disable in two stages: 1. Set Settings.Global.AIRPLANE_MODE_ON as early as possible for subsystems to react to it during their initialization. 2. Trigger the public ConnectiviyService API to enable airplane mode. This has to be done during later stages in initialization because it requires sending broadcasts, so some RF leakage may still happen before airplane mode is enabled (time window of a few seconds). Bluetooth is not currently disabled and needs to be fixed by another change. WiFi and NFC are turned off alongside cellular modems. Test: manual Bug: 120145930 Change-Id: I1d61990a9d6f7cd046d28b3e49ecf402dd485063 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 7bbc543a6a..a33338164c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -279,7 +279,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( - st)); + st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off -- cgit v1.2.3 From 2d4e9092b015b14419cf9a2ecbd64b12c431ee89 Mon Sep 17 00:00:00 2001 From: Rene Mayrhofer Date: Wed, 28 Nov 2018 11:32:40 -0800 Subject: Enable airplane mode when booting in safe mode Make it possible to boot in airplane mode when it was not turned on before shutdown/reboot, either for situations where this is required by regulation or to work around problems in normal boot. When safe mode is engaged (Vol-Down), disabled in two stages: 1. Set Settings.Global.AIRPLANE_MODE_ON as early as possible for subsystems to react to it during their initialization. 2. Trigger the public ConnectiviyService API to enable airplane mode. This has to be done during later stages in initialization because it requires sending broadcasts, so some RF leakage may still happen before airplane mode is enabled (time window of a few seconds). Bluetooth is not currently disabled and needs to be fixed by another change. WiFi and NFC are turned off alongside cellular modems. Test: manual Bug: 120145930 Change-Id: I1d61990a9d6f7cd046d28b3e49ecf402dd485063 (cherry picked from commit afc9bc80941ea015cb591a0032e7553b5805fcc6) --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 555e89947a..5ea3390d4e 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -279,7 +279,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( - st)); + st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); if (isAirplaneModeOn()) { // Clear registered LE apps to force shut-off -- cgit v1.2.3 From 370a8ae8d0e015a5e01a3c1c2c3b1387e3026b08 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Sun, 13 Jan 2019 16:04:31 -0800 Subject: Add 2 new ways to check for Support for Hearing Aids Profile The getProfileProxy will return false if Hearing Aids Profile is not supported. Also the getSupportedProfiles will return the correct support for Hearing Aids even when Bluetooth is disabled. Test: Manual testing with configuration enabled and disabled. Bug: 119617521 Change-Id: I146bd3bc36d4c474f7bca18a05b679fb8e70ca63 --- .../server/bluetooth/BluetoothManagerService.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 5ea3390d4e..b60dd0f52c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -208,6 +208,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private int mErrorRecoveryRetryCounter; private final int mSystemUiUid; + private boolean mIsHearingAidProfileSupported; + // Save a ProfileServiceConnections object for each of the bound // bluetooth profile services private final Map mProfileServices = new HashMap<>(); @@ -391,13 +393,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); + mIsHearingAidProfileSupported = context.getResources() + .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported); + // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils - boolean isHearingAidEnabled; String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS); if (!TextUtils.isEmpty(value)) { - isHearingAidEnabled = Boolean.parseBoolean(value); + boolean isHearingAidEnabled = Boolean.parseBoolean(value); Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled); + if (isHearingAidEnabled && !mIsHearingAidProfileSupported) { + // Overwrite to enable support by FeatureFlag + mIsHearingAidProfileSupported = true; + } } IntentFilter filter = new IntentFilter(); @@ -679,6 +687,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + @Override + public boolean isHearingAidProfileSupported() { + return mIsHearingAidProfileSupported; + } + // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = new ContentObserver(null) { -- cgit v1.2.3 From 11b45bb70b048c6a3ed91e5eaf93b80df618c8ff Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 23 Apr 2019 20:00:18 -0700 Subject: Bluetooth: Check if packageName belongs to callingUid in binder calls * Several Bluetooth APIs take packageName parameter from Apps, which is resolved through ActivityThread.currentPackageName() * Add checks to make sure that packageName passed through binder calls actually belongs to the calling uid Bug: 120574260 Test: make, enable/disable Bluetooth Change-Id: If6593cf8cbab91eb27b9f22b635f984c04ec2de2 --- .../server/bluetooth/BluetoothManagerService.java | 49 +++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c4bc52c6f4..e88568424f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -19,6 +19,7 @@ package com.android.server; import android.Manifest; import android.app.ActivityManager; import android.app.AppGlobals; +import android.app.AppOpsManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; @@ -210,6 +211,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mIsHearingAidProfileSupported; + private AppOpsManager mAppOps; + // Save a ProfileServiceConnections object for each of the bound // bluetooth profile services private final Map mProfileServices = new HashMap<>(); @@ -742,6 +745,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public int updateBleAppCount(IBinder token, boolean enable, String packageName) { + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + } ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); @@ -857,6 +866,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); @@ -864,7 +880,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } - int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); + int callingAppId = UserHandle.getAppId(callingUid); if (callingAppId != Process.NFC_UID) { throw new SecurityException("no permission to enable Bluetooth quietly"); @@ -891,6 +907,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!callerSystem) { + // Check if packageName belongs to callingUid + checkPackage(callingUid, packageName); + if (!checkIfCallerIsForegroundUser()) { Slog.w(TAG, "enable(): not allowed for non-active and non system user"); return false; @@ -928,6 +947,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; if (!callerSystem) { + // Check if packageName belongs to callingUid + checkPackage(callingUid, packageName); + if (!checkIfCallerIsForegroundUser()) { Slog.w(TAG, "disable(): not allowed for non-active and non system user"); return false; @@ -990,6 +1012,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + /** + * Check if AppOpsManager is available and the packageName belongs to uid + * + * A null package belongs to any uid + */ + private void checkPackage(int uid, String packageName) { + if (mAppOps == null) { + Slog.w(TAG, "checkPackage(): called before system boot up, uid " + + uid + ", packageName " + packageName); + throw new IllegalStateException("System has not boot yet"); + } + if (packageName == null) { + Slog.w(TAG, "checkPackage(): called with null packageName from " + uid); + return; + } + try { + mAppOps.checkPackage(uid, packageName); + } catch (SecurityException e) { + Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid); + android.util.EventLog.writeEvent(0x534e4554, "120574260", uid, ""); + throw new SecurityException(e.getMessage()); + } + } + /** * Check if the caller must still pass permission check or if the caller is exempted * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check. @@ -1122,6 +1168,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, "Bluetooth boot completed"); } + mAppOps = mContext.getSystemService(AppOpsManager.class); UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); -- cgit v1.2.3 From 4e34f0d8884bb32936bc30e2446f6c8c0a5b7560 Mon Sep 17 00:00:00 2001 From: Jack He Date: Wed, 24 Apr 2019 16:21:12 -0700 Subject: Bluetooth: Remove safetynet logging for 120574260 Bug: 120574260 Test: make Change-Id: Id86c139e654428f8d4376f2d0359329e47c052b9 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index e88568424f..6573c3bf79 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1031,7 +1031,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mAppOps.checkPackage(uid, packageName); } catch (SecurityException e) { Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid); - android.util.EventLog.writeEvent(0x534e4554, "120574260", uid, ""); throw new SecurityException(e.getMessage()); } } -- cgit v1.2.3 From 1652b94a121a19863c554551c57406cbef504ce8 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 26 Mar 2019 21:38:08 +0800 Subject: Fix binder leakage when turning off Bluetooth * In current design, Bluetooth AdapterState stops all BR/EDR profiles' service and triggers onServiceDisconnected callback to all binder clients before BluetoothManagerService invokes onBluetoothStateChange(false), which means unbind service would never be called in framework. * Do unbind service when onServiceDisconnected is invoked. * Move profile binder logic to BluetoothProfileConnector except: - BluetoothHeadset: its binder logic is in BluetoothManagerService - BluetoothPbap: it has an individual ServiceListener Bug: 129037442 Bug: 129437895 Test: Bluetooth ON/OFF stress test. adb shell dumpsys activity services | egrep "com.android.bluetooth" to check whether AppBindRecord for com.android.bluetooth grows Merged-In: Id0d85866d386962b94d2d966f0a864b1da165d13 Change-Id: Id0d85866d386962b94d2d966f0a864b1da165d13 --- .../server/bluetooth/BluetoothManagerService.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b60dd0f52c..223eb552f8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1094,11 +1094,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { synchronized (mProfileServices) { - ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); + Integer profile = new Integer(bluetoothProfile); + ProfileServiceConnections psc = mProfileServices.get(profile); if (psc == null) { return; } psc.removeProxy(proxy); + if (psc.isEmpty()) { + // All prxoies are disconnected, unbind with the service. + try { + mContext.unbindService(psc); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); + } + mProfileServices.remove(profile); + } } } @@ -1255,6 +1265,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mProxies.kill(); } + private boolean isEmpty() { + return mProxies.getRegisteredCallbackCount() == 0; + } + @Override public void onServiceConnected(ComponentName className, IBinder service) { // remove timeout message -- cgit v1.2.3 From 70d76596569ec6c17761bdc4099015e756e7b61b Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 26 Mar 2019 21:38:08 +0800 Subject: Fix binder leakage when turning off Bluetooth * In current design, Bluetooth AdapterState stops all BR/EDR profiles' service and triggers onServiceDisconnected callback to all binder clients before BluetoothManagerService invokes onBluetoothStateChange(false), which means unbind service would never be called in framework. * Do unbind service when onServiceDisconnected is invoked. * Move profile binder logic to BluetoothProfileConnector except: - BluetoothHeadset: its binder logic is in BluetoothManagerService - BluetoothPbap: it has an individual ServiceListener Bug: 129037442 Bug: 129437895 Test: Bluetooth ON/OFF stress test. adb shell dumpsys activity services | egrep "com.android.bluetooth" to check whether AppBindRecord for com.android.bluetooth grows Change-Id: Id0d85866d386962b94d2d966f0a864b1da165d13 --- .../server/bluetooth/BluetoothManagerService.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c4bc52c6f4..9405ed26e5 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1091,11 +1091,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void unbindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { synchronized (mProfileServices) { - ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); + Integer profile = new Integer(bluetoothProfile); + ProfileServiceConnections psc = mProfileServices.get(profile); if (psc == null) { return; } psc.removeProxy(proxy); + if (psc.isEmpty()) { + // All prxoies are disconnected, unbind with the service. + try { + mContext.unbindService(psc); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); + } + mProfileServices.remove(profile); + } } } @@ -1252,6 +1262,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mProxies.kill(); } + private boolean isEmpty() { + return mProxies.getRegisteredCallbackCount() == 0; + } + @Override public void onServiceConnected(ComponentName className, IBinder service) { // remove timeout message -- cgit v1.2.3 From 126dc8bbaeed8bc25251b688273e21a315d108e9 Mon Sep 17 00:00:00 2001 From: Zongheng Wang Date: Mon, 8 Jul 2019 15:22:04 -0700 Subject: Do not turn on Bluetooth when booting into Safe Mode Bug: 122691743 Test: Boot into Safe Mode and Bluetooth is not turned on. Change-Id: I653b2f58c462631e9c4cc868c4ec1932ff907999 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 223eb552f8..89b59cf4a7 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1142,7 +1142,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBluetoothDisallowed) { return; } - if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { + final boolean isSafeMode = mContext.getPackageManager().isSafeMode(); + if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) { if (DBG) { Slog.d(TAG, "Auto-enabling Bluetooth."); } -- cgit v1.2.3 From 96067532ad3ca7966ea5cfd5ebf966675f9a9334 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Wed, 20 Nov 2019 17:59:11 +0800 Subject: Limit the retry attemps on restarting Bluetooth * Back off the delay time of resarting Bluetooth when there's continous turn on failures. * Stop to restart Bluetooth if we are seeing back to back Bluetooth crashes, so we won't see endless diaglogs popping out. Bug: 144572641 Test: Manual Change-Id: Ifeffa214256eab61901c123fc88b037fc6d7dd50 --- .../server/bluetooth/BluetoothManagerService.java | 48 ++++++++++++---------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 208b63888e..798a4c663c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -98,7 +98,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind //Maximum msec to wait for service restart - private static final int SERVICE_RESTART_TIME_MS = 200; + private static final int SERVICE_RESTART_TIME_MS = 400; //Maximum msec to wait for restart due to error private static final int ERROR_RESTART_TIME_MS = 3000; //Maximum msec to delay MESSAGE_USER_SWITCHED @@ -1635,13 +1635,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // ActivityManager detects it. // The waiting for (b) and (c) is accomplished by // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE - // message. On slower devices, that delay needs to be - // on the order of (2 * SERVICE_RESTART_TIME_MS). + // message. The delay time is backed off if Bluetooth + // continuously failed to turn on itself. // waitForOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } break; @@ -1820,7 +1820,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { waitForOnOff(false, true); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } } if (newState == BluetoothAdapter.STATE_ON @@ -1863,7 +1863,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Send a Bluetooth Restart message Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, SERVICE_RESTART_TIME_MS); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); } sendBluetoothServiceDownCallback(); @@ -1886,14 +1886,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } case MESSAGE_RESTART_BLUETOOTH_SERVICE: { - Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE"); - /* Enable without persisting the setting as - it doesnt change when IBluetooth - service restarts */ - mEnable = true; - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, - mContext.getPackageName(), true); - handleEnable(mQuietEnable); + mErrorRecoveryRetryCounter++; + Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count=" + + mErrorRecoveryRetryCounter); + if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) { + /* Enable without persisting the setting as + it doesnt change when IBluetooth + service restarts */ + mEnable = true; + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED, + mContext.getPackageName(), true); + handleEnable(mQuietEnable); + } else { + Slog.e(TAG, "Reach maximum retry to restart Bluetooth!"); + } break; } case MESSAGE_TIMEOUT_BIND: { @@ -2332,13 +2338,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnable = false; - if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { - // Send a Bluetooth Restart message to reenable bluetooth - Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); - } else { - // todo: notify user to power down and power up phone to make bluetooth work. - } + // Send a Bluetooth Restart message to reenable bluetooth + Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); } private boolean isBluetoothDisallowed() { @@ -2374,6 +2376,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private int getServiceRestartMs() { + return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS; + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { -- cgit v1.2.3 From b997c1f1fa16b9658adfb10a770dc9b1baedb018 Mon Sep 17 00:00:00 2001 From: Zach Johnson Date: Tue, 26 Nov 2019 21:30:07 -0800 Subject: Implement isEnabled in terms of getState Bug: 145171640 Test: compile & check everything works normally Change-Id: I169e220ab83546d76317e518652c66c9bd2229a2 --- .../server/bluetooth/BluetoothManagerService.java | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 208b63888e..2827bd3261 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -613,22 +613,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean isEnabled() { - if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { - Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user"); - return false; - } - - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - return mBluetooth.isEnabled(); - } - } catch (RemoteException e) { - Slog.e(TAG, "isEnabled()", e); - } finally { - mBluetoothLock.readLock().unlock(); - } - return false; + return getState() == BluetoothAdapter.STATE_ON; } public int getState() { -- cgit v1.2.3 From e76a4104da52fa6a2edfda86ddb5e3d124efb734 Mon Sep 17 00:00:00 2001 From: Zach Johnson Date: Tue, 26 Nov 2019 21:46:08 -0800 Subject: Call parameterized version of IBluetooth.enable Bug: 145171640 Test: compile & verify starts Change-Id: I725d1b81b78455b7febe250161d9eb9859434d2a --- .../server/bluetooth/BluetoothManagerService.java | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 2827bd3261..87149d37f1 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1751,14 +1751,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Do enable request try { - if (!mQuietEnable) { - if (!mBluetooth.enable()) { - Slog.e(TAG, "IBluetooth.enable() returned false"); - } - } else { - if (!mBluetooth.enableNoAutoConnect()) { - Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false"); - } + if (!mBluetooth.enable(mQuietEnable)) { + Slog.e(TAG, "IBluetooth.enable() returned false"); } } catch (RemoteException e) { Slog.e(TAG, "Unable to call enable()", e); @@ -2027,14 +2021,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (mBluetooth != null) { //Enable bluetooth try { - if (!mQuietEnable) { - if (!mBluetooth.enable()) { - Slog.e(TAG, "IBluetooth.enable() returned false"); - } - } else { - if (!mBluetooth.enableNoAutoConnect()) { - Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false"); - } + if (!mBluetooth.enable(mQuietEnable)) { + Slog.e(TAG, "IBluetooth.enable() returned false"); } } catch (RemoteException e) { Slog.e(TAG, "Unable to call enable()", e); -- cgit v1.2.3 From 028e5cae047509a536304398c92e87f369a296bb Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Fri, 29 Nov 2019 22:11:11 +0100 Subject: Do not call SystemConfig.getInstance() from Bluetooth (1/2) Move call to SystemConfig.getInstance into BluetoothManagerService Bug: 145297991 Change-Id: I6edd91b831a240117757cb6683d8a373e861db99 --- .../server/bluetooth/BluetoothManagerService.java | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 798a4c663c..a318844359 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -74,6 +74,7 @@ import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; +import java.util.ArrayList; import java.util.LinkedList; import java.util.Locale; import java.util.Map; @@ -695,6 +696,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mIsHearingAidProfileSupported; } + @Override + /** @hide */ + public java.util.List getSystemConfigEnabledProfilesForPackage(String packageName) { + if (Binder.getCallingUid() != Process.BLUETOOTH_UID) { + Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth"); + return null; + } + + SystemConfig systemConfig = SystemConfig.getInstance(); + if (systemConfig == null) { + return null; + } + + android.util.ArrayMap componentEnabledStates = + systemConfig.getComponentsEnabledStates(packageName); + if (componentEnabledStates == null) { + return null; + } + + ArrayList enabledProfiles = new ArrayList(); + for (Map.Entry entry : componentEnabledStates.entrySet()) { + if (entry.getValue()) { + enabledProfiles.add(entry.getKey()); + } + } + + return enabledProfiles; + } + // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = new ContentObserver(null) { -- cgit v1.2.3 From 492c97c1c8552980aec761670ee7893ab5867713 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 6 Nov 2019 15:00:48 -0800 Subject: Remove a few hard coded references to SystemUI in fw/base/services Bug: 143775123 Test: atest ScreenshotHelperTest Test: atest AlarmManagerTest Change-Id: I2fefe2968e23bc2d06aa52266c2eeeb90f4733ee --- .../server/bluetooth/BluetoothManagerService.java | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 119b987f7a..470300e648 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -16,6 +16,9 @@ package com.android.server; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; +import static android.os.UserHandle.USER_SYSTEM; + import android.Manifest; import android.app.ActivityManager; import android.app.AppGlobals; @@ -42,6 +45,7 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; @@ -242,10 +246,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. - if (userId == UserHandle.USER_SYSTEM + if (userId == USER_SYSTEM && UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { - if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( + if (userId == USER_SYSTEM && newRestrictions.getBoolean( UserManager.DISALLOW_BLUETOOTH)) { updateOppLauncherComponentState(userId, true); // Sharing disallowed sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, @@ -437,18 +441,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } int systemUiUid = -1; - try { - // Check if device is configured with no home screen, which implies no SystemUI. - boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen); - if (!noHome) { - systemUiUid = mContext.getPackageManager() - .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, - UserHandle.USER_SYSTEM); - } + // Check if device is configured with no home screen, which implies no SystemUI. + boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen); + if (!noHome) { + PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); + systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(), + MATCH_SYSTEM_ONLY, USER_SYSTEM); + } + if (systemUiUid >= 0) { Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid)); - } catch (PackageManager.NameNotFoundException e) { + } else { // Some platforms, such as wearables do not have a system ui. - Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); + Slog.w(TAG, "Unable to resolve SystemUI's UID."); } mSystemUiUid = systemUiUid; } -- cgit v1.2.3 From 9a68067a4289606fbcc968b7eb096d23b5e6d244 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Wed, 16 Oct 2019 20:27:23 +0800 Subject: Context-aware Bluetooth airplane mode Do not automatically turn off Bluetooth when airplane mode is turned on and Bluetooth is in one of the following situations: 1. Bluetooth A2DP is connected. 2. Bluetooth Hearing Aid profile is connected. Bug: 142831248 Test: Manual Change-Id: I7f10b27102d91cc7a9803f74c88a4af80a294fb9 --- .../server/bluetooth/BluetoothManagerService.java | 131 ++++++++++++--------- 1 file changed, 74 insertions(+), 57 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index cdfd310a85..fa8eda54e5 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -68,6 +68,7 @@ import android.util.Slog; import android.util.StatsLog; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.server.pm.UserRestrictionsUtils; @@ -138,7 +139,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Bluetooth persisted setting is on // but Airplane mode will affect Bluetooth state at start up // and Airplane mode will have higher priority. - private static final int BLUETOOTH_ON_AIRPLANE = 2; + @VisibleForTesting + static final int BLUETOOTH_ON_AIRPLANE = 2; private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; @@ -159,6 +161,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mBinding; private boolean mUnbinding; + private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; + // used inside handler thread private boolean mQuietEnable = false; private boolean mEnable; @@ -257,68 +261,65 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; - private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { - @Override - public void onChange(boolean unused) { - synchronized (this) { - if (isBluetoothPersistedStateOn()) { - if (isAirplaneModeOn()) { - persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); - } else { - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - } + public void onAirplaneModeChanged() { + synchronized (this) { + if (isBluetoothPersistedStateOn()) { + if (isAirplaneModeOn()) { + persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); + } else { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } + } - int st = BluetoothAdapter.STATE_OFF; - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - st = mBluetooth.getState(); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call getState", e); - return; - } finally { - mBluetoothLock.readLock().unlock(); + int st = BluetoothAdapter.STATE_OFF; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + st = mBluetooth.getState(); } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + return; + } finally { + mBluetoothLock.readLock().unlock(); + } - Slog.d(TAG, - "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( - st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); + Slog.d(TAG, + "Airplane Mode change - current state: " + BluetoothAdapter.nameForState( + st) + ", isAirplaneModeOn()=" + isAirplaneModeOn()); - if (isAirplaneModeOn()) { - // Clear registered LE apps to force shut-off - clearBleApps(); + if (isAirplaneModeOn()) { + // Clear registered LE apps to force shut-off + clearBleApps(); - // If state is BLE_ON make sure we trigger disableBLE - if (st == BluetoothAdapter.STATE_BLE_ON) { - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - addActiveLog( - BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, - mContext.getPackageName(), false); - mBluetooth.onBrEdrDown(); - mEnable = false; - mEnableExternal = false; - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBrEdrDown", e); - } finally { - mBluetoothLock.readLock().unlock(); + // If state is BLE_ON make sure we trigger disableBLE + if (st == BluetoothAdapter.STATE_BLE_ON) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName(), false); + mBluetooth.onBrEdrDown(); + mEnable = false; + mEnableExternal = false; } - } else if (st == BluetoothAdapter.STATE_ON) { - sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, - mContext.getPackageName()); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); } - } else if (mEnableExternal) { - sendEnableMsg(mQuietEnableExternal, - BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + } else if (st == BluetoothAdapter.STATE_ON) { + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, mContext.getPackageName()); } + } else if (mEnableExternal) { + sendEnableMsg(mQuietEnableExternal, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName()); } } - }; + } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -430,9 +431,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS); if (airplaneModeRadios == null || airplaneModeRadios.contains( Settings.Global.RADIO_BLUETOOTH)) { - mContentResolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, - mAirplaneModeObserver); + mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener( + this, IoThread.get().getLooper(), context); } int systemUiUid = -1; @@ -478,6 +478,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return state != BLUETOOTH_OFF; } + private boolean isBluetoothPersistedStateOnAirplane() { + if (!supportBluetoothPersistedState()) { + return false; + } + int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1); + if (DBG) { + Slog.d(TAG, "Bluetooth persisted state: " + state); + } + return state == BLUETOOTH_ON_AIRPLANE; + } + /** * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH */ @@ -954,10 +965,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } synchronized (mReceiver) { - if (persist) { - persistBluetoothSetting(BLUETOOTH_OFF); + if (!isBluetoothPersistedStateOnAirplane()) { + if (persist) { + persistBluetoothSetting(BLUETOOTH_OFF); + } + mEnableExternal = false; } - mEnableExternal = false; sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); } @@ -1185,6 +1198,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); } + if (mBluetoothAirplaneModeListener != null) { + mBluetoothAirplaneModeListener.start( + new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext)); + } } /** -- cgit v1.2.3 From a5ff0917296a796c862b44d9121460952d2cb57a Mon Sep 17 00:00:00 2001 From: Muhammad Qureshi Date: Tue, 28 Jan 2020 10:54:17 -0800 Subject: Use FrameworkStatsLog instead of StatsLog As part of statsd becoming a Mainline module in R, autogenerated StatsLog.write() calls are going away and replaced by *StatsLog.java that is autogenerated for each module. This CL replaces some usages of StatsLog with FrameworkStatsLog. Bug: 145952197 Test: m Change-Id: Iaa2db34a7be4c3215f62cc36661ba8ac81656baa --- .../com/android/server/bluetooth/BluetoothManagerService.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 3774b64533..311a494ee5 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -69,17 +69,17 @@ import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.HashMap; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.Locale; import java.util.Map; @@ -87,7 +87,6 @@ import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; - class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -2300,9 +2299,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { new ActiveLog(reason, packageName, enable, System.currentTimeMillis())); } - int state = enable ? StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : - StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; - StatsLog.write_non_chained(StatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, + int state = enable ? FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : + FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, Binder.getCallingUid(), null, state, reason, packageName); } -- cgit v1.2.3 From 2167e541b1840a617b3632047d63719234a7ab1c Mon Sep 17 00:00:00 2001 From: Mike Ma Date: Wed, 12 Feb 2020 13:07:47 -0800 Subject: Implement dumpsys bluetooth_manager --proto Add BluetoothManagerServiceDumpProto for protobuf dumpsys of bluetooth manager service. Primarily used by incident service to capture an incident report proto. Command to invoke (any of the following after lunch and env setup): $ adb shell dumpsys bluetooth_manager --proto $ adb shell incident 3050 $ incident_report 3050 Bug: 146085372 Test: Execute the above commands and compare the output against normal dumpsys Change-Id: I7ccef334ffeae02316db3afff929998b544972b1 --- .../server/bluetooth/BluetoothManagerService.java | 131 +++++++++++++-------- 1 file changed, 83 insertions(+), 48 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 311a494ee5..a4a42bcaec 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -69,6 +69,7 @@ import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -196,6 +197,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName; } + void dump(ProtoOutputStream proto) { + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason); + } } private final LinkedList mActiveLogs = new LinkedList<>(); @@ -2408,56 +2415,56 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { return; } + if ((args.length > 0) && args[0].startsWith("--proto")) { + dumpProto(fd); + return; + } String errorMsg = null; - boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); - - if (!protoOut) { - writer.println("Bluetooth Status"); - writer.println(" enabled: " + isEnabled()); - writer.println(" state: " + BluetoothAdapter.nameForState(mState)); - writer.println(" address: " + mAddress); - writer.println(" name: " + mName); - if (mEnable) { - long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; - String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", - (int) (onDuration / (1000 * 60 * 60)), - (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), - (int) (onDuration % 1000)); - writer.println(" time since enabled: " + onDurationString); - } - - if (mActiveLogs.size() == 0) { - writer.println("\nBluetooth never enabled!"); - } else { - writer.println("\nEnable log:"); - for (ActiveLog log : mActiveLogs) { - writer.println(" " + log); - } + writer.println("Bluetooth Status"); + writer.println(" enabled: " + isEnabled()); + writer.println(" state: " + BluetoothAdapter.nameForState(mState)); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName); + if (mEnable) { + long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; + String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", + (int) (onDuration / (1000 * 60 * 60)), + (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), + (int) (onDuration % 1000)); + writer.println(" time since enabled: " + onDurationString); + } + + if (mActiveLogs.size() == 0) { + writer.println("\nBluetooth never enabled!"); + } else { + writer.println("\nEnable log:"); + for (ActiveLog log : mActiveLogs) { + writer.println(" " + log); } + } - writer.println( - "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); - if (mCrashes == CRASH_LOG_MAX_SIZE) { - writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); - } - for (Long time : mCrashTimestamps) { - writer.println(" " + timeToLog(time)); - } + writer.println( + "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); + if (mCrashes == CRASH_LOG_MAX_SIZE) { + writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); + } + for (Long time : mCrashTimestamps) { + writer.println(" " + timeToLog(time)); + } - writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") - + "registered"); - for (ClientDeathRecipient app : mBleApps.values()) { - writer.println(" " + app.getPackageName()); - } + writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") + + " registered"); + for (ClientDeathRecipient app : mBleApps.values()) { + writer.println(" " + app.getPackageName()); + } - writer.println(""); - writer.flush(); - if (args.length == 0) { - // Add arg to produce output - args = new String[1]; - args[0] = "--print"; - } + writer.println(""); + writer.flush(); + if (args.length == 0) { + // Add arg to produce output + args = new String[1]; + args[0] = "--print"; } if (mBluetoothBinder == null) { @@ -2470,14 +2477,42 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } if (errorMsg != null) { - // Silently return if we are extracting metrics in Protobuf format - if (protoOut) { - return; - } writer.println(errorMsg); } } + private void dumpProto(FileDescriptor fd) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled()); + proto.write(BluetoothManagerServiceDumpProto.STATE, mState); + proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, + BluetoothAdapter.nameForState(mState)); + proto.write(BluetoothManagerServiceDumpProto.ADDRESS, mAddress); + proto.write(BluetoothManagerServiceDumpProto.NAME, mName); + if (mEnable) { + proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime); + } + proto.write(BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS, + SystemClock.elapsedRealtime()); + for (ActiveLog log : mActiveLogs) { + long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS); + log.dump(proto); + proto.end(token); + } + proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes); + proto.write(BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED, + mCrashes == CRASH_LOG_MAX_SIZE); + for (Long time : mCrashTimestamps) { + proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time); + } + proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size()); + for (ClientDeathRecipient app : mBleApps.values()) { + proto.write(BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES, + app.getPackageName()); + } + proto.flush(); + } + private static String getEnableDisableReasonString(int reason) { switch (reason) { case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST: -- cgit v1.2.3 From e18a909013a8f521a0876ab5fd67c2ec8d151323 Mon Sep 17 00:00:00 2001 From: weichinweng Date: Thu, 5 Mar 2020 10:37:44 +0800 Subject: Fix bluetooth can't turn off during network reset (2/3) Remove disable Bluetooth action from AdapterService and move to BluetoothManagerService. Add factory reset reason into Bluetooth enable/disable reason list. Bug: 110181479 Test: manual Change-Id: I4bff3c3bb75fbb0d1e13c459c0d9d3fd3b8b3195 --- .../server/bluetooth/BluetoothManagerService.java | 104 ++++++++++++++------- 1 file changed, 70 insertions(+), 34 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index a4a42bcaec..03ca1c610f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -85,6 +85,7 @@ import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -272,6 +273,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + public boolean onFactoryReset() { + // Wait for stable state if bluetooth is temporary state. + int state = getState(); + if (state == BluetoothAdapter.STATE_BLE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_OFF) { + if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) { + return false; + } + } + + // Clear registered LE apps to force shut-off Bluetooth + clearBleApps(); + state = getState(); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth == null) { + return false; + } + if (state == BluetoothAdapter.STATE_BLE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.onBrEdrDown(); + return true; + } else if (state == BluetoothAdapter.STATE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.disable(); + return true; + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to shutdown Bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + return false; + } + public void onAirplaneModeChanged() { synchronized (this) { if (isBluetoothPersistedStateOn()) { @@ -1670,7 +1711,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by "waitForOnOff(false, true)". + // is accomplished by + // "waitForState(Set.of(BluetoothAdapter.STATE_OFF))". // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1680,7 +1722,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); @@ -1693,10 +1735,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); mEnable = false; handleDisable(); - waitForOnOff(false, false); + waitForState(Set.of(BluetoothAdapter.STATE_OFF, + BluetoothAdapter.STATE_TURNING_ON, + BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_BLE_TURNING_OFF)); } else { mEnable = false; handleDisable(); @@ -1819,9 +1866,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); handleDisable(); - waitForOnOff(false, false); + waitForState(Set.of(BluetoothAdapter.STATE_OFF, + BluetoothAdapter.STATE_TURNING_ON, + BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_BLE_TURNING_OFF)); } break; } @@ -1853,7 +1905,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); @@ -1982,7 +2034,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); @@ -1997,7 +2049,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); - boolean didDisableTimeout = !waitForOnOff(false, true); + boolean didDisableTimeout = + !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); @@ -2243,12 +2296,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - /** - * 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) { + private boolean waitForState(Set states) { int i = 0; while (i < 10) { try { @@ -2256,18 +2304,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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; - } + if (states.contains(mBluetooth.getState())) { + return true; } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); @@ -2275,14 +2313,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - if (on || off) { - SystemClock.sleep(300); - } else { - SystemClock.sleep(50); - } + SystemClock.sleep(300); i++; } - Slog.e(TAG, "waitForOnOff time out"); + Slog.e(TAG, "waitForState " + states + " time out"); return false; } @@ -2343,7 +2377,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName(), false); handleDisable(); - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); sendBluetoothServiceDownCallback(); @@ -2533,6 +2567,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return "USER_SWITCH"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: return "RESTORE_USER_SETTING"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: + return "FACTORY_RESET"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: default: return "UNKNOWN[" + reason + "]"; } -- cgit v1.2.3 From e466ff5d119d7ad9913e98203a92adc2fe875af2 Mon Sep 17 00:00:00 2001 From: weichinweng Date: Thu, 5 Mar 2020 10:37:44 +0800 Subject: Fix bluetooth can't turn off during network reset (2/3) Remove disable Bluetooth action from AdapterService and move to BluetoothManagerService. Add factory reset reason into Bluetooth enable/disable reason list. Bug: 110181479 Test: manual Change-Id: I4bff3c3bb75fbb0d1e13c459c0d9d3fd3b8b3195 Merged-In: I4bff3c3bb75fbb0d1e13c459c0d9d3fd3b8b3195 (cherry picked from commit e18a909013a8f521a0876ab5fd67c2ec8d151323) --- .../server/bluetooth/BluetoothManagerService.java | 104 ++++++++++++++------- 1 file changed, 70 insertions(+), 34 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index fa8eda54e5..b92f23573a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -79,6 +79,7 @@ import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -261,6 +262,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + public boolean onFactoryReset() { + // Wait for stable state if bluetooth is temporary state. + int state = getState(); + if (state == BluetoothAdapter.STATE_BLE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_OFF) { + if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) { + return false; + } + } + + // Clear registered LE apps to force shut-off Bluetooth + clearBleApps(); + state = getState(); + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth == null) { + return false; + } + if (state == BluetoothAdapter.STATE_BLE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.onBrEdrDown(); + return true; + } else if (state == BluetoothAdapter.STATE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.disable(); + return true; + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to shutdown Bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + return false; + } + public void onAirplaneModeChanged() { synchronized (this) { if (isBluetoothPersistedStateOn()) { @@ -1630,7 +1671,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by "waitForOnOff(false, true)". + // is accomplished by + // "waitForState(Set.of(BluetoothAdapter.STATE_OFF))". // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1640,7 +1682,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); @@ -1653,10 +1695,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); mEnable = false; handleDisable(); - waitForOnOff(false, false); + waitForState(Set.of(BluetoothAdapter.STATE_OFF, + BluetoothAdapter.STATE_TURNING_ON, + BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_BLE_TURNING_OFF)); } else { mEnable = false; handleDisable(); @@ -1779,9 +1826,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); handleDisable(); - waitForOnOff(false, false); + waitForState(Set.of(BluetoothAdapter.STATE_OFF, + BluetoothAdapter.STATE_TURNING_ON, + BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_BLE_TURNING_OFF)); } break; } @@ -1813,7 +1865,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); @@ -1942,7 +1994,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } - waitForOnOff(true, false); + waitForState(Set.of(BluetoothAdapter.STATE_ON)); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); @@ -1957,7 +2009,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); - boolean didDisableTimeout = !waitForOnOff(false, true); + boolean didDisableTimeout = + !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); @@ -2203,12 +2256,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - /** - * 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) { + private boolean waitForState(Set states) { int i = 0; while (i < 10) { try { @@ -2216,18 +2264,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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; - } + if (states.contains(mBluetooth.getState())) { + return true; } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); @@ -2235,14 +2273,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } finally { mBluetoothLock.readLock().unlock(); } - if (on || off) { - SystemClock.sleep(300); - } else { - SystemClock.sleep(50); - } + SystemClock.sleep(300); i++; } - Slog.e(TAG, "waitForOnOff time out"); + Slog.e(TAG, "waitForState " + states + " time out"); return false; } @@ -2303,7 +2337,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName(), false); handleDisable(); - waitForOnOff(false, true); + waitForState(Set.of(BluetoothAdapter.STATE_OFF)); sendBluetoothServiceDownCallback(); @@ -2465,6 +2499,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return "USER_SWITCH"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: return "RESTORE_USER_SETTING"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: + return "FACTORY_RESET"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: default: return "UNKNOWN[" + reason + "]"; } -- cgit v1.2.3 From ef2b72fdcdace32df2640e30f67acd286759a803 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Thu, 19 Mar 2020 15:58:28 +0800 Subject: Sequentially handle enable and disable * Replace thread sleeps in MESSAGE_ENABLE and MESSAGE_DISABLE to delay messages. To make sure we do not block the state change process while waiting for a state change callback. * Prevent handling enable or disable at the same time by deferring the the request when we are enabling or disabling Bluetooth. Bug: 128569058 Test: Manual Change-Id: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475 Merged-In: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475 --- .../server/bluetooth/BluetoothManagerService.java | 127 +++++++++++++++++++-- 1 file changed, 116 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index fa8eda54e5..11c1405d59 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -106,9 +106,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int USER_SWITCHED_TIME_MS = 200; // Delay for the addProxy function in msec private static final int ADD_PROXY_DELAY_MS = 100; + // Delay for retrying enable and disable in msec + private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; + private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; + private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_ADAPTER = 20; private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; @@ -130,6 +134,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int RESTORE_SETTING_TO_OFF = 0; private static final int MAX_ERROR_RESTART_RETRIES = 6; + private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; // Bluetooth persisted setting is off private static final int BLUETOOTH_OFF = 0; @@ -160,6 +165,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; @@ -1597,8 +1604,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_ENABLE: + int quietEnable = msg.arg1; + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, + quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = " + + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1621,7 +1638,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - mQuietEnable = (msg.arg1 == 1); + mQuietEnable = (quietEnable == 1); if (mBluetooth == null) { handleEnable(mQuietEnable); } else { @@ -1630,7 +1647,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by "waitForOnOff(false, true)". + // is accomplished by sending delay a message + // MESSAGE_HANDLE_ENABLE_DELAYED // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1640,28 +1658,108 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForOnOff(false, true); - Message restartMsg = - mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + mWaitForEnableRetry = 0; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); } break; case MESSAGE_DISABLE: + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), + ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth + + ", mBinding = " + mBinding); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); + if (mEnable && mBluetooth != null) { - waitForOnOff(true, false); + mWaitForDisableRetry = 0; + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { mEnable = false; handleDisable(); - waitForOnOff(false, false); - } else { + } + break; + + case MESSAGE_HANDLE_ENABLE_DELAYED: { + // The Bluetooth is turning off, wait for STATE_OFF + if (mState != BluetoothAdapter.STATE_OFF) { + if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForEnableRetry++; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_OFF timeout"); + } + } + // Either state is changed to STATE_OFF or reaches the maximum retry, we + // should move forward to the next step. + mWaitForEnableRetry = 0; + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + Slog.d(TAG, "Handle enable is finished"); + break; + } + + case MESSAGE_HANDLE_DISABLE_DELAYED: { + boolean disabling = (msg.arg1 == 1); + Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); + if (!disabling) { + // The Bluetooth is turning on, wait for STATE_ON + if (mState != BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_ON timeout"); + } + } + // Either state is changed to STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + mWaitForDisableRetry = 0; mEnable = false; handleDisable(); + // Wait for state exiting STATE_ON + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { + // The Bluetooth is turning off, wait for exiting STATE_ON + if (mState == BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for exiting STATE_ON timeout"); + } + } + // Either state is exited from STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + Slog.d(TAG, "Handle disable is finished"); } break; + } case MESSAGE_RESTORE_USER_SETTING: if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { @@ -2031,6 +2129,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { + Slog.d(TAG, "binding Bluetooth service"); //Start bind timeout and bind Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); @@ -2418,6 +2517,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" " + app.getPackageName()); } + writer.println("\nBluetoothManagerService:"); + writer.println(" mEnable:" + mEnable); + writer.println(" mQuietEnable:" + mQuietEnable); + writer.println(" mEnableExternal:" + mEnableExternal); + writer.println(" mQuietEnableExternal:" + mQuietEnableExternal); + writer.println(""); writer.flush(); if (args.length == 0) { -- cgit v1.2.3 From 828326ebe0e269c99991783ed9ac5a4248291410 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Thu, 19 Mar 2020 16:15:58 +0800 Subject: Sequentially handle enable and disable * Replace thread sleeps in MESSAGE_ENABLE and MESSAGE_DISABLE to delay messages. To make sure we do not block the state change process while waiting for a state change callback. * Prevent handling enable or disable at the same time by deferring the the request when we are enabling or disabling Bluetooth. Bug: 128569058 Test: Manual Change-Id: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475 --- .../server/bluetooth/BluetoothManagerService.java | 133 ++++++++++++++++++--- 1 file changed, 116 insertions(+), 17 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 03ca1c610f..1bf559a170 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -112,9 +112,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int USER_SWITCHED_TIME_MS = 200; // Delay for the addProxy function in msec private static final int ADD_PROXY_DELAY_MS = 100; + // Delay for retrying enable and disable in msec + private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; + private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; + private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_ADAPTER = 20; private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; @@ -136,6 +140,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int RESTORE_SETTING_TO_OFF = 0; private static final int MAX_ERROR_RESTART_RETRIES = 6; + private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; // Bluetooth persisted setting is off private static final int BLUETOOTH_OFF = 0; @@ -166,6 +171,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; @@ -1678,8 +1685,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_ENABLE: + int quietEnable = msg.arg1; + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, + quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = " + + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1702,7 +1719,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - mQuietEnable = (msg.arg1 == 1); + mQuietEnable = (quietEnable == 1); if (mBluetooth == null) { handleEnable(mQuietEnable); } else { @@ -1711,8 +1728,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by - // "waitForState(Set.of(BluetoothAdapter.STATE_OFF))". + // is accomplished by sending delay a message + // MESSAGE_HANDLE_ENABLE_DELAYED // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1722,33 +1739,108 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForState(Set.of(BluetoothAdapter.STATE_OFF)); - Message restartMsg = - mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + mWaitForEnableRetry = 0; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); } break; case MESSAGE_DISABLE: + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), + ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth + + ", mBinding = " + mBinding); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); + if (mEnable && mBluetooth != null) { - waitForState(Set.of(BluetoothAdapter.STATE_ON)); + mWaitForDisableRetry = 0; + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { mEnable = false; handleDisable(); - waitForState(Set.of(BluetoothAdapter.STATE_OFF, - BluetoothAdapter.STATE_TURNING_ON, - BluetoothAdapter.STATE_TURNING_OFF, - BluetoothAdapter.STATE_BLE_TURNING_ON, - BluetoothAdapter.STATE_BLE_ON, - BluetoothAdapter.STATE_BLE_TURNING_OFF)); - } else { + } + break; + + case MESSAGE_HANDLE_ENABLE_DELAYED: { + // The Bluetooth is turning off, wait for STATE_OFF + if (mState != BluetoothAdapter.STATE_OFF) { + if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForEnableRetry++; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_OFF timeout"); + } + } + // Either state is changed to STATE_OFF or reaches the maximum retry, we + // should move forward to the next step. + mWaitForEnableRetry = 0; + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + Slog.d(TAG, "Handle enable is finished"); + break; + } + + case MESSAGE_HANDLE_DISABLE_DELAYED: { + boolean disabling = (msg.arg1 == 1); + Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); + if (!disabling) { + // The Bluetooth is turning on, wait for STATE_ON + if (mState != BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_ON timeout"); + } + } + // Either state is changed to STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + mWaitForDisableRetry = 0; mEnable = false; handleDisable(); + // Wait for state exiting STATE_ON + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { + // The Bluetooth is turning off, wait for exiting STATE_ON + if (mState == BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for exiting STATE_ON timeout"); + } + } + // Either state is exited from STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + Slog.d(TAG, "Handle disable is finished"); } break; + } case MESSAGE_RESTORE_USER_SETTING: if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { @@ -2124,6 +2216,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { + Slog.d(TAG, "binding Bluetooth service"); //Start bind timeout and bind Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); @@ -2493,6 +2586,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" " + app.getPackageName()); } + writer.println("\nBluetoothManagerService:"); + writer.println(" mEnable:" + mEnable); + writer.println(" mQuietEnable:" + mQuietEnable); + writer.println(" mEnableExternal:" + mEnableExternal); + writer.println(" mQuietEnableExternal:" + mQuietEnableExternal); + writer.println(""); writer.flush(); if (args.length == 0) { -- cgit v1.2.3 From 78cb0998affedc80b0e4f1c83d58c5250eb07dd1 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 23 Mar 2020 13:48:33 +0800 Subject: Independent methods to enable/disable BLE mode * Use IBluetoothManager.enableBle() and disableBle() to toggle BLE only mode instead of updateBleAppCount() then enable(). * Fix BluetoothAdapter.disableBle sometime won't disable Bluetooth. * Add active log if Bluetooth is disabled via disableBle(). Bug: 139454316 Test: enableBle() -> disableBle() and check Bluetooth is OFF. Change-Id: I173d5fed1b47ff68a6504741e25754e65cbd1455 --- .../server/bluetooth/BluetoothManagerService.java | 168 +++++++++++++-------- 1 file changed, 107 insertions(+), 61 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index fa8eda54e5..cca02aac3d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -740,13 +740,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable, String packageName) { - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } + private int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); @@ -771,13 +765,94 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, appCount + " registered Ble Apps"); } - if (appCount == 0 && mEnable) { - disableBleScanMode(); + return appCount; + } + + private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); + } + return false; } - if (appCount == 0 && !mEnableExternal) { - sendBrEdrDownCallback(); + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + + if (requireForeground && !checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "Not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); } - return appCount; + return true; + } + + public boolean enableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "enableBle(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + updateBleAppCount(token, true, packageName); + + if (mState == BluetoothAdapter.STATE_ON + || mState == BluetoothAdapter.STATE_BLE_ON + || mState == BluetoothAdapter.STATE_TURNING_ON + || mState == BluetoothAdapter.STATE_TURNING_OFF) { + Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + return true; + } + synchronized (mReceiver) { + // waive WRITE_SECURE_SETTINGS permission check + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + } + return true; + } + + public boolean disableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "disableBLE(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + + if (mState == BluetoothAdapter.STATE_OFF) { + Slog.d(TAG, "disableBLE(): Already disabled"); + return false; + } + updateBleAppCount(token, false, packageName); + + if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { + if (mEnable) { + disableBleScanMode(); + } + if (!mEnableExternal) { + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, false); + sendBrEdrDownCallback(); + } + } + return true; } // Clear all apps using BLE scan only mode. @@ -855,29 +930,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enableNoAutoConnect(String packageName) { - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, false)) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); } return false; } - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } - int callingAppId = UserHandle.getAppId(callingUid); + int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); if (callingAppId != Process.NFC_UID) { throw new SecurityException("no permission to enable Bluetooth quietly"); } @@ -892,32 +957,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable(String packageName) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, true)) { if (DBG) { Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } return false; } - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "enable(): not allowed for non-active and non system user"); - return false; - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && !isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; } if (DBG) { @@ -939,25 +991,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean disable(String packageName, boolean persist) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "disable(): not allowed for non-active and non system user"); - return false; + if (!checkBluetoothPermissions(packageName, true)) { + if (DBG) { + Slog.d(TAG, "disable(): not disabling - bluetooth disallowed"); } + return false; + } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; } if (DBG) { -- cgit v1.2.3 From 820d21e7ca4f9ad6a0b0632c449669cf9192af8c Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Thu, 19 Mar 2020 16:15:58 +0800 Subject: Sequentially handle enable and disable * Replace thread sleeps in MESSAGE_ENABLE and MESSAGE_DISABLE to delay messages. To make sure we do not block the state change process while waiting for a state change callback. * Prevent handling enable or disable at the same time by deferring the the request when we are enabling or disabling Bluetooth. Bug: 128569058 Test: Manual Change-Id: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475 --- .../server/bluetooth/BluetoothManagerService.java | 133 ++++++++++++++++++--- 1 file changed, 116 insertions(+), 17 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b92f23573a..15a59ced54 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -107,9 +107,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int USER_SWITCHED_TIME_MS = 200; // Delay for the addProxy function in msec private static final int ADD_PROXY_DELAY_MS = 100; + // Delay for retrying enable and disable in msec + private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; + private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; + private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_ADAPTER = 20; private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; @@ -131,6 +135,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int RESTORE_SETTING_TO_OFF = 0; private static final int MAX_ERROR_RESTART_RETRIES = 6; + private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10; // Bluetooth persisted setting is off private static final int BLUETOOTH_OFF = 0; @@ -161,6 +166,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; @@ -1638,8 +1645,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; case MESSAGE_ENABLE: + int quietEnable = msg.arg1; + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, + quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = " + + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; @@ -1662,7 +1679,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - mQuietEnable = (msg.arg1 == 1); + mQuietEnable = (quietEnable == 1); if (mBluetooth == null) { handleEnable(mQuietEnable); } else { @@ -1671,8 +1688,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This - // is accomplished by - // "waitForState(Set.of(BluetoothAdapter.STATE_OFF))". + // is accomplished by sending delay a message + // MESSAGE_HANDLE_ENABLE_DELAYED // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and @@ -1682,33 +1699,108 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. The delay time is backed off if Bluetooth // continuously failed to turn on itself. // - waitForState(Set.of(BluetoothAdapter.STATE_OFF)); - Message restartMsg = - mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); - mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + mWaitForEnableRetry = 0; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); } break; case MESSAGE_DISABLE: + if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding + || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), + ENABLE_DISABLE_DELAY_MS); + break; + } + if (DBG) { - Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth); + Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth + + ", mBinding = " + mBinding); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); + if (mEnable && mBluetooth != null) { - waitForState(Set.of(BluetoothAdapter.STATE_ON)); + mWaitForDisableRetry = 0; + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { mEnable = false; handleDisable(); - waitForState(Set.of(BluetoothAdapter.STATE_OFF, - BluetoothAdapter.STATE_TURNING_ON, - BluetoothAdapter.STATE_TURNING_OFF, - BluetoothAdapter.STATE_BLE_TURNING_ON, - BluetoothAdapter.STATE_BLE_ON, - BluetoothAdapter.STATE_BLE_TURNING_OFF)); - } else { + } + break; + + case MESSAGE_HANDLE_ENABLE_DELAYED: { + // The Bluetooth is turning off, wait for STATE_OFF + if (mState != BluetoothAdapter.STATE_OFF) { + if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForEnableRetry++; + Message enableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); + mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_OFF timeout"); + } + } + // Either state is changed to STATE_OFF or reaches the maximum retry, we + // should move forward to the next step. + mWaitForEnableRetry = 0; + Message restartMsg = + mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); + mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + Slog.d(TAG, "Handle enable is finished"); + break; + } + + case MESSAGE_HANDLE_DISABLE_DELAYED: { + boolean disabling = (msg.arg1 == 1); + Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); + if (!disabling) { + // The Bluetooth is turning on, wait for STATE_ON + if (mState != BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for STATE_ON timeout"); + } + } + // Either state is changed to STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + mWaitForDisableRetry = 0; mEnable = false; handleDisable(); + // Wait for state exiting STATE_ON + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { + // The Bluetooth is turning off, wait for exiting STATE_ON + if (mState == BluetoothAdapter.STATE_ON) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = mHandler.obtainMessage( + MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, + ENABLE_DISABLE_DELAY_MS); + break; + } else { + Slog.e(TAG, "Wait for exiting STATE_ON timeout"); + } + } + // Either state is exited from STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + Slog.d(TAG, "Handle disable is finished"); } break; + } case MESSAGE_RESTORE_USER_SETTING: if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) { @@ -2084,6 +2176,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { + Slog.d(TAG, "binding Bluetooth service"); //Start bind timeout and bind Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS); @@ -2452,6 +2545,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" " + app.getPackageName()); } + writer.println("\nBluetoothManagerService:"); + writer.println(" mEnable:" + mEnable); + writer.println(" mQuietEnable:" + mQuietEnable); + writer.println(" mEnableExternal:" + mEnableExternal); + writer.println(" mQuietEnableExternal:" + mQuietEnableExternal); + writer.println(""); writer.flush(); if (args.length == 0) { -- cgit v1.2.3 From 10b8502dc5fb36768d710564dede34460c0a65a3 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 23 Mar 2020 14:11:49 +0800 Subject: Fix Bluetooth auto turns ON in airplane mode Fix a race condition that mBleApps is cleared while turning ON BLE, this causes Bluetooth turns on classic profiles instead of stays in BLE_ON state. Bug: 142220937 Test: enableBle() -> turn on airplane mode, check Bluetooth does not turn to ON. Change-Id: I3cea5384f734dde269cf93a93ed7cc4173f669a0 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index cca02aac3d..fcb9af572e 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -881,6 +881,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } + if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { + // Airplane mode is turned on while enabling BLE only mode, disable + // BLE now. + disableBleScanMode(); + sendBrEdrDownCallback(); + return; + } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); -- cgit v1.2.3 From ea9e0298b346934247cfb1911299d824a9227d8e Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 23 Mar 2020 13:48:33 +0800 Subject: Independent methods to enable/disable BLE mode * Use IBluetoothManager.enableBle() and disableBle() to toggle BLE only mode instead of updateBleAppCount() then enable(). * Fix BluetoothAdapter.disableBle sometime won't disable Bluetooth. * Add active log if Bluetooth is disabled via disableBle(). Bug: 139454316 Test: enableBle() -> disableBle() and check Bluetooth is OFF. Change-Id: I173d5fed1b47ff68a6504741e25754e65cbd1455 --- .../server/bluetooth/BluetoothManagerService.java | 168 +++++++++++++-------- 1 file changed, 107 insertions(+), 61 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 1bf559a170..d7b4f2e8f1 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -828,13 +828,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable, String packageName) { - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } + private int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); @@ -859,13 +853,94 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, appCount + " registered Ble Apps"); } - if (appCount == 0 && mEnable) { - disableBleScanMode(); + return appCount; + } + + private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); + } + return false; } - if (appCount == 0 && !mEnableExternal) { - sendBrEdrDownCallback(); + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + + if (requireForeground && !checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "Not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); } - return appCount; + return true; + } + + public boolean enableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "enableBle(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + updateBleAppCount(token, true, packageName); + + if (mState == BluetoothAdapter.STATE_ON + || mState == BluetoothAdapter.STATE_BLE_ON + || mState == BluetoothAdapter.STATE_TURNING_ON + || mState == BluetoothAdapter.STATE_TURNING_OFF) { + Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + return true; + } + synchronized (mReceiver) { + // waive WRITE_SECURE_SETTINGS permission check + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + } + return true; + } + + public boolean disableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "disableBLE(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + + if (mState == BluetoothAdapter.STATE_OFF) { + Slog.d(TAG, "disableBLE(): Already disabled"); + return false; + } + updateBleAppCount(token, false, packageName); + + if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { + if (mEnable) { + disableBleScanMode(); + } + if (!mEnableExternal) { + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, false); + sendBrEdrDownCallback(); + } + } + return true; } // Clear all apps using BLE scan only mode. @@ -943,29 +1018,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enableNoAutoConnect(String packageName) { - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, false)) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); } return false; } - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } - int callingAppId = UserHandle.getAppId(callingUid); + int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); if (callingAppId != Process.NFC_UID) { throw new SecurityException("no permission to enable Bluetooth quietly"); } @@ -980,32 +1045,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable(String packageName) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, true)) { if (DBG) { Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } return false; } - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "enable(): not allowed for non-active and non system user"); - return false; - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && !isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; } if (DBG) { @@ -1027,25 +1079,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean disable(String packageName, boolean persist) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "disable(): not allowed for non-active and non system user"); - return false; + if (!checkBluetoothPermissions(packageName, true)) { + if (DBG) { + Slog.d(TAG, "disable(): not disabling - bluetooth disallowed"); } + return false; + } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; } if (DBG) { -- cgit v1.2.3 From 8823fdc4845476b88aea3ef2ea42dbbf57b75586 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 23 Mar 2020 14:11:49 +0800 Subject: Fix Bluetooth auto turns ON in airplane mode Fix a race condition that mBleApps is cleared while turning ON BLE, this causes Bluetooth turns on classic profiles instead of stays in BLE_ON state. Bug: 142220937 Test: enableBle() -> turn on airplane mode, check Bluetooth does not turn to ON. Change-Id: I3cea5384f734dde269cf93a93ed7cc4173f669a0 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index d7b4f2e8f1..192ea72224 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -969,6 +969,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } + if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { + // Airplane mode is turned on while enabling BLE only mode, disable + // BLE now. + disableBleScanMode(); + sendBrEdrDownCallback(); + return; + } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); -- cgit v1.2.3 From 9d30d542c8c6240a3de0637cec05774c1d4fffe8 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 9 Mar 2020 15:42:46 +0800 Subject: Synchronize adapter registration with mCallbacks Move register/unregister callback to the caller thread. This fixes a problem that if an app registers adapter while the BluetoothManagerService is turning on Bluetooth, the app would get a null IBluetooth and would not receive any callback after Bluetooth is turned on. Bug: 149890859 Test: Manual Change-Id: Ia79f6bd1fd6ffab814a15053aeaae031faf875dd --- .../server/bluetooth/BluetoothManagerService.java | 70 ++++++++++------------ 1 file changed, 30 insertions(+), 40 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 168c8cd713..ebaebae630 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -113,8 +113,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; - private static final int MESSAGE_REGISTER_ADAPTER = 20; - private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; @@ -590,10 +588,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in registerAdapter"); return null; } - Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); - + synchronized (mCallbacks) { + mCallbacks.register(callback); + } return mBluetooth; } @@ -603,9 +600,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); + synchronized (mCallbacks) { + mCallbacks.unregister(callback); + } } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { @@ -1478,18 +1475,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1497,18 +1496,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1836,17 +1837,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName()); } break; - - case MESSAGE_REGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.register(callback); - break; - } - case MESSAGE_UNREGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.unregister(callback); - break; - } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; -- cgit v1.2.3 From 96b659bc9d02c649f9780083040cf4eaf99c6b3a Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Mon, 9 Mar 2020 15:42:46 +0800 Subject: Synchronize adapter registration with mCallbacks Move register/unregister callback to the caller thread. This fixes a problem that if an app registers adapter while the BluetoothManagerService is turning on Bluetooth, the app would get a null IBluetooth and would not receive any callback after Bluetooth is turned on. Bug: 149890859 Test: Manual Change-Id: Ia79f6bd1fd6ffab814a15053aeaae031faf875dd Merged-In: Ia79f6bd1fd6ffab814a15053aeaae031faf875dd --- .../server/bluetooth/BluetoothManagerService.java | 70 ++++++++++------------ 1 file changed, 30 insertions(+), 40 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 192ea72224..3c0d880916 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -119,8 +119,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; - private static final int MESSAGE_REGISTER_ADAPTER = 20; - private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; @@ -642,10 +640,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in registerAdapter"); return null; } - Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); - + synchronized (mCallbacks) { + mCallbacks.register(callback); + } return mBluetooth; } @@ -655,9 +652,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); + synchronized (mCallbacks) { + mCallbacks.unregister(callback); + } } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { @@ -1559,18 +1556,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1578,18 +1577,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1917,17 +1918,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName()); } break; - - case MESSAGE_REGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.register(callback); - break; - } - case MESSAGE_UNREGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.unregister(callback); - break; - } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; -- cgit v1.2.3 From 4247e445baa9f02ad07885467701fdd1f6ff8a7f Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 26 May 2020 13:28:38 +0800 Subject: Disable Bluetooth if BLE was disabled while enabling * Call onBrEdrDown if BLE app count is 0 when entering BLE_ON state and the Bluetooth ON was triggered via enableBle(). This fixes an issue that Bluetooth automatically turns ON if gms calls enableBle() then disableBle() in a short time. * Fix a deadlock bug that acquires writeLock in a readLock. Bug: 153767389 Bug: 155950370 Test: Manual Change-Id: I4f92581465de81ffe9b45fb042b5cc43e5ab4136 --- .../android/server/bluetooth/BluetoothManagerService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 192ea72224..249e376b52 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -957,7 +957,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } /** - * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on. + * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on, + * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off. */ private void continueFromBleOnState() { if (DBG) { @@ -969,11 +970,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } - if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { - // Airplane mode is turned on while enabling BLE only mode, disable - // BLE now. - disableBleScanMode(); - sendBrEdrDownCallback(); + if (!mEnableExternal && !isBleAppPresent()) { + Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now"); + mEnable = false; + mBluetooth.onBrEdrDown(); return; } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { -- cgit v1.2.3 From 6a60987f068879234001f777cdbb07dd7397954f Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 26 May 2020 13:28:38 +0800 Subject: Disable Bluetooth if BLE was disabled while enabling * Call onBrEdrDown if BLE app count is 0 when entering BLE_ON state and the Bluetooth ON was triggered via enableBle(). This fixes an issue that Bluetooth automatically turns ON if gms calls enableBle() then disableBle() in a short time. * Fix a deadlock bug that acquires writeLock in a readLock. Bug: 153767389 Bug: 155950370 Test: Manual Change-Id: I4f92581465de81ffe9b45fb042b5cc43e5ab4136 Merged-In: I4f92581465de81ffe9b45fb042b5cc43e5ab4136 --- .../android/server/bluetooth/BluetoothManagerService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index ebaebae630..2297d4b7c6 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -873,7 +873,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } /** - * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on. + * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on, + * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off. */ private void continueFromBleOnState() { if (DBG) { @@ -885,11 +886,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } - if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { - // Airplane mode is turned on while enabling BLE only mode, disable - // BLE now. - disableBleScanMode(); - sendBrEdrDownCallback(); + if (!mEnableExternal && !isBleAppPresent()) { + Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now"); + mEnable = false; + mBluetooth.onBrEdrDown(); return; } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { -- cgit v1.2.3 From 49c70e6f1264ac5e7587bd4769eb89099dadce01 Mon Sep 17 00:00:00 2001 From: Zach Johnson Date: Fri, 22 May 2020 11:22:45 -0700 Subject: Restart BT when init flags change Restarts immediately, a future patch will ensure we restart at a non-interruptive time. Bug: 156757711 Test: atest BluetoothInstrumentationTests Tag: #feature Change-Id: I8aad97b8c21f28d4a18ae597f3838de9caee150a --- .../server/bluetooth/BluetoothManagerService.java | 195 +++++++++++++-------- 1 file changed, 121 insertions(+), 74 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8f076332c0..151f4d1e0d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -59,6 +59,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; +import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; @@ -109,6 +110,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int ADD_PROXY_DELAY_MS = 100; // Delay for retrying enable and disable in msec private static final int ENABLE_DISABLE_DELAY_MS = 300; + private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @@ -128,6 +130,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_ADD_PROXY_DELAYED = 400; private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; private static final int MESSAGE_RESTORE_USER_SETTING = 500; + private static final int MESSAGE_INIT_FLAGS_CHANGED = 600; private static final int RESTORE_SETTING_TO_ON = 1; private static final int RESTORE_SETTING_TO_OFF = 0; @@ -267,6 +270,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener = + new DeviceConfig.OnPropertiesChangedListener() { + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { + if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { + return; + } + boolean foundInit = false; + for (String name : properties.getKeyset()) { + if (name.startsWith("INIT_")) { + foundInit = true; + break; + } + } + if (!foundInit) { + return; + } + mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); + } + }; + public boolean onFactoryReset() { // Wait for stable state if bluetooth is temporary state. int state = getState(); @@ -496,6 +523,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = systemUiUid; + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_BLUETOOTH, + (Runnable r) -> r.run(), + mDeviceConfigChangedListener); } /** @@ -2108,80 +2139,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /* disable and enable BT when detect a user switch */ if (mBluetooth != null && isEnabled()) { - try { - mBluetoothLock.readLock().lock(); - if (mBluetooth != null) { - mBluetooth.unregisterCallback(mBluetoothCallback); - } - } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister", re); - } finally { - mBluetoothLock.readLock().unlock(); - } - - if (mState == BluetoothAdapter.STATE_TURNING_OFF) { - // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE - bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); - mState = BluetoothAdapter.STATE_OFF; - } - if (mState == BluetoothAdapter.STATE_OFF) { - bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); - mState = BluetoothAdapter.STATE_TURNING_ON; - } - - waitForState(Set.of(BluetoothAdapter.STATE_ON)); - - if (mState == BluetoothAdapter.STATE_TURNING_ON) { - bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); - } - - unbindAllBluetoothProfileServices(); - // disable - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, - mContext.getPackageName(), false); - handleDisable(); - // Pbap service need receive STATE_TURNING_OFF intent to close - bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, - BluetoothAdapter.STATE_TURNING_OFF); - - boolean didDisableTimeout = - !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); - - bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, - BluetoothAdapter.STATE_OFF); - sendBluetoothServiceDownCallback(); - - try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; - } finally { - mBluetoothLock.writeLock().unlock(); - } - - // - // If disabling Bluetooth times out, wait for an - // additional amount of time to ensure the process is - // shut down completely before attempting to restart. - // - if (didDisableTimeout) { - SystemClock.sleep(3000); - } else { - SystemClock.sleep(100); - } - - mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); - mState = BluetoothAdapter.STATE_OFF; - // enable - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH, - mContext.getPackageName(), true); - // mEnable flag could have been reset on disableBLE. Reenable it. - mEnable = true; - handleEnable(mQuietEnable); + restartForReason(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH); } else if (mBinding || mBluetooth != null) { Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); userMsg.arg2 = 1 + msg.arg2; @@ -2208,8 +2166,95 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } handleEnable(mQuietEnable); } + break; + } + case MESSAGE_INIT_FLAGS_CHANGED: { + if (DBG) { + Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED"); + } + mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + if (mBluetooth != null && isEnabled()) { + restartForReason( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); + } + break; + } + } + } + + private void restartForReason(int reason) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + mBluetooth.unregisterCallback(mBluetoothCallback); + } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to unregister", re); + } finally { + mBluetoothLock.readLock().unlock(); + } + + if (mState == BluetoothAdapter.STATE_TURNING_OFF) { + // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE + bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); + mState = BluetoothAdapter.STATE_OFF; + } + if (mState == BluetoothAdapter.STATE_OFF) { + bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); + mState = BluetoothAdapter.STATE_TURNING_ON; + } + + waitForState(Set.of(BluetoothAdapter.STATE_ON)); + + if (mState == BluetoothAdapter.STATE_TURNING_ON) { + bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); + } + + unbindAllBluetoothProfileServices(); + // disable + addActiveLog(reason, mContext.getPackageName(), false); + handleDisable(); + // Pbap service need receive STATE_TURNING_OFF intent to close + bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, + BluetoothAdapter.STATE_TURNING_OFF); + + boolean didDisableTimeout = + !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); + + bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_OFF); + sendBluetoothServiceDownCallback(); + + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); } + mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } + + // + // If disabling Bluetooth times out, wait for an + // additional amount of time to ensure the process is + // shut down completely before attempting to restart. + // + if (didDisableTimeout) { + SystemClock.sleep(3000); + } else { + SystemClock.sleep(100); + } + + mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); + mState = BluetoothAdapter.STATE_OFF; + // enable + addActiveLog(reason, mContext.getPackageName(), true); + // mEnable flag could have been reset on disableBLE. Reenable it. + mEnable = true; + handleEnable(mQuietEnable); } } @@ -2643,6 +2688,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return "RESTORE_USER_SETTING"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: return "FACTORY_RESET"; + case BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED: + return "INIT_FLAGS_CHANGED"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: default: return "UNKNOWN[" + reason + "]"; } -- cgit v1.2.3 From 37f4b40fbbb8e712dda525c5531177f6d2f513cd Mon Sep 17 00:00:00 2001 From: Chen Chen Date: Thu, 23 Jul 2020 14:38:32 -0700 Subject: BluetoothManagerService: enforce BLUETOOTH_PRIVILEGED for onFactoryReset Bug: 159061926 Test: Try app_debug.apk in the bug, and make sure Bluetooth won't be turned off by the app Change-Id: I7d7e684be7908fc95f4f87528fb0ba7e5ace9f4a --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0d4efed25d..8c38b66dd4 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -95,6 +95,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final String BLUETOOTH_PRIVILEGED = + android.Manifest.permission.BLUETOOTH_PRIVILEGED; private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address"; @@ -279,6 +281,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { }; public boolean onFactoryReset() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, + "Need BLUETOOTH_PRIVILEGED permission"); + // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON -- cgit v1.2.3 From 07f75cf7c0f237ffce9b41c60d20f6c6ed3d50c2 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Thu, 3 Sep 2020 15:50:28 -0700 Subject: [bluetooth] system_server should not call non forUser Settings.Secure.get* methods BUG: 166312046 Test: builds Change-Id: Ia8ce189e50bcabf8949df422e1a89c86c5492e08 --- .../server/bluetooth/BluetoothManagerService.java | 30 ++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f372c6f85e..0d79240a4b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -166,6 +166,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private String mAddress; private String mName; private final ContentResolver mContentResolver; + private final int mUserId; private final RemoteCallbackList mCallbacks; private final RemoteCallbackList mStateChangeCallbacks; private IBinder mBluetoothBinder; @@ -481,6 +482,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mName = null; mErrorRecoveryRetryCounter = 0; mContentResolver = context.getContentResolver(); + mUserId = mContentResolver.getUserId(); // Observe BLE scan only mode settings change. registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList(); @@ -625,7 +627,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mContext.getResources() .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation) - && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) + && Settings.Secure.getIntForUser(mContentResolver, + SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0, mUserId) == 0) { // if the valid flag is not set, don't load the address and name if (DBG) { @@ -633,8 +636,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } return; } - mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); - mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); + mName = Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, mUserId); + mAddress = Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, mUserId); if (DBG) { Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } @@ -648,26 +653,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void storeNameAndAddress(String name, String address) { if (name != null) { - Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); + Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name, + mUserId); mName = name; if (DBG) { - Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver, - SECURE_SETTINGS_BLUETOOTH_NAME)); + Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, + mUserId)); } } if (address != null) { - Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); + Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + address, mUserId); mAddress = address; if (DBG) { Slog.d(TAG, - "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver, - SECURE_SETTINGS_BLUETOOTH_ADDRESS)); + "Stored Bluetoothaddress: " + Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + mUserId)); } } if ((name != null) && (address != null)) { - Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); + Settings.Secure.putIntForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1, + mUserId); } } -- cgit v1.2.3 From 66ac01aedaa07d86151954e1a656c48817c804ba Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 16 Sep 2020 15:48:47 +0200 Subject: Bluetooth: log who changes adapter name This is very helpful to find which third party app modified the adapter name. Bug: 168605944 Test: manual - change name, observe logcat output Change-Id: I9a13c89e6ef416286411f786e233d81507c9d53a --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 2e4d44cef4..bb567b4e2c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -412,7 +412,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); if (DBG) { - Slog.d(TAG, "Bluetooth Adapter name changed to " + newName); + Slog.d(TAG, "Bluetooth Adapter name changed to " + newName + " by " + + mContext.getPackageName()); } if (newName != null) { storeNameAndAddress(newName, null); -- cgit v1.2.3 From 119a0467e8cec9c218d06012f03bd0c0072ed997 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 6 Oct 2020 11:18:09 -0600 Subject: Tighten up Binder.clearCallingIdentity() usage. The recently added AndroidFrameworkBinderIdentity Error Prone checker examines code to ensure that any cleared identities are restored to avoid obscure security vulnerabilities. This change is a purely mechanical refactoring that adds the "final" keyword to the cleared identity to ensure that it's not accidentally modified before eventually being cleared. Here's the exact command used to generate this CL: $ find . -name "*.java" -exec sed -Ei \ 's/ (long \w+ = .+?clearCallingIdentity)/ final \1/' \ {} \; Bug: 155703208 Test: make Exempt-From-Owner-Approval: trivial refactoring Change-Id: I832c9d70c3dfcd8d669cf71939d97837becc973a --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 4e405cc7f7..011231c016 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -604,7 +604,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "Persisting Bluetooth Setting: " + value); } // waive WRITE_SECURE_SETTINGS permission check - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); Binder.restoreCallingIdentity(callingIdentity); } @@ -2378,7 +2378,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int foregroundUser; int callingUser = UserHandle.getCallingUserId(); int callingUid = Binder.getCallingUid(); - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); UserInfo ui = um.getProfileParent(callingUser); int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; @@ -2605,7 +2605,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean isBluetoothDisallowed() { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { return mContext.getSystemService(UserManager.class) .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); -- cgit v1.2.3 From 039c048ddd9c73db6d34766ade91044ce1cfef87 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Tue, 13 Oct 2020 15:21:54 -0700 Subject: BluetoothManagerService: Separate DeviceConfigListener Use its own class instead. Test: FrameworksServicesTests Test: Push bluetooth INIT_ flags Change-Id: I4452eacffd11020b6c8fa1cb2854fb91c11cac69 --- .../server/bluetooth/BluetoothManagerService.java | 38 ++++++---------------- 1 file changed, 10 insertions(+), 28 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index bb567b4e2c..b5d28089db 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -63,7 +63,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; -import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; @@ -177,6 +176,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; + private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener; + // used inside handler thread private boolean mQuietEnable = false; private boolean mEnable; @@ -281,29 +282,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; - private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener = - new DeviceConfig.OnPropertiesChangedListener() { - @Override - public void onPropertiesChanged(DeviceConfig.Properties properties) { - if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { - return; - } - boolean foundInit = false; - for (String name : properties.getKeyset()) { - if (name.startsWith("INIT_")) { - foundInit = true; - break; - } - } - if (!foundInit) { - return; - } - mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); - mHandler.sendEmptyMessageDelayed( - MESSAGE_INIT_FLAGS_CHANGED, - DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); - } - }; + @VisibleForTesting + public void onInitFlagsChanged() { + mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); + } public boolean onFactoryReset() { // Wait for stable state if bluetooth is temporary state. @@ -535,10 +520,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Unable to resolve SystemUI's UID."); } mSystemUiUid = systemUiUid; - DeviceConfig.addOnPropertiesChangedListener( - DeviceConfig.NAMESPACE_BLUETOOTH, - (Runnable r) -> r.run(), - mDeviceConfigChangedListener); + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); } /** -- cgit v1.2.3 From 13ebdff9d9e3df737ab73533054700ef5f845aab Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Tue, 13 Oct 2020 16:06:19 -0700 Subject: BluetoothAirplaneModeListener -> BluetoothModeChangeHelper Common code can be used for BluetoothDeviceConfigListener. Test: atest FrameworksServicesTests Change-Id: Ic5ab3c04876c341bde79c03f0551719c5f774437 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b5d28089db..cecf690171 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1350,9 +1350,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); } + BluetoothModeChangeHelper bluetoothModeChangeHelper = + new BluetoothModeChangeHelper(mContext); + if (mBluetoothAirplaneModeListener != null) { - mBluetoothAirplaneModeListener.start( - new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext)); + mBluetoothAirplaneModeListener.start(bluetoothModeChangeHelper); } } -- cgit v1.2.3 From e96443f27d5c575687adec92f7c0e01a960f13cd Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Tue, 13 Oct 2020 16:29:15 -0700 Subject: BluetoothDeviceConfigListener: Don't restart when connected Similar to airplane mode change, don't send onInitFlagsChanged to BluetoothManagerService when A2dp or Hearing aid is connected. Instead, check after 24 hours. Test: FrameworksServicesTests Test: Push bluetooth INIT_ flags Change-Id: Ib036852aa1cf8e3ddd87af7d17d16ad1c66c820e --- .../server/bluetooth/BluetoothManagerService.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index cecf690171..e57d0f600c 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -115,6 +115,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Delay for retrying enable and disable in msec private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300; + private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @@ -174,6 +175,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private int mWaitForEnableRetry; private int mWaitForDisableRetry; + private BluetoothModeChangeHelper mBluetoothModeChangeHelper; + private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener; @@ -520,7 +523,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Unable to resolve SystemUI's UID."); } mSystemUiUid = systemUiUid; - mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); } /** @@ -1350,12 +1352,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); } - BluetoothModeChangeHelper bluetoothModeChangeHelper = - new BluetoothModeChangeHelper(mContext); + mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext); if (mBluetoothAirplaneModeListener != null) { - mBluetoothAirplaneModeListener.start(bluetoothModeChangeHelper); + mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); } /** @@ -2198,6 +2200,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED"); } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); + break; + } if (mBluetooth != null && isEnabled()) { restartForReason( BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); -- cgit v1.2.3 From ba3049eb34d2c9d75aa5aa33b3783fe03f5318d6 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Thu, 15 Oct 2020 11:32:24 -0700 Subject: Bluetooth: Check INIT flag change on audio disconnect We also listen for A2DP or hearing aid disconnect and then reevaluate INIT flag change. Test: FrameworksServicesTests Test: Push bluetooth INIT_ flags Change-Id: I93fa880aa64506577a7937e6666b1942d28458ea --- .../android/server/bluetooth/BluetoothManagerService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index e57d0f600c..e919f39c21 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -23,7 +23,9 @@ import android.Manifest; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.IBluetooth; @@ -439,6 +441,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessage(msg); } } + } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action) + || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { + final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, + BluetoothProfile.STATE_CONNECTED); + if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) + && state == BluetoothProfile.STATE_DISCONNECTED + && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + onInitFlagsChanged(); + } } } }; @@ -489,6 +500,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); filter.addAction(Intent.ACTION_SETTING_RESTORED); + filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); -- cgit v1.2.3 From e4a729947ee7a9269f873e2bf943c449bcfaf910 Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Mon, 9 Nov 2020 16:44:29 -0800 Subject: Move UserManagerInternal out of android.os Moving this class out of android.os will reportedly greatly reduce ART overhead. Test: compiles Test: atest FrameworksServicesTests FrameworksCoreTests Bug: 165817914 Exempt-From-Owner-Approval: no-op refactoring Change-Id: I1f3e77120979e2f336e5f42e4ec6e459d6492083 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f6a29aa917..0a68428784 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -63,8 +63,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; -import android.os.UserManagerInternal; -import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; @@ -77,6 +75,8 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; +import com.android.server.pm.UserManagerInternal; +import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; -- cgit v1.2.3 From 7113f77d5c5bc9d350ae10d6e50641ecd026f149 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Thu, 10 Dec 2020 13:01:26 -0800 Subject: Bluetooth: Check state correctly when client wants to bind Use mState instead of mEnable to check Bluetooth server status. mEnable is used to indicate whether the next action is enabling or disabling the Bluetooth stack, whereas mState indicates the current state. Test: atest FrameworksServicesTests Bug: 173941366 Change-Id: Id85494f7f40a0201061e74fbf3f08f70a632a62c --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0b8b352640..aab05532e2 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1265,7 +1265,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { - if (!mEnable) { + if (mState != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + ", while Bluetooth was disabled"); @@ -1431,7 +1431,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - if (!mEnable || state != BluetoothAdapter.STATE_ON) { + if (state != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Unable to bindService while Bluetooth is disabled"); } -- cgit v1.2.3 From 8c1bad91e18d3c18e22e3297d27bffde2f69ae99 Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 16 Mar 2021 16:05:42 -0700 Subject: Bluetooth: Wait for provisioning after init flag change * Wait for device provisioning to be completed before restart stack after an init flag change Bug: 181226310 Test: make, setup wizard Change-Id: I1128d9ef25b7703da31cfe55a812aaa745ab5f41 --- .../server/bluetooth/BluetoothManagerService.java | 46 +++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index aab05532e2..992ef2657a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -453,6 +453,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) && state == BluetoothProfile.STATE_DISCONNECTED && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Device disconnected, reactivating pending flag changes"); onInitFlagsChanged(); } } @@ -810,6 +811,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return enabledProfiles; } + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, + 0) != 0; + } + + // Monitor change of BLE scan only mode settings. + private void registerForProvisioningStateChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + if (!isDeviceProvisioned()) { + if (DBG) { + Slog.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not " + + "provisioned"); + } + return; + } + if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) { + Slog.i(TAG, "Device provisioned, reactivating pending flag changes"); + onInitFlagsChanged(); + } + } + }; + + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false, + contentObserver); + } + // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = new ContentObserver(null) { @@ -1375,7 +1405,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetoothAirplaneModeListener != null) { mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } - mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); + registerForProvisioningStateChange(); + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG); } /** @@ -2219,12 +2250,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + " ms due to existing connections"); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); + break; + } + if (!isDeviceProvisioned()) { + Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + + "ms because device is not provisioned"); mHandler.sendEmptyMessageDelayed( MESSAGE_INIT_FLAGS_CHANGED, DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); break; } if (mBluetooth != null && isEnabled()) { + Slog.i(TAG, "Restarting Bluetooth due to init flag change"); restartForReason( BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); } -- cgit v1.2.3 From 4e1e3f7fcaf5ec6392dc869e683bbd7be2ec2e8d Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Wed, 24 Mar 2021 17:37:07 +0000 Subject: Replace BLUETOOTH and BLUETOOTH_ADMIN permission checks in BluetoothManagerService. This replaces the checks for the legacy bluetooth permissions with checks for the new BLUETOOTH_CONNECT permission. All of the new checks are done as ForPreflight in this CL, i.e. app ops will be checked but not noted. Changes to make some of the checks ForDataDelivery (i.e. noting the app op) will be made in follow-ups - this requires additional work as the calling package and attribution tag must be plumbed through from the app side. Bug: 183203469 Test: builds Change-Id: I7b99a203ac25a8dcc0d33f442b08203244bff534 --- .../server/bluetooth/BluetoothManagerService.java | 51 +++++++++++++++++----- 1 file changed, 40 insertions(+), 11 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f0c9ba93b0..09cfac0056 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -16,7 +16,10 @@ package com.android.server; +import static android.Manifest.permission.BLUETOOTH_CONNECT; +import static android.content.PermissionChecker.PERMISSION_HARD_DENIED; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; @@ -43,6 +46,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.PermissionChecker; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; @@ -95,8 +99,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; - private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; - private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; private static final String BLUETOOTH_PRIVILEGED = android.Manifest.permission.BLUETOOTH_PRIVILEGED; @@ -696,14 +698,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in unregisterAdapter"); return; } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return; + } synchronized (mCallbacks) { mCallbacks.unregister(callback); } } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return; + } if (callback == null) { Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); return; @@ -714,7 +720,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return; + } if (callback == null) { Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); return; @@ -945,8 +953,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return false; + } } return true; } @@ -1672,7 +1681,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public String getAddress() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return null; + } if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Slog.w(TAG, "getAddress(): not allowed for non-active and non system user"); @@ -1704,7 +1715,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public String getName() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!checkConnectPermissionForPreflight(mContext)) { + return null; + } if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Slog.w(TAG, "getName(): not allowed for non-active and non system user"); @@ -2459,7 +2472,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); } private void bluetoothStateChangeHandler(int prevState, int newState) { @@ -2538,7 +2551,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); } } @@ -2827,4 +2840,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { default: return "UNKNOWN[" + reason + "]"; } } + + /** + * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns + * false if the result is a soft denial. Throws SecurityException if the result is a hard + * denial. + * + *

Should be used in situations where the app op should not be noted. + */ + private static boolean checkConnectPermissionForPreflight(Context context) { + int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight( + context, BLUETOOTH_CONNECT); + if (permissionCheckResult == PERMISSION_HARD_DENIED) { + throw new SecurityException("Need BLUETOOTH_CONNECT permission"); + } + return permissionCheckResult == PERMISSION_GRANTED; + } } -- cgit v1.2.3 From 8f80e4a05b3f1b227f40de5ec0e9a6297154ffc0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 2 Apr 2021 08:06:09 -0600 Subject: Update Bluetooth API annotations. Recent work has introduced a new "Nearby devices" runtime permission which protects all existing Bluetooth APIs; we've done this by defining a to convert the old BLUETOOTH and BLUETOOTH_ADMIN permissions into one of three new permissions: * BLUETOOTH_ADVERTISE: Required to be able to advertise to nearby Bluetooth devices. * BLUETOOTH_CONNECT: Allows applications to connect to paired bluetooth devices. * BLUETOOTH_SCAN: Required to be able to discover and pair nearby Bluetooth devices. At its core, this change begins updating the Bluetooth APIs to have correct @RequiresPermission indicating which permission is actually enforced internally. To ensure alignment across Binder, the newly added "RequiresPermissionChecker" Error Prone checker was used to discover any inconsistencies, ensuring correctness from server-side enforcement up through to the public APIs. In addition, since developers will continue building apps for both modern and legacy platforms, this change introduces new auto-doc annotations which will emit helpful consistent documentation describing the behavior of older devices that are still using the old permission model. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I02aa127e8e07f239561f4f2a3bbdfc6fccb82f7f --- .../server/bluetooth/BluetoothManagerService.java | 46 +++++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 09cfac0056..feed2205dc 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -23,6 +23,8 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; @@ -304,6 +306,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); + final long token = Binder.clearCallingIdentity(); + try { + return onFactoryResetInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + private boolean onFactoryResetInternal() { // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON @@ -343,6 +358,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void onAirplaneModeChanged() { synchronized (this) { if (isBluetoothPersistedStateOn()) { @@ -707,9 +723,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { - if (!checkConnectPermissionForPreflight(mContext)) { - return; - } if (callback == null) { Slog.w(TAG, "registerStateChangeCallback: Callback is null!"); return; @@ -720,9 +733,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { - if (!checkConnectPermissionForPreflight(mContext)) { - return; - } if (callback == null) { Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!"); return; @@ -935,6 +945,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return appCount; } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { if (isBluetoothDisallowed()) { if (DBG) { @@ -990,6 +1001,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean disableBle(String packageName, IBinder token) throws RemoteException { if (!checkBluetoothPermissions(packageName, false)) { if (DBG) { @@ -1040,6 +1052,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on, * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off. */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) private void continueFromBleOnState() { if (DBG) { Slog.d(TAG, "continueFromBleOnState()"); @@ -1072,6 +1085,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that BREDR part is down * and turn off all service and stack if no LE app needs it */ + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) private void sendBrEdrDownCallback() { if (DBG) { Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks"); @@ -1265,12 +1282,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * * @hide */ + @SuppressLint("AndroidFrameworkRequiresPermission") private boolean checkBluetoothPermissionWhenWirelessConsentRequired() { int result = mContext.checkCallingPermission( android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED); return result == PackageManager.PERMISSION_GRANTED; } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void unbindAndFinish() { if (DBG) { Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding @@ -2300,6 +2319,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED + }) private void restartForReason(int reason) { try { mBluetoothLock.readLock().lock(); @@ -2376,6 +2399,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private void handleEnable(boolean quietMode) { mQuietEnable = quietMode; @@ -2418,6 +2442,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private void handleDisable() { try { mBluetoothLock.readLock().lock(); @@ -2475,6 +2500,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); } + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; if (prevState == newState) { // No change. Nothing to do. @@ -2615,6 +2644,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) private void recoverBluetoothServiceFromError(boolean clearBle) { Slog.e(TAG, "recoverBluetoothServiceFromError"); try { @@ -2848,6 +2881,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * *

Should be used in situations where the app op should not be noted. */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private static boolean checkConnectPermissionForPreflight(Context context) { int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight( context, BLUETOOTH_CONNECT); -- cgit v1.2.3 From 3614e0a2a9aa949c68f3afb52fcee71a4fa39e48 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 16 Apr 2021 15:34:54 -0600 Subject: Add missing Bluetooth API permission enforcement. Recent work has been using Error Prone rules and annotations to reflect the current state of permission enforcement across the Bluetooth stack, and we're now in a position were we can add new permission enforcement that had been missing. We've currently standardized on saying that APIs that return device or Bluetooth state information (without sharing details about any particular remote Bluetooth device) do not need to be permission protected. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I37a9e03ecdca6f7a6eb9d7f094e2f95a97036612 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index feed2205dc..c3a5d1f871 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -714,9 +714,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in unregisterAdapter"); return; } - if (!checkConnectPermissionForPreflight(mContext)) { - return; - } synchronized (mCallbacks) { mCallbacks.unregister(callback); } -- cgit v1.2.3 From f0a1cae1d658c6915f9d663f1eca70f02c8c3581 Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Tue, 20 Apr 2021 09:56:45 +0100 Subject: Pass AttributionSource to AdapterService methods. This adds attribution source to AdapterService bluetooth method calls. This is now required to allow the app ops for the new bluetooth permissions (BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE, and BLUETOOTH_SCAN) to be noted. Bug: 183626112 Test: atest AdapterServiceTest Test: atest CtsPermissionTestCases:android.permission.cts.NearbyDevicesPermissionTest Change-Id: I8d1fe41ca9945a3baab584f248a17b3a1eb255f7 --- .../server/bluetooth/BluetoothManagerService.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c3a5d1f871..6c1c9d3a57 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -347,7 +347,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); - mBluetooth.disable(); + mBluetooth.disable(mContext.getAttributionSource()); return true; } } catch (RemoteException e) { @@ -1714,7 +1714,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - return mBluetooth.getAddress(); + return mBluetooth.getAddressWithAttribution(mContext.getAttributionSource()); } } catch (RemoteException e) { Slog.e(TAG, @@ -1743,7 +1743,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - return mBluetooth.getName(); + return mBluetooth.getName(mContext.getAttributionSource()); } } catch (RemoteException e) { Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); @@ -1830,7 +1830,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } else if (mBluetooth != null) { try { - storeNameAndAddress(mBluetooth.getName(), mBluetooth.getAddress()); + storeNameAndAddress( + mBluetooth.getName(mContext.getAttributionSource()), + mBluetooth.getAddressWithAttribution( + mContext.getAttributionSource())); } catch (RemoteException re) { Slog.e(TAG, "Unable to grab names", re); } @@ -2096,7 +2099,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Do enable request try { - if (!mBluetooth.enable(mQuietEnable)) { + if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) { Slog.e(TAG, "IBluetooth.enable() returned false"); } } catch (RemoteException e) { @@ -2417,7 +2420,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (mBluetooth != null) { //Enable bluetooth try { - if (!mBluetooth.enable(mQuietEnable)) { + if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) { Slog.e(TAG, "IBluetooth.enable() returned false"); } } catch (RemoteException e) { @@ -2447,7 +2450,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, "Sending off request."); } - if (!mBluetooth.disable()) { + if (!mBluetooth.disable(mContext.getAttributionSource())) { Slog.e(TAG, "IBluetooth.disable() returned false"); } } -- cgit v1.2.3 From d7c55664839ca7e6237cd0ef0f36eb51a4ee7ae6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 20 Apr 2021 12:30:37 -0600 Subject: Annotations for Bluetooth broadcast intents. Recent work has been using Error Prone rules and annotations to reflect the current state of permission enforcement across the Bluetooth stack, and we're now in a position were we can add new permission enforcement that had been missing. We've currently standardized on saying that APIs that return device or Bluetooth state information (without sharing details about any particular remote Bluetooth device) do not need to be permission protected. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I53ac7a4fe1dea57316048c3cac4fa237b6ba3d38 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c3a5d1f871..a68103f68d 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2494,7 +2494,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } @RequiresPermission(allOf = { @@ -2577,7 +2577,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } -- cgit v1.2.3 From 93fcf85ab95cf2c8cfbde41f6745ba0d9d328058 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Tue, 13 Apr 2021 21:43:22 -0700 Subject: Temp allowlist bluetooth broadcast to start FGS for 10 seconds. Add an overloaded version of Context.sendBroadcastMultiplePermissions() that can specify BroadcastOptions, it is called by com.android.bluetooth package. Bug: 182816627 Test: atest AdapterServiceTest Test: atest AvrcpControllerStateMachineTest Test: atest BondStateMachineTest Test: atest MapClientStateMachineTest Test: atest RemoteDevicesTest Change-Id: I8bb2d2ed98ece70ebbe9d3a1b549b966d690de4f --- .../server/bluetooth/BluetoothManagerService.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 08c9c2a2c9..84e675e7f3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -20,14 +20,17 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.content.PermissionChecker.PERMISSION_HARD_DENIED; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothHearingAid; @@ -62,6 +65,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PowerExemptionManager; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -2497,7 +2501,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions()); } @RequiresPermission(allOf = { @@ -2580,7 +2584,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, + getTempAllowlistBroadcastOptions()); } } @@ -2890,4 +2895,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } return permissionCheckResult == PERMISSION_GRANTED; } + + static @NonNull Bundle getTempAllowlistBroadcastOptions() { + final long duration = 10_000; + final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); + bOptions.setTemporaryAppAllowlist(duration, + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); + return bOptions.toBundle(); + } } -- cgit v1.2.3 From 4dabcb764f1948823dcd74eefb3440afcab07db2 Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Thu, 22 Apr 2021 19:05:17 +0100 Subject: Pass attribution source to BT APIs. This adds attribution source to BT method calls. This is now required to allow the app ops for the new BT permissions (BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE, and BLUETOOTH_SCAN) to be noted. Bug: 183626112 Test: atest BluetoothInstrumentationTests Change-Id: I81598553b762e491d6364064a2e1ef41dec89bf9 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 08c9c2a2c9..583e54b578 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1099,7 +1099,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBleAppPresent()) { // Need to stay at BLE ON. Disconnect all Gatt connections try { - mBluetoothGatt.unregAll(); + mBluetoothGatt.unregAll(mContext.getAttributionSource()); } catch (RemoteException e) { Slog.e(TAG, "Unable to disconnect all apps.", e); } -- cgit v1.2.3 From 43ee69eed974cd7ebc4784416a6e1e251464cc36 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 23 Apr 2021 14:13:57 -0600 Subject: Long-tail of AttributionSource plumbing. Wires up AttributionSource across the remaining long-tail of Bluetooth AIDL interfaces, ensuring that developers can accurately make calls chained back to a specific Context. Moves "for data delivery" permission checks to happen in a single location on each interface to ensure they're performed consistently with the new AttributionSource arguments. Note that "for data delivery" isn't the best name; it's designed to represent that the requested action was performed and should result in the relevant appop being noted for the caller. This change has the positive side effect of ensuring that all interfaces are consistently enforcing the BLUETOOTH_CONNECT permission, even in the case where BLUETOOTH_PRIVILEGED is also required; this is what ensures that revoking the "Nearby devices" permission takes effect for all callers. Additionally, standardizing on enforcing permissions closer to the AIDL entry point reduces the need for @RequiresPermission annotations to be carried around inside the Bluetooth stack. Bug: 183626112 Test: atest BluetoothInstrumentationTests Change-Id: I8023dda654e325b8bfa2f0cdb994ad63a2b429d4 --- .../server/bluetooth/BluetoothManagerService.java | 83 ++++++++++++++-------- 1 file changed, 55 insertions(+), 28 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 583e54b578..a24d813d59 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.content.PermissionChecker.PERMISSION_HARD_DENIED; +import static android.content.PermissionChecker.PID_UNKNOWN; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_SYSTEM; @@ -42,6 +43,7 @@ import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; import android.content.ActivityNotFoundException; +import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -302,13 +304,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); } - public boolean onFactoryReset() { + public boolean onFactoryReset(AttributionSource attributionSource) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); final long token = Binder.clearCallingIdentity(); try { - return onFactoryResetInternal(); + return onFactoryResetInternal(attributionSource); } finally { Binder.restoreCallingIdentity(token); } @@ -318,7 +320,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - private boolean onFactoryResetInternal() { + private boolean onFactoryResetInternal(AttributionSource attributionSource) { // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON @@ -347,7 +349,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); - mBluetooth.disable(mContext.getAttributionSource()); + mBluetooth.disable(attributionSource); return true; } } catch (RemoteException e) { @@ -943,7 +945,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { + private boolean checkBluetoothPermissions(AttributionSource attributionSource, String message, + boolean requireForeground) { if (isBluetoothDisallowed()) { if (DBG) { Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); @@ -954,22 +957,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { final int callingUid = Binder.getCallingUid(); final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; if (!isCallerSystem) { - checkPackage(callingUid, packageName); + checkPackage(callingUid, attributionSource.getPackageName()); if (requireForeground && !checkIfCallerIsForegroundUser()) { Slog.w(TAG, "Not allowed for non-active and non system user"); return false; } - if (!checkConnectPermissionForPreflight(mContext)) { + if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, message)) { return false; } } return true; } - public boolean enableBle(String packageName, IBinder token) throws RemoteException { - if (!checkBluetoothPermissions(packageName, false)) { + public boolean enableBle(AttributionSource attributionSource, IBinder token) + throws RemoteException { + final String packageName = attributionSource.getPackageName(); + if (!checkBluetoothPermissions(attributionSource, "enableBle", false)) { if (DBG) { Slog.d(TAG, "enableBle(): bluetooth disallowed"); } @@ -999,8 +1004,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) - public boolean disableBle(String packageName, IBinder token) throws RemoteException { - if (!checkBluetoothPermissions(packageName, false)) { + public boolean disableBle(AttributionSource attributionSource, IBinder token) + throws RemoteException { + final String packageName = attributionSource.getPackageName(); + if (!checkBluetoothPermissions(attributionSource, "disableBle", false)) { if (DBG) { Slog.d(TAG, "disableBLE(): bluetooth disallowed"); } @@ -1118,8 +1125,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } - public boolean enableNoAutoConnect(String packageName) { - if (!checkBluetoothPermissions(packageName, false)) { + public boolean enableNoAutoConnect(AttributionSource attributionSource) { + final String packageName = attributionSource.getPackageName(); + if (!checkBluetoothPermissions(attributionSource, "enableNoAutoConnect", false)) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); } @@ -1145,8 +1153,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean enable(String packageName) throws RemoteException { - if (!checkBluetoothPermissions(packageName, true)) { + public boolean enable(AttributionSource attributionSource) throws RemoteException { + final String packageName = attributionSource.getPackageName(); + if (!checkBluetoothPermissions(attributionSource, "enable", true)) { if (DBG) { Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } @@ -1179,8 +1188,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - public boolean disable(String packageName, boolean persist) throws RemoteException { - if (!checkBluetoothPermissions(packageName, true)) { + public boolean disable(AttributionSource attributionSource, boolean persist) + throws RemoteException { + final String packageName = attributionSource.getPackageName(); + if (!checkBluetoothPermissions(attributionSource, "disable", true)) { if (DBG) { Slog.d(TAG, "disable(): not disabling - bluetooth disallowed"); } @@ -1696,8 +1707,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public String getAddress() { - if (!checkConnectPermissionForPreflight(mContext)) { + public String getAddress(AttributionSource attributionSource) { + if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getAddress")) { return null; } @@ -1730,8 +1741,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mAddress; } - public String getName() { - if (!checkConnectPermissionForPreflight(mContext)) { + public String getName(AttributionSource attributionSource) { + if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getName")) { return null; } @@ -2874,6 +2885,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private static boolean checkPermissionForDataDelivery(Context context, String permission, + AttributionSource attributionSource, String message) { + final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource( + context, permission, PID_UNKNOWN, + new AttributionSource(context.getAttributionSource(), attributionSource), message); + if (result == PERMISSION_GRANTED) { + return true; + } + + final String msg = "Need " + permission + " permission for " + attributionSource + ": " + + message; + if (result == PERMISSION_HARD_DENIED) { + throw new SecurityException(msg); + } else { + Log.w(TAG, msg); + return false; + } + } + /** * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns * false if the result is a soft denial. Throws SecurityException if the result is a hard @@ -2882,12 +2912,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { *

Should be used in situations where the app op should not be noted. */ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - private static boolean checkConnectPermissionForPreflight(Context context) { - int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight( - context, BLUETOOTH_CONNECT); - if (permissionCheckResult == PERMISSION_HARD_DENIED) { - throw new SecurityException("Need BLUETOOTH_CONNECT permission"); - } - return permissionCheckResult == PERMISSION_GRANTED; + public static boolean checkConnectPermissionForDataDelivery( + Context context, AttributionSource attributionSource, String message) { + return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, + attributionSource, message); } } -- cgit v1.2.3 From a2d365484c43a19ab6f67152651d61f3b0667b47 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 29 Apr 2021 07:12:20 -0600 Subject: Ensure privileged APIs require runtime permission. When users revoke a runtime permission, they expect all interactions to be blocked, including those protected by the BLUETOOTH_PRIVILEGED permission. This change finishes applying that policy to any remaining Bluetooth APIs which didn't already implement it. To keep the implementation straightforward, this change does "data delivery" checks when registering for callbacks; the ideal behavior would be to wait until data is actually delivered through the callbacks, but RemoteCallbackList doesn't have support for AttributionSource yet. Bug: 186405452 Test: atest BluetoothInstrumentationTests Change-Id: Idd7be143eb8baff020a0718065293baae708041b --- .../server/bluetooth/BluetoothManagerService.java | 52 +++++++++------------- 1 file changed, 22 insertions(+), 30 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index c5246c7073..85ff2be43b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -312,19 +312,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); - final long token = Binder.clearCallingIdentity(); - try { - return onFactoryResetInternal(attributionSource); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - private boolean onFactoryResetInternal(AttributionSource attributionSource) { // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON @@ -347,7 +334,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); - mBluetooth.onBrEdrDown(); + mBluetooth.onBrEdrDown(attributionSource); return true; } else if (state == BluetoothAdapter.STATE_ON) { addActiveLog( @@ -404,7 +391,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, mContext.getPackageName(), false); - mBluetooth.onBrEdrDown(); + mBluetooth.onBrEdrDown(mContext.getAttributionSource()); mEnable = false; mEnableExternal = false; } @@ -888,7 +875,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth != null) { addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, mContext.getPackageName(), false); - mBluetooth.onBrEdrDown(); + mBluetooth.onBrEdrDown(mContext.getAttributionSource()); } } catch (RemoteException e) { Slog.e(TAG, "error when disabling bluetooth", e); @@ -1037,7 +1024,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (!mEnableExternal) { addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName, false); - sendBrEdrDownCallback(); + sendBrEdrDownCallback(attributionSource); } } return true; @@ -1074,12 +1061,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (!mEnableExternal && !isBleAppPresent()) { Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now"); mEnable = false; - mBluetooth.onBrEdrDown(); + mBluetooth.onBrEdrDown(mContext.getAttributionSource()); return; } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON - mBluetooth.onLeServiceUp(); + mBluetooth.onLeServiceUp(mContext.getAttributionSource()); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } } catch (RemoteException e) { @@ -1097,7 +1084,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - private void sendBrEdrDownCallback() { + private void sendBrEdrDownCallback(AttributionSource attributionSource) { if (DBG) { Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks"); } @@ -1110,7 +1097,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBleAppPresent()) { // Need to stay at BLE ON. Disconnect all Gatt connections try { - mBluetoothGatt.unregAll(mContext.getAttributionSource()); + mBluetoothGatt.unregAll(attributionSource); } catch (RemoteException e) { Slog.e(TAG, "Unable to disconnect all apps.", e); } @@ -1118,7 +1105,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - mBluetooth.onBrEdrDown(); + mBluetooth.onBrEdrDown(attributionSource); } } catch (RemoteException e) { Slog.e(TAG, "Call to onBrEdrDown() failed.", e); @@ -1319,7 +1306,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth != null) { //Unregister callback object try { - mBluetooth.unregisterCallback(mBluetoothCallback); + mBluetooth.unregisterCallback(mBluetoothCallback, + mContext.getAttributionSource()); } catch (RemoteException re) { Slog.e(TAG, "Unable to unregister BluetoothCallback", re); } @@ -1729,7 +1717,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - return mBluetooth.getAddressWithAttribution(mContext.getAttributionSource()); + return mBluetooth.getAddressWithAttribution(attributionSource); } } catch (RemoteException e) { Slog.e(TAG, @@ -1758,7 +1746,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - return mBluetooth.getName(mContext.getAttributionSource()); + return mBluetooth.getName(attributionSource); } } catch (RemoteException e) { Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); @@ -1886,7 +1874,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int state = mBluetooth.getState(); if (state == BluetoothAdapter.STATE_BLE_ON) { Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); - mBluetooth.onLeServiceUp(); + mBluetooth.onLeServiceUp(mContext.getAttributionSource()); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); break; } @@ -2105,7 +2093,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { //Register callback object try { - mBluetooth.registerCallback(mBluetoothCallback); + mBluetooth.registerCallback(mBluetoothCallback, + mContext.getAttributionSource()); } catch (RemoteException re) { Slog.e(TAG, "Unable to register BluetoothCallback", re); } @@ -2342,7 +2331,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - mBluetooth.unregisterCallback(mBluetoothCallback); + mBluetooth.unregisterCallback(mBluetoothCallback, + mContext.getAttributionSource()); } } catch (RemoteException re) { Slog.e(TAG, "Unable to unregister", re); @@ -2569,7 +2559,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothStateCallback(false); // BT is OFF for general users // Broadcast as STATE_OFF newState = BluetoothAdapter.STATE_OFF; - sendBrEdrDownCallback(); + sendBrEdrDownCallback(mContext.getAttributionSource()); } } else if (newState == BluetoothAdapter.STATE_ON) { boolean isUp = (newState == BluetoothAdapter.STATE_ON); @@ -2670,7 +2660,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { //Unregister callback object - mBluetooth.unregisterCallback(mBluetoothCallback); + mBluetooth.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); } } catch (RemoteException re) { Slog.e(TAG, "Unable to unregister", re); @@ -2890,6 +2880,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + @SuppressLint("AndroidFrameworkRequiresPermission") private static boolean checkPermissionForDataDelivery(Context context, String permission, AttributionSource attributionSource, String message) { final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource( @@ -2916,6 +2907,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * *

Should be used in situations where the app op should not be noted. */ + @SuppressLint("AndroidFrameworkRequiresPermission") @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static boolean checkConnectPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message) { -- cgit v1.2.3 From 4eac11658fb7da2562325d7a8e2c6bd88e52bc05 Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Wed, 2 Jun 2021 10:34:56 +0800 Subject: Use finally block for Binder.restoreCallingIdentity 1. Use final for Binder.clearCallingIdentity() to protect not being overwritten. 2. Protect it in the finally block of the try statement to avoid missing restore the CallingIdentity as exception. Bug: 189819183 Test: Manual test Ignore-AOSP-First: prevent merge conflict Change-Id: I2dd4cfc1aacecb0b77fa4c82b48b24b284271779 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 85ff2be43b..b4912bbc89 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -614,8 +614,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } // waive WRITE_SECURE_SETTINGS permission check final long callingIdentity = Binder.clearCallingIdentity(); - Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); - Binder.restoreCallingIdentity(callingIdentity); + try { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.BLUETOOTH_ON, value); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } } /** -- cgit v1.2.3 From 0a67fabedbf8f985ba2c7b85591213a3f053590a Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Wed, 2 Jun 2021 10:34:56 +0800 Subject: Use finally block for Binder.restoreCallingIdentity 1. Use final for Binder.clearCallingIdentity() to protect not being overwritten. 2. Protect it in the finally block of the try statement to avoid missing restore the CallingIdentity as exception. Bug: 189819183 Test: Manual test Change-Id: I2dd4cfc1aacecb0b77fa4c82b48b24b284271779 Merged-In: I2dd4cfc1aacecb0b77fa4c82b48b24b284271779 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 992ef2657a..12a94e1996 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -601,8 +601,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } // waive WRITE_SECURE_SETTINGS permission check long callingIdentity = Binder.clearCallingIdentity(); - Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON, value); - Binder.restoreCallingIdentity(callingIdentity); + try { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.BLUETOOTH_ON, value); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } } /** -- cgit v1.2.3 From d7cf1c83e412d47a3b24c601d18f6cf7bdf6f870 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Wed, 2 Jun 2021 14:30:37 +0800 Subject: Broadcast Bluetooth state to OFF properly In current logic, we broadcast Bluetooth state OFF at BLE_ON state. However, if Bluetooth gets crashed, we won't have the chance to send OFF intent as we never get to BLE_ON. This change makes the BluetoothManagerService skips the OFF intent only if the previous state is a BLE state. Bug: 189271317 Test: manual Change-Id: I3936766ab8bdd45d59550dacb64bdc0323bb424d Merged-In: I3936766ab8bdd45d59550dacb64bdc0323bb424d --- .../server/bluetooth/BluetoothManagerService.java | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 992ef2657a..8dcd9410a6 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2452,6 +2452,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } + private boolean isBleState(int state) { + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_BLE_TURNING_OFF: + return true; + } + return false; + } + private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; if (prevState == newState) { // No change. Nothing to do. @@ -2470,8 +2480,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothServiceDownCallback(); unbindAndFinish(); sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; + + /* Currently, the OFF intent is broadcasted externally only when we transition + * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state, + * we are guaranteed that the OFF intent has been broadcasted earlier and we + * can safely skip it. + * Conversely, if the previous state is not a BLE state, it indicates that some + * sort of crash has occurred, moving us directly to STATE_OFF without ever + * passing through BLE_ON. We should broadcast the OFF intent in this case. */ + isStandardBroadcast = !isBleState(prevState); } else if (!intermediate_off) { // connect to GattService @@ -2524,6 +2541,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Show prevState of BLE_ON as OFF to standard users prevState = BluetoothAdapter.STATE_OFF; } + if (DBG) { + Slog.d(TAG, + "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); -- cgit v1.2.3 From 5666c0d4fe4785bc3049b660cdb167be29fc46e3 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Wed, 2 Jun 2021 14:30:37 +0800 Subject: Broadcast Bluetooth state to OFF properly In current logic, we broadcast Bluetooth state OFF at BLE_ON state. However, if Bluetooth gets crashed, we won't have the chance to send OFF intent as we never get to BLE_ON. This change makes the BluetoothManagerService skips the OFF intent only if the previous state is a BLE state. Bug: 189271317 Bug: 195032127 Test: manual Change-Id: I3936766ab8bdd45d59550dacb64bdc0323bb424d (cherry picked from commit 1b2f8bc9843b2d6ba7ba199a89412c8fb632f508) --- .../server/bluetooth/BluetoothManagerService.java | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 85ff2be43b..b7c61a0d25 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2505,6 +2505,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions()); } + private boolean isBleState(int state) { + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_BLE_TURNING_OFF: + return true; + } + return false; + } + @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, @@ -2527,8 +2537,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothServiceDownCallback(); unbindAndFinish(); sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; + + /* Currently, the OFF intent is broadcasted externally only when we transition + * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state, + * we are guaranteed that the OFF intent has been broadcasted earlier and we + * can safely skip it. + * Conversely, if the previous state is not a BLE state, it indicates that some + * sort of crash has occurred, moving us directly to STATE_OFF without ever + * passing through BLE_ON. We should broadcast the OFF intent in this case. */ + isStandardBroadcast = !isBleState(prevState); } else if (!intermediate_off) { // connect to GattService @@ -2581,6 +2598,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Show prevState of BLE_ON as OFF to standard users prevState = BluetoothAdapter.STATE_OFF; } + if (DBG) { + Slog.d(TAG, + "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); -- cgit v1.2.3 From a44dee9fc7fc187eb74dadbdbd033feed71fa3e3 Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Fri, 13 Aug 2021 16:03:12 -0700 Subject: Allow SHELL_UID to disable Bluetooth for testing Bug: 189952422 Test: atest VtsHalBluetoothV1_0TargetTest Change-Id: Id45a43b824b2be49fb38686f9582484931024187 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 707ac322d5..bf28603b06 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2430,7 +2430,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { foregroundUser = ActivityManager.getCurrentUser(); valid = (callingUser == foregroundUser) || parentUser == foregroundUser - || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; + || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid + || callingAppId == Process.SHELL_UID; if (DBG && !valid) { Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + " parentUser=" + parentUser + " foregroundUser=" -- cgit v1.2.3 From 08fbafc03fcb06156224966f45d14af522e9dcb6 Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Fri, 13 Aug 2021 16:03:12 -0700 Subject: Allow SHELL_UID to disable Bluetooth for testing Bug: 189952422 Test: atest VtsHalBluetoothV1_0TargetTest Change-Id: Id45a43b824b2be49fb38686f9582484931024187 Merged-In: Id45a43b824b2be49fb38686f9582484931024187 --- service/java/com/android/server/bluetooth/BluetoothManagerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index b7c61a0d25..dc7904ddf8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -2479,7 +2479,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { foregroundUser = ActivityManager.getCurrentUser(); valid = (callingUser == foregroundUser) || parentUser == foregroundUser - || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid; + || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid + || callingAppId == Process.SHELL_UID; if (DBG && !valid) { Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser + " parentUser=" + parentUser + " foregroundUser=" -- cgit v1.2.3 From e5fd3e413cde4507d83730c440ba098bad2001c2 Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 18 Jun 2021 10:51:19 +0200 Subject: remove getSystemConfigEnabledProfilesForPackage Remove hidden api for mainline project. This commit is only for getSystemConfigEnabledProfilesForPackage because this will trigger a SEDenial Bug: 190440540 Test: Manual Tag: #refactor Merged-In: Icb822ab703e7617d2c96275d94f682d30171998f Change-Id: Icb822ab703e7617d2c96275d94f682d30171998f --- .../server/bluetooth/BluetoothManagerService.java | 32 +--------------------- 1 file changed, 1 insertion(+), 31 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0d3b064489..608cbf2d3a 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -25,9 +25,9 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGRO import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; -import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; @@ -93,7 +93,6 @@ import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Locale; @@ -804,35 +803,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mIsHearingAidProfileSupported; } - @Override - /** @hide */ - public java.util.List getSystemConfigEnabledProfilesForPackage(String packageName) { - if (Binder.getCallingUid() != Process.BLUETOOTH_UID) { - Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth"); - return null; - } - - SystemConfig systemConfig = SystemConfig.getInstance(); - if (systemConfig == null) { - return null; - } - - android.util.ArrayMap componentEnabledStates = - systemConfig.getComponentsEnabledStates(packageName); - if (componentEnabledStates == null) { - return null; - } - - ArrayList enabledProfiles = new ArrayList(); - for (Map.Entry entry : componentEnabledStates.entrySet()) { - if (entry.getValue()) { - enabledProfiles.add(entry.getKey()); - } - } - - return enabledProfiles; - } - private boolean isDeviceProvisioned() { return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0; -- cgit v1.2.3 From 0ba52e7126b0da1bffea5a91d413282a69aac019 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Thu, 2 Sep 2021 18:40:07 +0800 Subject: Avoid Bluetooth gets turned on by enableBle BluetoothHandler was not able to tell whether the MESSAGE_ENABLE was from enable() or enableBle(), which sometimes lead to Bluetooth gets turned to STATE_ON by an enableBle() call. Fix this problem by adding a BLE specific argument in the message to differ the calls. Bug: 191404687 Test: Manual Change-Id: Ic9df612ec0e396932df2fb3bf3a5874bd4e7443c --- .../server/bluetooth/BluetoothManagerService.java | 50 ++++++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index dc7904ddf8..51066dd837 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -25,9 +25,9 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGRO import static android.os.UserHandle.USER_SYSTEM; import android.Manifest; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; -import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; @@ -187,8 +187,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; - private int mWaitForEnableRetry; - private int mWaitForDisableRetry; private BluetoothModeChangeHelper mBluetoothModeChangeHelper; @@ -982,14 +980,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mState == BluetoothAdapter.STATE_ON || mState == BluetoothAdapter.STATE_BLE_ON || mState == BluetoothAdapter.STATE_TURNING_ON - || mState == BluetoothAdapter.STATE_TURNING_OFF) { - Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + || mState == BluetoothAdapter.STATE_TURNING_OFF + || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { + Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on"); return true; } synchronized (mReceiver) { // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false, - BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, true); } return true; } @@ -1802,6 +1801,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private class BluetoothHandler extends Handler { boolean mGetNameAddressOnly = false; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; BluetoothHandler(Looper looper) { super(looper); @@ -1852,11 +1853,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_ENABLE: int quietEnable = msg.arg1; + int isBle = msg.arg2; if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { // We are handling enable or disable right now, wait for it. mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, - quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + quietEnable, isBle), ENABLE_DISABLE_DELAY_MS); break; } @@ -1871,13 +1873,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { + boolean isHandled = true; int state = mBluetooth.getState(); - if (state == BluetoothAdapter.STATE_BLE_ON) { - Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); - mBluetooth.onLeServiceUp(mContext.getAttributionSource()); - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - break; + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + if (isBle == 1) { + Slog.i(TAG, "Already at BLE_ON State"); + } else { + Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); + mBluetooth.onLeServiceUp(mContext.getAttributionSource()); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + break; + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_TURNING_ON: + case BluetoothAdapter.STATE_ON: + Slog.i(TAG, "MESSAGE_ENABLE: already enabled"); + break; + default: + isHandled = false; + break; } + if (isHandled) break; } } catch (RemoteException e) { Slog.e(TAG, "", e); @@ -2643,7 +2660,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendEnableMsg(boolean quietMode, int reason, String packageName) { - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); + sendEnableMsg(quietMode, reason, packageName, false); + } + + private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, + isBle ? 1 : 0)); addActiveLog(reason, packageName, true); mLastEnabledTime = SystemClock.elapsedRealtime(); } -- cgit v1.2.3 From d19ee50bfa14ca999ff5ad58d1f1c90b578f3ba5 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Thu, 2 Sep 2021 18:40:07 +0800 Subject: Avoid Bluetooth gets turned on by enableBle BluetoothHandler was not able to tell whether the MESSAGE_ENABLE was from enable() or enableBle(), which sometimes lead to Bluetooth gets turned to STATE_ON by an enableBle() call. Fix this problem by adding a BLE specific argument in the message to differ the calls. Bug: 191404687 Test: Manual Change-Id: Ic9df612ec0e396932df2fb3bf3a5874bd4e7443c (cherry picked from commit 0ba52e7126b0da1bffea5a91d413282a69aac019) --- .../server/bluetooth/BluetoothManagerService.java | 48 ++++++++++++++++------ 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 608cbf2d3a..d911388de3 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -186,8 +186,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; - private int mWaitForEnableRetry; - private int mWaitForDisableRetry; private BluetoothModeChangeHelper mBluetoothModeChangeHelper; @@ -956,14 +954,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mState == BluetoothAdapter.STATE_ON || mState == BluetoothAdapter.STATE_BLE_ON || mState == BluetoothAdapter.STATE_TURNING_ON - || mState == BluetoothAdapter.STATE_TURNING_OFF) { - Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + || mState == BluetoothAdapter.STATE_TURNING_OFF + || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) { + Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on"); return true; } synchronized (mReceiver) { // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false, - BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, true); } return true; } @@ -1776,6 +1775,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private class BluetoothHandler extends Handler { boolean mGetNameAddressOnly = false; + private int mWaitForEnableRetry; + private int mWaitForDisableRetry; BluetoothHandler(Looper looper) { super(looper); @@ -1826,11 +1827,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_ENABLE: int quietEnable = msg.arg1; + int isBle = msg.arg2; if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { // We are handling enable or disable right now, wait for it. mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, - quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + quietEnable, isBle), ENABLE_DISABLE_DELAY_MS); break; } @@ -1845,13 +1847,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub { try { mBluetoothLock.readLock().lock(); if (mBluetooth != null) { + boolean isHandled = true; int state = mBluetooth.getState(); - if (state == BluetoothAdapter.STATE_BLE_ON) { - Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); - mBluetooth.onLeServiceUp(mContext.getAttributionSource()); - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); - break; + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + if (isBle == 1) { + Slog.i(TAG, "Already at BLE_ON State"); + } else { + Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); + mBluetooth.onLeServiceUp(mContext.getAttributionSource()); + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + break; + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_TURNING_ON: + case BluetoothAdapter.STATE_ON: + Slog.i(TAG, "MESSAGE_ENABLE: already enabled"); + break; + default: + isHandled = false; + break; } + if (isHandled) break; } } catch (RemoteException e) { Slog.e(TAG, "", e); @@ -2617,7 +2634,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void sendEnableMsg(boolean quietMode, int reason, String packageName) { - mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); + sendEnableMsg(quietMode, reason, packageName, false); + } + + private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) { + mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, + isBle ? 1 : 0)); addActiveLog(reason, packageName, true); mLastEnabledTime = SystemClock.elapsedRealtime(); } -- cgit v1.2.3 From e46d1c756e270f2a737355944107c1744e20f142 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Wed, 21 Apr 2021 19:03:20 +0200 Subject: Bluetooth: ensure adapter name and address can't be read from 3p apps Privacy checks in Settings.getStringForUser are using reflection to find secured values, so move constant definition to proper place. Test: verified against PoC Bug: 172838801 Change-Id: I2d94101b677e71011273c2674edc197840fb1411 --- .../server/bluetooth/BluetoothManagerService.java | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 51066dd837..cf2f8598b4 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -110,10 +110,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String BLUETOOTH_PRIVILEGED = android.Manifest.permission.BLUETOOTH_PRIVILEGED; - private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; - private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address"; - private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name"; - private static final int ACTIVE_LOG_MAX_SIZE = 20; private static final int CRASH_LOG_MAX_SIZE = 100; @@ -636,7 +632,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mContext.getResources() .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation) && Settings.Secure.getIntForUser(mContentResolver, - SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0, mUserId) + Settings.Secure.BLUETOOTH_NAME, 0, mUserId) == 0) { // if the valid flag is not set, don't load the address and name if (DBG) { @@ -645,9 +641,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } mName = Settings.Secure.getStringForUser( - mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, mUserId); + mContentResolver, Settings.Secure.BLUETOOTH_NAME, mUserId); mAddress = Settings.Secure.getStringForUser( - mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, mUserId); + mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, mUserId); if (DBG) { Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } @@ -661,30 +657,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void storeNameAndAddress(String name, String address) { if (name != null) { - Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name, + Settings.Secure.putStringForUser(mContentResolver, Settings.Secure.BLUETOOTH_NAME, name, mUserId); mName = name; if (DBG) { Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getStringForUser( - mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, + mContentResolver, Settings.Secure.BLUETOOTH_NAME, mUserId)); } } if (address != null) { - Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + Settings.Secure.putStringForUser(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, address, mUserId); mAddress = address; if (DBG) { Slog.d(TAG, "Stored Bluetoothaddress: " + Settings.Secure.getStringForUser( - mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, mUserId)); } } if ((name != null) && (address != null)) { - Settings.Secure.putIntForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1, + Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 1, mUserId); } } -- cgit v1.2.3 From f599dc49a2b0e598cfaacefebb4c24cbabf06299 Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Thu, 2 Sep 2021 11:52:23 -0700 Subject: Make BluetoothAdapter#disable(boolean persist) a @SystemApi Bug: 196235708 Test: build, flash car hardware, test basic functionality Change-Id: I952c3d2ce3b7ec70a384e9a96e172d6ab90c23e8 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index d911388de3..f62935ab1b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1154,6 +1154,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean disable(AttributionSource attributionSource, boolean persist) throws RemoteException { + if (!persist) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, + "Need BLUETOOTH_PRIVILEGED permission"); + } + final String packageName = attributionSource.getPackageName(); if (!checkBluetoothPermissions(attributionSource, "disable", true)) { if (DBG) { @@ -2599,7 +2604,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions()); } } -- cgit v1.2.3 From 5c9ab293ead54180c2f2b95bc37bebf01bd36b1e Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Tue, 23 Nov 2021 19:33:12 +0800 Subject: As airplane mode turn on, keep BT on if LE audio profile connected Bug: 207464971 Test: w/o LE audio device, and turn on/off airplane mode Change-Id: I1865c5ff7e8c04a4188dc7c379223e48c8b29ad9 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index f62935ab1b..8860a81641 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -35,6 +35,7 @@ import android.app.BroadcastOptions; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothHearingAid; +import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.IBluetooth; @@ -456,12 +457,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action) - || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { + || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action) + || BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(action)) { final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) && state == BluetoothProfile.STATE_DISCONNECTED - && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + && !mBluetoothModeChangeHelper.isMediaProfileConnected()) { Slog.i(TAG, "Device disconnected, reactivating pending flag changes"); onInitFlagsChanged(); } @@ -2291,7 +2293,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED"); } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); - if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + if (mBluetoothModeChangeHelper.isMediaProfileConnected()) { Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by " + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS + " ms due to existing connections"); -- cgit v1.2.3 From e5db50fddc932560bfe78c82ed79062278768cc6 Mon Sep 17 00:00:00 2001 From: Himanshu Rawat Date: Mon, 13 Dec 2021 03:29:14 +0000 Subject: Global settings for Bluetooth (Settings.Global.BLUETOOTH_ON) must be set to BLUETOOTH_ON_BLUETOOTH whenever non-BLE MESSAGE_ENABLE is handled irrespective of the state. Bug: 208777033 Test: Manual Change-Id: I5b0460f7741cc80fae367bc1cbf4602087a10975 --- .../java/com/android/server/bluetooth/BluetoothManagerService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8860a81641..450e9881be 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -1850,6 +1850,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; + if (isBle == 0) { + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + } + // Use service interface to get the exact state try { mBluetoothLock.readLock().lock(); @@ -1863,7 +1867,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else { Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); mBluetooth.onLeServiceUp(mContext.getAttributionSource()); - persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } break; case BluetoothAdapter.STATE_BLE_TURNING_ON: -- cgit v1.2.3 From fbbb005a03fa7fb0fda87afd7d6015d44cae7a3c Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Tue, 17 Nov 2020 09:11:17 +0000 Subject: gtbs: Add Generic Telephone Bearer Service support Tag: #feature Bug: 159786353 Sponsor: jpawlowski@ Test: build Change-Id: I8264ade4b07df17fc0207437dfdcae7028cc20ff --- .../com/android/server/bluetooth/BluetoothManagerService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 8860a81641..2c6bf2bd37 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -46,6 +46,7 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; +import android.bluetooth.IBluetoothLeCallControl; import android.content.ActivityNotFoundException; import android.content.AttributionSource; import android.content.BroadcastReceiver; @@ -1328,11 +1329,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + bluetoothProfile); } - if (bluetoothProfile != BluetoothProfile.HEADSET) { + Intent intent; + if (bluetoothProfile == BluetoothProfile.HEADSET) { + intent = new Intent(IBluetoothHeadset.class.getName()); + } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) { + intent = new Intent(IBluetoothLeCallControl.class.getName()); + } else { return false; } - Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); if (!psc.bindService()) { return false; -- cgit v1.2.3 From 6bf87965a2b4220de686a0526f83ff010f1e252f Mon Sep 17 00:00:00 2001 From: Jack He Date: Fri, 7 Jan 2022 00:09:07 +0000 Subject: Revert "gtbs: Add Generic Telephone Bearer Service support" Revert "gtbs: Add Generic Telephone Bearer Service implementation" Revert submission 1873900-gtbs Reason for revert: broke cellular call over BT, see b/213412267 Reverted Changes: I284ddacfc:gtbs: Add Generic Telephone Bearer Service impleme... I8264ade4b:gtbs: Add Generic Telephone Bearer Service support... I996cd5ff9:Add support for Generic Telephone Bearer service (... Bug: 213412267 Tag: #feature Test: answer cellular call by pressing button on HFP headset Change-Id: I9c6b12b794b7378fd852238ad06890f46922c095 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 2c6bf2bd37..8860a81641 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -46,7 +46,6 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; -import android.bluetooth.IBluetoothLeCallControl; import android.content.ActivityNotFoundException; import android.content.AttributionSource; import android.content.BroadcastReceiver; @@ -1329,15 +1328,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + bluetoothProfile); } - Intent intent; - if (bluetoothProfile == BluetoothProfile.HEADSET) { - intent = new Intent(IBluetoothHeadset.class.getName()); - } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) { - intent = new Intent(IBluetoothLeCallControl.class.getName()); - } else { + if (bluetoothProfile != BluetoothProfile.HEADSET) { return false; } + Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); if (!psc.bindService()) { return false; -- cgit v1.2.3 From 90bd65132b36a8d9225b5645e14d1f54083fa108 Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Tue, 17 Nov 2020 09:11:17 +0000 Subject: gtbs: Add Generic Telephone Bearer Service support Tag: #feature Bug: 159786353 Bug: 213412267 Sponsor: jpawlowski@ Test: build Change-Id: Iecd56b91ce59f6b014878691fe4c6fae826b73f9 --- .../com/android/server/bluetooth/BluetoothManagerService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java') diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 450e9881be..c8b4f1109b 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -46,6 +46,7 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; +import android.bluetooth.IBluetoothLeCallControl; import android.content.ActivityNotFoundException; import android.content.AttributionSource; import android.content.BroadcastReceiver; @@ -1328,11 +1329,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + bluetoothProfile); } - if (bluetoothProfile != BluetoothProfile.HEADSET) { + Intent intent; + if (bluetoothProfile == BluetoothProfile.HEADSET) { + intent = new Intent(IBluetoothHeadset.class.getName()); + } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) { + intent = new Intent(IBluetoothLeCallControl.class.getName()); + } else { return false; } - Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); if (!psc.bindService()) { return false; -- cgit v1.2.3