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

Commit 67c41fdd authored by Hyundo Moon's avatar Hyundo Moon
Browse files

MediaRouter2: Add getDefaultController()

The controller which can control the system routes (phone speaker,
bluetooth, etc) is returned by this new method.

This CL makes the default controller can know the current system route,
and make SessionCallback#onSessionInfoChanged() be called when
the current system route is changed.

Note that selecting route (BT / speaker) via this controller is not
yet supported by this CL.

Bug: 147937954
Test: atest mediaroutertest
      Also, manually checked logs by connecting bluetooth device.
Change-Id: I8c6254855f8121d1d2331959224fe7237affa1e2
parent 4b083362
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ interface IMediaRouterService {

    // Methods for media router 2
    List<MediaRoute2Info> getSystemRoutes();
    RoutingSessionInfo getSystemSessionInfo();
    void registerClient2(IMediaRouter2Client client, String packageName);
    void unregisterClient2(IMediaRouter2Client client);
    void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route,
+53 −3
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ public class MediaRouter2 {
    @GuardedBy("sRouterLock")
    final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();

    final RoutingController mDefaultController;

    @GuardedBy("sRouterLock")
    private RouteDiscoveryPreference mDiscoveryPreference = RouteDiscoveryPreference.EMPTY;

@@ -116,19 +118,26 @@ public class MediaRouter2 {
        mHandler = new Handler(Looper.getMainLooper());

        List<MediaRoute2Info> currentSystemRoutes = null;
        RoutingSessionInfo currentSystemSessionInfo = null;
        try {
            currentSystemRoutes = mMediaRouterService.getSystemRoutes();
            currentSystemSessionInfo = mMediaRouterService.getSystemSessionInfo();
        } catch (RemoteException ex) {
            Log.e(TAG, "Unable to get current currentSystemRoutes", ex);
            Log.e(TAG, "Unable to get current system's routes / session info", ex);
        }

        if (currentSystemRoutes == null || currentSystemRoutes.isEmpty()) {
            throw new RuntimeException("Null or empty currentSystemRoutes. Something is wrong.");
        }

        if (currentSystemSessionInfo == null) {
            throw new RuntimeException("Null currentSystemSessionInfo. Something is wrong.");
        }

        for (MediaRoute2Info route : currentSystemRoutes) {
            mRoutes.put(route.getId(), route);
        }
        mDefaultController = new DefaultRoutingController(currentSystemSessionInfo);
    }

    /**
@@ -340,6 +349,22 @@ public class MediaRouter2 {
        }
    }

    /**
     * Gets a {@link RoutingController} which can control the routes provided by system.
     * e.g. Phone speaker, wired headset, Bluetooth, etc.
     * <p>
     * Note: The default controller can't be released. Calling {@link RoutingController#release()}
     * will be no-op.
     * <p>
     * This method will always return the same instance.
     *
     * @hide
     */
    @NonNull
    public RoutingController getDefaultController() {
        return mDefaultController;
    }

    /**
     * Sends a media control request to be performed asynchronously by the route's destination.
     *
@@ -526,6 +551,15 @@ public class MediaRouter2 {
            return;
        }

        if (sessionInfo.isSystemSession()) {
            // The session info is sent from SystemMediaRoute2Provider.
            RoutingController defaultController = getDefaultController();
            RoutingSessionInfo oldInfo = defaultController.getRoutingSessionInfo();
            defaultController.setRoutingSessionInfo(sessionInfo);
            notifySessionInfoChanged(defaultController, oldInfo, sessionInfo);
            return;
        }

        RoutingController matchingController;
        synchronized (sRouterLock) {
            matchingController = mRoutingControllers.get(sessionInfo.getId());
@@ -766,7 +800,7 @@ public class MediaRouter2 {
     *
     * @hide
     */
    public final class RoutingController {
    public class RoutingController {
        private final Object mControllerLock = new Object();

        @GuardedBy("mControllerLock")
@@ -1074,7 +1108,6 @@ public class MediaRouter2 {
        // TODO: This method uses two locks (mLock outside, sLock inside).
        //       Check if there is any possiblity of deadlock.
        private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) {

            List<MediaRoute2Info> routes = new ArrayList<>();
            synchronized (sRouterLock) {
                // TODO: Maybe able to change using Collection.stream()?
@@ -1089,6 +1122,23 @@ public class MediaRouter2 {
        }
    }

    class DefaultRoutingController extends RoutingController {
        DefaultRoutingController(@NonNull RoutingSessionInfo sessionInfo) {
            super(sessionInfo);
        }

        @Override
        public void release() {
            // Do nothing. DefaultRoutingController will never be released
        }

        @Override
        public boolean isReleased() {
            // DefaultRoutingController will never be released
            return false;
        }
    }

    final class RouteCallbackRecord {
        public final Executor mExecutor;
        public final RouteCallback mRouteCallback;
+0 −7
Original line number Diff line number Diff line
@@ -29,9 +29,6 @@ public class MediaRouter2Utils {
    static final String TAG = "MR2Utils";
    static final String SEPARATOR = ":";

    /**
     * @hide
     */
    @NonNull
    public static String toUniqueId(@NonNull String providerId, @NonNull String id) {
        if (TextUtils.isEmpty(providerId)) {
@@ -49,8 +46,6 @@ public class MediaRouter2Utils {
    /**
     * Gets provider ID from unique ID.
     * If the corresponding provider ID could not be generated, it will return null.
     *
     * @hide
     */
    @Nullable
    public static String getProviderId(@NonNull String uniqueId) {
@@ -75,8 +70,6 @@ public class MediaRouter2Utils {
    /**
     * Gets the original ID (i.e. non-unique route/session ID) from unique ID.
     * If the corresponding ID could not be generated, it will return null.
     *
     * @hide
     */
    @Nullable
    public static String getOriginalId(@NonNull String uniqueId) {
+26 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public final class RoutingSessionInfo implements Parcelable {
    final List<String> mTransferrableRoutes;
    @Nullable
    final Bundle mControlHints;
    final boolean mIsSystemSession;

    RoutingSessionInfo(@NonNull Builder builder) {
        Objects.requireNonNull(builder, "builder must not be null.");
@@ -78,6 +79,7 @@ public final class RoutingSessionInfo implements Parcelable {
                convertToUniqueRouteIds(builder.mTransferrableRoutes));

        mControlHints = builder.mControlHints;
        mIsSystemSession = builder.mIsSystemSession;
    }

    RoutingSessionInfo(@NonNull Parcel src) {
@@ -93,6 +95,7 @@ public final class RoutingSessionInfo implements Parcelable {
        mTransferrableRoutes = ensureList(src.createStringArrayList());

        mControlHints = src.readBundle();
        mIsSystemSession = src.readBoolean();
    }

    private static String ensureString(String str) {
@@ -193,6 +196,15 @@ public final class RoutingSessionInfo implements Parcelable {
        return mControlHints;
    }

    /**
     * Gets whether this session is in system media route provider.
     * @hide
     */
    @Nullable
    public boolean isSystemSession() {
        return mIsSystemSession;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -208,6 +220,7 @@ public final class RoutingSessionInfo implements Parcelable {
        dest.writeStringList(mDeselectableRoutes);
        dest.writeStringList(mTransferrableRoutes);
        dest.writeBundle(mControlHints);
        dest.writeBoolean(mIsSystemSession);
    }

    @Override
@@ -278,6 +291,7 @@ public final class RoutingSessionInfo implements Parcelable {
     * Builder class for {@link RoutingSessionInfo}.
     */
    public static final class Builder {
        // TODO: Reorder these (important ones first)
        final String mId;
        final String mClientPackageName;
        String mProviderId;
@@ -286,6 +300,7 @@ public final class RoutingSessionInfo implements Parcelable {
        final List<String> mDeselectableRoutes;
        final List<String> mTransferrableRoutes;
        Bundle mControlHints;
        boolean mIsSystemSession;

        /**
         * Constructor for builder to create {@link RoutingSessionInfo}.
@@ -333,6 +348,7 @@ public final class RoutingSessionInfo implements Parcelable {
            mTransferrableRoutes = new ArrayList<>(sessionInfo.mTransferrableRoutes);

            mControlHints = sessionInfo.mControlHints;
            mIsSystemSession = sessionInfo.mIsSystemSession;
        }

        /**
@@ -490,6 +506,16 @@ public final class RoutingSessionInfo implements Parcelable {
            return this;
        }

        /**
         * Sets whether this session is in system media route provider.
         * @hide
         */
        @NonNull
        public Builder setSystemSession(boolean isSystemSession) {
            mIsSystemSession = isSystemSession;
            return this;
        }

        /**
         * Builds a routing session info.
         *
+8 −0
Original line number Diff line number Diff line
@@ -692,6 +692,14 @@ public class MediaRouter2Test {
        }
    }

    // TODO: Consider adding tests with bluetooth connection/disconnection.
    @Test
    public void testGetDefaultController() {
        final RoutingController defaultController = mRouter2.getDefaultController();
        assertNotNull(defaultController);
        assertFalse(defaultController.isReleased());
    }

    // Helper for getting routes easily
    static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
        Map<String, MediaRoute2Info> routeMap = new HashMap<>();
Loading