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

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

Merge changes I582e1297,Ia1fda27b into main

* changes:
  Make misc parcelable performance improvements
  Add MR2 listener for the list of apps with system session overrides
parents 15523e08 2b272ac5
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ public final class AppId implements Parcelable {
                @Override
                public AppId createFromParcel(Parcel in) {
                    return new AppId(
                            in.readString(),
                            in.readParcelable(UserHandle.class.getClassLoader(), UserHandle.class));
                            in.readString8(),
                            in.readTypedObject(UserHandle.CREATOR));
                }

                @Override
@@ -56,8 +56,8 @@ public final class AppId implements Parcelable {

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mPackageName);
        dest.writeParcelable(mUserHandle, flags);
        dest.writeString8(mPackageName);
        dest.writeTypedObject(mUserHandle, flags);
    }

    @Override
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.media.RouteDiscoveryPreference;
import android.media.RouteListingPreference;
import android.media.RoutingSessionInfo;
import android.media.SuggestedDeviceInfo;
import android.media.AppId;

/**
 * {@hide}
@@ -39,5 +40,6 @@ oneway interface IMediaRouter2Manager {
    void notifyDeviceSuggestionRequested();
    void notifyRoutesUpdated(in List<MediaRoute2Info> routes);
    void notifyRequestFailed(int requestId, int reason);
    void notifySystemSessionOverridesChanged(in List<AppId> appsWithOverrides);
    void invalidateInstance();
}
+161 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -1077,6 +1078,38 @@ public final class MediaRouter2 {
        }
    }

    /**
     * Registers a {@link SystemSessionOverridesListener}.
     *
     * <p>Passing the same listener to this method twice updates the associated {@code executor} but
     * does not register the same callback twice.
     *
     * @param executor the executor to execute the listener on
     * @param listener the {@link SystemSessionOverridesListener} to register
     * @throws UnsupportedOperationException if this method is called on a non-proxy instance
     *     (instances created using {@link #getInstance(Context)})
     * @hide
     */
    public void registerSystemSessionOverridesListener(
            @NonNull Executor executor, @NonNull SystemSessionOverridesListener listener) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(listener);
        mImpl.registerSystemSessionOverridesListener(executor, listener);
    }

    /**
     * Unregisters the given {@link SystemSessionOverridesListener}.
     *
     * @param listener the {@link SystemSessionOverridesListener} to unregister
     * @throws UnsupportedOperationException if this method is called on a non-proxy instance
     *     (instances created using {@link #getInstance(Context)})
     * @hide
     */
    public void unregisterSystemSessionOverridesListener(
            @NonNull SystemSessionOverridesListener listener) {
        mImpl.unregisterSystemSessionOverridesListener(listener);
    }

    /**
     * Sets an {@link OnGetControllerHintsListener} to send hints when creating a
     * {@link RoutingController}. To send the hints, listener should be set <em>BEFORE</em> calling
@@ -1929,6 +1962,38 @@ public final class MediaRouter2 {
        public void onControllerUpdated(@NonNull RoutingController controller) {}
    }

    /**
     * Listens for changes in the list of apps with an overriding system routing session.
     *
     * <p>An overriding system routing session is a system {@link RoutingSessionInfo session} that
     * overrides the global system routing, which applies to all apps (typically describing the
     * audio framework's routing decisions, for example {@link
     * android.media.AudioManager#getPreferredDeviceForStrategy}).
     *
     * <p>By default, applications' system routing session (queried using {@link
     * #getSystemController()}) will be the global session. However, specific apps see a different
     * {@link #getSystemController() system session} when affected by a {@link
     * MediaRoute2ProviderService#onCreateSystemRoutingSession service-managed} system routing
     * session that overrides the global session. This listener reports changes to the set of apps
     * affected by a system session override.
     *
     * <p>The list of apps with overriding system sessions is useful, for example, to display a
     * dedicated volume slider in SysUI when a physical volume rocker switch is pressed.
     *
     * <p>A client interested in specific aspects (for example, volume level) of the overriding
     * system routing session should register a {@link #getInstance(Context, String, UserHandle)
     * proxy router} for the relevant app and listen for {@link #registerControllerCallback}routing
     * session changes.
     *
     * @see #registerSystemSessionOverridesListener
     * @hide
     */
    public interface SystemSessionOverridesListener {

        /** Called when the set of apps with an overriding system session changes. */
        void onSystemSessionOverridesChanged(Set<AppId> appIdsWithOverridingSystemSession);
    }

    /**
     * Represents an active scan request registered in the system.
     *
@@ -2522,6 +2587,27 @@ public final class MediaRouter2 {
        }
    }

    private record SystemSessionOverridesListenerRecord(
            Executor mExecutor, SystemSessionOverridesListener mSystemSessionOverridesListener) {

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof SystemSessionOverridesListenerRecord)) {
                return false;
            }
            return mSystemSessionOverridesListener
                    == ((SystemSessionOverridesListenerRecord) obj).mSystemSessionOverridesListener;
        }

        @Override
        public int hashCode() {
            return mSystemSessionOverridesListener.hashCode();
        }
    }

    static final class RouteCallbackRecord {
        public final Executor mExecutor;
        public final RouteCallback mRouteCallback;
@@ -2848,6 +2934,25 @@ public final class MediaRouter2 {
         * associated with this router.
         */
        boolean wasTransferredBySelf(RoutingSessionInfo sessionInfo);

        /**
         * Registers a {@link SystemSessionOverridesListener}.
         *
         * <p>Passing the same listener to this method twice updates the associated {@code executor}
         * but does not register the same callback twice.
         *
         * @param executor the executor to execute the listener on
         * @param listener The listener to register.
         */
        void registerSystemSessionOverridesListener(
                Executor executor, SystemSessionOverridesListener listener);

        /**
         * Unregisters a {@link SystemSessionOverridesListener}.
         *
         * @param listener The listener to unregister.
         */
        void unregisterSystemSessionOverridesListener(SystemSessionOverridesListener listener);
    }

    /**
@@ -2865,6 +2970,9 @@ public final class MediaRouter2 {
        private final IMediaRouter2Manager.Stub mClient;
        private final CopyOnWriteArrayList<MediaRouter2Manager.TransferRequest>
                mTransferRequests = new CopyOnWriteArrayList<>();

        private final CopyOnWriteArraySet<SystemSessionOverridesListenerRecord>
                mSystemSessionOverridesListenerRecords = new CopyOnWriteArraySet<>();
        private final AtomicInteger mScanRequestCount = new AtomicInteger(/* initialValue= */ 0);

        // Fields originating from MediaRouter2.
