Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +20 −3 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import com.android.bluetooth.telephony.BluetoothInCallService; import com.android.bluetooth.vc.VolumeControlService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.modules.utils.BackgroundThread; import com.android.modules.utils.BytesMatcher; Loading Loading @@ -2314,8 +2315,7 @@ public class AdapterService extends Service { mService.enforceCallingPermission( android.Manifest.permission.BLUETOOTH_PRIVILEGED, null); // Post on the main handler to be sure the cleanup has completed before calling exit mService.mHandler.post( Runnable killAction = () -> { if (Flags.killInsteadOfExit()) { Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())"); Loading @@ -2324,7 +2324,24 @@ public class AdapterService extends Service { Log.i(TAG, "killBluetoothProcess: Calling System.exit"); System.exit(0); } }); }; // Post on the main handler to let the cleanup complete before calling exit mService.mHandler.post(killAction); try { // Wait for Bluetooth to be killed from its main thread Thread.sleep(950); // SystemServer is waiting 1000 ms, we need to wait less here } catch (InterruptedException e) { Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill"); } // Bluetooth cannot be killed on the main thread; it is in a deadLock. // Trying to recover by killing the Bluetooth from the binder thread. // This is bad :( Counter.logIncrement("bluetooth.value_kill_from_binder_thread"); Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder"); killAction.run(); } @Override Loading service/src/com/android/server/bluetooth/BluetoothManagerService.java +48 −43 Original line number Diff line number Diff line Loading @@ -1244,10 +1244,12 @@ class BluetoothManagerService { mAdapterLock.writeLock().lock(); try { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); if (mAdapter != null) { if (mAdapter == null) { return; } try { mAdapter.unregisterCallback( mBluetoothCallback, mContext.getAttributionSource()); mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); } catch (RemoteException e) { Log.e(TAG, "Unable to unregister BluetoothCallback", e); } Loading @@ -1263,36 +1265,39 @@ class BluetoothManagerService { try { mAdapter.getAdapterBinder() .asBinder() .linkToDeath(() -> binderDead.complete(null), 0); .linkToDeath( () -> { Log.i(TAG, "Successfully received Bluetooth death"); binderDead.complete(null); }, 0); } catch (RemoteException e) { Log.e(TAG, "Failed to linkToDeath", e); binderDead.complete(null); } // Unbind first to avoid receiving "onServiceDisconnected" // Unbind first to avoid receiving unwanted "onServiceDisconnected" mContext.unbindService(mConnection); try { // Force kill the bluetooth to make sure the process is not reused. // Note that in a perfect world, we should be able to re-init the same process. // Unfortunately, this require an heavy rework of the shutdown implementation // Force kill Bluetooth to make sure its process is not reused. // Note: In a perfect world, we should be able to re-init the same process. // Unfortunately, this requires an heavy rework of the Bluetooth app // TODO: b/339501753 - Properly stop Bluetooth without killing it mAdapter.killBluetoothProcess(); // if the kill throw, skip waiting as there is no bluetooth to wait for binderDead.get(1, TimeUnit.SECONDS); } catch (android.os.DeadObjectException e) { // Reduce error -> info since Bluetooth may already be dead prior to this call // Reduce exception to info and skip waiting (Bluetooth is dead as wanted) Log.i(TAG, "Bluetooth already dead 💀"); } catch (RemoteException e) { Log.e(TAG, "Unexpected error when calling killBluetoothProcess", e); Log.e(TAG, "Unexpected RemoteException when calling killBluetoothProcess", e); } catch (TimeoutException | InterruptedException | ExecutionException e) { Log.e(TAG, "Bluetooth death not received in time", e); Log.e(TAG, "Bluetooth death not received correctly", e); } mAdapter = null; mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } } finally { mAdapterLock.writeLock().unlock(); } Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +20 −3 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import com.android.bluetooth.telephony.BluetoothInCallService; import com.android.bluetooth.vc.VolumeControlService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.modules.utils.BackgroundThread; import com.android.modules.utils.BytesMatcher; Loading Loading @@ -2314,8 +2315,7 @@ public class AdapterService extends Service { mService.enforceCallingPermission( android.Manifest.permission.BLUETOOTH_PRIVILEGED, null); // Post on the main handler to be sure the cleanup has completed before calling exit mService.mHandler.post( Runnable killAction = () -> { if (Flags.killInsteadOfExit()) { Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())"); Loading @@ -2324,7 +2324,24 @@ public class AdapterService extends Service { Log.i(TAG, "killBluetoothProcess: Calling System.exit"); System.exit(0); } }); }; // Post on the main handler to let the cleanup complete before calling exit mService.mHandler.post(killAction); try { // Wait for Bluetooth to be killed from its main thread Thread.sleep(950); // SystemServer is waiting 1000 ms, we need to wait less here } catch (InterruptedException e) { Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill"); } // Bluetooth cannot be killed on the main thread; it is in a deadLock. // Trying to recover by killing the Bluetooth from the binder thread. // This is bad :( Counter.logIncrement("bluetooth.value_kill_from_binder_thread"); Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder"); killAction.run(); } @Override Loading
service/src/com/android/server/bluetooth/BluetoothManagerService.java +48 −43 Original line number Diff line number Diff line Loading @@ -1244,10 +1244,12 @@ class BluetoothManagerService { mAdapterLock.writeLock().lock(); try { mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); if (mAdapter != null) { if (mAdapter == null) { return; } try { mAdapter.unregisterCallback( mBluetoothCallback, mContext.getAttributionSource()); mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); } catch (RemoteException e) { Log.e(TAG, "Unable to unregister BluetoothCallback", e); } Loading @@ -1263,36 +1265,39 @@ class BluetoothManagerService { try { mAdapter.getAdapterBinder() .asBinder() .linkToDeath(() -> binderDead.complete(null), 0); .linkToDeath( () -> { Log.i(TAG, "Successfully received Bluetooth death"); binderDead.complete(null); }, 0); } catch (RemoteException e) { Log.e(TAG, "Failed to linkToDeath", e); binderDead.complete(null); } // Unbind first to avoid receiving "onServiceDisconnected" // Unbind first to avoid receiving unwanted "onServiceDisconnected" mContext.unbindService(mConnection); try { // Force kill the bluetooth to make sure the process is not reused. // Note that in a perfect world, we should be able to re-init the same process. // Unfortunately, this require an heavy rework of the shutdown implementation // Force kill Bluetooth to make sure its process is not reused. // Note: In a perfect world, we should be able to re-init the same process. // Unfortunately, this requires an heavy rework of the Bluetooth app // TODO: b/339501753 - Properly stop Bluetooth without killing it mAdapter.killBluetoothProcess(); // if the kill throw, skip waiting as there is no bluetooth to wait for binderDead.get(1, TimeUnit.SECONDS); } catch (android.os.DeadObjectException e) { // Reduce error -> info since Bluetooth may already be dead prior to this call // Reduce exception to info and skip waiting (Bluetooth is dead as wanted) Log.i(TAG, "Bluetooth already dead 💀"); } catch (RemoteException e) { Log.e(TAG, "Unexpected error when calling killBluetoothProcess", e); Log.e(TAG, "Unexpected RemoteException when calling killBluetoothProcess", e); } catch (TimeoutException | InterruptedException | ExecutionException e) { Log.e(TAG, "Bluetooth death not received in time", e); Log.e(TAG, "Bluetooth death not received correctly", e); } mAdapter = null; mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } } finally { mAdapterLock.writeLock().unlock(); } Loading