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

Commit 799110db authored by Antony Sargent's avatar Antony Sargent
Browse files

Add variant of showSystemOutputSwitcher that takes sessionToken

Apps that want to launch the media routing system output switcher from
within their app's UI can call the existing showSystemOutputSwitcher()
method. However, apps with multiple MediaSession's had no way to
indicate which session the output switcher should use, and the session
the current code picks by default might not be the one the developer
wanted to present to the user. This CL fixes that by adding a variant
of showSystemOutputSwitcher() that takes a MediaSession.Token
argument.

Bug: 402802435
Bug: 367799834
Flag: com.android.media.flags.enable_route_visibility_control_api
Test: atest OutputSwitcherTest
Change-Id: I8b4f6ec2b803d9c687a57c73206731ed012080f1
parent 40d44785
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25347,6 +25347,7 @@ package android.media {
    method public void setRouteListingPreference(@Nullable android.media.RouteListingPreference);
    method @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control") @RequiresPermission(anyOf={android.Manifest.permission.MEDIA_CONTENT_CONTROL, android.Manifest.permission.MEDIA_ROUTING_CONTROL}) public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int);
    method public boolean showSystemOutputSwitcher();
    method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") public boolean showSystemOutputSwitcher(@NonNull android.media.session.MediaSession.Token);
    method public void stop();
    method public void transferTo(@NonNull android.media.MediaRoute2Info);
    method public void unregisterControllerCallback(@NonNull android.media.MediaRouter2.ControllerCallback);
+6 −3
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
import android.media.INearbyMediaDevicesProvider;
import android.media.MediaRoute2Info;
import android.media.session.MediaSession;

import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
@@ -400,10 +402,11 @@ oneway interface IStatusBar
     * Shows the media output switcher dialog.
     *
     * @param targetPackageName The package name for which to show the output switcher.
     * @param targetUserHandle The UserHandle on which the package for which to show the output
     *     switcher is running.
     * @param targetUserHandle The UserHandle on which the output switcher should run.
     * @param sessionToken An optional specific MediaSession to use instead of the default.
     */
    void showMediaOutputSwitcher(String targetPackageName, in UserHandle targetUserHandle);
    void showMediaOutputSwitcher(String targetPackageName, in UserHandle targetUserHandle,
        in @nullable MediaSession.Token sessionToken);

    /** Enters desktop mode from the current focused app.
    *
+5 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.media.RouteDiscoveryPreference;
import android.media.RouteListingPreference;
import android.media.RoutingSessionInfo;
import android.media.SuggestedDeviceInfo;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.os.UserHandle;
/**
@@ -53,7 +54,8 @@ interface IMediaRouterService {
    // Methods for MediaRouter2
    List<MediaRoute2Info> getSystemRoutes(String callerPackageName, boolean isProxyRouter);
    RoutingSessionInfo getSystemSessionInfo();
    boolean showMediaOutputSwitcherWithRouter2(String packageName);
    boolean showMediaOutputSwitcherWithRouter2(String packageName,
            in @nullable MediaSession.Token sessionToken);

    void registerRouter2(IMediaRouter2 router, String packageName);
    void unregisterRouter2(IMediaRouter2 router);
@@ -102,7 +104,8 @@ interface IMediaRouterService {
    void setSessionVolumeWithManager(IMediaRouter2Manager manager, int requestId,
            String sessionId, int volume);
    void releaseSessionWithManager(IMediaRouter2Manager manager, int requestId, String sessionId);
    boolean showMediaOutputSwitcherWithProxyRouter(IMediaRouter2Manager manager);
    boolean showMediaOutputSwitcherWithProxyRouter(IMediaRouter2Manager manager,
            in @nullable MediaSession.Token sessionToken);
    void setDeviceSuggestionsWithManager(IMediaRouter2Manager manager,
            in @nullable List<SuggestedDeviceInfo> suggestedDeviceInfo);
Map<String, List<SuggestedDeviceInfo>> getDeviceSuggestionsWithManager(
+30 −6
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import static com.android.media.flags.Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES;
import static com.android.media.flags.Flags.FLAG_ENABLE_GET_TRANSFERABLE_ROUTES;
import static com.android.media.flags.Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL;
import static com.android.media.flags.Flags.FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API;
import static com.android.media.flags.Flags.FLAG_ENABLE_SCREEN_OFF_SCANNING;
import static com.android.media.flags.Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API;

@@ -35,6 +36,7 @@ import android.annotation.TestApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -839,7 +841,27 @@ public final class MediaRouter2 {
     * call is ignored because the app is in the background.
     */
    public boolean showSystemOutputSwitcher() {
        return mImpl.showSystemOutputSwitcher();
        return mImpl.showSystemOutputSwitcher(null);
    }

    /**
     * Shows the system output switcher dialog for a specific {@link MediaSession}.
     *
     * <p>The {@link MediaSession.Token} argument allows the system to identify which
     * {@link RoutingSessionInfo routing session} to display as active. This is done via
     * {@link MediaSession#setPlaybackToRemote} and {@link VolumeProvider#getVolumeControlId} when
     * playing remotely, and {@link MediaSession#setPlaybackToLocal} when playing on this device.
     *
     * <p>This method is preferred over {@link #showSystemOutputSwitcher()} to prevent the system
     * from making wrong inferences about where playback is happening.
     *
     * @return {@code true} if the output switcher dialog is being shown, or {@code false} if the
     * call is ignored because the app is in the background.
     */
    @FlaggedApi(FLAG_ENABLE_ROUTE_VISIBILITY_CONTROL_API)
    public boolean showSystemOutputSwitcher(@NonNull MediaSession.Token sessionToken) {
        Objects.requireNonNull(sessionToken, "sessionToken must not be null");
        return mImpl.showSystemOutputSwitcher(sessionToken);
    }

    /**
@@ -2709,7 +2731,7 @@ public final class MediaRouter2 {

        void notifyDeviceSuggestionRequested();

        boolean showSystemOutputSwitcher();
        boolean showSystemOutputSwitcher(@Nullable MediaSession.Token token);

        List<MediaRoute2Info> getAllRoutes();

@@ -2941,9 +2963,10 @@ public final class MediaRouter2 {
        }

        @Override
        public boolean showSystemOutputSwitcher() {
        public boolean showSystemOutputSwitcher(MediaSession.Token sessionToken) {
            try {
                return mMediaRouterService.showMediaOutputSwitcherWithProxyRouter(mClient);
                return mMediaRouterService.showMediaOutputSwitcherWithProxyRouter(mClient,
                        sessionToken);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
@@ -3891,10 +3914,11 @@ public final class MediaRouter2 {
        }

        @Override
        public boolean showSystemOutputSwitcher() {
        public boolean showSystemOutputSwitcher(@Nullable MediaSession.Token sessionToken) {
            synchronized (mLock) {
                try {
                    return mMediaRouterService.showMediaOutputSwitcherWithRouter2(mPackageName);
                    return mMediaRouterService.showMediaOutputSwitcherWithRouter2(mPackageName,
                            sessionToken);
                } catch (RemoteException ex) {
                    ex.rethrowFromSystemServer();
                }
+5 −2
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.systemui.media.dialog;

import android.annotation.MainThread;
import android.annotation.Nullable;
import android.content.Context;
import android.media.session.MediaSession;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -53,14 +55,15 @@ public class MediaOutputSwitcherDialogUI implements CoreStartable, CommandQueue.

    @Override
    @MainThread
    public void showMediaOutputSwitcher(String packageName, UserHandle userHandle) {
    public void showMediaOutputSwitcher(String packageName, UserHandle userHandle,
            @Nullable MediaSession.Token sessionToken) {
        if (!TextUtils.isEmpty(packageName)) {
            mMediaOutputDialogManager.createAndShow(
                    packageName,
                    /* aboveStatusBar= */ false,
                    /* view= */ null,
                    userHandle,
                    /* token */ null);
                    sessionToken);
        } else {
            Log.e(TAG, "Unable to launch media output dialog. Package name is empty.");
        }
Loading