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

Commit 8a3ce3b4 authored by Joe Antonetti's avatar Joe Antonetti
Browse files

[Handoff][2/N] Decoupled Association Store from Business Logic

Completely decouple transport logic from business logic, allowing everything to flow nicely through TaskContinuityManagerService

Flag: android.companion.enable_task_continuity
Bug: 400970610
Test: Updated Unit Tests
Change-Id: I875e9d47d35fe15e906e31398749930728d79926
parent 3b321d7c
Loading
Loading
Loading
Loading
+39 −79
Original line number Original line Diff line number Diff line
@@ -19,11 +19,9 @@ package com.android.server.companion.datatransfer.continuity;
import static com.android.server.companion.datatransfer.contextsync.BitmapUtils.renderDrawableToByteArray;
import static com.android.server.companion.datatransfer.contextsync.BitmapUtils.renderDrawableToByteArray;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
import android.app.TaskStackListener;
import android.app.TaskStackListener;
import android.companion.AssociationInfo;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
@@ -32,7 +30,6 @@ import android.graphics.drawable.Drawable;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Slog;
import android.util.Slog;


import com.android.server.companion.datatransfer.continuity.connectivity.ConnectedAssociationStore;
import com.android.server.companion.datatransfer.continuity.connectivity.TaskContinuityMessenger;
import com.android.server.companion.datatransfer.continuity.connectivity.TaskContinuityMessenger;
import com.android.server.companion.datatransfer.continuity.messages.ContinuityDeviceConnected;
import com.android.server.companion.datatransfer.continuity.messages.ContinuityDeviceConnected;
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskAddedMessage;
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskAddedMessage;
@@ -41,21 +38,16 @@ import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskU
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskInfo;
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskInfo;


import java.io.IOException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Objects;
import java.util.Objects;
import java.util.stream.Collectors;


/**
/**
 * Responsible for broadcasting recent tasks on the current device to the user's
 * Responsible for broadcasting recent tasks on the current device to the user's
 *
 *
 * other devices via {@link CompanionDeviceManager}.
 * other devices via {@link CompanionDeviceManager}.
 */
 */
