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

Commit 81bd4aa6 authored by Aritra Sen's avatar Aritra Sen
Browse files

Revert "Move fallback device logic into ActiveDeviceManager"

This reverts commit 57d0b689.

Reason for revert:  b/299687033 

Change-Id: I52a2d86e781913ba8eb8a1d371c6875afa5cf23e
parent 6d3e697d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1285,6 +1285,16 @@ public class A2dpService extends ProfileService {
                .a2dpConnectionStateChanged(device, fromState, toState);
    }

    /**
     * Retrieves the most recently connected device in the A2DP connected devices list.
     */
    public BluetoothDevice getFallbackDevice() {
        DatabaseManager dbManager = mAdapterService.getDatabase();
        return dbManager != null ? dbManager
            .getMostRecentlyConnectedDevicesInList(getConnectedDevices())
            : null;
    }

    /**
     * Binder object: must be a static class or memory leak may occur.
     */
+2 −46
Original line number Diff line number Diff line
@@ -1012,13 +1012,13 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
        A2dpService a2dpService = mFactory.getA2dpService();
        BluetoothDevice a2dpFallbackDevice = null;
        if (a2dpService != null) {
            a2dpFallbackDevice = getA2dpFallbackDevice();
            a2dpFallbackDevice = a2dpService.getFallbackDevice();
        }

        HeadsetService headsetService = mFactory.getHeadsetService();
        BluetoothDevice headsetFallbackDevice = null;
        if (headsetService != null) {
            headsetFallbackDevice = getHfpFallbackDevice();
            headsetFallbackDevice = headsetService.getFallbackDevice();
        }

        List<BluetoothDevice> connectedDevices = new ArrayList<>();
