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

Commit 4c33e9fb authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

Clean up correct state machine

MceStateMachine#doQuit is called inside tearDown(),
which call MceStateMachine#onQuitting,
which cleans up the device.

During the testing, a new state machine can be assigned
to the same device ID, which could be cleaned up by
the previous state machine.

By accepting the state machine instance, this change
prevent this.

Bug: 308622269
Test: atest MediaClientServiceTest
Change-Id: I2310845445a2d040a81331147f42b11cbe5b92a5
parent 576b2a85
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -367,9 +367,10 @@ public class MapClientService extends ProfileService {
     * cleanupDevice removes the associated state machine from the instance map
     *
     * @param device BluetoothDevice address of remote device
     * @param sm the state machine to clean up or null for cleaning up any state machine.
     */
    @VisibleForTesting
    public void cleanupDevice(BluetoothDevice device) {
    public void cleanupDevice(BluetoothDevice device, MceStateMachine sm) {
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
@@ -379,8 +380,12 @@ public class MapClientService extends ProfileService {
        synchronized (mMapInstanceMap) {
            MceStateMachine stateMachine = mMapInstanceMap.get(device);
            if (stateMachine != null) {
                if (sm == null || stateMachine == sm) {
                    mMapInstanceMap.remove(device);
                    stateMachine.doQuit();
                } else {
                    Log.w(TAG, "Trying to clean up wrong state machine");
                }
            }
        }
        if (DBG) {
+1 −1
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ class MceStateMachine extends StateMachine {
    @Override
    protected void onQuitting() {
        if (mService != null) {
            mService.cleanupDevice(mDevice);
            mService.cleanupDevice(mDevice, this);
        }
    }

+26 −2
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public class MapClientServiceTest {
        doReturn(true, false).when(mAdapterService).isStartedProfile(anyString());
        TestUtils.startService(mServiceRule, MapClientService.class);
        mService = MapClientService.getMapClientService();

        assertThat(mService).isNotNull();
        // Try getting the Bluetooth adapter
        mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -237,11 +238,34 @@ public class MapClientServiceTest {
        MceStateMachine sm = mock(MceStateMachine.class);
        mService.getInstanceMap().put(mRemoteDevice, sm);

        mService.cleanupDevice(mRemoteDevice);

        mService.cleanupDevice(mRemoteDevice, sm);
        assertThat(mService.getInstanceMap()).doesNotContainKey(mRemoteDevice);
    }

    @Test
    public void disconnect_doesNotCleanUpNewStateMachineOfSameDevice() {
        int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED;
        when(mDatabaseManager.getProfileConnectionPolicy(
                        mRemoteDevice, BluetoothProfile.MAP_CLIENT))
                .thenReturn(connectionPolicy);

        mService.connect(mRemoteDevice);
        MceStateMachine connectedSm = mService.getInstanceMap().get(mRemoteDevice);
        assertThat(connectedSm).isNotNull();

        connectedSm.sendMessage(MceStateMachine.MSG_MAS_SDP_DONE, mock(SdpMasRecord.class));
        connectedSm.sendMessage(MceStateMachine.MSG_MAS_CONNECTED);
        TestUtils.waitForLooperToFinishScheduledTask(connectedSm.getHandler().getLooper());

        mService.disconnect(mRemoteDevice);
        assertThat(mService.getInstanceMap()).containsKey(mRemoteDevice);
        MceStateMachine sm = mock(MceStateMachine.class);
        mService.getInstanceMap().put(mRemoteDevice, sm);
        TestUtils.waitForLooperToFinishScheduledTask(connectedSm.getHandler().getLooper());

        assertThat(mService.getInstanceMap()).containsKey(mRemoteDevice);
    }

    @Test
    public void aclDisconnectedNoTransport_whenConnected_doesNotCallDisconnect() {
        int connectionState = BluetoothProfile.STATE_CONNECTED;
+1 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ public class MapClientTest {
        TestUtils.waitForLooperToFinishScheduledTask(sm.getHandler().getLooper());

        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, sm.getState());
        mService.cleanupDevice(device);
        mService.cleanupDevice(device, sm);
        Assert.assertNull(mService.getInstanceMap().get(device));
    }