class TaskBroadcaster
class TaskBroadcaster extends TaskStackListener {
    extends TaskStackListener
    implements ConnectedAssociationStore.Observer {


    private static final String TAG = "TaskBroadcaster";
    private static final String TAG = "TaskBroadcaster";


@@ -64,7 +56,7 @@ class TaskBroadcaster
    private final TaskContinuityMessenger mTaskContinuityMessenger;
    private final TaskContinuityMessenger mTaskContinuityMessenger;
    private final PackageManager mPackageManager;
    private final PackageManager mPackageManager;


    private boolean mIsBroadcasting = false;
    private boolean mIsListeningToActivityTaskManager = false;


    public TaskBroadcaster(
    public TaskBroadcaster(
        @NonNull Context context,
        @NonNull Context context,
@@ -79,56 +71,35 @@ class TaskBroadcaster
        mTaskContinuityMessenger = taskContinuityMessenger;
        mTaskContinuityMessenger = taskContinuityMessenger;
    }
    }


    void startBroadcasting(){
    public void onDeviceConnected(int id) {
        if (mIsBroadcasting) {
        Slog.v(TAG, "Transport connected for association id: " + id);
            Slog.v(TAG, "TaskBroadcaster is already broadcasting");
        sendDeviceConnectedMessage(id);
            return;
        synchronized (this) {
        }
            if (!mIsListeningToActivityTaskManager) {

        Slog.v(TAG, "Starting broadcasting");
        mTaskContinuityMessenger.getConnectedAssociationStore().addObserver(this);
                mActivityTaskManager.registerTaskStackListener(this);
                mActivityTaskManager.registerTaskStackListener(this);

                mIsListeningToActivityTaskManager = true;
        mIsBroadcasting = true;
            }
        }
        }

    void stopBroadcasting(){
        if (!mIsBroadcasting) {
            Slog.v(TAG, "TaskBroadcaster is not broadcasting");
            return;
    }
    }


        Slog.v(TAG, "Stopping broadcasting");
    public void onAllDevicesDisconnected() {
        mIsBroadcasting = false;
        synchronized (this) {
        mTaskContinuityMessenger.getConnectedAssociationStore().removeObserver(this);
            if (mIsListeningToActivityTaskManager) {
                mActivityTaskManager.unregisterTaskStackListener(this);
                mActivityTaskManager.unregisterTaskStackListener(this);
                mIsListeningToActivityTaskManager = false;
            }
            }

    @Override
    public void onTransportConnected(AssociationInfo associationInfo) {
        Slog.v(
            TAG,
            "Transport connected for association id: " + associationInfo.getId());
        sendDeviceConnectedMessage(associationInfo.getId());
        }
        }

    @Override
    public void onTransportDisconnected(int associationId) {
        Slog.v(
            TAG,
            "Transport disconnected for association id: " + associationId);
    }
    }


    @Override
    @Override
    public void onTaskCreated(
    public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
        int taskId,
        ComponentName componentName) throws RemoteException {

        Slog.v(TAG, "onTaskCreated: taskId=" + taskId);
        Slog.v(TAG, "onTaskCreated: taskId=" + taskId);
        RunningTaskInfo taskInfo = getRunningTask(taskId);
        if (taskInfo == null) {
            Slog.w(TAG, "Could not find RunningTaskInfo for taskId: " + taskId);
            return;
        }


        ActivityManager.RunningTaskInfo taskInfo = getRunningTask(taskId);

        if (taskInfo != null) {
        RemoteTaskInfo remoteTaskInfo = createRemoteTaskInfo(taskInfo);
        RemoteTaskInfo remoteTaskInfo = createRemoteTaskInfo(taskInfo);
        if (remoteTaskInfo == null) {
        if (remoteTaskInfo == null) {
            Slog.w(TAG, "Could not create RemoteTaskInfo for task: " + taskInfo.taskId);
            Slog.w(TAG, "Could not create RemoteTaskInfo for task: " + taskInfo.taskId);
@@ -137,15 +108,11 @@ class TaskBroadcaster


        RemoteTaskAddedMessage taskAddedMessage = new RemoteTaskAddedMessage(remoteTaskInfo);
        RemoteTaskAddedMessage taskAddedMessage = new RemoteTaskAddedMessage(remoteTaskInfo);
        mTaskContinuityMessenger.sendMessage(taskAddedMessage);
        mTaskContinuityMessenger.sendMessage(taskAddedMessage);
        } else {
            Slog.w(TAG, "Could not find RunningTaskInfo for taskId: " + taskId);
        }
    }
    }


    @Override
    @Override
    public void onTaskRemoved(int taskId) throws RemoteException {
    public void onTaskRemoved(int taskId) throws RemoteException {
        Slog.v(TAG, "onTaskRemoved: taskId=" + taskId);
        Slog.v(TAG, "onTaskRemoved: taskId=" + taskId);

        RemoteTaskRemovedMessage taskRemovedMessage = new RemoteTaskRemovedMessage(taskId);
        RemoteTaskRemovedMessage taskRemovedMessage = new RemoteTaskRemovedMessage(taskId);
        mTaskContinuityMessenger.sendMessage(taskRemovedMessage);
        mTaskContinuityMessenger.sendMessage(taskRemovedMessage);
    }
    }
@@ -170,17 +137,10 @@ class TaskBroadcaster
            "Sending device connected message for association id: "
            "Sending device connected message for association id: "
                + associationId);
                + associationId);


        List<ActivityManager.RunningTaskInfo> runningTasks = getRunningTasks();
        List<RemoteTaskInfo> remoteTasks = getRunningTasks().stream()

            .map(this::createRemoteTaskInfo)
        List<RemoteTaskInfo> remoteTasks = new ArrayList<>();
            .filter(Objects::nonNull)
        for (ActivityManager.RunningTaskInfo taskInfo : runningTasks) {
            .collect(Collectors.toList());
            RemoteTaskInfo remoteTaskInfo = createRemoteTaskInfo(taskInfo);
            if (remoteTaskInfo != null) {
                remoteTasks.add(remoteTaskInfo);
            } else {
                Slog.w(TAG, "Could not create RemoteTaskInfo for task: " + taskInfo.taskId);
            }
        }


