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

Commit efe4374e authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

MediaRouter: save sessions in media router service

Each MediaRoute2Provider instance saves session infos
published by MediaRoute2ProviderService.

For that, MediaRouter2ProviderService notifies provider info and session
infos simultaneously and to minimize the number of binder calls,
schedulePublishState is added into MediaRoute2ProviderService.

The saved sessions can be obtained by calling MRM.getActiveSessions().

Test: atest mediaroutertest
 && manually call MRM.getActiveSessions()

Change-Id: I6938105f8d154ad9542f7e7c6210a451ee4ae90d
parent f6a55e1b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Bundle;
 * @hide
 */
oneway interface IMediaRoute2ProviderClient {
    void updateProviderInfo(in MediaRoute2ProviderInfo info);
    void updateState(in MediaRoute2ProviderInfo providerInfo,
            in List<RouteSessionInfo> sessionInfos);
    void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, long requestId);
}
+3 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.media.IMediaRouter2Manager;
import android.media.IMediaRouterClient;
import android.media.MediaRoute2Info;
import android.media.MediaRouterClientState;
import android.media.RouteSessionInfo;

/**
 * {@hide}
@@ -63,4 +64,6 @@ interface IMediaRouterService {
            in MediaRoute2Info route, int volume);
    void requestUpdateVolume2Manager(IMediaRouter2Manager manager,
            in MediaRoute2Info route, int direction);

    List<RouteSessionInfo> getActiveSessions(IMediaRouter2Manager manager);
}
+33 −13
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @hide
@@ -48,6 +49,7 @@ public abstract class MediaRoute2ProviderService extends Service {

    private final Handler mHandler;
    private final Object mSessionLock = new Object();
    private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
    private ProviderStub mStub;
    private IMediaRoute2ProviderClient mClient;
    private MediaRoute2ProviderInfo mProviderInfo;
@@ -132,20 +134,22 @@ public abstract class MediaRoute2ProviderService extends Service {
     */
    public final void updateSessionInfo(@NonNull RouteSessionInfo sessionInfo) {
        Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
        int sessionId = sessionInfo.getSessionId();

        //TODO: notify updated session info
        int sessionId = sessionInfo.getSessionId();
        if (sessionInfo.getSelectedRoutes().isEmpty()) {
            releaseSession(sessionId);
            return;
        }

        synchronized (mSessionLock) {
            if (mSessionInfo.containsKey(sessionId)) {
                mSessionInfo.put(sessionId, sessionInfo);
                schedulePublishState();
            } else {
                Log.w(TAG, "Ignoring unknown session info.");
                return;
            }
        }
        if (sessionInfo.getSelectedRoutes().isEmpty()) {
            releaseSession(sessionId);
        }
    }

    /**
@@ -169,6 +173,7 @@ public abstract class MediaRoute2ProviderService extends Service {
                }
                mSessionInfo.put(sessionInfo.getSessionId(), sessionInfo);
            }
            schedulePublishState();
        }

        if (mClient == null) {
@@ -192,11 +197,12 @@ public abstract class MediaRoute2ProviderService extends Service {
        //TODO: notify media router service of release.
        RouteSessionInfo sessionInfo;
        synchronized (mSessionLock) {
            sessionInfo = mSessionInfo.put(sessionId, null);
            sessionInfo = mSessionInfo.remove(sessionId);
        }
        if (sessionInfo != null) {
            mHandler.sendMessage(obtainMessage(
                    MediaRoute2ProviderService::onDestroySession, this, sessionId, sessionInfo));
            schedulePublishState();
        }
    }

@@ -268,23 +274,37 @@ public abstract class MediaRoute2ProviderService extends Service {
    /**
     * Updates provider info and publishes routes and session info.
     */
    public final void updateProviderInfo(MediaRoute2ProviderInfo info) {
        mProviderInfo = info;
        publishState();
    public final void updateProviderInfo(@NonNull MediaRoute2ProviderInfo providerInfo) {
        mProviderInfo = Objects.requireNonNull(providerInfo, "providerInfo must not be null");
        schedulePublishState();
    }

    void setClient(IMediaRoute2ProviderClient client) {
        mClient = client;
        publishState();
        schedulePublishState();
    }

    void schedulePublishState() {
        if (mStatePublishScheduled.compareAndSet(false, true)) {
            mHandler.post(this::publishState);
        }
    }

    private void publishState() {
        if (!mStatePublishScheduled.compareAndSet(true, false)) {
            return;
        }

    void publishState() {
        //TODO: sends session info
        if (mClient == null) {
            return;
        }

        List<RouteSessionInfo> sessionInfos;
        synchronized (mSessionLock) {
            sessionInfos = new ArrayList<>(mSessionInfo.values());
        }
        try {
            mClient.updateProviderInfo(mProviderInfo);
            mClient.updateState(mProviderInfo, sessionInfos);
        } catch (RemoteException ex) {
            Log.w(TAG, "Failed to send onProviderInfoUpdated");
        }
+12 −1
Original line number Diff line number Diff line
@@ -176,7 +176,18 @@ public class MediaRouter2Manager {
    }

    @NonNull
    public List<RouteSessionInfo> getRouteSessions() {
    public List<RouteSessionInfo> getActiveSessions() {
        Client client;
        synchronized (sLock) {
            client = mClient;
        }
        if (client != null) {
            try {
                return mMediaRouterService.getActiveSessions(client);
            } catch (RemoteException ex) {
                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
            }
        }
        return Collections.emptyList();
    }

+2 −2
Original line number Diff line number Diff line
@@ -280,12 +280,12 @@ public class MediaRouterManagerTest {
        });

        //TODO: it fails due to not releasing session
        assertEquals(0, mManager.getActiveRoutes().size());
        assertEquals(0, mManager.getActiveSessions().size());

        mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
        latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);

        assertEquals(1, mManager.getActiveRoutes().size());
        assertEquals(1, mManager.getActiveSessions().size());

        //TODO: release the session
        /*
Loading