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

Commit 1106db1b authored by Santiago Seifert's avatar Santiago Seifert
Browse files

Add support for SELF_SCAN_ONLY providers

Bug: 278249714
Test: atest CtsMediaBetterTogetherTestCases
Change-Id: If24d505e889f933a9b4512b3aa5be0a2c91dc1ee
parent bb33a6ef
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -80,6 +80,18 @@ public abstract class MediaRoute2ProviderService extends Service {
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";

    /**
     * A category indicating that the associated provider is only intended for use within the app
     * that hosts the provider.
     *
     * <p>Declaring this category helps the system save resources by avoiding the launch of services
     * whose routes are known to be private to the app that provides them.
     *
     * @hide
     */
    public static final String CATEGORY_SELF_SCAN_ONLY =
            "android.media.MediaRoute2ProviderService.SELF_SCAN_ONLY";

    /**
     * The request ID to pass {@link #notifySessionCreated(long, RoutingSessionInfo)}
     * when {@link MediaRoute2ProviderService} created a session although there was no creation
+4 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

abstract class MediaRoute2Provider {
    final ComponentName mComponentName;
@@ -56,7 +57,9 @@ abstract class MediaRoute2Provider {
    public abstract void requestCreateSession(long requestId, String packageName, String routeId,
            @Nullable Bundle sessionHints);
    public abstract void releaseSession(long requestId, String sessionId);
    public abstract void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference);

    public abstract void updateDiscoveryPreference(
            Set<String> activelyScanningPackages, RouteDiscoveryPreference discoveryPreference);

    public abstract void selectRoute(long requestId, String sessionId, String routeId);
    public abstract void deselectRoute(long requestId, String sessionId, String routeId);
+26 −8
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Maintains a connection to a particular {@link MediaRoute2ProviderService}.
@@ -61,6 +62,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
    private final Context mContext;
    private final int mUserId;
    private final Handler mHandler;
    private final boolean mIsSelfScanOnlyProvider;

    // Connection state
    private boolean mRunning;
@@ -70,14 +72,19 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider

    private boolean mIsManagerScanning;
    private RouteDiscoveryPreference mLastDiscoveryPreference = null;
    private boolean mLastDiscoveryPreferenceIncludesThisPackage = false;

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

    MediaRoute2ProviderServiceProxy(@NonNull Context context, @NonNull ComponentName componentName,
    MediaRoute2ProviderServiceProxy(
            @NonNull Context context,
            @NonNull ComponentName componentName,
            boolean isSelfScanOnlyProvider,
            int userId) {
        super(componentName);
        mContext = Objects.requireNonNull(context, "Context must not be null.");
        mIsSelfScanOnlyProvider = isSelfScanOnlyProvider;
        mUserId = userId;
        mHandler = new Handler(Looper.myLooper());
    }
@@ -107,8 +114,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
    }

    @Override
    public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) {
    public void updateDiscoveryPreference(
            Set<String> activelyScanningPackages, RouteDiscoveryPreference discoveryPreference) {
        mLastDiscoveryPreference = discoveryPreference;
        mLastDiscoveryPreferenceIncludesThisPackage =
                activelyScanningPackages.contains(mComponentName.getPackageName());
        if (mConnectionReady) {
            mActiveConnection.updateDiscoveryPreference(discoveryPreference);
        }
@@ -209,11 +219,15 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider

    private boolean shouldBind() {
        if (mRunning) {
            // Bind when there is a discovery preference or an active route session.
            return (mLastDiscoveryPreference != null
                    && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
                    || !getSessionInfos().isEmpty()
                    || mIsManagerScanning;
            boolean shouldBind =
                    mLastDiscoveryPreference != null
                            && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty();
            if (mIsSelfScanOnlyProvider) {
                shouldBind &= mLastDiscoveryPreferenceIncludesThisPackage;
            }
            shouldBind |= mIsManagerScanning;
            shouldBind |= !getSessionInfos().isEmpty();
            return shouldBind;
        }
        return false;
    }
@@ -301,7 +315,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
        if (mActiveConnection == connection) {
            mConnectionReady = true;
            if (mLastDiscoveryPreference != null) {
                updateDiscoveryPreference(mLastDiscoveryPreference);
                updateDiscoveryPreference(
                        mLastDiscoveryPreferenceIncludesThisPackage
                                ? Set.of(mComponentName.getPackageName())
                                : Set.of(),
                        mLastDiscoveryPreference);
            }
        }
    }
+20 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.media;

import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -34,6 +36,7 @@ import android.util.Slog;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

/**
 * Watches changes of packages, or scan them for finding media route providers.
@@ -41,8 +44,8 @@ import java.util.Collections;
final class MediaRoute2ProviderWatcher {
    private static final String TAG = "MR2ProviderWatcher";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final PackageManager.ResolveInfoFlags RESOLVE_INFO_FLAGS_NONE =
            PackageManager.ResolveInfoFlags.of(0);
    private static final PackageManager.ResolveInfoFlags RESOLVE_INFO_FLAGS =
            PackageManager.ResolveInfoFlags.of(GET_RESOLVED_FILTER);

    private final Context mContext;
    private final Callback mCallback;
@@ -118,15 +121,25 @@ final class MediaRoute2ProviderWatcher {
        int targetIndex = 0;
        Intent intent = new Intent(MediaRoute2ProviderService.SERVICE_INTERFACE);
        for (ResolveInfo resolveInfo :
                mPackageManager.queryIntentServicesAsUser(
                        intent, RESOLVE_INFO_FLAGS_NONE, mUserId)) {
                mPackageManager.queryIntentServicesAsUser(intent, RESOLVE_INFO_FLAGS, mUserId)) {
            ServiceInfo serviceInfo = resolveInfo.serviceInfo;
            if (serviceInfo != null) {
                boolean isSelfScanOnlyProvider = false;
                Iterator<String> categoriesIterator = resolveInfo.filter.categoriesIterator();
                if (categoriesIterator != null) {
                    while (categoriesIterator.hasNext()) {
                        isSelfScanOnlyProvider |=
                                MediaRoute2ProviderService.CATEGORY_SELF_SCAN_ONLY.equals(
                                        categoriesIterator.next());
                    }
                }
                int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
                if (sourceIndex < 0) {
                    MediaRoute2ProviderServiceProxy proxy =
                            new MediaRoute2ProviderServiceProxy(mContext,
                            new MediaRoute2ProviderServiceProxy(
                                    mContext,
                                    new ComponentName(serviceInfo.packageName, serviceInfo.name),
                                    isSelfScanOnlyProvider,
                                    mUserId);
                    proxy.start();
                    mProxies.add(targetIndex++, proxy);
+29 −16
Original line number Diff line number Diff line
@@ -1477,6 +1477,7 @@ class MediaRouter2ServiceImpl {
        final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>();
        final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>();
        RouteDiscoveryPreference mCompositeDiscoveryPreference = RouteDiscoveryPreference.EMPTY;
        Set<String> mActivelyScanningPackages = Set.of();
        final UserHandler mHandler;

        UserRecord(int userId) {
@@ -1524,7 +1525,12 @@ class MediaRouter2ServiceImpl {
                pw.println(indent + "<no manager records>");
            }

            mCompositeDiscoveryPreference.dump(pw, indent);
            pw.println(indent + "Composite discovery preference:");
            mCompositeDiscoveryPreference.dump(pw, indent + "  ");
            pw.println(
                    indent
                            + "Packages actively scanning: "
                            + String.join(", ", mActivelyScanningPackages));

            if (!mHandler.runWithScissors(() -> mHandler.dump(pw, indent), 1000)) {
                pw.println(indent + "<could not dump handler state>");
@@ -1833,7 +1839,9 @@ class MediaRouter2ServiceImpl {
        public void onAddProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) {
            proxy.setCallback(this);
            mRouteProviders.add(proxy);
            proxy.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
            proxy.updateDiscoveryPreference(
                    mUserRecord.mActivelyScanningPackages,
                    mUserRecord.mCompositeDiscoveryPreference);
        }

        @Override
@@ -2340,8 +2348,8 @@ class MediaRouter2ServiceImpl {
                    return;
                }
                notifySessionInfoChangedToRouters(getRouterRecords(true), sessionInfo);
                notifySessionInfoChangedToRouters(getRouterRecords(false),
                        mSystemProvider.getDefaultSessionInfo());
                notifySessionInfoChangedToRouters(
                        getRouterRecords(false), mSystemProvider.getDefaultSessionInfo());
                return;
            }

@@ -2710,8 +2718,8 @@ class MediaRouter2ServiceImpl {
            if (service == null) {
                return;
            }
            List<RouteDiscoveryPreference> discoveryPreferences = Collections.emptyList();
            List<RouterRecord> routerRecords = getRouterRecords();
            List<RouterRecord> activeRouterRecords = Collections.emptyList();
            List<RouterRecord> allRouterRecords = getRouterRecords();
            List<ManagerRecord> managerRecords = getManagerRecords();

            boolean isManagerScanning = false;
@@ -2722,18 +2730,15 @@ class MediaRouter2ServiceImpl {
                                <= sPackageImportanceForScanning);

                if (isManagerScanning) {
                    discoveryPreferences = routerRecords.stream()
                            .map(record -> record.mDiscoveryPreference)
                            .collect(Collectors.toList());
                    activeRouterRecords = allRouterRecords;
                } else {
                    discoveryPreferences =
                            routerRecords.stream()
                    activeRouterRecords =
                            allRouterRecords.stream()
                                    .filter(
                                            record ->
                                                    service.mActivityManager.getPackageImportance(
                                                                    record.mPackageName)
                                                            <= sPackageImportanceForScanning)
                                    .map(record -> record.mDiscoveryPreference)
                                    .collect(Collectors.toList());
                }
            }
@@ -2751,22 +2756,30 @@ class MediaRouter2ServiceImpl {
            // to query route providers once to obtain all of the routes of interest, which
            // can be subsequently filtered for the individual discovery preferences.
            Set<String> preferredFeatures = new HashSet<>();
            Set<String> activelyScanningPackages = new HashSet<>();
            boolean activeScan = false;
            for (RouteDiscoveryPreference preference : discoveryPreferences) {
            for (RouterRecord activeRouterRecord : activeRouterRecords) {
                RouteDiscoveryPreference preference = activeRouterRecord.mDiscoveryPreference;
                preferredFeatures.addAll(preference.getPreferredFeatures());
                activeScan |= preference.shouldPerformActiveScan();
                if (preference.shouldPerformActiveScan()) {
                    activeScan = true;
                    activelyScanningPackages.add(activeRouterRecord.mPackageName);
                }
            }
            RouteDiscoveryPreference newPreference = new RouteDiscoveryPreference.Builder(
                    List.copyOf(preferredFeatures), activeScan || isManagerScanning).build();

            synchronized (service.mLock) {
                if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)) {
                if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)
                        && activelyScanningPackages.equals(mUserRecord.mActivelyScanningPackages)) {
                    return;
                }
                mUserRecord.mCompositeDiscoveryPreference = newPreference;
                mUserRecord.mActivelyScanningPackages = activelyScanningPackages;
            }
            for (MediaRoute2Provider provider : mRouteProviders) {
                provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
                provider.updateDiscoveryPreference(
                        activelyScanningPackages, mUserRecord.mCompositeDiscoveryPreference);
            }
        }

Loading