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

Commit 71de7328 authored by Santiago Seifert's avatar Santiago Seifert Committed by Android (Google) Code Review
Browse files

Merge "Populate transfer initiation data for remote routes" into main

parents f1c08c50 2a4670c2
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.ComponentName;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRouter2;
import android.media.MediaRouter2Utils;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
import android.os.Bundle;
@@ -226,8 +227,23 @@ abstract class MediaRoute2Provider {
            return route2Info != null && mTargetOriginalRouteId.equals(route2Info.getOriginalId());
        }

        public boolean isTargetRouteIdInList(@NonNull List<String> routeOriginalIdList) {
            return routeOriginalIdList.stream().anyMatch(mTargetOriginalRouteId::equals);
        /**
         * Returns whether the given list of {@link MediaRoute2Info#getOriginalId() original ids}
         * contains the {@link #mTargetOriginalRouteId target route id}.
         */
        public boolean isTargetRouteIdInRouteOriginalIdList(
                @NonNull List<String> originalRouteIdList) {
            return originalRouteIdList.stream().anyMatch(mTargetOriginalRouteId::equals);
        }

        /**
         * Returns whether the given list of {@link MediaRoute2Info#getId() unique ids} contains the
         * {@link #mTargetOriginalRouteId target route id}.
         */
        public boolean isTargetRouteIdInRouteUniqueIdList(@NonNull List<String> uniqueRouteIdList) {
            return uniqueRouteIdList.stream()
                    .map(MediaRouter2Utils::getOriginalId)
                    .anyMatch(mTargetOriginalRouteId::equals);
        }
    }
}
+130 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -41,6 +42,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
@@ -49,7 +51,9 @@ import com.android.media.flags.Flags;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@@ -77,7 +81,16 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
    private boolean mLastDiscoveryPreferenceIncludesThisPackage = false;

    @GuardedBy("mLock")
    final List<RoutingSessionInfo> mReleasingSessions = new ArrayList<>();
    private final List<RoutingSessionInfo> mReleasingSessions = new ArrayList<>();

    // We keep pending requests for transfers and sessions creation separately because transfers
    // don't have an associated request id and session creations don't have a session id.
    @GuardedBy("mLock")
    private final LongSparseArray<SessionCreationOrTransferRequest>
            mRequestIdToSessionCreationRequest;

    @GuardedBy("mLock")
    private final Map<String, SessionCreationOrTransferRequest> mSessionOriginalIdToTransferRequest;

    MediaRoute2ProviderServiceProxy(
            @NonNull Context context,
@@ -87,6 +100,8 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
            int userId) {
        super(componentName);
        mContext = Objects.requireNonNull(context, "Context must not be null.");
        mRequestIdToSessionCreationRequest = new LongSparseArray<>();
        mSessionOriginalIdToTransferRequest = new HashMap<>();
        mIsSelfScanOnlyProvider = isSelfScanOnlyProvider;
        mUserId = userId;
        mHandler = new Handler(looper);
@@ -109,6 +124,18 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
            @NonNull UserHandle transferInitiatorUserHandle,
            @NonNull String transferInitiatorPackageName) {
        if (mConnectionReady) {
            if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                synchronized (mLock) {
                    mRequestIdToSessionCreationRequest.put(
                            requestId,
                            new SessionCreationOrTransferRequest(
                                    requestId,
                                    routeOriginalId,
                                    transferReason,
                                    transferInitiatorUserHandle,
                                    transferInitiatorPackageName));
                }
            }
            mActiveConnection.requestCreateSession(
                    requestId, packageName, routeOriginalId, sessionHints);
            updateBinding();
@@ -118,6 +145,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
    @Override
    public void releaseSession(long requestId, String sessionId) {
        if (mConnectionReady) {
            if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                synchronized (mLock) {
                    mSessionOriginalIdToTransferRequest.remove(sessionId);
                }
            }
            mActiveConnection.releaseSession(requestId, sessionId);
            updateBinding();
        }
@@ -158,6 +190,18 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
            String routeOriginalId,
            @RoutingSessionInfo.TransferReason int transferReason) {
        if (mConnectionReady) {
            if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                synchronized (mLock) {
                    mSessionOriginalIdToTransferRequest.put(
                            sessionOriginalId,
                            new SessionCreationOrTransferRequest(
                                    requestId,
                                    routeOriginalId,
                                    transferReason,
                                    transferInitiatorUserHandle,
                                    transferInitiatorPackageName));
                }
            }
            mActiveConnection.transferToRoute(requestId, sessionOriginalId, routeOriginalId);
        }
    }