@@ -1128,50 +1128,6 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac
        }
    }

    /** Retrieves the most recently connected device in the A2DP connected devices list. */
    public BluetoothDevice getA2dpFallbackDevice() {
        DatabaseManager dbManager = mAdapterService.getDatabase();
        synchronized (mLock) {
            return dbManager != null
                    ? dbManager.getMostRecentlyConnectedDevicesInList(mA2dpConnectedDevices)
                    : null;
        }
    }

    /** Retrieves the most recently connected device in the A2DP connected devices list. */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public BluetoothDevice getHfpFallbackDevice() {
        DatabaseManager dbManager = mAdapterService.getDatabase();
        return dbManager != null
                ? dbManager.getMostRecentlyConnectedDevicesInList(getHfpFallbackCandidates())
                : null;
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    List<BluetoothDevice> getHfpFallbackCandidates() {
        List<BluetoothDevice> fallbackCandidates;
        synchronized (mLock) {
            fallbackCandidates = new ArrayList<>(mHfpConnectedDevices);
        }
        List<BluetoothDevice> uninterestedCandidates = new ArrayList<>();
        for (BluetoothDevice device : fallbackCandidates) {
            byte[] deviceType =
                    mDbManager.getCustomMeta(device, BluetoothDevice.METADATA_DEVICE_TYPE);
            BluetoothClass deviceClass = device.getBluetoothClass();
            if ((deviceClass != null
                            && deviceClass.getMajorDeviceClass()
                                    == BluetoothClass.Device.WEARABLE_WRIST_WATCH)
                    || (deviceType != null
                            && BluetoothDevice.DEVICE_TYPE_WATCH.equals(new String(deviceType)))) {
                uninterestedCandidates.add(device);
            }
        }
        for (BluetoothDevice device : uninterestedCandidates) {
            fallbackCandidates.remove(device);
        }
        return fallbackCandidates;
    }

    @VisibleForTesting
    BluetoothDevice getA2dpActiveDevice() {
        return mA2dpActiveDevice;
+39 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.modules.utils.build.SdkLevel.isAtLeastU;

import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
@@ -53,7 +54,6 @@ import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
@@ -126,7 +126,6 @@ public class HeadsetService extends ProfileService {
    private int mMaxHeadsetConnections = 1;
    private BluetoothDevice mActiveDevice;
    private AdapterService mAdapterService;
    private ActiveDeviceManager mActiveDeviceManager;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
    private Handler mStateMachinesThreadHandler;
@@ -185,7 +184,6 @@ public class HeadsetService extends ProfileService {
                "AdapterService cannot be null when HeadsetService starts");
        mDatabaseManager = Objects.requireNonNull(mAdapterService.getDatabase(),
                "DatabaseManager cannot be null when HeadsetService starts");
        mActiveDeviceManager = Objects.requireNonNull(mAdapterService.getActiveDeviceManager());
        // Step 2: Start handler thread for state machines
        mStateMachinesThread = new HandlerThread("HeadsetService.StateMachines");
        mStateMachinesThread.start();
@@ -1344,7 +1342,7 @@ public class HeadsetService extends ProfileService {
            // we need to check if another device is connected and set it active instead.
            // Calling this before any other active related calls has the same effect as
            // a classic active device switch.
            BluetoothDevice fallbackDevice = mActiveDeviceManager.getHfpFallbackDevice();
            BluetoothDevice fallbackDevice = getFallbackDevice();
            if (fallbackDevice != null && mActiveDevice != null
                    && getConnectionState(mActiveDevice) != BluetoothProfile.STATE_CONNECTED) {
                setActiveDevice(fallbackDevice);
@@ -1998,8 +1996,11 @@ public class HeadsetService extends ProfileService {
                setActiveDevice(null);
            }
        }
        mActiveDeviceManager.profileConnectionStateChanged(
                BluetoothProfile.HEADSET, device, fromState, toState);

        mAdapterService
                .getActiveDeviceManager()
                .profileConnectionStateChanged(BluetoothProfile.HEADSET, device, fromState,
                    toState);
        mAdapterService
                .getSilenceDeviceManager()
                .hfpConnectionStateChanged(device, fromState, toState);
@@ -2261,6 +2262,38 @@ public class HeadsetService extends ProfileService {
                == mStateMachinesThread.getId());
    }

    /**
     * Retrieves the most recently connected device in the A2DP connected devices list.
     */
    public BluetoothDevice getFallbackDevice() {
        DatabaseManager dbManager = mAdapterService.getDatabase();
        return dbManager != null ? dbManager
            .getMostRecentlyConnectedDevicesInList(getFallbackCandidates(dbManager))
            : null;
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    List<BluetoothDevice> getFallbackCandidates(DatabaseManager dbManager) {
        List<BluetoothDevice> fallbackCandidates = getConnectedDevices();
        List<BluetoothDevice> uninterestedCandidates = new ArrayList<>();
        for (BluetoothDevice device : fallbackCandidates) {
            byte[] deviceType = dbManager.getCustomMeta(device,
                    BluetoothDevice.METADATA_DEVICE_TYPE);
            BluetoothClass deviceClass = device.getBluetoothClass();
            if ((deviceClass != null
                    && deviceClass.getMajorDeviceClass()
                    == BluetoothClass.Device.WEARABLE_WRIST_WATCH)
                    || (deviceType != null
                    && BluetoothDevice.DEVICE_TYPE_WATCH.equals(new String(deviceType)))) {
                uninterestedCandidates.add(device);
            }
        }
        for (BluetoothDevice device : uninterestedCandidates) {
            fallbackCandidates.remove(device);
        }
        return fallbackCandidates;
    }

    @Override
    public void dump(StringBuilder sb) {
        boolean isScoOn = mSystemInterface.getAudioManager().isBluetoothScoOn();
+16 −66
Original line number Diff line number Diff line
@@ -63,9 +63,8 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -149,6 +148,21 @@ public class ActiveDeviceManagerTest {
        when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId);
        when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId))
                .thenReturn(connectedHearingAidDevices);

        when(mA2dpService.getFallbackDevice()).thenAnswer(invocation -> {
            if (!mDeviceConnectionStack.isEmpty() && Objects.equals(mA2dpDevice,
                    mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1))) {
                return mA2dpDevice;
            }
            return null;
        });
        when(mHeadsetService.getFallbackDevice()).thenAnswer(invocation -> {
            if (!mDeviceConnectionStack.isEmpty() && Objects.equals(mHeadsetDevice,
                    mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1))) {
                return mHeadsetDevice;
            }
            return null;
        });
    }

    @After
