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

Commit 0c8ef807 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "SystemServer: prevent state change after crash" into main

parents 91791857 f1fbeb1f
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;
import static android.bluetooth.BluetoothAdapter.nameForState;
import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE;
import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST;
import static android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH;
@@ -216,6 +217,11 @@ class BluetoothManagerService {
            new IBluetoothCallback.Stub() {
                @Override
                public void onBluetoothStateChange(int prevState, int newState) {
                    Log.d(
                            TAG,
                            "IBluetoothCallback.onBluetoothStateChange:"
                                    + (" prevState=" + nameForState(prevState))
                                    + (" newState=" + nameForState(newState)));
                    mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState)
                            .sendToTarget();
                }
@@ -226,6 +232,7 @@ class BluetoothManagerService {
                    if (name.isEmpty()) {
                        throw new IllegalArgumentException("Invalid Empty name");
                    }
                    Log.d(TAG, "IBluetoothCallback.onAdapterNameChange: " + name);
                    mHandler.post(() -> storeName(name));
                }

@@ -235,6 +242,7 @@ class BluetoothManagerService {
                    if (!BluetoothAdapter.checkBluetoothAddress(address)) {
                        throw new IllegalArgumentException("Invalid address");
                    }
                    Log.d(TAG, "IBluetoothCallback.onAdapterAddressChange: " + logAddress(address));
                    mHandler.post(() -> storeAddress(address));
                }
            };
