Rename TaskReceiver to TaskContinuityMessageReceiver

Rename TaskReceiver to a more generic TaskContinuityMessageReceiver, and update it to flow received messages out to TaskContinuityManagerService.


Flag: android.companion.enable_task_continuity
Test: Added unit tests
Bug: 400970610
Change-Id: I477b37939c0e5d3357ccd135258014761ce12c8e
diff --git a/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityManagerService.java b/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityManagerService.java
index c682305..e203d33 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityManagerService.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityManagerService.java
@@ -18,10 +18,12 @@
 
 import android.companion.datatransfer.continuity.ITaskContinuityManager;
 import android.content.Context;
+import android.util.Slog;
+
+import com.android.server.companion.datatransfer.continuity.messages.TaskContinuityMessage;
 
 import com.android.server.SystemService;
 
-
 /**
  * Service to handle task continuity features
  *
@@ -30,25 +32,34 @@
  */
 public final class TaskContinuityManagerService extends SystemService {
 
+    private static final String TAG = "TaskContinuityManagerService";
+
     private TaskContinuityManagerServiceImpl mTaskContinuityManagerService;
     private TaskBroadcaster mTaskBroadcaster;
-    private TaskReceiver mTaskReceiver;
+    private TaskContinuityMessageReceiver mTaskContinuityMessageReceiver;
 
     public TaskContinuityManagerService(Context context) {
         super(context);
         mTaskBroadcaster = new TaskBroadcaster(context);
-        mTaskReceiver = new TaskReceiver(context);
+        mTaskContinuityMessageReceiver = new TaskContinuityMessageReceiver(context);
     }
 
     @Override
     public void onStart() {
         mTaskContinuityManagerService = new TaskContinuityManagerServiceImpl();
         mTaskBroadcaster.startBroadcasting();
-        mTaskReceiver.startListening();
+        mTaskContinuityMessageReceiver.startListening(this::onTaskContinuityMessageReceived);
         publishBinderService(Context.TASK_CONTINUITY_SERVICE, mTaskContinuityManagerService);
     }
 
     private final class TaskContinuityManagerServiceImpl extends ITaskContinuityManager.Stub {
 
     }
+
+    private void onTaskContinuityMessageReceived(
+        int associationId,
+        TaskContinuityMessage taskContinuityMessage) {
+
+        Slog.v(TAG, "Received message from association id: " + associationId);
+    }
 }
diff --git a/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskReceiver.java b/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiver.java
similarity index 62%
rename from services/companion/java/com/android/server/companion/datatransfer/continuity/TaskReceiver.java
rename to services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiver.java
index 383ad15..f2a71aa 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskReceiver.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiver.java
@@ -22,15 +22,17 @@
 import android.companion.CompanionDeviceManager;
 import android.util.Slog;
 
+import com.android.server.companion.datatransfer.continuity.messages.TaskContinuityMessage;
+
 import java.util.function.BiConsumer;
 
 /**
  * Responsible for receiving task continuity messages from the user's other
  * devices.
  */
