Loading media/java/android/media/MediaRouter2Manager.java +10 −5 Original line number Diff line number Diff line Loading @@ -178,8 +178,9 @@ public class MediaRouter2Manager { /** * Gets routing controllers of an application with the given package name. * If the application isn't running or it doesn't use {@link MediaRouter2}, an empty list * will be returned. * The first element of the returned list is the system routing controller. * * @see MediaRouter2#getSystemController() */ @NonNull public List<RoutingController> getRoutingControllers(@NonNull String packageName) { Loading @@ -188,7 +189,8 @@ public class MediaRouter2Manager { List<RoutingController> controllers = new ArrayList<>(); for (RoutingSessionInfo sessionInfo : getActiveSessions()) { if (TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) { if (sessionInfo.isSystemSession() || TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) { controllers.add(new RoutingController(sessionInfo)); } } Loading @@ -196,8 +198,11 @@ public class MediaRouter2Manager { } /** * Gets the list of all active routing sessions. It doesn't include default routing sessions * of applications. * Gets the list of all active routing sessions. * The first element of the list is the system routing session containing * phone speakers, wired headset, Bluetooth devices. * The system routing session is shared by apps such that controlling it will affect * all apps. */ @NonNull public List<RoutingSessionInfo> getActiveSessions() { Loading media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +6 −6 Original line number Diff line number Diff line Loading @@ -246,7 +246,7 @@ public class MediaRouterManagerTest { } }); assertEquals(0, mManager.getRoutingControllers(mPackageName).size()); assertEquals(1, mManager.getRoutingControllers(mPackageName).size()); mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)); latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); Loading @@ -254,14 +254,14 @@ public class MediaRouterManagerTest { List<MediaRouter2Manager.RoutingController> controllers = mManager.getRoutingControllers(mPackageName); assertEquals(1, controllers.size()); assertEquals(2, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(0); MediaRouter2Manager.RoutingController routingController = controllers.get(1); awaitOnRouteChangedManager( () -> routingController.release(), ROUTE_ID1, route -> TextUtils.equals(route.getClientPackageName(), null)); assertEquals(0, mManager.getRoutingControllers(mPackageName).size()); assertEquals(1, mManager.getRoutingControllers(mPackageName).size()); } /** Loading Loading @@ -290,8 +290,8 @@ public class MediaRouterManagerTest { List<MediaRouter2Manager.RoutingController> controllers = mManager.getRoutingControllers(mPackageName); assertEquals(1, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(0); assertEquals(2, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(1); awaitOnRouteChangedManager( () -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID5_TO_TRANSFER_TO)), Loading services/core/java/com/android/server/media/BluetoothRouteProvider.java +53 −4 Original line number Diff line number Diff line Loading @@ -29,12 +29,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.MediaRoute2Info; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.R; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; Loading @@ -59,7 +60,6 @@ class BluetoothRouteProvider { private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener(); // TODO: The mActiveDevice should be set when BluetoothRouteProvider is created. private BluetoothDevice mActiveDevice = null; static synchronized BluetoothRouteProvider getInstance(@NonNull Context context, Loading Loading @@ -104,6 +104,43 @@ class BluetoothRouteProvider { mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, null); } /** * Clears the active device for all known profiles. */ public void clearActiveDevices() { BluetoothA2dp a2dpProfile = mA2dpProfile; BluetoothHearingAid hearingAidProfile = mHearingAidProfile; if (a2dpProfile != null) { a2dpProfile.setActiveDevice(null); } if (hearingAidProfile != null) { hearingAidProfile.setActiveDevice(null); } } /** * Sets the active device. * @param deviceId the id of the Bluetooth device */ public void setActiveDevice(@NonNull String deviceId) { BluetoothRouteInfo btRouteInfo = mBluetoothRoutes.get(deviceId); if (btRouteInfo == null) { Slog.w(TAG, "setActiveDevice: unknown device id=" + deviceId); return; } BluetoothA2dp a2dpProfile = mA2dpProfile; BluetoothHearingAid hearingAidProfile = mHearingAidProfile; if (a2dpProfile != null && btRouteInfo.connectedProfiles.get(BluetoothProfile.A2DP, false)) { a2dpProfile.setActiveDevice(btRouteInfo.btDevice); } if (hearingAidProfile != null && btRouteInfo.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) { hearingAidProfile.setActiveDevice(btRouteInfo.btDevice); } } private void addEventReceiver(String action, BluetoothEventReceiver eventReceiver) { mEventReceiverMap.put(action, eventReceiver); mIntentFilter.addAction(action); Loading Loading @@ -157,12 +194,12 @@ class BluetoothRouteProvider { private void setRouteConnectionStateForDevice(BluetoothDevice device, @MediaRoute2Info.ConnectionState int state) { if (device == null) { Log.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null"); Slog.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null"); return; } BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); if (btRoute == null) { Log.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null"); Slog.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null"); return; } if (btRoute.route.getConnectionState() != state) { Loading @@ -184,24 +221,36 @@ class BluetoothRouteProvider { // These callbacks run on the main thread. private final class BluetoothProfileListener implements BluetoothProfile.ServiceListener { public void onServiceConnected(int profile, BluetoothProfile proxy) { List<BluetoothDevice> activeDevices; switch (profile) { case BluetoothProfile.A2DP: mA2dpProfile = (BluetoothA2dp) proxy; // It may contain null. activeDevices = Collections.singletonList(mA2dpProfile.getActiveDevice()); break; case BluetoothProfile.HEARING_AID: mHearingAidProfile = (BluetoothHearingAid) proxy; activeDevices = mHearingAidProfile.getActiveDevices(); break; default: return; } //TODO: Check a pair of HAP devices whether there exist two or more active devices. for (BluetoothDevice device : proxy.getConnectedDevices()) { BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); if (btRoute == null) { btRoute = createBluetoothRoute(device); mBluetoothRoutes.put(device.getAddress(), btRoute); } if (activeDevices.contains(device)) { mActiveDevice = device; setRouteConnectionStateForDevice(device, MediaRoute2Info.CONNECTION_STATE_CONNECTED); } btRoute.connectedProfiles.put(profile, true); } notifyBluetoothRoutesUpdated(); } public void onServiceDisconnected(int profile) { Loading services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +21 −25 Original line number Diff line number Diff line Loading @@ -760,17 +760,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::selectRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading @@ -783,17 +778,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "deselectClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "deslectClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::deselectRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading @@ -806,17 +796,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::transferToRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading Loading @@ -1166,7 +1151,7 @@ class MediaRouter2ServiceImpl { requestId, sessionHints); } private void selectRouteOnHandler(@NonNull Client2Record clientRecord, private void selectRouteOnHandler(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "selecting")) { Loading @@ -1182,7 +1167,7 @@ class MediaRouter2ServiceImpl { provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); } private void deselectRouteOnHandler(@NonNull Client2Record clientRecord, private void deselectRouteOnHandler(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "deselecting")) { Loading @@ -1198,7 +1183,7 @@ class MediaRouter2ServiceImpl { provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); } private void transferToRouteOnHandler(@NonNull Client2Record clientRecord, private void transferToRouteOnHandler(Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "transferring to")) { Loading @@ -1215,7 +1200,7 @@ class MediaRouter2ServiceImpl { route.getOriginalId()); } private boolean checkArgumentsForSessionControl(@NonNull Client2Record clientRecord, private boolean checkArgumentsForSessionControl(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route, @NonNull String description) { if (route == null) { Slog.w(TAG, "Ignoring " + description + " null route"); Loading @@ -1236,6 +1221,17 @@ class MediaRouter2ServiceImpl { return false; } // Bypass checking client if it's the system session (clientRecord should be null) if (TextUtils.equals(getProviderId(uniqueSessionId), mSystemProvider.getUniqueId())) { return true; } //TODO: Handle RCN case. if (clientRecord == null) { Slog.w(TAG, "Ignoring " + description + " route from unknown client."); return false; } Client2Record matchingRecord = mSessionToClientMap.get(uniqueSessionId); if (matchingRecord != clientRecord) { Slog.w(TAG, "Ignoring " + description + " route from non-matching client. " Loading services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +29 −18 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { SystemMediaRoute2Provider.class.getPackageName$(), SystemMediaRoute2Provider.class.getName()); //TODO: Clean up these when audio manager support multiple bt devices MediaRoute2Info mDefaultRoute; @NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); Loading @@ -91,6 +90,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); initializeDefaultRoute(); mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { mBluetoothRoutes = routes; publishRoutes(); Loading @@ -103,7 +103,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { notifySessionInfoUpdated(); } }); initializeRoutes(); initializeSessionInfo(); } @Override Loading @@ -119,17 +119,21 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { @Override public void selectRoute(String sessionId, String routeId) { //TODO: implement method // Do nothing since we don't support multiple BT yet. } @Override public void deselectRoute(String sessionId, String routeId) { //TODO: implement method // Do nothing since we don't support multiple BT yet. } @Override public void transferToRoute(String sessionId, String routeId) { //TODO: implement method if (TextUtils.equals(routeId, mDefaultRoute.getId())) { mBtRouteProvider.clearActiveDevices(); } else { mBtRouteProvider.setActiveDevice(routeId); } } //TODO: implement method Loading @@ -147,8 +151,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { public void requestUpdateVolume(String routeId, int delta) { } void initializeRoutes() { //TODO: adds necessary info private void initializeDefaultRoute() { mDefaultRoute = new MediaRoute2Info.Builder( DEFAULT_ROUTE_ID, mContext.getResources().getText(R.string.default_audio_route_name).toString()) Loading @@ -172,7 +175,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { // route yet. updateAudioRoutes(newAudioRoutes); } } private void initializeSessionInfo() { mBluetoothRoutes = mBtRouteProvider.getBluetoothRoutes(); MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); Loading @@ -183,11 +188,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { setProviderState(builder.build()); mHandler.post(() -> notifyProviderState()); // Note: No lock needed when initializing. //TODO: clean up this // This is required because it is not instantiated in the main thread and // BluetoothRoutesUpdatedListener can be called before this function synchronized (mLock) { updateSessionInfosIfNeededLocked(); } } void updateAudioRoutes(AudioRoutesInfo newRoutes) { private void updateAudioRoutes(AudioRoutesInfo newRoutes) { int name = R.string.default_audio_route_name; mCurAudioRoutesInfo.mainType = newRoutes.mainType; if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0 Loading Loading @@ -226,15 +235,22 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { .setSystemSession(true); String activeBtDeviceAddress = mBtRouteProvider.getActiveDeviceAddress(); RoutingSessionInfo newSessionInfo; if (!TextUtils.isEmpty(activeBtDeviceAddress)) { // Bluetooth route. Set the route ID with the device's address. newSessionInfo = builder.addSelectedRoute(activeBtDeviceAddress).build(); builder.addSelectedRoute(activeBtDeviceAddress); builder.addTransferrableRoute(mDefaultRoute.getId()); } else { // Default device newSessionInfo = builder.addSelectedRoute(mDefaultRoute.getId()).build(); builder.addSelectedRoute(mDefaultRoute.getId()); } for (MediaRoute2Info route : mBluetoothRoutes) { if (!TextUtils.equals(activeBtDeviceAddress, route.getId())) { builder.addTransferrableRoute(route.getId()); } } RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build(); if (Objects.equals(oldSessionInfo, newSessionInfo)) { return false; } else { Loading @@ -244,11 +260,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } } /** * The first route should be the currently selected system route. * For example, if there are two system routes (BT and device speaker), * BT will be the first route in the list. */ void publishRoutes() { MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); builder.addRoute(mDefaultRoute); Loading Loading
media/java/android/media/MediaRouter2Manager.java +10 −5 Original line number Diff line number Diff line Loading @@ -178,8 +178,9 @@ public class MediaRouter2Manager { /** * Gets routing controllers of an application with the given package name. * If the application isn't running or it doesn't use {@link MediaRouter2}, an empty list * will be returned. * The first element of the returned list is the system routing controller. * * @see MediaRouter2#getSystemController() */ @NonNull public List<RoutingController> getRoutingControllers(@NonNull String packageName) { Loading @@ -188,7 +189,8 @@ public class MediaRouter2Manager { List<RoutingController> controllers = new ArrayList<>(); for (RoutingSessionInfo sessionInfo : getActiveSessions()) { if (TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) { if (sessionInfo.isSystemSession() || TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) { controllers.add(new RoutingController(sessionInfo)); } } Loading @@ -196,8 +198,11 @@ public class MediaRouter2Manager { } /** * Gets the list of all active routing sessions. It doesn't include default routing sessions * of applications. * Gets the list of all active routing sessions. * The first element of the list is the system routing session containing * phone speakers, wired headset, Bluetooth devices. * The system routing session is shared by apps such that controlling it will affect * all apps. */ @NonNull public List<RoutingSessionInfo> getActiveSessions() { Loading
media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +6 −6 Original line number Diff line number Diff line Loading @@ -246,7 +246,7 @@ public class MediaRouterManagerTest { } }); assertEquals(0, mManager.getRoutingControllers(mPackageName).size()); assertEquals(1, mManager.getRoutingControllers(mPackageName).size()); mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)); latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); Loading @@ -254,14 +254,14 @@ public class MediaRouterManagerTest { List<MediaRouter2Manager.RoutingController> controllers = mManager.getRoutingControllers(mPackageName); assertEquals(1, controllers.size()); assertEquals(2, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(0); MediaRouter2Manager.RoutingController routingController = controllers.get(1); awaitOnRouteChangedManager( () -> routingController.release(), ROUTE_ID1, route -> TextUtils.equals(route.getClientPackageName(), null)); assertEquals(0, mManager.getRoutingControllers(mPackageName).size()); assertEquals(1, mManager.getRoutingControllers(mPackageName).size()); } /** Loading Loading @@ -290,8 +290,8 @@ public class MediaRouterManagerTest { List<MediaRouter2Manager.RoutingController> controllers = mManager.getRoutingControllers(mPackageName); assertEquals(1, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(0); assertEquals(2, controllers.size()); MediaRouter2Manager.RoutingController routingController = controllers.get(1); awaitOnRouteChangedManager( () -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID5_TO_TRANSFER_TO)), Loading
services/core/java/com/android/server/media/BluetoothRouteProvider.java +53 −4 Original line number Diff line number Diff line Loading @@ -29,12 +29,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.MediaRoute2Info; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.R; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; Loading @@ -59,7 +60,6 @@ class BluetoothRouteProvider { private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener(); // TODO: The mActiveDevice should be set when BluetoothRouteProvider is created. private BluetoothDevice mActiveDevice = null; static synchronized BluetoothRouteProvider getInstance(@NonNull Context context, Loading Loading @@ -104,6 +104,43 @@ class BluetoothRouteProvider { mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, null); } /** * Clears the active device for all known profiles. */ public void clearActiveDevices() { BluetoothA2dp a2dpProfile = mA2dpProfile; BluetoothHearingAid hearingAidProfile = mHearingAidProfile; if (a2dpProfile != null) { a2dpProfile.setActiveDevice(null); } if (hearingAidProfile != null) { hearingAidProfile.setActiveDevice(null); } } /** * Sets the active device. * @param deviceId the id of the Bluetooth device */ public void setActiveDevice(@NonNull String deviceId) { BluetoothRouteInfo btRouteInfo = mBluetoothRoutes.get(deviceId); if (btRouteInfo == null) { Slog.w(TAG, "setActiveDevice: unknown device id=" + deviceId); return; } BluetoothA2dp a2dpProfile = mA2dpProfile; BluetoothHearingAid hearingAidProfile = mHearingAidProfile; if (a2dpProfile != null && btRouteInfo.connectedProfiles.get(BluetoothProfile.A2DP, false)) { a2dpProfile.setActiveDevice(btRouteInfo.btDevice); } if (hearingAidProfile != null && btRouteInfo.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) { hearingAidProfile.setActiveDevice(btRouteInfo.btDevice); } } private void addEventReceiver(String action, BluetoothEventReceiver eventReceiver) { mEventReceiverMap.put(action, eventReceiver); mIntentFilter.addAction(action); Loading Loading @@ -157,12 +194,12 @@ class BluetoothRouteProvider { private void setRouteConnectionStateForDevice(BluetoothDevice device, @MediaRoute2Info.ConnectionState int state) { if (device == null) { Log.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null"); Slog.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null"); return; } BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); if (btRoute == null) { Log.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null"); Slog.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null"); return; } if (btRoute.route.getConnectionState() != state) { Loading @@ -184,24 +221,36 @@ class BluetoothRouteProvider { // These callbacks run on the main thread. private final class BluetoothProfileListener implements BluetoothProfile.ServiceListener { public void onServiceConnected(int profile, BluetoothProfile proxy) { List<BluetoothDevice> activeDevices; switch (profile) { case BluetoothProfile.A2DP: mA2dpProfile = (BluetoothA2dp) proxy; // It may contain null. activeDevices = Collections.singletonList(mA2dpProfile.getActiveDevice()); break; case BluetoothProfile.HEARING_AID: mHearingAidProfile = (BluetoothHearingAid) proxy; activeDevices = mHearingAidProfile.getActiveDevices(); break; default: return; } //TODO: Check a pair of HAP devices whether there exist two or more active devices. for (BluetoothDevice device : proxy.getConnectedDevices()) { BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress()); if (btRoute == null) { btRoute = createBluetoothRoute(device); mBluetoothRoutes.put(device.getAddress(), btRoute); } if (activeDevices.contains(device)) { mActiveDevice = device; setRouteConnectionStateForDevice(device, MediaRoute2Info.CONNECTION_STATE_CONNECTED); } btRoute.connectedProfiles.put(profile, true); } notifyBluetoothRoutesUpdated(); } public void onServiceDisconnected(int profile) { Loading
services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +21 −25 Original line number Diff line number Diff line Loading @@ -760,17 +760,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::selectRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading @@ -783,17 +778,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "deselectClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "deslectClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::deselectRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading @@ -806,17 +796,12 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown manager."); return; } //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?) Client2Record clientRecord = managerRecord.mUserRecord.mHandler .findClientforSessionLocked(sessionId); if (clientRecord == null) { Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown session."); return; } clientRecord.mUserRecord.mHandler.sendMessage( managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::transferToRouteOnHandler, clientRecord.mUserRecord.mHandler, managerRecord.mUserRecord.mHandler, clientRecord, sessionId, route)); } Loading Loading @@ -1166,7 +1151,7 @@ class MediaRouter2ServiceImpl { requestId, sessionHints); } private void selectRouteOnHandler(@NonNull Client2Record clientRecord, private void selectRouteOnHandler(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "selecting")) { Loading @@ -1182,7 +1167,7 @@ class MediaRouter2ServiceImpl { provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); } private void deselectRouteOnHandler(@NonNull Client2Record clientRecord, private void deselectRouteOnHandler(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "deselecting")) { Loading @@ -1198,7 +1183,7 @@ class MediaRouter2ServiceImpl { provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); } private void transferToRouteOnHandler(@NonNull Client2Record clientRecord, private void transferToRouteOnHandler(Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route) { if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route, "transferring to")) { Loading @@ -1215,7 +1200,7 @@ class MediaRouter2ServiceImpl { route.getOriginalId()); } private boolean checkArgumentsForSessionControl(@NonNull Client2Record clientRecord, private boolean checkArgumentsForSessionControl(@Nullable Client2Record clientRecord, String uniqueSessionId, MediaRoute2Info route, @NonNull String description) { if (route == null) { Slog.w(TAG, "Ignoring " + description + " null route"); Loading @@ -1236,6 +1221,17 @@ class MediaRouter2ServiceImpl { return false; } // Bypass checking client if it's the system session (clientRecord should be null) if (TextUtils.equals(getProviderId(uniqueSessionId), mSystemProvider.getUniqueId())) { return true; } //TODO: Handle RCN case. if (clientRecord == null) { Slog.w(TAG, "Ignoring " + description + " route from unknown client."); return false; } Client2Record matchingRecord = mSessionToClientMap.get(uniqueSessionId); if (matchingRecord != clientRecord) { Slog.w(TAG, "Ignoring " + description + " route from non-matching client. " Loading
services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +29 −18 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { SystemMediaRoute2Provider.class.getPackageName$(), SystemMediaRoute2Provider.class.getName()); //TODO: Clean up these when audio manager support multiple bt devices MediaRoute2Info mDefaultRoute; @NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST; final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); Loading @@ -91,6 +90,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); initializeDefaultRoute(); mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { mBluetoothRoutes = routes; publishRoutes(); Loading @@ -103,7 +103,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { notifySessionInfoUpdated(); } }); initializeRoutes(); initializeSessionInfo(); } @Override Loading @@ -119,17 +119,21 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { @Override public void selectRoute(String sessionId, String routeId) { //TODO: implement method // Do nothing since we don't support multiple BT yet. } @Override public void deselectRoute(String sessionId, String routeId) { //TODO: implement method // Do nothing since we don't support multiple BT yet. } @Override public void transferToRoute(String sessionId, String routeId) { //TODO: implement method if (TextUtils.equals(routeId, mDefaultRoute.getId())) { mBtRouteProvider.clearActiveDevices(); } else { mBtRouteProvider.setActiveDevice(routeId); } } //TODO: implement method Loading @@ -147,8 +151,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { public void requestUpdateVolume(String routeId, int delta) { } void initializeRoutes() { //TODO: adds necessary info private void initializeDefaultRoute() { mDefaultRoute = new MediaRoute2Info.Builder( DEFAULT_ROUTE_ID, mContext.getResources().getText(R.string.default_audio_route_name).toString()) Loading @@ -172,7 +175,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { // route yet. updateAudioRoutes(newAudioRoutes); } } private void initializeSessionInfo() { mBluetoothRoutes = mBtRouteProvider.getBluetoothRoutes(); MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); Loading @@ -183,11 +188,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { setProviderState(builder.build()); mHandler.post(() -> notifyProviderState()); // Note: No lock needed when initializing. //TODO: clean up this // This is required because it is not instantiated in the main thread and // BluetoothRoutesUpdatedListener can be called before this function synchronized (mLock) { updateSessionInfosIfNeededLocked(); } } void updateAudioRoutes(AudioRoutesInfo newRoutes) { private void updateAudioRoutes(AudioRoutesInfo newRoutes) { int name = R.string.default_audio_route_name; mCurAudioRoutesInfo.mainType = newRoutes.mainType; if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0 Loading Loading @@ -226,15 +235,22 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { .setSystemSession(true); String activeBtDeviceAddress = mBtRouteProvider.getActiveDeviceAddress(); RoutingSessionInfo newSessionInfo; if (!TextUtils.isEmpty(activeBtDeviceAddress)) { // Bluetooth route. Set the route ID with the device's address. newSessionInfo = builder.addSelectedRoute(activeBtDeviceAddress).build(); builder.addSelectedRoute(activeBtDeviceAddress); builder.addTransferrableRoute(mDefaultRoute.getId()); } else { // Default device newSessionInfo = builder.addSelectedRoute(mDefaultRoute.getId()).build(); builder.addSelectedRoute(mDefaultRoute.getId()); } for (MediaRoute2Info route : mBluetoothRoutes) { if (!TextUtils.equals(activeBtDeviceAddress, route.getId())) { builder.addTransferrableRoute(route.getId()); } } RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build(); if (Objects.equals(oldSessionInfo, newSessionInfo)) { return false; } else { Loading @@ -244,11 +260,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } } /** * The first route should be the currently selected system route. * For example, if there are two system routes (BT and device speaker), * BT will be the first route in the list. */ void publishRoutes() { MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); builder.addRoute(mDefaultRoute); Loading