Merge "Bind provider services when necessary" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a00481f6a6
@@ -26,9 +26,9 @@ import android.os.Bundle;
|
|||||||
*/
|
*/
|
||||||
oneway interface IMediaRoute2ProviderServiceCallback {
|
oneway interface IMediaRoute2ProviderServiceCallback {
|
||||||
// TODO: Change it to updateRoutes?
|
// TODO: Change it to updateRoutes?
|
||||||
void updateState(in MediaRoute2ProviderInfo providerInfo);
|
void notifyProviderUpdated(in MediaRoute2ProviderInfo providerInfo);
|
||||||
void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo);
|
void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo);
|
||||||
void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
|
void notifySessionsUpdated(in List<RoutingSessionInfo> sessionInfo);
|
||||||
void notifySessionReleased(in RoutingSessionInfo sessionInfo);
|
void notifySessionReleased(in RoutingSessionInfo sessionInfo);
|
||||||
void notifyRequestFailed(long requestId, int reason);
|
void notifyRequestFailed(long requestId, int reason);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ public abstract class MediaRoute2ProviderService extends Service {
|
|||||||
private final Object mSessionLock = new Object();
|
private final Object mSessionLock = new Object();
|
||||||
private final Object mRequestIdsLock = new Object();
|
private final Object mRequestIdsLock = new Object();
|
||||||
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
|
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
|
||||||
|
private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false);
|
||||||
private MediaRoute2ProviderServiceStub mStub;
|
private MediaRoute2ProviderServiceStub mStub;
|
||||||
private IMediaRoute2ProviderServiceCallback mRemoteCallback;
|
private IMediaRoute2ProviderServiceCallback mRemoteCallback;
|
||||||
private volatile MediaRoute2ProviderInfo mProviderInfo;
|
private volatile MediaRoute2ProviderInfo mProviderInfo;
|
||||||
@@ -287,16 +288,8 @@ public abstract class MediaRoute2ProviderService extends Service {
|
|||||||
Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
|
Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
|
||||||
return;
|
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) {
|
void setCallback(IMediaRoute2ProviderServiceCallback callback) {
|
||||||
mRemoteCallback = callback;
|
mRemoteCallback = callback;
|
||||||
schedulePublishState();
|
schedulePublishState();
|
||||||
|
scheduleUpdateSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedulePublishState() {
|
void schedulePublishState() {
|
||||||
@@ -497,12 +491,40 @@ public abstract class MediaRoute2ProviderService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mRemoteCallback.updateState(mProviderInfo);
|
mRemoteCallback.notifyProviderUpdated(mProviderInfo);
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
Log.w(TAG, "Failed to publish provider state.", 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}.
|
* 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).
|
* When the max size is reached, the first element is removed (FIFO).
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ abstract class MediaRoute2Provider {
|
|||||||
mUniqueId = componentName.flattenToShortString();
|
mUniqueId = componentName.flattenToShortString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCallback(MediaRoute2ProviderServiceProxy.Callback callback) {
|
public void setCallback(Callback callback) {
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.server.media;
|
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.annotation.NonNull;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -43,6 +47,7 @@ import com.android.internal.annotations.GuardedBy;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -64,6 +69,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
private Connection mActiveConnection;
|
private Connection mActiveConnection;
|
||||||
private boolean mConnectionReady;
|
private boolean mConnectionReady;
|
||||||
|
|
||||||
|
private boolean mIsManagerScanning;
|
||||||
private RouteDiscoveryPreference mLastDiscoveryPreference = null;
|
private RouteDiscoveryPreference mLastDiscoveryPreference = null;
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -86,6 +92,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
|
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setManagerScanning(boolean managerScanning) {
|
||||||
|
if (mIsManagerScanning != managerScanning) {
|
||||||
|
mIsManagerScanning = managerScanning;
|
||||||
|
updateBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestCreateSession(long requestId, String packageName, String routeId,
|
public void requestCreateSession(long requestId, String packageName, String routeId,
|
||||||
Bundle sessionHints) {
|
Bundle sessionHints) {
|
||||||
@@ -209,7 +222,8 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
// Bind when there is a discovery preference or an active route session.
|
// Bind when there is a discovery preference or an active route session.
|
||||||
return (mLastDiscoveryPreference != null
|
return (mLastDiscoveryPreference != null
|
||||||
&& !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
|
&& !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
|
||||||
|| !getSessionInfos().isEmpty();
|
|| !getSessionInfos().isEmpty()
|
||||||
|
|| mIsManagerScanning;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -311,13 +325,12 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onProviderStateUpdated(Connection connection,
|
private void onProviderUpdated(Connection connection, MediaRoute2ProviderInfo providerInfo) {
|
||||||
MediaRoute2ProviderInfo providerInfo) {
|
|
||||||
if (mActiveConnection != connection) {
|
if (mActiveConnection != connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, this + ": State changed ");
|
Slog.d(TAG, this + ": updated");
|
||||||
}
|
}
|
||||||
setAndNotifyProviderState(providerInfo);
|
setAndNotifyProviderState(providerInfo);
|
||||||
}
|
}
|
||||||
@@ -350,40 +363,44 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
mCallback.onSessionCreated(this, requestId, newSession);
|
mCallback.onSessionCreated(this, requestId, newSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) {
|
private int findSessionByIdLocked(RoutingSessionInfo session) {
|
||||||
|
for (int i = 0; i < mSessionInfos.size(); i++) {
|
||||||
|
if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onSessionsUpdated(Connection connection, List<RoutingSessionInfo> sessions) {
|
||||||
if (mActiveConnection != connection) {
|
if (mActiveConnection != connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (updatedSession == null) {
|
|
||||||
Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from "
|
|
||||||
+ mComponentName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedSession = assignProviderIdForSession(updatedSession);
|
int targetIndex = 0;
|
||||||
|
|
||||||
boolean found = false;
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
for (int i = 0; i < mSessionInfos.size(); i++) {
|
for (RoutingSessionInfo session : sessions) {
|
||||||
if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) {
|
if (session == null) continue;
|
||||||
mSessionInfos.set(i, updatedSession);
|
session = assignProviderIdForSession(session);
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
int sourceIndex = findSessionByIdLocked(session);
|
||||||
for (RoutingSessionInfo releasingSession : mReleasingSessions) {
|
if (sourceIndex < 0) {
|
||||||
if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) {
|
mSessionInfos.add(targetIndex++, session);
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Slog.w(TAG, "onSessionUpdated: Matching session info not found");
|
for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) {
|
||||||
return;
|
RoutingSessionInfo releasedSession = mSessionInfos.remove(i);
|
||||||
|
dispatchSessionReleased(releasedSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCallback.onSessionUpdated(this, updatedSession);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
|
private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
|
||||||
@@ -424,6 +441,21 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
mCallback.onSessionReleased(this, releaedSession);
|
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) {
|
private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) {
|
||||||
return new RoutingSessionInfo.Builder(sessionInfo)
|
return new RoutingSessionInfo.Builder(sessionInfo)
|
||||||
.setOwnerPackageName(mComponentName.getPackageName())
|
.setOwnerPackageName(mComponentName.getPackageName())
|
||||||
@@ -436,7 +468,7 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
|
if (requestId == REQUEST_ID_NONE) {
|
||||||
Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
|
Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -561,16 +593,16 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
mHandler.post(() -> onConnectionDied(Connection.this));
|
mHandler.post(() -> onConnectionDied(Connection.this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
|
void postProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
|
||||||
mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
|
mHandler.post(() -> onProviderUpdated(Connection.this, providerInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) {
|
void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) {
|
||||||
mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo));
|
mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postSessionUpdated(RoutingSessionInfo sessionInfo) {
|
void postSessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
|
||||||
mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
|
mHandler.post(() -> onSessionsUpdated(Connection.this, sessionInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postSessionReleased(RoutingSessionInfo sessionInfo) {
|
void postSessionReleased(RoutingSessionInfo sessionInfo) {
|
||||||
@@ -595,10 +627,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateState(MediaRoute2ProviderInfo providerInfo) {
|
public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
|
||||||
Connection connection = mConnectionRef.get();
|
Connection connection = mConnectionRef.get();
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
connection.postProviderStateUpdated(providerInfo);
|
connection.postProviderUpdated(providerInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,10 +643,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
|
public void notifySessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
|
||||||
Connection connection = mConnectionRef.get();
|
Connection connection = mConnectionRef.get();
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
connection.postSessionUpdated(sessionInfo);
|
connection.postSessionsUpdated(sessionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2156,6 +2156,8 @@ class MediaRouter2ServiceImpl {
|
|||||||
List<RouterRecord> routerRecords = getRouterRecords();
|
List<RouterRecord> routerRecords = getRouterRecords();
|
||||||
List<ManagerRecord> managerRecords = getManagerRecords();
|
List<ManagerRecord> managerRecords = getManagerRecords();
|
||||||
|
|
||||||
|
boolean shouldBindProviders = false;
|
||||||
|
|
||||||
if (service.mPowerManager.isInteractive()) {
|
if (service.mPowerManager.isInteractive()) {
|
||||||
boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
|
boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
|
||||||
manager.mIsScanning && service.mActivityManager
|
manager.mIsScanning && service.mActivityManager
|
||||||
@@ -2166,6 +2168,7 @@ class MediaRouter2ServiceImpl {
|
|||||||
discoveryPreferences = routerRecords.stream()
|
discoveryPreferences = routerRecords.stream()
|
||||||
.map(record -> record.mDiscoveryPreference)
|
.map(record -> record.mDiscoveryPreference)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
shouldBindProviders = true;
|
||||||
} else {
|
} else {
|
||||||
discoveryPreferences = routerRecords.stream().filter(record ->
|
discoveryPreferences = routerRecords.stream().filter(record ->
|
||||||
service.mActivityManager.getPackageImportance(record.mPackageName)
|
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) {
|
synchronized (service.mLock) {
|
||||||
RouteDiscoveryPreference newPreference =
|
RouteDiscoveryPreference newPreference =
|
||||||
new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
|
new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
|
||||||
|
|||||||
Reference in New Issue
Block a user