@@ -353,7 +361,7 @@ class BluetoothManagerService {
        Log.d(
                TAG,
                ("delayModeChangedIfNeeded(" + modechanged + "):")
                        + (" state=" + BluetoothAdapter.nameForState(state))
                        + (" state=" + nameForState(state))
                        + (" Airplane.isOnOverrode=" + AirplaneModeListener.isOnOverrode())
                        + (" Airplane.isOn=" + AirplaneModeListener.isOn())
                        + (" isSatelliteModeOn()=" + isSatelliteModeOn())
@@ -458,7 +466,7 @@ class BluetoothManagerService {
            Log.d(
                    TAG,
                    ("handleAirplaneModeChanged(" + isAirplaneModeOn + "):")
                            + (" currentState=" + BluetoothAdapter.nameForState(currentState)));
                            + (" currentState=" + nameForState(currentState)));

            if (isAirplaneModeOn) {
                forceToOffFromModeChange(currentState, ENABLE_DISABLE_REASON_AIRPLANE_MODE);
@@ -1596,8 +1604,12 @@ class BluetoothManagerService {
                    Log.d(
                            TAG,
                            "MESSAGE_BLUETOOTH_STATE_CHANGE:"
                                    + (" prevState=" + BluetoothAdapter.nameForState(prevState))
                                    + (" newState=" + BluetoothAdapter.nameForState(newState)));
                                    + (" prevState=" + nameForState(prevState))
                                    + (" newState=" + nameForState(newState)));
                    if (mAdapter == null) {
                        Log.e(TAG, "State change received after bluetooth has crashed");
                        break;
                    }
                    bluetoothStateChangeHandler(prevState, newState);
                    // handle error state transition case from TURNING_ON to OFF
                    // unbind and rebind bluetooth service and enable bluetooth
@@ -1955,8 +1967,8 @@ class BluetoothManagerService {
                TAG,
                "broadcastIntentStateChange:"
                        + (" action=" + action.substring(action.lastIndexOf('.') + 1))
                        + (" prevState=" + BluetoothAdapter.nameForState(prevState))
                        + (" newState=" + BluetoothAdapter.nameForState(newState)));
                        + (" prevState=" + nameForState(prevState))
                        + (" newState=" + nameForState(newState)));
        // Send broadcast message to everyone else
        Intent intent = new Intent(action);
        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
@@ -2304,9 +2316,7 @@ class BluetoothManagerService {
        final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
        proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled());
        proto.write(BluetoothManagerServiceDumpProto.STATE, mState.get());
        proto.write(
                BluetoothManagerServiceDumpProto.STATE_NAME,
                BluetoothAdapter.nameForState(mState.get()));
        proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, nameForState(mState.get()));
        proto.write(BluetoothManagerServiceDumpProto.ADDRESS, logAddress(mAddress));
        proto.write(BluetoothManagerServiceDumpProto.NAME, mName);
        if (mEnable) {
+46 −7
Original line number Diff line number Diff line
@@ -22,9 +22,11 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;

import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_SERVICE_CONNECTED;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_STATE_CHANGE;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_DISABLE;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_ENABLE;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_RESTART_BLUETOOTH_SERVICE;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_TIMEOUT_BIND;

import static com.google.common.truth.Truth.assertThat;
@@ -173,6 +175,7 @@ public class BluetoothManagerServiceTest {
                        any(ServiceConnection.class),
                        anyInt(),
                        any(UserHandle.class));
        doNothing().when(mContext).unbindService(any());

        BluetoothServerProxy.setInstanceForTesting(mBluetoothServerProxy);

@@ -244,7 +247,6 @@ public class BluetoothManagerServiceTest {
                        any(ServiceConnection.class),
                        anyInt(),
                        any(UserHandle.class));
        doNothing().when(mContext).unbindService(any());
        mManagerService.enableBle("enable_bindFailure_removesTimeout", mBinder);
        syncHandler(MESSAGE_ENABLE);
        verify(mContext).unbindService(any());
@@ -269,18 +271,22 @@ public class BluetoothManagerServiceTest {
        //   * if user ask to enable again, it will start a second bind but the first still run
    }

    private void acceptBluetoothBinding(IBinder binder, String name, int n) {
        ComponentName compName = new ComponentName("", "com.android.bluetooth." + name);
    private BluetoothManagerService.BluetoothServiceConnection acceptBluetoothBinding() {
        ComponentName compName =
                new ComponentName("", "com.android.bluetooth.btservice.AdapterService");

        ArgumentCaptor<BluetoothManagerService.BluetoothServiceConnection> captor =
                ArgumentCaptor.forClass(BluetoothManagerService.BluetoothServiceConnection.class);
        verify(mContext, times(n))
        verify(mContext)
                .bindServiceAsUser(
                        any(Intent.class), captor.capture(), anyInt(), any(UserHandle.class));
        assertThat(captor.getAllValues().size()).isEqualTo(n);
        assertThat(captor.getAllValues().size()).isEqualTo(1);

        captor.getAllValues().get(n - 1).onServiceConnected(compName, binder);
        BluetoothManagerService.BluetoothServiceConnection serviceConnection =
                captor.getAllValues().get(0);
        serviceConnection.onServiceConnected(compName, mBinder);
        syncHandler(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
        return serviceConnection;
    }

    private static IBluetoothCallback captureBluetoothCallback(AdapterBinder adapterBinder)
@@ -294,7 +300,7 @@ public class BluetoothManagerServiceTest {

    IBluetoothCallback transition_offToBleOn() throws Exception {
        // Binding of IBluetooth
        acceptBluetoothBinding(mBinder, "btservice.AdapterService", 1);
        acceptBluetoothBinding();

        // TODO(b/280518177): This callback is too early, bt is not ON nor BLE_ON
        verify(mManagerCallback).onBluetoothServiceUp(any());
@@ -361,4 +367,37 @@ public class BluetoothManagerServiceTest {

        assertThat(mManagerService.getState()).isEqualTo(STATE_ON);
    }

    @Test
    public void crash_whileTransitionState_canRecover() throws Exception {
        mManagerService.enableBle("crash_whileTransitionState_canRecover", mBinder);
        syncHandler(MESSAGE_ENABLE);

        BluetoothManagerService.BluetoothServiceConnection serviceConnection =
                acceptBluetoothBinding();

        IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder);
        verify(mAdapterBinder).offToBleOn(anyBoolean(), any());
        btCallback.onBluetoothStateChange(STATE_OFF, STATE_BLE_TURNING_ON);
        syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
        assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);

        serviceConnection.onServiceDisconnected(
                new ComponentName("", "com.android.bluetooth.btservice.AdapterService"));
        syncHandler(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
        assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);

        // Send a late bluetoothStateChange (since it can happen concurrently)
        btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON);
        syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);

        // Bluetooth is still OFF and doesn't crash
        assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);

        mLooper.moveTimeForward(120_000);
        Message msg = mLooper.nextMessage();
        assertThat(msg).isNotNull();
        assertThat(msg.what).isEqualTo(MESSAGE_RESTART_BLUETOOTH_SERVICE);
        // Discard the msg without executing it
    }
}