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

Commit ca9db78a authored by Hyundo Moon's avatar Hyundo Moon
Browse files

MediaRouter2: Implement RouteSessionController#release

This CL implements followings:
 - RouteSessionController#release
 - Router side logic of calling SessionCallback#onSessionReleased()

The test should be added when MediaRouterService actually notifies
the clients of session release. (i.e. No new test added.)

Bug: 146400872
Test: atest mediaroutertest
Change-Id: I2bad73e00986903b8c925704b0144d9e75f3bbf7
parent cdbf6678
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -30,4 +30,5 @@ oneway interface IMediaRouter2Client {
    void notifyRoutesChanged(in List<MediaRoute2Info> routes);
    void notifyRoutesChanged(in List<MediaRoute2Info> routes);
    void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, int requestId);
    void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, int requestId);
    void notifySessionInfoChanged(in RouteSessionInfo sessionInfo);
    void notifySessionInfoChanged(in RouteSessionInfo sessionInfo);
    void notifySessionReleased(in RouteSessionInfo sessionInfo);
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ interface IMediaRouterService {
    void selectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void selectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void deselectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void deselectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void transferToRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void transferToRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
    void releaseSession(IMediaRouter2Client client, String sessionId);


    void registerManager(IMediaRouter2Manager manager, String packageName);
    void registerManager(IMediaRouter2Manager manager, String packageName);
    void unregisterManager(IMediaRouter2Manager manager);
    void unregisterManager(IMediaRouter2Manager manager);
+142 −59
Original line number Original line Diff line number Diff line
@@ -96,7 +96,7 @@ public class MediaRouter2 {


    private static final String TAG = "MR2";
    private static final String TAG = "MR2";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final Object sLock = new Object();
    private static final Object sRouterLock = new Object();


    @GuardedBy("sLock")
    @GuardedBy("sLock")
    private static MediaRouter2 sInstance;
    private static MediaRouter2 sInstance;
@@ -122,8 +122,9 @@ public class MediaRouter2 {


    // TODO: Make MediaRouter2 is always connected to the MediaRouterService.
    // TODO: Make MediaRouter2 is always connected to the MediaRouterService.
    @GuardedBy("sLock")
    @GuardedBy("sLock")
    private Client2 mClient;
    Client2 mClient;


    @GuardedBy("sLock")
    private Map<String, RouteSessionController> mSessionControllers = new ArrayMap<>();
    private Map<String, RouteSessionController> mSessionControllers = new ArrayMap<>();


    private AtomicInteger mSessionCreationRequestCnt = new AtomicInteger(1);
    private AtomicInteger mSessionCreationRequestCnt = new AtomicInteger(1);
@@ -138,7 +139,7 @@ public class MediaRouter2 {
     */
     */
    public static MediaRouter2 getInstance(@NonNull Context context) {
    public static MediaRouter2 getInstance(@NonNull Context context) {
        Objects.requireNonNull(context, "context must not be null");
        Objects.requireNonNull(context, "context must not be null");
        synchronized (sLock) {
        synchronized (sRouterLock) {
            if (sInstance == null) {
            if (sInstance == null) {
                sInstance = new MediaRouter2(context.getApplicationContext());
                sInstance = new MediaRouter2(context.getApplicationContext());
            }
            }
@@ -210,7 +211,7 @@ public class MediaRouter2 {
            return;
            return;
        }
        }


        synchronized (sLock) {
        synchronized (sRouterLock) {
            if (mClient == null) {
            if (mClient == null) {
                Client2 client = new Client2();
                Client2 client = new Client2();
                try {
                try {
@@ -242,7 +243,7 @@ public class MediaRouter2 {
            return;
            return;
        }
        }


        synchronized (sLock) {
        synchronized (sRouterLock) {
            if (mRouteCallbackRecords.size() == 0 && mClient != null) {
            if (mRouteCallbackRecords.size() == 0 && mClient != null) {
                try {
                try {
                    mMediaRouterService.unregisterClient2(mClient);
                    mMediaRouterService.unregisterClient2(mClient);
@@ -266,7 +267,7 @@ public class MediaRouter2 {


        List<String> newControlCategories = new ArrayList<>(controlCategories);
        List<String> newControlCategories = new ArrayList<>(controlCategories);


        synchronized (sLock) {
        synchronized (sRouterLock) {
            mShouldUpdateRoutes = true;
            mShouldUpdateRoutes = true;


            // invoke callbacks due to control categories change
            // invoke callbacks due to control categories change
@@ -291,7 +292,7 @@ public class MediaRouter2 {
     */
     */
    @NonNull
    @NonNull
    public List<MediaRoute2Info> getRoutes() {
    public List<MediaRoute2Info> getRoutes() {
        synchronized (sLock) {
        synchronized (sRouterLock) {
            if (mShouldUpdateRoutes) {
            if (mShouldUpdateRoutes) {
                mShouldUpdateRoutes = false;
                mShouldUpdateRoutes = false;


@@ -372,7 +373,7 @@ public class MediaRouter2 {
        mSessionCreationRequests.add(request);
        mSessionCreationRequests.add(request);


        Client2 client;
        Client2 client;
        synchronized (sLock) {
        synchronized (sRouterLock) {
            client = mClient;
            client = mClient;
        }
        }
        if (client != null) {
        if (client != null) {
@@ -400,7 +401,7 @@ public class MediaRouter2 {
        Objects.requireNonNull(request, "request must not be null");
        Objects.requireNonNull(request, "request must not be null");


        Client2 client;
        Client2 client;
        synchronized (sLock) {
        synchronized (sRouterLock) {
            client = mClient;
            client = mClient;
        }
        }
        if (client != null) {
        if (client != null) {
@@ -424,7 +425,7 @@ public class MediaRouter2 {
        Objects.requireNonNull(route, "route must not be null");
        Objects.requireNonNull(route, "route must not be null");


        Client2 client;
        Client2 client;
        synchronized (sLock) {
        synchronized (sRouterLock) {
            client = mClient;
            client = mClient;
        }
        }
        if (client != null) {
        if (client != null) {
@@ -448,7 +449,7 @@ public class MediaRouter2 {
        Objects.requireNonNull(route, "route must not be null");
        Objects.requireNonNull(route, "route must not be null");


        Client2 client;
        Client2 client;
        synchronized (sLock) {
        synchronized (sRouterLock) {
            client = mClient;
            client = mClient;
        }
        }
        if (client != null) {
        if (client != null) {
@@ -496,7 +497,7 @@ public class MediaRouter2 {
        //  2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
        //  2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
        //     does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
        //     does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
        List<MediaRoute2Info> addedRoutes = new ArrayList<>();
        List<MediaRoute2Info> addedRoutes = new ArrayList<>();
        synchronized (sLock) {
        synchronized (sRouterLock) {
            for (MediaRoute2Info route : routes) {
            for (MediaRoute2Info route : routes) {
                mRoutes.put(route.getUniqueId(), route);
                mRoutes.put(route.getUniqueId(), route);
                if (route.supportsControlCategories(mControlCategories)) {
                if (route.supportsControlCategories(mControlCategories)) {
@@ -512,7 +513,7 @@ public class MediaRouter2 {


    void removeRoutesOnHandler(List<MediaRoute2Info> routes) {
    void removeRoutesOnHandler(List<MediaRoute2Info> routes) {
        List<MediaRoute2Info> removedRoutes = new ArrayList<>();
        List<MediaRoute2Info> removedRoutes = new ArrayList<>();
        synchronized (sLock) {
        synchronized (sRouterLock) {
            for (MediaRoute2Info route : routes) {
            for (MediaRoute2Info route : routes) {
                mRoutes.remove(route.getUniqueId());
                mRoutes.remove(route.getUniqueId());
                if (route.supportsControlCategories(mControlCategories)) {
                if (route.supportsControlCategories(mControlCategories)) {
@@ -528,7 +529,7 @@ public class MediaRouter2 {


    void changeRoutesOnHandler(List<MediaRoute2Info> routes) {
    void changeRoutesOnHandler(List<MediaRoute2Info> routes) {
        List<MediaRoute2Info> changedRoutes = new ArrayList<>();
        List<MediaRoute2Info> changedRoutes = new ArrayList<>();
        synchronized (sLock) {
        synchronized (sRouterLock) {
            for (MediaRoute2Info route : routes) {
            for (MediaRoute2Info route : routes) {
                mRoutes.put(route.getUniqueId(), route);
                mRoutes.put(route.getUniqueId(), route);
                if (route.supportsControlCategories(mControlCategories)) {
                if (route.supportsControlCategories(mControlCategories)) {
@@ -596,7 +597,9 @@ public class MediaRouter2 {


        if (sessionInfo != null) {
        if (sessionInfo != null) {
            RouteSessionController controller = new RouteSessionController(sessionInfo);
            RouteSessionController controller = new RouteSessionController(sessionInfo);
            synchronized (sRouterLock) {
                mSessionControllers.put(controller.getUniqueSessionId(), controller);
                mSessionControllers.put(controller.getUniqueSessionId(), controller);
            }
            notifySessionCreated(controller);
            notifySessionCreated(controller);
        }
        }
    }
    }
@@ -607,8 +610,10 @@ public class MediaRouter2 {
            return;
            return;
        }
        }


        RouteSessionController matchingController = mSessionControllers.get(
        RouteSessionController matchingController;
                sessionInfo.getUniqueSessionId());
        synchronized (sRouterLock) {
            matchingController = mSessionControllers.get(sessionInfo.getUniqueSessionId());
        }


        if (matchingController == null) {
        if (matchingController == null) {
            Log.w(TAG, "changeSessionInfoOnHandler: Matching controller not found. uniqueSessionId="
            Log.w(TAG, "changeSessionInfoOnHandler: Matching controller not found. uniqueSessionId="
@@ -627,6 +632,40 @@ public class MediaRouter2 {
        notifySessionInfoChanged(matchingController, oldInfo, sessionInfo);
        notifySessionInfoChanged(matchingController, oldInfo, sessionInfo);
    }
    }


    void releaseControllerOnHandler(RouteSessionInfo sessionInfo) {
        if (sessionInfo == null) {
            Log.w(TAG, "releaseControllerOnHandler: Ignoring null sessionInfo.");
            return;
        }

        final String uniqueSessionId = sessionInfo.getUniqueSessionId();
        RouteSessionController matchingController;
        synchronized (sRouterLock) {
            matchingController = mSessionControllers.get(uniqueSessionId);
        }

        if (matchingController == null) {
            if (DEBUG) {
                Log.d(TAG, "releaseControllerOnHandler: Matching controller not found. "
                        + "uniqueSessionId=" + sessionInfo.getUniqueSessionId());
            }
            return;
        }

        RouteSessionInfo oldInfo = matchingController.getRouteSessionInfo();
        if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) {
            Log.w(TAG, "releaseControllerOnHandler: Provider IDs are not matched. old="
                    + oldInfo.getProviderId() + ", new=" + sessionInfo.getProviderId());
            return;
        }

        synchronized (sRouterLock) {
            mSessionControllers.remove(uniqueSessionId, matchingController);
        }
        matchingController.release();
        notifyControllerReleased(matchingController);
    }

    private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
    private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
        for (RouteCallbackRecord record: mRouteCallbackRecords) {
        for (RouteCallbackRecord record: mRouteCallbackRecords) {
            record.mExecutor.execute(
            record.mExecutor.execute(
@@ -671,6 +710,13 @@ public class MediaRouter2 {
        }
        }
    }
    }


    private void notifyControllerReleased(RouteSessionController controller) {
        for (SessionCallbackRecord record: mSessionCallbackRecords) {
            record.mExecutor.execute(
                    () -> record.mSessionCallback.onSessionReleased(controller));
        }
    }

    /**
    /**
     * Callback for receiving events about media route discovery.
     * Callback for receiving events about media route discovery.
     */
     */
@@ -737,14 +783,20 @@ public class MediaRouter2 {
                @NonNull RouteSessionInfo newInfo) {}
                @NonNull RouteSessionInfo newInfo) {}


        /**
        /**
         * Called when the session is released. Session can be released by the controller using
         * Called when the session is released by {@link MediaRoute2ProviderService}.
         * {@link RouteSessionController#release(boolean)}, or by the
         * Before this method is called, the controller would be released by the system,
         * {@link MediaRoute2ProviderService} itself. One can do clean-ups here.
         * which means the {@link RouteSessionController#isReleased()} will always return true
         * for the {@code controller} here.
         * <p>
         * Note: Calling {@link RouteSessionController#release()} will <em>NOT</em> trigger
         * this method to be called.
         *
         * TODO: Add tests for checking whether this method is called.
         * TODO: When service process dies, this should be called.
         *
         *
         * TODO: When Provider#notifySessionDestroyed is introduced, add @see for the method.
         * @see RouteSessionController#isReleased()
         */
         */
        public void onSessionReleased(@NonNull RouteSessionController controller, int reason,
        public void onSessionReleased(@NonNull RouteSessionController controller) {}
                boolean shouldStop) {}
    }
    }


    /**
    /**
@@ -755,7 +807,7 @@ public class MediaRouter2 {
     * TODO: Need to add toString()
     * TODO: Need to add toString()
     */
     */
    public final class RouteSessionController {
    public final class RouteSessionController {
        private final Object mLock = new Object();
        private final Object mControllerLock = new Object();


        @GuardedBy("mLock")
        @GuardedBy("mLock")
        private RouteSessionInfo mSessionInfo;
        private RouteSessionInfo mSessionInfo;
@@ -771,7 +823,7 @@ public class MediaRouter2 {
         * @return the ID of the session
         * @return the ID of the session
         */
         */
        public int getSessionId() {
        public int getSessionId() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mSessionInfo.getSessionId();
                return mSessionInfo.getSessionId();
            }
            }
        }
        }
@@ -782,7 +834,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public String getUniqueSessionId() {
        public String getUniqueSessionId() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mSessionInfo.getUniqueSessionId();
                return mSessionInfo.getUniqueSessionId();
            }
            }
        }
        }
@@ -792,7 +844,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public String getControlCategory() {
        public String getControlCategory() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mSessionInfo.getControlCategory();
                return mSessionInfo.getControlCategory();
            }
            }
        }
        }
@@ -802,7 +854,7 @@ public class MediaRouter2 {
         */
         */
        @Nullable
        @Nullable
        public Bundle getControlHints() {
        public Bundle getControlHints() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mSessionInfo.getControlHints();
                return mSessionInfo.getControlHints();
            }
            }
        }
        }
@@ -812,7 +864,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public List<MediaRoute2Info> getSelectedRoutes() {
        public List<MediaRoute2Info> getSelectedRoutes() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return getRoutesWithIdsLocked(mSessionInfo.getSelectedRoutes());
                return getRoutesWithIdsLocked(mSessionInfo.getSelectedRoutes());
            }
            }
        }
        }
@@ -822,7 +874,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public List<MediaRoute2Info> getSelectableRoutes() {
        public List<MediaRoute2Info> getSelectableRoutes() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return getRoutesWithIdsLocked(mSessionInfo.getSelectableRoutes());
                return getRoutesWithIdsLocked(mSessionInfo.getSelectableRoutes());
            }
            }
        }
        }
@@ -832,7 +884,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public List<MediaRoute2Info> getDeselectableRoutes() {
        public List<MediaRoute2Info> getDeselectableRoutes() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return getRoutesWithIdsLocked(mSessionInfo.getDeselectableRoutes());
                return getRoutesWithIdsLocked(mSessionInfo.getDeselectableRoutes());
            }
            }
        }
        }
@@ -842,7 +894,7 @@ public class MediaRouter2 {
         */
         */
        @NonNull
        @NonNull
        public List<MediaRoute2Info> getTransferrableRoutes() {
        public List<MediaRoute2Info> getTransferrableRoutes() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return getRoutesWithIdsLocked(mSessionInfo.getTransferrableRoutes());
                return getRoutesWithIdsLocked(mSessionInfo.getTransferrableRoutes());
            }
            }
        }
        }
@@ -853,10 +905,9 @@ public class MediaRouter2 {
         * Also, any operations to this instance will be ignored once released.
         * Also, any operations to this instance will be ignored once released.
         *
         *
         * @see #release
         * @see #release
         * @see SessionCallback#onSessionReleased
         */
         */
        public boolean isReleased() {
        public boolean isReleased() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mIsReleased;
                return mIsReleased;
            }
            }
        }
        }
@@ -876,6 +927,12 @@ public class MediaRouter2 {
         */
         */
        public void selectRoute(@NonNull MediaRoute2Info route) {
        public void selectRoute(@NonNull MediaRoute2Info route) {
            Objects.requireNonNull(route, "route must not be null");
            Objects.requireNonNull(route, "route must not be null");
            synchronized (mControllerLock) {
                if (mIsReleased) {
                    Log.w(TAG, "selectRoute() called on released controller. Ignoring.");
                    return;
                }
            }


            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
            if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
@@ -890,12 +947,12 @@ public class MediaRouter2 {
            }
            }


            Client2 client;
            Client2 client;
            synchronized (sLock) {
            synchronized (sRouterLock) {
                client = mClient;
                client = mClient;
            }
            }
            if (client != null) {
            if (client != null) {
                try {
                try {
                    mMediaRouterService.selectRoute(mClient, getUniqueSessionId(), route);
                    mMediaRouterService.selectRoute(client, getUniqueSessionId(), route);
                } catch (RemoteException ex) {
                } catch (RemoteException ex) {
                    Log.e(TAG, "Unable to select route for session.", ex);
                    Log.e(TAG, "Unable to select route for session.", ex);
                }
                }
@@ -917,6 +974,12 @@ public class MediaRouter2 {
         */
         */
        public void deselectRoute(@NonNull MediaRoute2Info route) {
        public void deselectRoute(@NonNull MediaRoute2Info route) {
            Objects.requireNonNull(route, "route must not be null");
            Objects.requireNonNull(route, "route must not be null");
            synchronized (mControllerLock) {
                if (mIsReleased) {
                    Log.w(TAG, "deselectRoute() called on released controller. Ignoring.");
                    return;
                }
            }


            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            if (!checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
            if (!checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
@@ -931,12 +994,12 @@ public class MediaRouter2 {
            }
            }


            Client2 client;
            Client2 client;
            synchronized (sLock) {
            synchronized (sRouterLock) {
                client = mClient;
                client = mClient;
            }
            }
            if (client != null) {
            if (client != null) {
                try {
                try {
                    mMediaRouterService.deselectRoute(mClient, getUniqueSessionId(), route);
                    mMediaRouterService.deselectRoute(client, getUniqueSessionId(), route);
                } catch (RemoteException ex) {
                } catch (RemoteException ex) {
                    Log.e(TAG, "Unable to remove route from session.", ex);
                    Log.e(TAG, "Unable to remove route from session.", ex);
                }
                }
@@ -958,6 +1021,12 @@ public class MediaRouter2 {
         */
         */
        public void transferToRoute(@NonNull MediaRoute2Info route) {
        public void transferToRoute(@NonNull MediaRoute2Info route) {
            Objects.requireNonNull(route, "route must not be null");
            Objects.requireNonNull(route, "route must not be null");
            synchronized (mControllerLock) {
                if (mIsReleased) {
                    Log.w(TAG, "transferToRoute() called on released controller. Ignoring.");
                    return;
                }
            }


            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
            if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
            if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
@@ -973,12 +1042,12 @@ public class MediaRouter2 {
            }
            }


            Client2 client;
            Client2 client;
            synchronized (sLock) {
            synchronized (sRouterLock) {
                client = mClient;
                client = mClient;
            }
            }
            if (client != null) {
            if (client != null) {
                try {
                try {
                    mMediaRouterService.transferToRoute(mClient, getUniqueSessionId(), route);
                    mMediaRouterService.transferToRoute(client, getUniqueSessionId(), route);
                } catch (RemoteException ex) {
                } catch (RemoteException ex) {
                    Log.e(TAG, "Unable to transfer to route for session.", ex);
                    Log.e(TAG, "Unable to transfer to route for session.", ex);
                }
                }
@@ -986,45 +1055,53 @@ public class MediaRouter2 {
        }
        }


        /**
        /**
         * Release this session.
         * Release this controller and corresponding session.
         * Any operation on this session after calling this method will be ignored.
         * Any operations on this controller after calling this method will be ignored.
         * The devices that are playing media will stop playing it.
         *
         *
         * @param stopMedia Should the media that is playing on the device be stopped after this
         * TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}.
         *                  session is released.
         * @see SessionCallback#onSessionReleased
         */
         */
        public void release(boolean stopMedia) {
        public void release() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                if (mIsReleased) {
                if (mIsReleased) {
                    Log.w(TAG, "release() called on released controller. Ignoring.");
                    return;
                    return;
                }
                }
                mIsReleased = true;
                mIsReleased = true;
            }
            }
            // TODO: Use stopMedia variable when the actual connection logic is implemented.

            Client2 client;
            synchronized (sRouterLock) {
                mSessionControllers.remove(getUniqueSessionId(), this);
                client = mClient;
            }
            if (client != null) {
                try {
                    mMediaRouterService.releaseSession(client, getUniqueSessionId());
                } catch (RemoteException ex) {
                    Log.e(TAG, "Unable to notify of controller release", ex);
                }
            }
        }
        }


        /**
         * @hide
         */
        @NonNull
        @NonNull
        public RouteSessionInfo getRouteSessionInfo() {
        RouteSessionInfo getRouteSessionInfo() {
            synchronized (mLock) {
            synchronized (mControllerLock) {
                return mSessionInfo;
                return mSessionInfo;
            }
            }
        }
        }


        /**
        void setRouteSessionInfo(@NonNull RouteSessionInfo info) {
         * @hide
            synchronized (mControllerLock) {
         */
        public void setRouteSessionInfo(@NonNull RouteSessionInfo info) {
            synchronized (mLock) {
                mSessionInfo = info;
                mSessionInfo = info;
            }
            }
        }
        }


        // 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) {
        private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) {
            List<MediaRoute2Info> routes = new ArrayList<>();
            List<MediaRoute2Info> routes = new ArrayList<>();
            synchronized (mLock) {
            synchronized (sRouterLock) {
                for (String routeId : routeIds) {
                for (String routeId : routeIds) {
                    MediaRoute2Info route = mRoutes.get(
                    MediaRoute2Info route = mRoutes.get(
                            MediaRoute2Info.toUniqueId(mSessionInfo.mProviderId, routeId));
                            MediaRoute2Info.toUniqueId(mSessionInfo.mProviderId, routeId));
@@ -1139,5 +1216,11 @@ public class MediaRouter2 {
            mHandler.sendMessage(obtainMessage(MediaRouter2::changeSessionInfoOnHandler,
            mHandler.sendMessage(obtainMessage(MediaRouter2::changeSessionInfoOnHandler,
                    MediaRouter2.this, sessionInfo));
                    MediaRouter2.this, sessionInfo));
        }
        }

        @Override
        public void notifySessionReleased(RouteSessionInfo sessionInfo) {
            mHandler.sendMessage(obtainMessage(MediaRouter2::releaseControllerOnHandler,
                    MediaRouter2.this, sessionInfo));
        }
    }
    }
}
}
+40 −2
Original line number Original line Diff line number Diff line
@@ -106,9 +106,47 @@ public class RouteSessionInfo implements Parcelable {


    /**
    /**
     * Gets non-unique session id (int) from unique session id (string).
     * Gets non-unique session id (int) from unique session id (string).
     * If the corresponding session id could not be generated, it will return null.
     * @hide
     */
     */
    public static int getSessionId(@NonNull String uniqueSessionId, @NonNull String providerId) {
    @Nullable
        return Integer.parseInt(uniqueSessionId.substring(providerId.length() + 1));
    public static Integer getSessionId(@NonNull String uniqueSessionId) {
        int lastIndexOfSeparator = uniqueSessionId.lastIndexOf("/");
        if (lastIndexOfSeparator == -1 || lastIndexOfSeparator + 1 >= uniqueSessionId.length()) {
            return null;
        }

        String integerString = uniqueSessionId.substring(lastIndexOfSeparator + 1);
        if (TextUtils.isEmpty(integerString)) {
            return null;
        }

        try {
            return Integer.parseInt(integerString);
        } catch (NumberFormatException ex) {
            return null;
        }
    }

    /**
     * Gets provider ID (string) from unique session id (string).
     * If the corresponding provider ID could not be generated, it will return null.
     * @hide
     *
     * TODO: This logic seems error-prone. Consider to use long uniqueId.
     */
    @Nullable
    public static String getProviderId(@NonNull String uniqueSessionId) {
        int lastIndexOfSeparator = uniqueSessionId.lastIndexOf("/");
        if (lastIndexOfSeparator == -1) {
            return null;
        }

        String result = uniqueSessionId.substring(0, lastIndexOfSeparator);
        if (TextUtils.isEmpty(result)) {
            return null;
        }
        return result;
    }
    }


    /**
    /**
+86 −9

File changed.

Preview size limit exceeded, changes collapsed.

Loading