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

Commit e5dc9059 authored by Joe Antonetti's avatar Joe Antonetti Committed by Android (Google) Code Review
Browse files

Merge "[Handoff][2/N] Filter Associations in TaskContinuityManager to those...

Merge "[Handoff][2/N] Filter Associations in TaskContinuityManager to those with Handoff enabled." into main
parents 02e3e78e 9cdcf55c
Loading
Loading
Loading
Loading
+23 −19
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -48,9 +49,9 @@ class ConnectedAssociationStore {

    interface Listener {
        void onTransportConnected(@NonNull AssociationInfo associationInfo);

        void onTransportDisconnected(
            int associationId,
            @NonNull Collection<AssociationInfo> connectedAssociations);
                int associationId, @NonNull Collection<AssociationInfo> connectedAssociations);
    }

    ConnectedAssociationStore(
@@ -75,8 +76,7 @@ class ConnectedAssociationStore {
            }
            mAssociationInfoConsumer = this::onTransportsChanged;
            mCompanionDeviceManager.addOnTransportsChangedListener(
                mExecutor,
                mAssociationInfoConsumer);
                    mExecutor, mAssociationInfoConsumer);
            Slog.i(TAG, "Enabled ConnectedAssociationStore.");
        }
    }
@@ -103,11 +103,19 @@ class ConnectedAssociationStore {

    @VisibleForTesting
    void onTransportsChanged(List<AssociationInfo> associationInfos) {
        Set<Integer> removedAssociations
            = new HashSet<>(mConnectedAssociations.keySet());
        List<AssociationInfo> newTaskContinuityAssociations = new ArrayList<>();
        for (AssociationInfo associationInfo : associationInfos) {
            int taskContinuityFlag = associationInfo.getSystemDataSyncFlags()
                    & CompanionDeviceManager.FLAG_TASK_CONTINUITY;
            if (taskContinuityFlag != 0) {
                newTaskContinuityAssociations.add(associationInfo);
            }
        }

        Set<Integer> removedAssociations = new HashSet<>(mConnectedAssociations.keySet());

        Set<AssociationInfo> addedAssociations = new HashSet<>();
        for (AssociationInfo associationInfo : associationInfos) {
        for (AssociationInfo associationInfo : newTaskContinuityAssociations) {
            if (!mConnectedAssociations.containsKey(associationInfo.getId())) {
                addedAssociations.add(associationInfo);
            }
@@ -118,18 +126,14 @@ class ConnectedAssociationStore {
        }

        for (Integer associationId : removedAssociations) {
            Slog.i(
                TAG,
                "Transport disconnected for association: " + associationId);
            Slog.i(TAG, "Transport disconnected for association: " + associationId);

            mConnectedAssociations.remove(associationId);
            mListener.onTransportDisconnected(associationId, associationInfos);
            mListener.onTransportDisconnected(associationId, newTaskContinuityAssociations);
        }

        for (AssociationInfo associationInfo : addedAssociations) {
            Slog.i(
                TAG,
                "Transport connected for association: " + associationInfo.getId());
            Slog.i(TAG, "Transport connected for association: " + associationInfo.getId());

            mConnectedAssociations.put(associationInfo.getId(), associationInfo);
            mListener.onTransportConnected(associationInfo);
+62 −29
Original line number Diff line number Diff line
@@ -67,37 +67,33 @@ public class ConnectedAssociationStoreTest {
    @Before
    public void setUp() throws RemoteException {
        MockitoAnnotations.initMocks(this);
        mMockContext = Mockito.spy(
        mMockContext =
                Mockito.spy(
                        new ContextWrapper(
                InstrumentationRegistry
                    .getInstrumentation()
                    .getTargetContext()));

        mCompanionDeviceManager = new CompanionDeviceManager(
                mMockCompanionDeviceManagerService,
                mMockContext);

        mConnectedAssociationStore = new ConnectedAssociationStore(
            mCompanionDeviceManager,
            mMockContext.getMainExecutor(),
            mMockListener);
                                InstrumentationRegistry.getInstrumentation().getTargetContext()));

        mCompanionDeviceManager =
                new CompanionDeviceManager(mMockCompanionDeviceManagerService, mMockContext);

        mConnectedAssociationStore =
                new ConnectedAssociationStore(
                        mCompanionDeviceManager, mMockContext.getMainExecutor(), mMockListener);
    }

    @Test
    public void testEnableAndDisable_registersListener() throws RemoteException {
        mConnectedAssociationStore.enable();
        verify(mMockCompanionDeviceManagerService, times(1)).addOnTransportsChangedListener(
            any());
        verify(mMockCompanionDeviceManagerService, times(1)).addOnTransportsChangedListener(any());

        mConnectedAssociationStore.disable();
        verify(mMockCompanionDeviceManagerService, times(1)).removeOnTransportsChangedListener(
            any());
        verify(mMockCompanionDeviceManagerService, times(1))
                .removeOnTransportsChangedListener(any());
    }

    @Test
    public void testOnTransportConnected_notifyObserver() throws RemoteException {
        // Simulate a new association connected.
        AssociationInfo associationInfo = createAssociationInfo(1, "name");
        AssociationInfo associationInfo = createAssociationInfo(1, "name", true);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo));

        // Verify the observer is notified.
@@ -107,7 +103,7 @@ public class ConnectedAssociationStoreTest {
    @Test
    public void testOnTransportDisconnected_notifyObserver() throws RemoteException {
        // Start with an association connected.
        AssociationInfo associationInfo = createAssociationInfo(1, "name");
        AssociationInfo associationInfo = createAssociationInfo(1, "name", true);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo));

        // Simulate the association being disconnected.
@@ -120,7 +116,7 @@ public class ConnectedAssociationStoreTest {
    @Test
    public void testOnTransportChanged_noChange_noNotification() throws RemoteException {
        // Start with an association connected.
        AssociationInfo associationInfo = createAssociationInfo(1, "name");
        AssociationInfo associationInfo = createAssociationInfo(1, "name", true);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo));

        // Simulate the same association still connected.
@@ -131,11 +127,43 @@ public class ConnectedAssociationStoreTest {
        verify(mMockListener, never()).onTransportDisconnected(eq(associationInfo.getId()), any());
    }

    @Test
    public void testOnTransportChanged_taskContinuityDisabled_notifiesObserver()
            throws RemoteException {
        // Start with an association connected.
        AssociationInfo associationInfo = createAssociationInfo(1, "name", true);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo));

        // Simulate the same association still connected.
        AssociationInfo associationInfo2 = createAssociationInfo(1, "name", false);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo2));

        // Verify the observer is only notified once for the initial connection.
        verify(mMockListener, times(1)).onTransportConnected(eq(associationInfo));
        verify(mMockListener, times(1)).onTransportDisconnected(eq(associationInfo.getId()), any());
    }

    @Test
    public void testOnTransportChanged_taskContinuityEnabled_notifiesObserver()
            throws RemoteException {
        // Start with an association connected.
        AssociationInfo associationInfo = createAssociationInfo(1, "name", false);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo));

        // Simulate the same association still connected.
        AssociationInfo associationInfo2 = createAssociationInfo(1, "name", true);
        mConnectedAssociationStore.onTransportsChanged(Collections.singletonList(associationInfo2));

        // Verify the observer is only notified once for the initial connection.
        verify(mMockListener, times(1)).onTransportConnected(eq(associationInfo2));
        verify(mMockListener, never()).onTransportDisconnected(eq(associationInfo.getId()), any());
    }

    @Test
    public void testGetConnectedAssociations() throws RemoteException {
        // Connect two associations.
        AssociationInfo associationInfo1 = createAssociationInfo(1, "name");
        AssociationInfo associationInfo2 = createAssociationInfo(2, "name");
        AssociationInfo associationInfo1 = createAssociationInfo(1, "name", true);
        AssociationInfo associationInfo2 = createAssociationInfo(2, "name", true);
        mConnectedAssociationStore.onTransportsChanged(List.of(associationInfo1, associationInfo2));

        // Verify that getConnectedAssociations returns the correct set.
@@ -153,9 +181,14 @@ public class ConnectedAssociationStoreTest {
                .containsExactly(associationInfo2);
    }

    private AssociationInfo createAssociationInfo(int associationId, String deviceName) {
    private AssociationInfo createAssociationInfo(
            int associationId, String deviceName, boolean isTaskContinuityEnabled) {
        int systemDataSyncFlags =
                isTaskContinuityEnabled ? CompanionDeviceManager.FLAG_TASK_CONTINUITY : 0;

        return new AssociationInfo.Builder(associationId, 0, "com.android.test")
                .setDisplayName(deviceName)
                .setSystemDataSyncFlags(systemDataSyncFlags)
                .build();
    }
}