@@ -3455,6 +3563,26 @@ public final class MediaRouter2 {
                    && Objects.equals(mClientPackageName, transferInitiatorPackageName);
        }

        @Override
        public void registerSystemSessionOverridesListener(
                Executor executor, SystemSessionOverridesListener listener) {
            var record = new SystemSessionOverridesListenerRecord(executor, listener);
            // We remove it first so as to ensure the latest provided executor for a given listener
            // is used.
            mSystemSessionOverridesListenerRecords.remove(record);
            mSystemSessionOverridesListenerRecords.add(record);
        }

        @Override
        public void unregisterSystemSessionOverridesListener(
                SystemSessionOverridesListener listener) {
            // We use a placeholder executor to keep the field non-nullable, but it will be ignored
            // in equality checks.
            mSystemSessionOverridesListenerRecords.remove(
                    new SystemSessionOverridesListenerRecord(
                            /* executor= */ Runnable::run, listener));
        }

        /**
         * Retrieves the system session info for the given package.
         *
@@ -3771,6 +3899,16 @@ public final class MediaRouter2 {
            mTransferCallbackRecords.clear();
        }

        private void notifySystemSessionOverridesChangedOnHandler(List<AppId> appsWithOverrides) {
            var appsWithOverridesAsSet = Set.copyOf(appsWithOverrides);
            for (var record : mSystemSessionOverridesListenerRecords) {
                record.mExecutor.execute(
                        () ->
                                record.mSystemSessionOverridesListener
                                        .onSystemSessionOverridesChanged(appsWithOverridesAsSet));
            }
        }

        private class Client extends IMediaRouter2Manager.Stub {

            @Override
@@ -3869,6 +4007,15 @@ public final class MediaRouter2 {
                                ProxyMediaRouter2Impl::onInvalidateInstanceOnHandler,
                                ProxyMediaRouter2Impl.this));
            }

            @Override
            public void notifySystemSessionOverridesChanged(List<AppId> appsWithOverrides) {
                mHandler.sendMessage(
                        obtainMessage(
                                ProxyMediaRouter2Impl::notifySystemSessionOverridesChangedOnHandler,
                                ProxyMediaRouter2Impl.this,
                                appsWithOverrides));
            }
        }
    }

@@ -4253,6 +4400,20 @@ public final class MediaRouter2 {
                    && Objects.equals(mContext.getPackageName(), transferInitiatorPackageName);
        }

        @Override
        public void registerSystemSessionOverridesListener(
                Executor executor, SystemSessionOverridesListener listener) {
            throw new UnsupportedOperationException(
                    "registerSystemSessionOverridesListener is only supported on proxy routers.");
        }

        @Override
        public void unregisterSystemSessionOverridesListener(
                SystemSessionOverridesListener listener) {
            throw new UnsupportedOperationException(
                    "unregisterSystemSessionOverridesListener is only supported on proxy routers.");
        }

        @GuardedBy("mLock")
        private void registerRouterStubIfNeededLocked() throws RemoteException {
            if (mStub == null) {
+5 −0
Original line number Diff line number Diff line
@@ -1179,5 +1179,10 @@ public final class MediaRouter2Manager {
            // Should never happen since MediaRouter2Manager should only be used with
            // MEDIA_CONTENT_CONTROL, which cannot be revoked.
        }

        @Override
        public void notifySystemSessionOverridesChanged(List<AppId> apps) {
            // Not supported by MR2Manager.
        }
    }
}
+31 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.media.AppId;
import android.media.AudioManager;
import android.media.IMediaRouter2;
import android.media.IMediaRouter2Manager;
@@ -79,6 +80,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -2408,6 +2410,8 @@ class MediaRouter2ServiceImpl {
        private final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>();
        final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>();

        private final Set<String> mLastPackagesWithSystemOverridesOnHandler = new ArraySet<>();

        // @GuardedBy("mLock")
        private final Map<String, Map<String, List<SuggestedDeviceInfo>>> mDeviceSuggestions =
                new HashMap<>();
@@ -3032,6 +3036,14 @@ class MediaRouter2ServiceImpl {
            }
        }

        public void notifySystemSessionOverridesChanged(List<AppId> appsWithOverrides) {
            try {
                mManager.notifySystemSessionOverridesChanged(appsWithOverrides);
            } catch (RemoteException ex) {
                logRemoteException("notifySystemSessionOverridesChanged", ex);
            }
        }

        private List<MediaRoute2Info> getVisibleRoutes(List<MediaRoute2Info> routes) {
            if (TextUtils.isEmpty(mTargetPackageName)) {
                // If the proxy router / manager doesn't target a specific app, it sees all
@@ -3800,15 +3812,33 @@ class MediaRouter2ServiceImpl {
                @NonNull RoutingSessionInfo sessionInfo,
                Set<String> packageNamesWithRoutingSessionOverrides) {
            List<ManagerRecord> managers = getManagerRecords();
            List<AppId> appsWithOverridesToReport = null;

            boolean isGlobalSession = TextUtils.isEmpty(sessionInfo.getClientPackageName());
            if (isGlobalSession
                    && !Objects.equals(
                            mUserRecord.mLastPackagesWithSystemOverridesOnHandler,
                            packageNamesWithRoutingSessionOverrides)) {
                appsWithOverridesToReport =
                        packageNamesWithRoutingSessionOverrides.stream()
                                .map(it -> new AppId(it, mUserRecord.mUserHandle))
                                .toList();
                mUserRecord.mLastPackagesWithSystemOverridesOnHandler.clear();
                mUserRecord.mLastPackagesWithSystemOverridesOnHandler.addAll(
                        packageNamesWithRoutingSessionOverrides);
            }
            for (ManagerRecord manager : managers) {
                if (Flags.enableMirroringInMediaRouter2()) {
                    if (appsWithOverridesToReport != null) {
                        manager.notifySystemSessionOverridesChanged(appsWithOverridesToReport);
                    }
                    String targetPackageName = manager.mTargetPackageName;
                    boolean skipDueToOverride =
                            targetPackageName != null
                                    && packageNamesWithRoutingSessionOverrides.contains(
                                            targetPackageName);
                    boolean sessionIsForTargetPackage =
                            TextUtils.isEmpty(sessionInfo.getClientPackageName()) // is global.
                            isGlobalSession
                                    || TextUtils.equals(
                                            targetPackageName, sessionInfo.getClientPackageName());
                    if (skipDueToOverride || !sessionIsForTargetPackage) {