        ContinuityDeviceConnected deviceConnectedMessage
        ContinuityDeviceConnected deviceConnectedMessage
            = new ContinuityDeviceConnected(remoteTasks);
            = new ContinuityDeviceConnected(remoteTasks);
@@ -188,10 +148,10 @@ class TaskBroadcaster
        mTaskContinuityMessenger.sendMessage(associationId, deviceConnectedMessage);
        mTaskContinuityMessenger.sendMessage(associationId, deviceConnectedMessage);
    }
    }


    private ActivityManager.RunningTaskInfo getRunningTask(int taskId) {
    private RunningTaskInfo getRunningTask(int taskId) {
        List<ActivityManager.RunningTaskInfo> runningTasks = getRunningTasks();
        List<RunningTaskInfo> runningTasks = getRunningTasks();
        if (runningTasks != null) {
        if (runningTasks != null) {
            for (ActivityManager.RunningTaskInfo info : runningTasks) {
            for (RunningTaskInfo info : runningTasks) {
                if (info.taskId == taskId) {
                if (info.taskId == taskId) {
                    return info;
                    return info;
                }
                }
@@ -201,11 +161,11 @@ class TaskBroadcaster
        return null;
        return null;
    }
    }


    private List<ActivityManager.RunningTaskInfo> getRunningTasks() {
    private List<RunningTaskInfo> getRunningTasks() {
        return mActivityTaskManager.getTasks(Integer.MAX_VALUE, true);
        return mActivityTaskManager.getTasks(Integer.MAX_VALUE, true);
    }
    }


    private RemoteTaskInfo createRemoteTaskInfo(ActivityManager.RunningTaskInfo taskInfo) {
    private RemoteTaskInfo createRemoteTaskInfo(RunningTaskInfo taskInfo) {
        PackageInfo packageInfo;
        PackageInfo packageInfo;
        try {
        try {
            packageInfo = mPackageManager.getPackageInfo(
            packageInfo = mPackageManager.getPackageInfo(
+23 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.companion.datatransfer.continuity;
package com.android.server.companion.datatransfer.continuity;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.companion.CompanionDeviceManager;
import android.companion.datatransfer.continuity.IHandoffRequestCallback;
import android.companion.datatransfer.continuity.IHandoffRequestCallback;
import android.companion.datatransfer.continuity.ITaskContinuityManager;
import android.companion.datatransfer.continuity.ITaskContinuityManager;
@@ -42,6 +43,7 @@ import com.android.server.SystemService;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Collection;


/**
/**
 * Service to handle task continuity features
 * Service to handle task continuity features
@@ -66,8 +68,7 @@ public final class TaskContinuityManagerService


        mTaskContinuityMessenger = new TaskContinuityMessenger(context, this);
        mTaskContinuityMessenger = new TaskContinuityMessenger(context, this);
        mTaskBroadcaster = new TaskBroadcaster(context, mTaskContinuityMessenger);
        mTaskBroadcaster = new TaskBroadcaster(context, mTaskContinuityMessenger);
        mRemoteTaskStore = new RemoteTaskStore(
        mRemoteTaskStore = new RemoteTaskStore();
            mTaskContinuityMessenger.getConnectedAssociationStore());
        mOutboundHandoffRequestController = new OutboundHandoffRequestController(
        mOutboundHandoffRequestController = new OutboundHandoffRequestController(
            context,
            context,
            mTaskContinuityMessenger);
            mTaskContinuityMessenger);
@@ -79,7 +80,6 @@ public final class TaskContinuityManagerService
    public void onStart() {
    public void onStart() {
        mTaskContinuityManagerService = new TaskContinuityManagerServiceImpl();
        mTaskContinuityManagerService = new TaskContinuityManagerServiceImpl();
        mTaskContinuityMessenger.enable();
        mTaskContinuityMessenger.enable();
        mTaskBroadcaster.startBroadcasting();
        publishBinderService(Context.TASK_CONTINUITY_SERVICE, mTaskContinuityManagerService);
        publishBinderService(Context.TASK_CONTINUITY_SERVICE, mTaskContinuityManagerService);
    }
    }


@@ -116,6 +116,26 @@ public final class TaskContinuityManagerService
        }
        }
    }
    }


    @Override
    public void onAssociationConnected(@NonNull AssociationInfo associationInfo) {
        mRemoteTaskStore.addDevice(
            associationInfo.getId(),
            associationInfo.getDisplayName().toString());

        mTaskBroadcaster.onDeviceConnected(associationInfo.getId());
    }

    @Override
    public void onAssociationDisconnected(
        int associationId,
        @NonNull Collection<AssociationInfo> connectedAssociations) {

        mRemoteTaskStore.removeDevice(associationId);
        if (connectedAssociations.isEmpty()) {
            mTaskBroadcaster.onAllDevicesDisconnected();
        }
    }

    @Override
    @Override
    public void onMessageReceived(
    public void onMessageReceived(
        int associationId,
        int associationId,
+54 −27
Original line number Original line Diff line number Diff line
@@ -19,9 +19,10 @@ package com.android.server.companion.datatransfer.continuity.connectivity;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.companion.AssociationInfo;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.companion.CompanionDeviceManager;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
@@ -29,36 +30,67 @@ import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.Objects;
import javax.annotation.concurrent.GuardedBy;


public class ConnectedAssociationStore {
class ConnectedAssociationStore {


    private static final String TAG = "ConnectedAssociationStore";
    private static final String TAG = "ConnectedAssociationStore";


    private final CompanionDeviceManager mCompanionDeviceManager;
    private final CompanionDeviceManager mCompanionDeviceManager;
    private final Listener mListener;
    private final Executor mExecutor;
    private final Map<Integer, AssociationInfo> mConnectedAssociations = new HashMap<>();
    private final Map<Integer, AssociationInfo> mConnectedAssociations = new HashMap<>();
    private final List<Observer> mObservers = new ArrayList<>();


    public interface Observer {
    @GuardedBy("this")
        void onTransportConnected(AssociationInfo associationInfo);
    private Consumer<List<AssociationInfo>> mAssociationInfoConsumer;
        void onTransportDisconnected(int associationId);

    interface Listener {
        void onTransportConnected(@NonNull AssociationInfo associationInfo);
        void onTransportDisconnected(
            int associationId,
            @NonNull Collection<AssociationInfo> connectedAssociations);
    }
    }


    public ConnectedAssociationStore(
    ConnectedAssociationStore(
        @NonNull CompanionDeviceManager companionDeviceManager,
        @NonNull CompanionDeviceManager companionDeviceManager,
        @NonNull Executor executor) {
        @NonNull Executor executor,
        @NonNull Listener listener) {

        Objects.requireNonNull(companionDeviceManager);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(listener);


        mCompanionDeviceManager = companionDeviceManager;
        mCompanionDeviceManager = companionDeviceManager;
        mCompanionDeviceManager.addOnTransportsChangedListener(
        mListener = listener;
                executor,
        mExecutor = executor;
                this::onTransportsChanged);
   }
   }


    public void addObserver(@NonNull Observer observer) {
    public void enable() {
        mObservers.add(observer);
        synchronized (this) {
            if (mAssociationInfoConsumer != null) {
                Slog.i(TAG, "ConnectedAssociationStore is already enabled.");
                return;
            }
            mAssociationInfoConsumer = this::onTransportsChanged;
            mCompanionDeviceManager.addOnTransportsChangedListener(
                mExecutor,
                mAssociationInfoConsumer);
            Slog.i(TAG, "Enabled ConnectedAssociationStore.");
        }
    }
    }


    public void removeObserver(@NonNull Observer observer) {
    public void disable() {
        mObservers.remove(observer);
        synchronized (this) {
            if (mAssociationInfoConsumer == null) {
                Slog.i(TAG, "ConnectedAssociationStore is already disabled.");
                return;
            }
            mCompanionDeviceManager.removeOnTransportsChangedListener(mAssociationInfoConsumer);
            mAssociationInfoConsumer = null;
            Slog.i(TAG, "Disabled ConnectedAssociationStore.");
        }
    }
    }


    public Collection<AssociationInfo> getConnectedAssociations() {
    public Collection<AssociationInfo> getConnectedAssociations() {
@@ -69,7 +101,8 @@ public class ConnectedAssociationStore {
        return mConnectedAssociations.get(associationId);
        return mConnectedAssociations.get(associationId);
    }
    }


    private void onTransportsChanged(List<AssociationInfo> associationInfos) {
    @VisibleForTesting
    void onTransportsChanged(List<AssociationInfo> associationInfos) {
        Set<Integer> removedAssociations
        Set<Integer> removedAssociations
            = new HashSet<>(mConnectedAssociations.keySet());
            = new HashSet<>(mConnectedAssociations.keySet());


@@ -85,27 +118,21 @@ public class ConnectedAssociationStore {
        }
        }


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


            mConnectedAssociations.remove(associationId);
            mConnectedAssociations.remove(associationId);

            mListener.onTransportDisconnected(associationId, associationInfos);
            for (Observer observer : mObservers) {
                observer.onTransportDisconnected(associationId);
            }
        }
        }


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


            mConnectedAssociations.put(associationInfo.getId(), associationInfo);
            mConnectedAssociations.put(associationInfo.getId(), associationInfo);

            mListener.onTransportConnected(associationInfo);
            for (Observer observer : mObservers) {
                observer.onTransportConnected(associationInfo);
            }
        }
        }
    }
    }
}
}
 No newline at end of file
+37 −4
Original line number Original line Diff line number Diff line
@@ -38,7 +38,7 @@ import java.util.Objects;
 * between devices. Internally, it uses the {@link CompanionDeviceManager} to send and receive
 * between devices. Internally, it uses the {@link CompanionDeviceManager} to send and receive
 * messages.
 * messages.
 */
 */
public class TaskContinuityMessenger {
public class TaskContinuityMessenger implements ConnectedAssociationStore.Listener {


    private static final String TAG = "TaskContinuityMessenger";
    private static final String TAG = "TaskContinuityMessenger";


@@ -51,6 +51,10 @@ public class TaskContinuityMessenger {
    private BiConsumer<Integer, byte[]> mIncomingMessageConsumer;
    private BiConsumer<Integer, byte[]> mIncomingMessageConsumer;


    public interface Listener {
    public interface Listener {
        void onAssociationConnected(@NonNull AssociationInfo associationInfo);
        void onAssociationDisconnected(
            int associationId,
            @NonNull Collection<AssociationInfo> connectedAssociations);
        void onMessageReceived(int associationId, @NonNull TaskContinuityMessage message);
        void onMessageReceived(int associationId, @NonNull TaskContinuityMessage message);
    }
    }


@@ -65,7 +69,8 @@ public class TaskContinuityMessenger {
        mCompanionDeviceManager = context.getSystemService(CompanionDeviceManager.class);
        mCompanionDeviceManager = context.getSystemService(CompanionDeviceManager.class);
        mConnectedAssociationStore = new ConnectedAssociationStore(
        mConnectedAssociationStore = new ConnectedAssociationStore(
            mCompanionDeviceManager,
            mCompanionDeviceManager,
            mExecutor);
            mExecutor,
            this);
    }
    }


    public void enable() {
    public void enable() {
@@ -80,6 +85,8 @@ public class TaskContinuityMessenger {
                MESSAGE_ONEWAY_TASK_CONTINUITY,
                MESSAGE_ONEWAY_TASK_CONTINUITY,
                mIncomingMessageConsumer);
                mIncomingMessageConsumer);
        }
        }

        mConnectedAssociationStore.enable();
    }
    }


    public void disable() {
    public void disable() {
@@ -93,6 +100,8 @@ public class TaskContinuityMessenger {
                mIncomingMessageConsumer);
                mIncomingMessageConsumer);
            mIncomingMessageConsumer = null;
            mIncomingMessageConsumer = null;
        }
        }

        mConnectedAssociationStore.disable();
    }
    }


    @NonNull
    @NonNull
@@ -111,13 +120,18 @@ public class TaskContinuityMessenger {
        int associationId,
        int associationId,
        @NonNull TaskContinuityMessage message) {
        @NonNull TaskContinuityMessage message) {


        Objects.requireNonNull(message);

        return sendMessage(new int[] {associationId}, message);
        return sendMessage(new int[] {associationId}, message);
    }
    }


    public SendMessageResult sendMessage(
    public SendMessageResult sendMessage(
        int[] associationIds,
        @NonNull int[] associationIds,
        @NonNull TaskContinuityMessage message) {
        @NonNull TaskContinuityMessage message) {


        Objects.requireNonNull(associationIds);
        Objects.requireNonNull(message);

        Slog.i(TAG, "Sending message to " + associationIds.length + " associations.");
        Slog.i(TAG, "Sending message to " + associationIds.length + " associations.");
        byte[] serializedMessage;
        byte[] serializedMessage;
        try {
        try {
@@ -148,6 +162,8 @@ public class TaskContinuityMessenger {
    }
    }


    public SendMessageResult sendMessage(@NonNull TaskContinuityMessage message) {
    public SendMessageResult sendMessage(@NonNull TaskContinuityMessage message) {
        Objects.requireNonNull(message);

        int[] connectedAssociations = mConnectedAssociationStore
        int[] connectedAssociations = mConnectedAssociationStore
            .getConnectedAssociations()
            .getConnectedAssociations()
            .stream()
            .stream()
@@ -157,6 +173,23 @@ public class TaskContinuityMessenger {
        return sendMessage(connectedAssociations, message);
        return sendMessage(connectedAssociations, message);
    }
    }


    @Override
    public void onTransportConnected(@NonNull AssociationInfo associationInfo) {
        Objects.requireNonNull(associationInfo);

        mListener.onAssociationConnected(associationInfo);
    }

    @Override
    public void onTransportDisconnected(
        int associationId,
        @NonNull Collection<AssociationInfo> connectedAssociations) {

        Objects.requireNonNull(connectedAssociations);

        mListener.onAssociationDisconnected(associationId, connectedAssociations);
    }

    private void onMessageReceived(int associationId, byte[] data) {
    private void onMessageReceived(int associationId, byte[] data) {
        Slog.v(TAG, "Received message from association id: " + associationId);
        Slog.v(TAG, "Received message from association id: " + associationId);
      try {
      try {
+42 −45
Original line number Original line Diff line number Diff line
@@ -15,13 +15,12 @@
 */
 */
package com.android.server.companion.datatransfer.continuity.tasks;
package com.android.server.companion.datatransfer.continuity.tasks;


import android.companion.AssociationInfo;
import android.annotation.NonNull;
import android.companion.datatransfer.continuity.IRemoteTaskListener;
import android.companion.datatransfer.continuity.IRemoteTaskListener;
import android.os.RemoteCallbackList;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Slog;
import android.util.Slog;


import com.android.server.companion.datatransfer.continuity.connectivity.ConnectedAssociationStore;
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskInfo;
import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskInfo;


import android.companion.datatransfer.continuity.RemoteTask;
import android.companion.datatransfer.continuity.RemoteTask;
@@ -30,21 +29,15 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;


public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
public class RemoteTaskStore {


    private static final String TAG = "RemoteTaskStore";
    private static final String TAG = "RemoteTaskStore";


    private final ConnectedAssociationStore mConnectedAssociationStore;
    private final Map<Integer, RemoteDeviceTaskList> mRemoteDeviceTaskLists = new HashMap<>();
    private final Map<Integer, RemoteDeviceTaskList> mRemoteDeviceTaskLists
    private final RemoteCallbackList<IRemoteTaskListener> mRemoteTaskListeners
        = new HashMap<>();
        = new RemoteCallbackList<>();
    private final RemoteCallbackList<IRemoteTaskListener>
        mRemoteTaskListeners = new RemoteCallbackList<>();

    public RemoteTaskStore(ConnectedAssociationStore connectedAssociationStore) {
        mConnectedAssociationStore = connectedAssociationStore;
        mConnectedAssociationStore.addObserver(this);
    }


    /**
    /**
     * Sets the task list of the given association id to the given tasks.
     * Sets the task list of the given association id to the given tasks.
@@ -53,9 +46,9 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
     * @param tasks The list of tasks currently available on the device on first
     * @param tasks The list of tasks currently available on the device on first
     * connection.
     * connection.
     */
     */
    public void setTasks(
    public void setTasks(int associationId, @NonNull List<RemoteTaskInfo> tasks) {
        int associationId,
        Objects.requireNonNull(tasks);
        List<RemoteTaskInfo> tasks) {

        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
                Slog.e(
                Slog.e(
@@ -70,7 +63,9 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
        }
        }
    }
    }


      public void addTask(int associationId, RemoteTaskInfo taskInfo) {
    public void addTask(int associationId, @NonNull RemoteTaskInfo taskInfo) {
        Objects.requireNonNull(taskInfo);

        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
                Slog.e(
                Slog.e(
@@ -95,7 +90,9 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
        }
        }
    }
    }


    public void updateTask(int associationId, RemoteTaskInfo taskInfo) {
    public void updateTask(int associationId, @NonNull RemoteTaskInfo taskInfo) {
        Objects.requireNonNull(taskInfo);

        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
            if (!mRemoteDeviceTaskLists.containsKey(associationId)) {
                return;
                return;
@@ -111,6 +108,7 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
     * @return A list of the most recent tasks from all devices in the task
     * @return A list of the most recent tasks from all devices in the task
     * store.
     * store.
     */
     */
    @NonNull
    public List<RemoteTask> getMostRecentTasks() {
    public List<RemoteTask> getMostRecentTasks() {
        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            List<RemoteTask> mostRecentTasks = new ArrayList<>();
            List<RemoteTask> mostRecentTasks = new ArrayList<>();
@@ -124,50 +122,53 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
        }
        }
    }
    }


    public void addListener(IRemoteTaskListener listener) {
    public void addListener(@NonNull IRemoteTaskListener listener) {
        Objects.requireNonNull(listener);

        synchronized (mRemoteTaskListeners) {
        synchronized (mRemoteTaskListeners) {
            mRemoteTaskListeners.register(listener);
            mRemoteTaskListeners.register(listener);
        }
        }
    }
    }


    public void removeListener(IRemoteTaskListener listener) {
    public void removeListener(@NonNull IRemoteTaskListener listener) {
        Objects.requireNonNull(listener);

        synchronized (mRemoteTaskListeners) {
        synchronized (mRemoteTaskListeners) {
            mRemoteTaskListeners.unregister(listener);
            mRemoteTaskListeners.unregister(listener);
        }
        }
    }
    }


    @Override
    public void addDevice(int id, @NonNull String name) {
    public void onTransportConnected(AssociationInfo associationInfo) {
        Objects.requireNonNull(name);

        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            if (!mRemoteDeviceTaskLists.containsKey(associationInfo.getId())) {
            if (!mRemoteDeviceTaskLists.containsKey(id)) {
                Slog.v(
                Slog.v(
                    TAG,
                    TAG,
                    "Creating new RemoteDeviceTaskList for association: "
                    "Creating new RemoteDeviceTaskList for association: " + id);
                        + associationInfo.getId());


                RemoteDeviceTaskList taskList
                RemoteDeviceTaskList taskList
                    = new RemoteDeviceTaskList(
                    = new RemoteDeviceTaskList(
                        associationInfo.getId(),
                        id,
                        associationInfo.getDisplayName().toString(),
                        name,
                        this::onMostRecentTaskChanged);
                        this::onMostRecentTaskChanged);


                mRemoteDeviceTaskLists.put(associationInfo.getId(), taskList);
                mRemoteDeviceTaskLists.put(id, taskList);
            } else {
            } else {
                Slog.v(
                Slog.v(
                    TAG,
                    TAG,
                    "Transport already connected for association: " + associationInfo.getId());
                    "Transport already connected for association: " + id);
            }
            }
        }
        }
    }
    }


    @Override
    public void removeDevice(int id) {
    public void onTransportDisconnected(int associationId) {
        synchronized (mRemoteDeviceTaskLists) {
        synchronized (mRemoteDeviceTaskLists) {
            Slog.v(
            Slog.v(
                TAG,
                TAG,
                "Deleting RemoteDeviceTaskList for association: " + associationId);
                "Deleting RemoteDeviceTaskList for association: " + id);


            mRemoteDeviceTaskLists.remove(associationId);
            mRemoteDeviceTaskLists.remove(id);
            notifyListeners();
            notifyListeners();
        }
        }
    }
    }
@@ -179,18 +180,14 @@ public class RemoteTaskStore implements ConnectedAssociationStore.Observer {
    private void notifyListeners() {
    private void notifyListeners() {
       synchronized (mRemoteTaskListeners) {
       synchronized (mRemoteTaskListeners) {
            List<RemoteTask> remoteTasks = getMostRecentTasks();
            List<RemoteTask> remoteTasks = getMostRecentTasks();
            int i = mRemoteTaskListeners.beginBroadcast();
            mRemoteTaskListeners.broadcast(
            while (i > 0) {
                (listener) -> {
                i--;
                    try {
                    try {
                    mRemoteTaskListeners
                        listener.onRemoteTasksChanged(remoteTasks);
                        .getBroadcastItem(i)
                        .onRemoteTasksChanged(remoteTasks);
                    } catch (RemoteException e) {
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Failed to notify listener: " + e.getMessage());
                        Slog.e(TAG, "Failed to notify listener: " + e.getMessage());
                    }
                    }
            }
            });
            mRemoteTaskListeners.finishBroadcast();
        }
        }
    }
    }
}
}
 No newline at end of file
Loading