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

Commit 44386a5a authored by Caitlin Cassidy's avatar Caitlin Cassidy
Browse files

[Media TTT] Add @SystemApis for all the media transfer callbacks.

This migrates the media transfer from just a service to a full-fledged
@SystemApi. Some of the testing infrastructure has not yet been migrated
to keep this CL slightly smaller.

Bug: 216318437
Test: systemui media.taptotransfer tests *still need to be updated*
Change-Id: Idf1f72de1343020668e158d74051c1dfb970cfcd
parent be251830
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -910,6 +910,19 @@ package android.app {
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarModeOverride();
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
    method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setNavBarModeOverride(int);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void updateMediaTapToTransferReceiverDisplay(int, @NonNull android.media.MediaRoute2Info);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void updateMediaTapToTransferSenderDisplay(int, @NonNull android.media.MediaRoute2Info, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
    field public static final int MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER = 0; // 0x0
    field public static final int MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER = 1; // 0x1
    field public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST = 1; // 0x1
    field public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST = 0; // 0x0
    field public static final int MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER = 8; // 0x8
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED = 6; // 0x6
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED = 4; // 0x4
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED = 2; // 0x2
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED = 7; // 0x7
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED = 5; // 0x5
    field public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED = 3; // 0x3
    field public static final int NAV_BAR_MODE_OVERRIDE_KIDS = 1; // 0x1
    field public static final int NAV_BAR_MODE_OVERRIDE_NONE = 0; // 0x0
  }
+263 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -27,6 +28,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.media.MediaRoute2Info;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -39,6 +41,7 @@ import android.view.View;

import com.android.internal.statusbar.IAddTileResultCallback;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.IUndoMediaTransferCallback;
import com.android.internal.statusbar.NotificationVisibility;

import java.lang.annotation.Retention;
@@ -338,6 +341,166 @@ public class StatusBarManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface NavBarModeOverride {}

    /**
     * State indicating that this sender device is close to a receiver device, so the user can
     * potentially *start* a cast to the receiver device if the user moves their device a bit
     * closer.
     * <p>
     * Important notes:
     * <ul>
     *     <li>This state represents that the device is close enough to inform the user that
     *     transferring is an option, but the device is *not* close enough to actually initiate a
     *     transfer yet.</li>
     *     <li>This state is for *starting* a cast. It should be used when this device is currently
     *     playing media locally and the media should be transferred to be played on the receiver
     *     device instead.</li>
     * </ul>
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST = 0;

    /**
     * State indicating that this sender device is close to a receiver device, so the user can
     * potentially *end* a cast on the receiver device if the user moves this device a bit closer.
     * <p>
     * Important notes:
     * <ul>
     *     <li>This state represents that the device is close enough to inform the user that
     *     transferring is an option, but the device is *not* close enough to actually initiate a
     *     transfer yet.</li>
     *     <li>This state is for *ending* a cast. It should be used when media is currently being
     *     played on the receiver device and the media should be transferred to play locally
     *     instead.</li>
     * </ul>
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST = 1;

    /**
     * State indicating that a media transfer from this sender device to a receiver device has been
     * started.
     * <p>
     * Important note: This state is for *starting* a cast. It should be used when this device is
     * currently playing media locally and the media has started being transferred to the receiver
     * device instead.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED = 2;

    /**
     * State indicating that a media transfer from the receiver and back to this sender device
     * has been started.
     * <p>
     * Important note: This state is for *ending* a cast. It should be used when media is currently
     * being played on the receiver device and the media has started being transferred to play
     * locally instead.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED = 3;

    /**
     * State indicating that a media transfer from this sender device to a receiver device has
     * finished successfully.
     * <p>
     * Important note: This state is for *starting* a cast. It should be used when this device had
     * previously been playing media locally and the media has successfully been transferred to the
     * receiver device instead.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED = 4;

    /**
     * State indicating that a media transfer from the receiver and back to this sender device has
     * finished successfully.
     * <p>
     * Important note: This state is for *ending* a cast. It should be used when media was
     * previously being played on the receiver device and has been successfully transferred to play
     * locally on this device instead.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED = 5;

    /**
     * State indicating that the attempted transfer to the receiver device has failed.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED = 6;

    /**
     * State indicating that the attempted transfer back to this device has failed.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED = 7;

    /**
     * State indicating that this sender device is no longer close to the receiver device.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER = 8;

    /** @hide */
    @IntDef(prefix = {"MEDIA_TRANSFER_SENDER_STATE_"}, value = {
            MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
            MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
            MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
            MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaTransferSenderState {}

    /**
     * State indicating that this receiver device is close to a sender device, so the user can
     * potentially start or end a cast to the receiver device if the user moves the sender device a
     * bit closer.
     * <p>
     * Important note: This state represents that the device is close enough to inform the user that
     * transferring is an option, but the device is *not* close enough to actually initiate a
     * transfer yet.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER = 0;

    /**
     * State indicating that this receiver device is no longer close to the sender device.
     *
     * @hide
     */
    @SystemApi
    public static final int MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER = 1;

    /** @hide */
    @IntDef(prefix = {"MEDIA_TRANSFER_RECEIVER_STATE_"}, value = {
            MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
            MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaTransferReceiverState {}

    @UnsupportedAppUsage
    private Context mContext;
    private IStatusBarService mService;
@@ -789,6 +952,81 @@ public class StatusBarManager {
        return navBarModeOverride;
    }

    /**
     * Notifies the system of a new media tap-to-transfer state for the <b>sender</b> device.
     *
     * <p>The callback should only be provided for the {@link
     * MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED} or {@link
     * MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED} states, since those are the
     * only states where an action can be un-done.
     *
     * @param displayState the new state for media tap-to-transfer.
     * @param routeInfo the media route information for the media being transferred.
     * @param undoExecutor an executor to run the callback on and must be provided if the
     *                     callback is non-null.
     * @param undoCallback a callback that will be triggered if the user elects to undo a media
     *                     transfer.
     *
     * @throws IllegalArgumentException if an undo callback is provided for states that are not a
     *   succeeded state.
     * @throws IllegalArgumentException if an executor is not provided when a callback is.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void updateMediaTapToTransferSenderDisplay(
            @MediaTransferSenderState int displayState,
            @NonNull MediaRoute2Info routeInfo,
            @Nullable Executor undoExecutor,
            @Nullable Runnable undoCallback
    ) {
        Objects.requireNonNull(routeInfo);
        if (displayState != MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED
                && displayState != MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED
                && undoCallback != null) {
            throw new IllegalArgumentException(
                    "The undoCallback should only be provided when the state is a "
                            + "transfer succeeded state");
        }
        if (undoCallback != null && undoExecutor == null) {
            throw new IllegalArgumentException(
                    "You must pass an executor when you pass an undo callback");
        }
        IStatusBarService svc = getService();
        try {
            UndoCallback callbackProxy = null;
            if (undoExecutor != null) {
                callbackProxy = new UndoCallback(undoExecutor, undoCallback);
            }
            svc.updateMediaTapToTransferSenderDisplay(displayState, routeInfo, callbackProxy);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Notifies the system of a new media tap-to-transfer state for the <b>receiver</b> device.
     *
     * @param displayState the new state for media tap-to-transfer.
     * @param routeInfo the media route information for the media being transferred.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void updateMediaTapToTransferReceiverDisplay(
            @MediaTransferReceiverState int displayState,
            @NonNull MediaRoute2Info routeInfo) {
        Objects.requireNonNull(routeInfo);
        IStatusBarService svc = getService();
        try {
            svc.updateMediaTapToTransferReceiverDisplay(displayState, routeInfo);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    public static String windowStateToString(int state) {
        if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
@@ -1071,4 +1309,29 @@ public class StatusBarManager {
            mExecutor.execute(() -> mCallback.accept(userResponse));
        }
    }

    /**
     * @hide
     */
    static final class UndoCallback extends IUndoMediaTransferCallback.Stub {
        @NonNull
        private final Executor mExecutor;
        @NonNull
        private final Runnable mCallback;

        UndoCallback(@NonNull Executor executor, @NonNull Runnable callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onUndoTriggered() {
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(mCallback);
            } finally {
                restoreCallingIdentity(callingIdentity);
            }
        }
    }
}
+13 −0
Original line number Diff line number Diff line
@@ -24,12 +24,14 @@ import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.media.MediaRoute2Info;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.service.notification.StatusBarNotification;
import android.view.InsetsVisibilities;

import com.android.internal.statusbar.IAddTileResultCallback;
import com.android.internal.statusbar.IUndoMediaTransferCallback;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.view.AppearanceRegion;

@@ -296,4 +298,15 @@ oneway interface IStatusBar

    void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback);
    void cancelRequestAddTile(in String packageName);

    /** Notifies System UI about an update to the media tap-to-transfer sender state. */
    void updateMediaTapToTransferSenderDisplay(
        int displayState,
        in MediaRoute2Info routeInfo,
        in IUndoMediaTransferCallback undoCallback);

    /** Notifies System UI about an update to the media tap-to-transfer receiver state. */
    void updateMediaTapToTransferReceiverDisplay(
        int displayState,
        in MediaRoute2Info routeInfo);
}
+13 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.media.MediaRoute2Info;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
@@ -33,6 +34,7 @@ import com.android.internal.logging.InstanceId;
import com.android.internal.statusbar.IAddTileResultCallback;
import com.android.internal.statusbar.ISessionListener;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IUndoMediaTransferCallback;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
@@ -196,4 +198,15 @@ interface IStatusBarService
    */
    void onSessionStarted(int sessionType, in InstanceId instanceId);
    void onSessionEnded(int sessionType, in InstanceId instanceId);

    /** Notifies System UI about an update to the media tap-to-transfer sender state. */
    void updateMediaTapToTransferSenderDisplay(
        int displayState,
        in MediaRoute2Info routeInfo,
        in IUndoMediaTransferCallback undoCallback);

    /** Notifies System UI about an update to the media tap-to-transfer receiver state. */
    void updateMediaTapToTransferReceiverDisplay(
        int displayState,
        in MediaRoute2Info routeInfo);
}
+5 −6
Original line number Diff line number Diff line
@@ -14,17 +14,16 @@
 * limitations under the License.
 */

package com.android.systemui.shared.mediattt;
package com.android.internal.statusbar;

/**
 * An interface that will be invoked by System UI if the user choose to undo a transfer.
 *
 * Other services will implement this interface and System UI will invoke it.
 * An interface that will be invoked if the user chooses to undo a transfer.
 */
interface IUndoTransferCallback {
interface IUndoMediaTransferCallback {

    /**
     * Invoked by SystemUI when the user requests to undo the media transfer that just occurred.
     * Invoked to notify callers that the user has chosen to undo the media transfer that just
     * occurred.
     *
     * Implementors of this method are repsonsible for actually undoing the transfer.
     */
Loading