Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adb7fbb0 authored by William Escande's avatar William Escande
Browse files

Exit Bluetooth upon system server request

This will remove some race condition around Bluetooth being re-attached while it is not yet off. Making the system server wait for the process to go down entirely

Bug: 339304157
Bug: 335521878
Bug: 339548431
Test: atest pts-bot,avatar from presubmit (they restart bluetooth a lot)
Flag: com.android.bluetooth.flags.explicit_kill_from_system_server
Change-Id: Id1207c4e362e5f7adc3c6633c68cc539cc757845
parent 2eb1f932
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -320,4 +320,7 @@ interface IBluetooth

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getActiveAudioDevicePolicy(in BluetoothDevice device, in AttributionSource source);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")
    oneway void killBluetoothProcess();
}
+30 −4
Original line number Diff line number Diff line
@@ -786,6 +786,10 @@ public class AdapterService extends Service {
    @Override
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean onUnbind(Intent intent) {
        if (Flags.explicitKillFromSystemServer()) {
            Log.d(TAG, "onUnbind()");
            return super.onUnbind(intent);
        }
        Log.d(TAG, "onUnbind() - calling cleanup");
        cleanup();
        return super.onUnbind(intent);
@@ -794,6 +798,9 @@ public class AdapterService extends Service {
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy()");
        if (Flags.explicitKillFromSystemServer()) {
            return;
        }
        if (!isMock()) {
            // TODO(b/27859763)
            Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack");
@@ -1414,10 +1421,13 @@ public class AdapterService extends Service {
            mBluetoothSocketManagerBinder = null;
        }

        if (!Flags.explicitKillFromSystemServer()) {
            // Bluetooth will be killed, no need to cleanup binder
            if (mBinder != null) {
                mBinder.cleanup();
                mBinder = null; // Do not remove. Otherwise Binder leak!
            }
        }

        mPreferredAudioProfilesCallbacks.kill();

@@ -2196,9 +2206,12 @@ public class AdapterService extends Service {
     * <p>Otherwise, a memory leak can occur from repeated starting/stopping the service...Please
     * refer to android.os.Binder for further details on why an inner instance class should be
     * avoided.
     *
     * <p>TODO: b/339548431 -- Delete this comment as it does not apply when we get killed
     */
    @VisibleForTesting
    public static class AdapterServiceBinder extends IBluetooth.Stub {
        // TODO: b/339548431 move variable to final
        private AdapterService mService;

        AdapterServiceBinder(AdapterService svc) {
@@ -2220,7 +2233,6 @@ public class AdapterService extends Service {

        @Override
        public int getState() {
            // don't check caller, may be called from system UI
            AdapterService service = getService();
            if (service == null) {
                return BluetoothAdapter.STATE_OFF;
@@ -2229,6 +2241,19 @@ public class AdapterService extends Service {
            return service.getState();
        }

        @Override
        public void killBluetoothProcess() {
            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(
                    () -> {
                        Log.i(TAG, "killBluetoothProcess: Calling System.exit");
                        System.exit(0);
                    });
        }

        @Override
        public void enable(boolean quietMode, AttributionSource attributionSource) {
            AdapterService service = getService();
@@ -6809,6 +6834,7 @@ public class AdapterService extends Service {
        }
    }

    // TODO: b/339548431 delete isMock
    // Returns if this is a mock object. This is currently used in testing so that we may not call
    // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
    // calling finalize() which in turn calls System.exit() and the process crashes.
+14 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.os.Message;
import android.os.SystemProperties;
import android.util.Log;

import com.android.bluetooth.flags.Flags;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

@@ -176,6 +177,19 @@ final class AdapterState extends StateMachine {
            return BluetoothAdapter.STATE_OFF;
        }

        @Override
        public void enter() {
            if (!Flags.explicitKillFromSystemServer()) {
                super.enter();
                return;
            }
            int prevState = mPrevState;
            super.enter();
            if (prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
                mAdapterService.cleanup();
            }
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ public class AdapterServiceBinderTest {
    }

    @After
    public void cleaUp() {
    public void cleanUp() {
        mBinder.cleanup();
    }

+6 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import com.android.server.bluetooth.BluetoothManagerService.timeToLog
class AdapterBinder(rawBinder: IBinder) {
    private val TAG = "AdapterBinder"
    val adapterBinder: IBluetooth = IBluetooth.Stub.asInterface(rawBinder)
    val createdAt = System.currentTimeMillis()
    private val createdAt = System.currentTimeMillis()

    override fun toString(): String =
        "[Binder=" + adapterBinder.hashCode() + ", createdAt=" + timeToLog(createdAt) + "]"
@@ -88,4 +88,9 @@ class AdapterBinder(rawBinder: IBinder) {
        }
        return false
    }

    @Throws(RemoteException::class)
    fun killBluetoothProcess() {
        adapterBinder.killBluetoothProcess()
    }
}
Loading