diff options
5 files changed, 115 insertions, 51 deletions
diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl index 1755657ddc64..63c52a142fdd 100644 --- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl +++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl @@ -26,9 +26,9 @@ import android.os.Bundle; */ oneway interface IMediaRoute2ProviderServiceCallback { // TODO: Change it to updateRoutes? - void updateState(in MediaRoute2ProviderInfo providerInfo); + void notifyProviderUpdated(in MediaRoute2ProviderInfo providerInfo); void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo); - void notifySessionUpdated(in RoutingSessionInfo sessionInfo); + void notifySessionsUpdated(in List<RoutingSessionInfo> sessionInfo); void notifySessionReleased(in RoutingSessionInfo sessionInfo); void notifyRequestFailed(long requestId, int reason); } diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index 93fe06ac99aa..49e0411cc4d1 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -141,6 +141,7 @@ public abstract class MediaRoute2ProviderService extends Service { private final Object mSessionLock = new Object(); private final Object mRequestIdsLock = new Object(); private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false); + private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false); private MediaRoute2ProviderServiceStub mStub; private IMediaRoute2ProviderServiceCallback mRemoteCallback; private volatile MediaRoute2ProviderInfo mProviderInfo; @@ -287,16 +288,8 @@ public abstract class MediaRoute2ProviderService extends Service { Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info."); return; } - - if (mRemoteCallback == null) { - return; - } - try { - mRemoteCallback.notifySessionUpdated(sessionInfo); - } catch (RemoteException ex) { - Log.w(TAG, "Failed to notify session info changed."); - } } + scheduleUpdateSessions(); } /** @@ -479,6 +472,7 @@ public abstract class MediaRoute2ProviderService extends Service { void setCallback(IMediaRoute2ProviderServiceCallback callback) { mRemoteCallback = callback; schedulePublishState(); + scheduleUpdateSessions(); } void schedulePublishState() { @@ -497,12 +491,40 @@ public abstract class MediaRoute2ProviderService extends Service { } try { - mRemoteCallback.updateState(mProviderInfo); + mRemoteCallback.notifyProviderUpdated(mProviderInfo); } catch (RemoteException ex) { Log.w(TAG, "Failed to publish provider state.", ex); } } + void scheduleUpdateSessions() { + if (mSessionUpdateScheduled.compareAndSet(false, true)) { + mHandler.post(this::updateSessions); + } + } + + private void updateSessions() { + if (!mSessionUpdateScheduled.compareAndSet(true, false)) { + return; + } + + if (mRemoteCallback == null) { + return; + } + + List<RoutingSessionInfo> sessions; + synchronized (mSessionLock) { + sessions = new ArrayList<>(mSessionInfo.values()); + } + + try { + mRemoteCallback.notifySessionsUpdated(sessions); + } catch (RemoteException ex) { + Log.w(TAG, "Failed to notify session info changed."); + } + + } + /** * Adds a requestId in the request ID list whose max size is {@link #MAX_REQUEST_IDS_SIZE}. * When the max size is reached, the first element is removed (FIFO). diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java index edc9d7c64146..204ebfc678f5 100644 --- a/services/core/java/com/android/server/media/MediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java @@ -47,7 +47,7 @@ abstract class MediaRoute2Provider { mUniqueId = componentName.flattenToShortString(); } - public void setCallback(MediaRoute2ProviderServiceProxy.Callback callback) { + public void setCallback(Callback callback) { mCallback = callback; } diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index ab38dca2387d..21f61ca3978a 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -16,6 +16,10 @@ package com.android.server.media; +import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE; + +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; @@ -43,6 +47,7 @@ import com.android.internal.annotations.GuardedBy; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -64,6 +69,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider private Connection mActiveConnection; private boolean mConnectionReady; + private boolean mIsManagerScanning; private RouteDiscoveryPreference mLastDiscoveryPreference = null; @GuardedBy("mLock") @@ -86,6 +92,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider pw.println(prefix + " mConnectionReady=" + mConnectionReady); } + public void setManagerScanning(boolean managerScanning) { + if (mIsManagerScanning != managerScanning) { + mIsManagerScanning = managerScanning; + updateBinding(); + } + } + @Override public void requestCreateSession(long requestId, String packageName, String routeId, Bundle sessionHints) { @@ -209,7 +222,8 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider // Bind when there is a discovery preference or an active route session. return (mLastDiscoveryPreference != null && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty()) - || !getSessionInfos().isEmpty(); + || !getSessionInfos().isEmpty() + || mIsManagerScanning; } return false; } @@ -311,13 +325,12 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } } - private void onProviderStateUpdated(Connection connection, - MediaRoute2ProviderInfo providerInfo) { + private void onProviderUpdated(Connection connection, MediaRoute2ProviderInfo providerInfo) { if (mActiveConnection != connection) { return; } if (DEBUG) { - Slog.d(TAG, this + ": State changed "); + Slog.d(TAG, this + ": updated"); } setAndNotifyProviderState(providerInfo); } @@ -350,40 +363,44 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mCallback.onSessionCreated(this, requestId, newSession); } - private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) { - if (mActiveConnection != connection) { - return; + private int findSessionByIdLocked(RoutingSessionInfo session) { + for (int i = 0; i < mSessionInfos.size(); i++) { + if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) { + return i; + } } - if (updatedSession == null) { - Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from " - + mComponentName); + return -1; + } + + + private void onSessionsUpdated(Connection connection, List<RoutingSessionInfo> sessions) { + if (mActiveConnection != connection) { return; } - updatedSession = assignProviderIdForSession(updatedSession); - - boolean found = false; + int targetIndex = 0; synchronized (mLock) { - for (int i = 0; i < mSessionInfos.size(); i++) { - if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) { - mSessionInfos.set(i, updatedSession); - found = true; - break; + for (RoutingSessionInfo session : sessions) { + if (session == null) continue; + session = assignProviderIdForSession(session); + + int sourceIndex = findSessionByIdLocked(session); + if (sourceIndex < 0) { + mSessionInfos.add(targetIndex++, session); + dispatchSessionCreated(REQUEST_ID_NONE, session); + } else if (sourceIndex < targetIndex) { + Slog.w(TAG, "Ignoring duplicate session ID: " + session.getId()); + } else { + mSessionInfos.set(sourceIndex, session); + Collections.swap(mSessionInfos, sourceIndex, targetIndex++); + dispatchSessionUpdated(session); } } - - if (!found) { - for (RoutingSessionInfo releasingSession : mReleasingSessions) { - if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) { - return; - } - } - Slog.w(TAG, "onSessionUpdated: Matching session info not found"); - return; + for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) { + RoutingSessionInfo releasedSession = mSessionInfos.remove(i); + dispatchSessionReleased(releasedSession); } } - - mCallback.onSessionUpdated(this, updatedSession); } private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) { @@ -424,6 +441,21 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mCallback.onSessionReleased(this, releaedSession); } + private void dispatchSessionCreated(long requestId, RoutingSessionInfo session) { + mHandler.sendMessage( + obtainMessage(mCallback::onSessionCreated, this, requestId, session)); + } + + private void dispatchSessionUpdated(RoutingSessionInfo session) { + mHandler.sendMessage( + obtainMessage(mCallback::onSessionUpdated, this, session)); + } + + private void dispatchSessionReleased(RoutingSessionInfo session) { + mHandler.sendMessage( + obtainMessage(mCallback::onSessionReleased, this, session)); + } + private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) { return new RoutingSessionInfo.Builder(sessionInfo) .setOwnerPackageName(mComponentName.getPackageName()) @@ -436,7 +468,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } - if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) { + if (requestId == REQUEST_ID_NONE) { Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE"); return; } @@ -561,16 +593,16 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mHandler.post(() -> onConnectionDied(Connection.this)); } - void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) { - mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo)); + void postProviderUpdated(MediaRoute2ProviderInfo providerInfo) { + mHandler.post(() -> onProviderUpdated(Connection.this, providerInfo)); } void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) { mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo)); } - void postSessionUpdated(RoutingSessionInfo sessionInfo) { - mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo)); + void postSessionsUpdated(List<RoutingSessionInfo> sessionInfo) { + mHandler.post(() -> onSessionsUpdated(Connection.this, sessionInfo)); } void postSessionReleased(RoutingSessionInfo sessionInfo) { @@ -595,10 +627,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } @Override - public void updateState(MediaRoute2ProviderInfo providerInfo) { + public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) { Connection connection = mConnectionRef.get(); if (connection != null) { - connection.postProviderStateUpdated(providerInfo); + connection.postProviderUpdated(providerInfo); } } @@ -611,10 +643,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } @Override - public void notifySessionUpdated(RoutingSessionInfo sessionInfo) { + public void notifySessionsUpdated(List<RoutingSessionInfo> sessionInfo) { Connection connection = mConnectionRef.get(); if (connection != null) { - connection.postSessionUpdated(sessionInfo); + connection.postSessionsUpdated(sessionInfo); } } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 1dbc8a926996..168ca551317a 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -2156,6 +2156,8 @@ class MediaRouter2ServiceImpl { List<RouterRecord> routerRecords = getRouterRecords(); List<ManagerRecord> managerRecords = getManagerRecords(); + boolean shouldBindProviders = false; + if (service.mPowerManager.isInteractive()) { boolean isManagerScanning = managerRecords.stream().anyMatch(manager -> manager.mIsScanning && service.mActivityManager @@ -2166,6 +2168,7 @@ class MediaRouter2ServiceImpl { discoveryPreferences = routerRecords.stream() .map(record -> record.mDiscoveryPreference) .collect(Collectors.toList()); + shouldBindProviders = true; } else { discoveryPreferences = routerRecords.stream().filter(record -> service.mActivityManager.getPackageImportance(record.mPackageName) @@ -2175,6 +2178,13 @@ class MediaRouter2ServiceImpl { } } + for (MediaRoute2Provider provider : mRouteProviders) { + if (provider instanceof MediaRoute2ProviderServiceProxy) { + ((MediaRoute2ProviderServiceProxy) provider) + .setManagerScanning(shouldBindProviders); + } + } + synchronized (service.mLock) { RouteDiscoveryPreference newPreference = new RouteDiscoveryPreference.Builder(discoveryPreferences).build(); |