Add getter for system session overrides
This is necessary in case SysUI crashes and needs to restart while a
mirroring session is already ongoing.
Bug: b/396394220
Test: atest CtsMediaRouterTestCases
Flag: com.android.media.flags.enable_mirroring_in_media_router_2
Change-Id: Ic3866066124f5b4c63dd4569e419a0c1415c702b
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 38c06c0..7ccbc10 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.content.Intent;
+import android.media.AppId;
import android.media.IMediaRouter2;
import android.media.IMediaRouter2Manager;
import android.media.IMediaRouterClient;
@@ -87,6 +88,7 @@
List<RoutingSessionInfo> getRemoteSessions(IMediaRouter2Manager manager);
RoutingSessionInfo getSystemSessionInfoForPackage(String callerPackageName,
String targetPackageName);
+ List<AppId> getSystemSessionOverridesAppIds(IMediaRouter2Manager manager);
void registerManager(IMediaRouter2Manager manager, String packageName);
void registerProxyRouter(IMediaRouter2Manager manager, String callingPackageName, String targetPackageName, in UserHandle targetUser);
void unregisterManager(IMediaRouter2Manager manager);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 6f816a4..4183be5 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -1318,6 +1318,18 @@
mImpl.setRouteVolume(route, volume);
}
+ /**
+ * Returns the set of apps currently affected by a system session override.
+ *
+ * <p>This method is only supported by proxy routers.
+ *
+ * @see SystemSessionOverridesListener
+ * @hide
+ */
+ public Set<AppId> getSystemSessionOverridesAppIds() {
+ return mImpl.getSystemSessionOverridesAppIds();
+ }
+
void syncRoutesOnHandler(
List<MediaRoute2Info> currentRoutes, RoutingSessionInfo currentSystemSessionInfo) {
if (currentRoutes == null || currentRoutes.isEmpty() || currentSystemSessionInfo == null) {
@@ -2971,6 +2983,13 @@
* @param listener The listener to unregister.
*/
void unregisterSystemSessionOverridesListener(SystemSessionOverridesListener listener);
+
+ /**
+ * Returns the set of apps affected by a system session override.
+ *
+ * @see SystemSessionOverridesListener
+ */
+ Set<AppId> getSystemSessionOverridesAppIds();
}
/**
@@ -3002,6 +3021,17 @@
private final List<InstanceInvalidatedCallbackRecord> mInstanceInvalidatedCallbackRecords =
new ArrayList<>();
+ /**
+ * Holds the last snapshot of ids of apps affected by a system session override.
+ *
+ * <p>Must hold an immutable set to avoid the need for a copy in {@link
+ * #getSystemSessionOverridesAppIds}.
+ *
+ * @see SystemSessionOverridesListener
+ */
+ @GuardedBy("mLock")
+ private Set<AppId> mLastSystemSessionSessionOverridesLocked = Set.of();
+
ProxyMediaRouter2Impl(
@NonNull Context context,
@NonNull String clientPackageName,
@@ -3019,11 +3049,22 @@
mContext.getApplicationContext().getPackageName(),
mClientPackageName,
mClientUser);
+ initSystemSessionOverridesSnapshot();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
+ private void initSystemSessionOverridesSnapshot() throws RemoteException {
+ if (!Flags.enableMirroringInMediaRouter2()) {
+ return;
+ }
+ synchronized (mLock) {
+ mLastSystemSessionSessionOverridesLocked =
+ Set.copyOf(mMediaRouterService.getSystemSessionOverridesAppIds(mClient));
+ }
+ }
+
public void registerInstanceInvalidatedCallback(
@Nullable Executor executor, @Nullable Runnable onInstanceInvalidatedListener) {
if (executor == null || onInstanceInvalidatedListener == null) {
@@ -3601,6 +3642,13 @@
/* executor= */ Runnable::run, listener));
}
+ @Override
+ public Set<AppId> getSystemSessionOverridesAppIds() {
+ synchronized (mLock) {
+ return mLastSystemSessionSessionOverridesLocked;
+ }
+ }
+
/**
* Retrieves the system session info for the given package.
*
@@ -3921,6 +3969,9 @@
private void notifySystemSessionOverridesChangedOnHandler(List<AppId> appsWithOverrides) {
var appsWithOverridesAsSet = Set.copyOf(appsWithOverrides);
+ synchronized (mLock) {
+ mLastSystemSessionSessionOverridesLocked = appsWithOverridesAsSet;
+ }
for (var record : mSystemSessionOverridesListenerRecords) {
record.mExecutor.execute(
() ->
@@ -4436,6 +4487,12 @@
"unregisterSystemSessionOverridesListener is only supported on proxy routers.");
}
+ @Override
+ public Set<AppId> getSystemSessionOverridesAppIds() {
+ throw new UnsupportedOperationException(
+ "getAppsWithSystemSessionOverrides is only supported on proxy routers.");
+ }
+
@GuardedBy("mLock")
private void registerRouterStubIfNeededLocked() throws RemoteException {
if (mStub == null) {
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 31cfb5a..74d4c4b 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -667,6 +667,19 @@
}
}
+ @NonNull
+ public List<AppId> getSystemSessionOverridesAppIds(@NonNull IMediaRouter2Manager manager) {
+ Objects.requireNonNull(manager, "manager must not be null");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return getSystemSessionOverridesAppIdsLocked(manager);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void registerManager(@NonNull IMediaRouter2Manager manager,
@NonNull String callerPackageName) {
@@ -1860,6 +1873,18 @@
return sessionInfos;
}
+ @GuardedBy("mLock")
+ public List<AppId> getSystemSessionOverridesAppIdsLocked(
+ @NonNull IMediaRouter2Manager manager) {
+ IBinder binder = manager.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+ if (managerRecord == null) {
+ Slog.w(TAG, "getSystemSessionOverridesAppIdsLocked: Ignoring unknown manager");
+ return Collections.emptyList();
+ }
+ return managerRecord.mUserRecord.getAppsWithSystemOverridesLocked();
+ }
+
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
@GuardedBy("mLock")
private void registerManagerLocked(
@@ -2410,7 +2435,8 @@
private final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>();
final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>();
- private final Set<String> mLastPackagesWithSystemOverridesOnHandler = new ArraySet<>();
+ // @GuardedBy("mLock")
+ private final Set<String> mLastPackagesWithSystemOverridesLocked = new ArraySet<>();
// @GuardedBy("mLock")
private final Map<String, Map<String, List<SuggestedDeviceInfo>>> mDeviceSuggestions =
@@ -2463,6 +2489,19 @@
return false;
}
+ @GuardedBy("mLock")
+ private List<AppId> getAppsWithSystemOverridesLocked() {
+ return mapPackageNamesToAppIdList(mLastPackagesWithSystemOverridesLocked);
+ }
+
+ /**
+ * Returns a list of {@link AppId app ids} corresponding to the given package names, created
+ * by associating each package name with {@link #mUserHandle}.
+ */
+ private List<AppId> mapPackageNamesToAppIdList(Collection<String> packageNames) {
+ return packageNames.stream().map(it -> new AppId(it, mUserHandle)).toList();
+ }
+
// @GuardedBy("mLock")
public void updateDeviceSuggestionsLocked(
String packageName,
@@ -3819,19 +3858,19 @@
boolean shouldShowVolumeUi) {
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);
+ synchronized (mLock) {
+ if (isGlobalSession
+ && !Objects.equals(
+ mUserRecord.mLastPackagesWithSystemOverridesLocked,
+ packageNamesWithRoutingSessionOverrides)) {
+ appsWithOverridesToReport =
+ mUserRecord.mapPackageNamesToAppIdList(
+ packageNamesWithRoutingSessionOverrides);
+ mUserRecord.mLastPackagesWithSystemOverridesLocked.clear();
+ mUserRecord.mLastPackagesWithSystemOverridesLocked.addAll(
+ packageNamesWithRoutingSessionOverrides);
+ }
}
for (ManagerRecord manager : managers) {
if (Flags.enableMirroringInMediaRouter2()) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 2ec2eda..5533c01 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -31,6 +31,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.media.AppId;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
@@ -606,6 +607,12 @@
}
// Binder call
+ @Override
+ public List<AppId> getSystemSessionOverridesAppIds(IMediaRouter2Manager manager) {
+ return mService2.getSystemSessionOverridesAppIds(manager);
+ }
+
+ // Binder call
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
@Override
public void registerManager(IMediaRouter2Manager manager, String callerPackageName) {