@@ -1117,49 +1131,6 @@ public class ActiveDeviceManagerTest {
        verify(mHearingAidService, timeout(TIMEOUT_MS)).removeActiveDevice(false);
    }

    @Test
    public void testGetFallbackCandidates() {
        BluetoothDevice deviceA = TestUtils.getTestDevice(mAdapter, 0);
        BluetoothDevice deviceB = TestUtils.getTestDevice(mAdapter, 1);

        // No connected device
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().isEmpty());

        // One connected device
        headsetConnected(deviceA, true);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().contains(deviceA));

        // Two connected devices
        headsetConnected(deviceB, false);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().contains(deviceA));
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().contains(deviceB));
    }

    @Test
    public void testGetFhpFallbackCandidates_HasWatchDevice() {
        BluetoothDevice deviceWatch = TestUtils.getTestDevice(mAdapter, 0);
        BluetoothDevice deviceRegular = TestUtils.getTestDevice(mAdapter, 1);

        // Make deviceWatch a watch
        mDatabaseManager.setCustomMeta(
                deviceWatch,
                BluetoothDevice.METADATA_DEVICE_TYPE,
                BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());

        // Has a connected watch device
        headsetConnected(deviceWatch, false);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().isEmpty());

        // Two connected devices with one watch
        headsetConnected(deviceRegular, true);
        TestUtils.waitForLooperToFinishScheduledTask(mActiveDeviceManager.getHandlerLooper());
        Assert.assertFalse(mActiveDeviceManager.getHfpFallbackCandidates().contains(deviceWatch));
        Assert.assertTrue(mActiveDeviceManager.getHfpFallbackCandidates().contains(deviceRegular));
    }

    /**
     * Helper to indicate A2dp connected for a device.
     */
@@ -1356,7 +1327,6 @@ public class ActiveDeviceManagerTest {

    private class TestDatabaseManager extends DatabaseManager {
        ArrayMap<BluetoothDevice, SparseIntArray> mProfileConnectionPolicy;
        final Map<String, Map<Integer, byte[]>> mMetadataCache = new HashMap<>();

        TestDatabaseManager(AdapterService service) {
            super(service);
@@ -1405,25 +1375,5 @@ public class ActiveDeviceManagerTest {
            }
            return policy.get(profile, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
        }

        @Override
        public boolean setCustomMeta(BluetoothDevice device, int key, byte[] newValue) {
            Map<Integer, byte[]> metadata = mMetadataCache.get(device.getAddress());
            if (metadata == null) {
                metadata = new ArrayMap<>();
                mMetadataCache.put(device.getAddress(), metadata);
            }
            metadata.put(key, newValue);
            return true;
        }

        @Override
        public byte[] getCustomMeta(BluetoothDevice device, int key) {
            Map<Integer, byte[]> metadata = mMetadataCache.get(device.getAddress());
            if (metadata == null) {
                return null;
            }
            return metadata.get(key);
        }
    }
}
+0 −2
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ public class ProfileServiceTest {
    @Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
    @Mock private AdapterService mMockAdapterService;
    @Mock private DatabaseManager mDatabaseManager;
    @Mock private ActiveDeviceManager mActiveDeviceManager;
    @Mock private LocationManager mLocationManager;

    private Class[] mProfiles;
@@ -149,7 +148,6 @@ public class ProfileServiceTest {
            }
        });
        doReturn(mDatabaseManager).when(mMockAdapterService).getDatabase();
        doReturn(mActiveDeviceManager).when(mMockAdapterService).getActiveDeviceManager();

        when(mMockAdapterService.getSystemService(Context.LOCATION_SERVICE))
                .thenReturn(mLocationManager);
Loading