-class TaskReceiver {
+class TaskContinuityMessageReceiver {
 
-    private static final String TAG = "TaskReceiver";
+    private static final String TAG = "TaskContinuityMessageReceiver";
 
     private final Context mContext;
     private final CompanionDeviceManager mCompanionDeviceManager;
@@ -38,9 +40,11 @@
     private final BiConsumer<Integer, byte[]> mOnMessageReceivedListener
         = this::onMessageReceived;
 
+    private BiConsumer<Integer, TaskContinuityMessage> mOnTaskContinuityMessageReceivedListener;
+
     private boolean mIsListening = false;
 
-    TaskReceiver(Context context) {
+    TaskContinuityMessageReceiver(Context context) {
         mContext = context;
         mCompanionDeviceManager = context
             .getSystemService(CompanionDeviceManager.class);
@@ -48,13 +52,17 @@
 
     /**
      * Starts listening for task continuity messages.
+     *
+     * @return true if listening was started successfully, false otherwise.
      */
-    void startListening() {
+    boolean startListening(
+        BiConsumer<Integer, TaskContinuityMessage> onTaskContinuityMessageReceivedListener) {
         if (mIsListening) {
-            Slog.v(TAG, "TaskReceiver is already listening");
-            return;
+            Slog.v(TAG, "TaskContinuityMessageReceiver is already listening");
+            return false;
         }
 
+        mOnTaskContinuityMessageReceivedListener = onTaskContinuityMessageReceivedListener;
         mCompanionDeviceManager.addOnMessageReceivedListener(
             mContext.getMainExecutor(),
             MESSAGE_TASK_CONTINUITY,
@@ -62,6 +70,7 @@
         );
 
         mIsListening = true;
+        return true;
     }
 
     /**
@@ -69,10 +78,12 @@
      */
     void stopListening() {
         if (!mIsListening) {
-            Slog.v(TAG, "TaskReceiver is not listening");
+            Slog.v(TAG, "TaskContinuityMessageReceiver is not listening");
             return;
         }
 
+        mOnTaskContinuityMessageReceivedListener = null;
+
         mCompanionDeviceManager.removeOnMessageReceivedListener(
             MESSAGE_TASK_CONTINUITY,
             mOnMessageReceivedListener);
@@ -82,5 +93,15 @@
 
     private void onMessageReceived(int associationId, byte[] data) {
         Slog.v(TAG, "Received message from association id: " + associationId);
+      try {
+            TaskContinuityMessage taskContinuityMessage = new TaskContinuityMessage(data);
+            if (mOnTaskContinuityMessageReceivedListener != null) {
+                mOnTaskContinuityMessageReceivedListener.accept(
+                    associationId,
+                    taskContinuityMessage);
+            }
+      } catch (Exception e) {
+        Slog.e(TAG, "Failed to parse task continuity message", e);
+      }
     }
 }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskReceiverTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiverTest.java
similarity index 60%
rename from services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskReceiverTest.java
rename to services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiverTest.java
index 40cea24..00c0161 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskReceiverTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/continuity/TaskContinuityMessageReceiverTest.java
@@ -38,6 +38,10 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.server.companion.datatransfer.continuity.messages.ContinuityDeviceConnected;
+import com.android.server.companion.datatransfer.continuity.messages.RemoteTaskInfo;
+import com.android.server.companion.datatransfer.continuity.messages.TaskContinuityMessage;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,11 +50,13 @@
 import java.util.Arrays;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
+import java.util.ArrayList;
+import java.util.List;
 
 @Presubmit
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class TaskReceiverTest {
+public class TaskContinuityMessageReceiverTest {
 
     private Context mMockContext;
 
@@ -59,7 +65,9 @@
 
     private CompanionDeviceManager mCompanionDeviceManager;
 
-    private TaskReceiver mTaskReceiver;
+    private TaskContinuityMessageReceiver mTaskContinuityMessageReceiver;
+
+    private List<TaskContinuityMessage> receivedMessages;
 
     @Before
     public void setUp() {
@@ -79,26 +87,28 @@
         when(mMockContext.getSystemService(Context.COMPANION_DEVICE_SERVICE))
             .thenReturn(mCompanionDeviceManager);
 
-        // Create TaskReceiver.
-        mTaskReceiver = new TaskReceiver(mMockContext);
+        receivedMessages = new ArrayList<>();
+
+        // Create TaskContinuityMessageReceiver.
+        mTaskContinuityMessageReceiver = new TaskContinuityMessageReceiver(mMockContext);
     }
 
     @Test
     public void testStopListening_doesNothingIfNotListening()
         throws Exception {
 
-        mTaskReceiver.stopListening();
+        mTaskContinuityMessageReceiver.stopListening();
         Mockito.verifyNoInteractions(mMockCompanionDeviceManagerService);
     }
 
     @Test
-    public void testStartAndStopListening_registersMessageListener()
+    public void testStartAndStopListening_registersListenersAndFlowsMessages()
         throws Exception {
 
         // Start listening, verifying a message listener is added.
         ArgumentCaptor<IOnMessageReceivedListener> listenerCaptor
             = ArgumentCaptor.forClass(IOnMessageReceivedListener.class);
-        mTaskReceiver.startListening();
+        assertThat(mTaskContinuityMessageReceiver.startListening(this::onMessageReceived)).isTrue();
         verify(mMockCompanionDeviceManagerService, times(1))
             .addOnMessageReceivedListener(
                 eq(MESSAGE_TASK_CONTINUITY),
@@ -106,11 +116,47 @@
         IOnMessageReceivedListener listener = listenerCaptor.getValue();
         assertThat(listener).isNotNull();
 
+        // Send a message to the listener.
+        int expectedAssociationId = 1;
+        int expectedForegroundTaskId = 1;
+        TaskContinuityMessage expectedMessage = new TaskContinuityMessage.Builder()
+            .setData(
+                new ContinuityDeviceConnected(
+                    expectedForegroundTaskId,
+                    new ArrayList<RemoteTaskInfo>()))
+            .build();
+
+        listener.onMessageReceived(expectedAssociationId, expectedMessage.toBytes());
+        TestableLooper.get(this).processAllMessages();
+        assertThat(receivedMessages).hasSize(1);
+        TaskContinuityMessage receivedMessage = receivedMessages.get(0);
+        assertThat(receivedMessage.getData()).isInstanceOf(ContinuityDeviceConnected.class);
+        ContinuityDeviceConnected actualData
+            = (ContinuityDeviceConnected) receivedMessage.getData();
+
+        assertThat(actualData.getCurrentForegroundTaskId())
+            .isEqualTo(expectedForegroundTaskId);
+
         // Stop listening, verifying the message listener is removed.
-        mTaskReceiver.stopListening();
+        mTaskContinuityMessageReceiver.stopListening();
         verify(mMockCompanionDeviceManagerService, times(1))
             .removeOnMessageReceivedListener(
                 eq(MESSAGE_TASK_CONTINUITY),
                 eq(listener));
     }
+
+    @Test
+    public void testStartListening_returnsFalseIfAlreadyListening()
+        throws Exception {
+
+        assertThat(mTaskContinuityMessageReceiver.startListening(this::onMessageReceived))
+            .isTrue();
+
+        assertThat(mTaskContinuityMessageReceiver.startListening(this::onMessageReceived))
+            .isFalse();
+    }
+
+    private void onMessageReceived(int associationId, TaskContinuityMessage message) {
+        receivedMessages.add(message);
+    }
 }
\ No newline at end of file