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

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

Merge "Add API Stubs for RequestHandoff method" into main

parents d0c0c0d4 5a367457
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -3478,7 +3478,18 @@ package android.companion.datatransfer.continuity {
  @FlaggedApi("android.companion.enable_task_continuity") public class TaskContinuityManager {
    method @NonNull public java.util.List<android.companion.datatransfer.continuity.RemoteTask> getRemoteTasks();
    method public void registerRemoteTaskListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.datatransfer.continuity.TaskContinuityManager.RemoteTaskListener);
    method public void requestHandoff(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.companion.datatransfer.continuity.TaskContinuityManager.HandoffRequestCallback);
    method public void unregisterRemoteTaskListener(@NonNull android.companion.datatransfer.continuity.TaskContinuityManager.RemoteTaskListener);
    field public static final int HANDOFF_REQUEST_RESULT_FAILURE_DEVICE_NOT_FOUND = 5; // 0x5
    field public static final int HANDOFF_REQUEST_RESULT_FAILURE_NO_DATA_PROVIDED_BY_TASK = 2; // 0x2
    field public static final int HANDOFF_REQUEST_RESULT_FAILURE_SENDER_LOST_CONNECTION = 3; // 0x3
    field public static final int HANDOFF_REQUEST_RESULT_FAILURE_TASK_NOT_FOUND = 1; // 0x1
    field public static final int HANDOFF_REQUEST_RESULT_FAILURE_TIMEOUT = 4; // 0x4
    field public static final int HANDOFF_REQUEST_RESULT_SUCCESS = 0; // 0x0
  }
  public static interface TaskContinuityManager.HandoffRequestCallback {
    method public void onHandoffRequestFinished(int, int, int);
  }
  public static interface TaskContinuityManager.RemoteTaskListener {
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.companion.datatransfer.continuity;

import android.companion.datatransfer.continuity.RemoteTask;

/**
 * {@hide}
 */
oneway interface IHandoffRequestCallback {
    void onHandoffRequestFinished(in int associationId, in int remoteTaskId, in int resultCode);
}
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.companion.datatransfer.continuity;

import android.companion.datatransfer.continuity.IHandoffRequestCallback;
import android.companion.datatransfer.continuity.IRemoteTaskListener;
import android.companion.datatransfer.continuity.RemoteTask;

@@ -28,5 +29,9 @@ interface ITaskContinuityManager {
    List<RemoteTask> getRemoteTasks();
    void registerRemoteTaskListener(IRemoteTaskListener listener);
    void unregisterRemoteTaskListener(IRemoteTaskListener listener);
    void requestHandoff(
        in int associationId,
        in int remoteTaskId,
        in IHandoffRequestCallback callback);

}
+130 −0
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package android.companion.datatransfer.continuity;

import android.companion.datatransfer.continuity.IHandoffRequestCallback;
import android.companion.datatransfer.continuity.IRemoteTaskListener;
import android.companion.datatransfer.continuity.RemoteTask;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.NonNull;
@@ -29,10 +31,13 @@ import android.util.ArrayMap;

import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * This class facilitates task continuity between devices owned by the same user.
@@ -51,6 +56,53 @@ public class TaskContinuityManager {

    private final RemoteTaskListenerHolder mListenerHolder;

    /** @hide */
    @IntDef(prefix = {"HANDOFF_REQUEST_RESULT"}, value = {
        HANDOFF_REQUEST_RESULT_SUCCESS,
        HANDOFF_REQUEST_RESULT_FAILURE_TASK_NOT_FOUND,
        HANDOFF_REQUEST_RESULT_FAILURE_NO_DATA_PROVIDED_BY_TASK,
        HANDOFF_REQUEST_RESULT_FAILURE_SENDER_LOST_CONNECTION,
        HANDOFF_REQUEST_RESULT_FAILURE_TIMEOUT,
        HANDOFF_REQUEST_RESULT_FAILURE_DEVICE_NOT_FOUND,
    })

    @Retention(RetentionPolicy.SOURCE)
    public @interface HandoffRequestResultCode {}

    /**
     * Indicate a request for handoff completed successfully.
     */
    public static final int HANDOFF_REQUEST_RESULT_SUCCESS = 0;

    /**
     * Indicates a request for handoff failed because a remote task with the specified ID was not
     * found on the remote device.
     */
    public static final int HANDOFF_REQUEST_RESULT_FAILURE_TASK_NOT_FOUND = 1;

    /**
     * Indicates a request for handoff failed because the remote task did not provide any data to
     * hand itself off to the current device.
     */
    public static final int HANDOFF_REQUEST_RESULT_FAILURE_NO_DATA_PROVIDED_BY_TASK = 2;

    /**
     * Indicates a request for handoff failed because the connection to the remote device was lost
     * before the request could be completed.
     */
    public static final int HANDOFF_REQUEST_RESULT_FAILURE_SENDER_LOST_CONNECTION = 3;

    /**
     * Indicates a request for handoff failed because the request timed out before it could be
     * completed.
     */
    public static final int HANDOFF_REQUEST_RESULT_FAILURE_TIMEOUT = 4;

    /**
     * Indicates a request for handoff failed because the remote device was not found.
     */
    public static final int HANDOFF_REQUEST_RESULT_FAILURE_DEVICE_NOT_FOUND = 5;

    /** @hide */
    public TaskContinuityManager(
        @NonNull Context context,
@@ -73,6 +125,24 @@ public class TaskContinuityManager {
        void onRemoteTasksChanged(@NonNull List<RemoteTask> remoteTasks);
    }

    /**
     * Callback to be invoked when a handoff request is completed.
     */
    public interface HandoffRequestCallback {

        /**
         * Invoked when a request to hand off a remote task has finished.
         *
         * @param associationId The ID of the association to which the remote device is connected.
         * @param remoteTaskId The ID of the task that was requested to be handed off.
         * @param resultCode The result code of the handoff request.
         */
        void onHandoffRequestFinished(
            int associationId,
            int remoteTaskId,
            @HandoffRequestResultCode int resultCode);
    }

    /**
     * Returns a list of tasks currently running on the remote devices owned by the user.
     */
@@ -97,6 +167,9 @@ public class TaskContinuityManager {
        @NonNull Executor executor,
        @NonNull RemoteTaskListener listener) {

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

        try {
            mListenerHolder.registerListener(executor, listener);
            // TODO: joeantonetti - Send an initial notification to the listener after it's
@@ -113,6 +186,8 @@ public class TaskContinuityManager {
     * @param listener The listener to be unregistered.
     */
    public void unregisterRemoteTaskListener(@NonNull RemoteTaskListener listener) {
        Objects.requireNonNull(listener);

        try {
            mListenerHolder.unregisterListener(listener);
        } catch (RemoteException e) {
@@ -120,6 +195,56 @@ public class TaskContinuityManager {
        }
    }

    /**
     * Requests a handoff of the specified remote task to the current device.
     *
     * @param associationId The ID of the association to which the remote device is connected. This
     *                      is the same ID returned by {@link RemoteTask#getDeviceId()}.
     * @param remoteTaskId The remote task to hand off.
     * @param executor The executor to be used to invoke the callback.
     * @param callback The callback to be invoked when the handoff request is finished.
     */
    public void requestHandoff(
        int associationId,
        int remoteTaskId,
        @NonNull Executor executor,
        @NonNull HandoffRequestCallback callback) {

        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);

        try {
            HandoffRequestCallbackHolder callbackHolder
                = new HandoffRequestCallbackHolder(executor, callback);

            mService.requestHandoff(associationId, remoteTaskId, callbackHolder);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private final class HandoffRequestCallbackHolder extends IHandoffRequestCallback.Stub {
        private final Executor mExecutor;
        private final HandoffRequestCallback mCallback;

        HandoffRequestCallbackHolder(
            @NonNull Executor executor,
            @NonNull HandoffRequestCallback callback) {

            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onHandoffRequestFinished(
            int associationId,
            int remoteTaskId,
            @HandoffRequestResultCode int resultCode) throws RemoteException {
            mExecutor.execute(
                () -> mCallback.onHandoffRequestFinished(associationId, remoteTaskId, resultCode));
        }
    }

    /**
     * Helper class which manages registered listeners and proxies them behind a single
     * IRemoteTaskListener, which is lazily registered with ITaskContinuityManager if there is
@@ -145,6 +270,9 @@ public class TaskContinuityManager {
            @NonNull Executor executor,
            @NonNull RemoteTaskListener listener) throws RemoteException {

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

            synchronized(mListeners) {
                if (!mRegistered) {
                    mService.registerRemoteTaskListener(this);
@@ -163,6 +291,8 @@ public class TaskContinuityManager {
        public void unregisterListener(
            @NonNull RemoteTaskListener listener) throws RemoteException {

            Objects.requireNonNull(listener);

            synchronized(mListeners) {
                mListeners.remove(listener);
                if (mListeners.isEmpty() && mRegistered) {
+10 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.companion.datatransfer.continuity;

import android.annotation.NonNull;
import android.companion.CompanionDeviceManager;
import android.companion.datatransfer.continuity.IHandoffRequestCallback;
import android.companion.datatransfer.continuity.ITaskContinuityManager;
import android.companion.datatransfer.continuity.IRemoteTaskListener;
import android.companion.datatransfer.continuity.RemoteTask;
@@ -83,6 +84,15 @@ public final class TaskContinuityManagerService extends SystemService {
        @Override
        public void unregisterRemoteTaskListener(@NonNull IRemoteTaskListener listener) {
        }

        @Override
        public void requestHandoff(
            int associationId,
            int remoteTaskId,
            @NonNull IHandoffRequestCallback callback) {

            // TODO: joeantonetti - Implement this method.
        }
    }

    private void onTaskContinuityMessageReceived(