@@ -384,6 +428,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
        String newSessionId = newSession.getId();

        synchronized (mLock) {
            if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                newSession =
                        createSessionWithPopulatedTransferInitiationDataLocked(
                                requestId, /* oldSessionInfo= */ null, newSession);
            }
            if (mSessionInfos.stream()
                    .anyMatch(session -> TextUtils.equals(session.getId(), newSessionId))
                    || mReleasingSessions.stream()
@@ -397,6 +446,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
        mCallback.onSessionCreated(this, requestId, newSession);
    }

    @GuardedBy("mLock")
    private int findSessionByIdLocked(RoutingSessionInfo session) {
        for (int i = 0; i < mSessionInfos.size(); i++) {
            if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) {
@@ -417,7 +467,6 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
            for (RoutingSessionInfo session : sessions) {
                if (session == null) continue;
                session = assignProviderIdForSession(session);

                int sourceIndex = findSessionByIdLocked(session);
                if (sourceIndex < 0) {
                    mSessionInfos.add(targetIndex++, session);
@@ -425,6 +474,12 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
                } else if (sourceIndex < targetIndex) {
                    Slog.w(TAG, "Ignoring duplicate session ID: " + session.getId());
                } else {
                    if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                        RoutingSessionInfo oldSessionInfo = mSessionInfos.get(sourceIndex);
                        session =
                                createSessionWithPopulatedTransferInitiationDataLocked(
                                        REQUEST_ID_NONE, oldSessionInfo, session);
                    }
                    mSessionInfos.set(sourceIndex, session);
                    Collections.swap(mSessionInfos, sourceIndex, targetIndex++);
                    dispatchSessionUpdated(session);
@@ -432,11 +487,65 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
            }
            for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) {
                RoutingSessionInfo releasedSession = mSessionInfos.remove(i);
                mSessionOriginalIdToTransferRequest.remove(releasedSession.getId());
                dispatchSessionReleased(releasedSession);
            }
        }
    }

    /**
     * Returns a {@link RoutingSessionInfo} with transfer initiation data from the given {@code
     * oldSessionInfo}, and any pending transfer or session creation requests.
     */
    @GuardedBy("mLock")
    private RoutingSessionInfo createSessionWithPopulatedTransferInitiationDataLocked(
            long requestId,
            @Nullable RoutingSessionInfo oldSessionInfo,
            @NonNull RoutingSessionInfo newSessionInfo) {
        SessionCreationOrTransferRequest pendingRequest =
                oldSessionInfo != null
                        ? mSessionOriginalIdToTransferRequest.get(newSessionInfo.getOriginalId())
                        : mRequestIdToSessionCreationRequest.get(requestId);
        boolean pendingTargetRouteInSelectedRoutes =
                pendingRequest != null
                        && pendingRequest.isTargetRouteIdInRouteUniqueIdList(
                                newSessionInfo.getSelectedRoutes());
        boolean pendingTargetRouteInTransferableRoutes =
                pendingRequest != null
                        && pendingRequest.isTargetRouteIdInRouteUniqueIdList(
                                newSessionInfo.getTransferableRoutes());

        int transferReason;
        UserHandle transferInitiatorUserHandle;
        String transferInitiatorPackageName;
        if (pendingTargetRouteInSelectedRoutes) { // The pending request has been satisfied.
            transferReason = pendingRequest.mTransferReason;
            transferInitiatorUserHandle = pendingRequest.mTransferInitiatorUserHandle;
            transferInitiatorPackageName = pendingRequest.mTransferInitiatorPackageName;
        } else if (oldSessionInfo != null) {
            // No pending request, we copy the values from the old session object.
            transferReason = oldSessionInfo.getTransferReason();
            transferInitiatorUserHandle = oldSessionInfo.getTransferInitiatorUserHandle();
            transferInitiatorPackageName = oldSessionInfo.getTransferInitiatorPackageName();
        } else { // There's a new session with no associated creation request, we use defaults.
            transferReason = RoutingSessionInfo.TRANSFER_REASON_FALLBACK;
            transferInitiatorUserHandle = UserHandle.of(mUserId);
            transferInitiatorPackageName = newSessionInfo.getClientPackageName();
        }
        if (pendingTargetRouteInSelectedRoutes || !pendingTargetRouteInTransferableRoutes) {
            // The pending request has been satisfied, or the target route is no longer available.
            if (oldSessionInfo != null) {
                mSessionOriginalIdToTransferRequest.remove(newSessionInfo.getId());
            } else if (pendingRequest != null) {
                mRequestIdToSessionCreationRequest.remove(pendingRequest.mRequestId);
            }
        }
        return new RoutingSessionInfo.Builder(newSessionInfo)
                .setTransferInitiator(transferInitiatorUserHandle, transferInitiatorPackageName)
                .setTransferReason(transferReason)
                .build();
    }

    private void onSessionReleased(Connection connection, RoutingSessionInfo releasedSession) {
        if (mActiveConnection != connection) {
            return;
@@ -450,6 +559,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider

        boolean found = false;
        synchronized (mLock) {
            mSessionOriginalIdToTransferRequest.remove(releasedSession.getId());
            for (RoutingSessionInfo session : mSessionInfos) {
                if (TextUtils.equals(session.getId(), releasedSession.getId())) {
                    mSessionInfos.remove(session);
@@ -498,6 +608,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
    }

    private void onRequestFailed(Connection connection, long requestId, int reason) {
        if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
            synchronized (mLock) {
                mRequestIdToSessionCreationRequest.remove(requestId);
            }
        }
        if (mActiveConnection != connection) {
            return;
        }
@@ -522,18 +637,29 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
                }
                mSessionInfos.clear();
                mReleasingSessions.clear();
                mRequestIdToSessionCreationRequest.clear();
                mSessionOriginalIdToTransferRequest.clear();
            }
        }
    }

    @Override
    protected String getDebugString() {
        int pendingSessionCreationCount;
        int pendingTransferCount;
        synchronized (mLock) {
            pendingSessionCreationCount = mRequestIdToSessionCreationRequest.size();
            pendingTransferCount = mSessionOriginalIdToTransferRequest.size();
        }
        return TextUtils.formatSimple(
                "ProviderServiceProxy - package: %s, bound: %b, connection (active:%b, ready:%b)",
                "ProviderServiceProxy - package: %s, bound: %b, connection (active:%b, ready:%b), "
                        + "pending (session creations: %d, transfers: %d)",
                mComponentName.getPackageName(),
                mBound,
                mActiveConnection != null,
                mConnectionReady);
                mConnectionReady,
                pendingSessionCreationCount,
                pendingTransferCount);
    }

    private final class Connection implements DeathRecipient {
+2 −1
Original line number Diff line number Diff line
@@ -443,7 +443,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
                        boolean isTransferringToTheSelectedRoute =
                                mPendingTransferRequest.isTargetRoute(selectedRoute);
                        boolean canBePotentiallyTransferred =
                                mPendingTransferRequest.isTargetRouteIdInList(transferableRoutes);
                                mPendingTransferRequest.isTargetRouteIdInRouteOriginalIdList(
                                        transferableRoutes);

                        if (isTransferringToTheSelectedRoute) {
                            transferReason = mPendingTransferRequest.mTransferReason;