Loading media/java/android/media/flags/media_better_together.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,16 @@ flag { bug: "275185436" } flag { name: "clean_up_dead_router_records_after_unbinding" namespace: "media_better_together" description: "Fixes a bug of notifying unbound router records that causes DeadObjectException." bug: "414836668" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "disable_set_bluetooth_ad2p_on_calls" namespace: "media_better_together" Loading services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +84 −13 Original line number Diff line number Diff line Loading @@ -1295,7 +1295,7 @@ class MediaRouter2ServiceImpl { throw new RuntimeException("MediaRouter2 died prematurely.", ex); } userRecord.mRouterRecords.add(routerRecord); userRecord.addRouterRecord(routerRecord); mAllRouterRecords.put(binder, routerRecord); userRecord.mHandler.sendMessage( Loading Loading @@ -1328,11 +1328,10 @@ class MediaRouter2ServiceImpl { Slog.i( TAG, TextUtils.formatSimple( "unregisterRouter2 | package: %s, router id: %d, died: %b", routerRecord.mPackageName, routerRecord.mRouterId, died)); "unregisterRouter2 | %s, died: %b", routerRecord.getDebugString(), died)); UserRecord userRecord = routerRecord.mUserRecord; userRecord.mRouterRecords.remove(routerRecord); userRecord.removeRouterRecord(routerRecord); routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers, routerRecord.mUserRecord.mHandler, Loading Loading @@ -1899,11 +1898,8 @@ class MediaRouter2ServiceImpl { Slog.i( TAG, TextUtils.formatSimple( "unregisterManager | package: %s, user: %d, manager: %d, died: %b", managerRecord.mOwnerPackageName, userRecord.mUserId, managerRecord.mManagerId, died)); "unregisterManager | %s, user: %d, died: %b", managerRecord.getDebugString(), userRecord.mUserId, died)); userRecord.mManagerRecords.remove(managerRecord); managerRecord.dispose(); Loading Loading @@ -2330,7 +2326,7 @@ class MediaRouter2ServiceImpl { final class UserRecord { public final int mUserId; //TODO: make records private for thread-safety final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>(); private final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>(); final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>(); // @GuardedBy("mLock") Loading @@ -2354,6 +2350,17 @@ class MediaRouter2ServiceImpl { mHandler.init(); } void addRouterRecord(RouterRecord routerRecord) { mRouterRecords.add(routerRecord); } void removeRouterRecord(RouterRecord routerRecord) { mRouterRecords.remove(routerRecord); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding()) { mHandler.removeRouterRecord(routerRecord); } } // TODO: This assumes that only one router exists in a package. // Do this in Android S or later. @GuardedBy("mLock") Loading @@ -2366,6 +2373,16 @@ class MediaRouter2ServiceImpl { return null; } /** Returns true if the given RouterRecord is binded to the service. */ boolean isRouterRecordBinded(RouterRecord routerRecordToCheck) { for (RouterRecord routerRecord : mRouterRecords) { if (routerRecord.mRouterId == routerRecordToCheck.mRouterId) { return true; } } return false; } // @GuardedBy("mLock") public void updateDeviceSuggestionsLocked( String packageName, Loading Loading @@ -3046,6 +3063,12 @@ class MediaRouter2ServiceImpl { @Override public void onSessionCreated(@NonNull MediaRoute2Provider provider, long uniqueRequestId, @NonNull RoutingSessionInfo sessionInfo) { Slog.i( TAG, "onSessionCreated with uniqueRequestId: " + uniqueRequestId + ", sessionInfo: " + sessionInfo); sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreatedOnHandler, this, provider, uniqueRequestId, sessionInfo)); } Loading Loading @@ -3112,6 +3135,24 @@ class MediaRouter2ServiceImpl { } } public void removeRouterRecord(RouterRecord routerRecord) { for (String sessionId : mSessionToRouterMap.keySet()) { RouterRecord routerRecordWithSession = mSessionToRouterMap.get(sessionId); if (routerRecordWithSession.mRouterId == routerRecord.mRouterId) { // Release the session associated with the RouterRecord being removed. The // onSessionReleasedOnHandler callback will then remove the RouterRecord from // mSessionToRouterMap. sendMessage( PooledLambda.obtainMessage( UserHandler::releaseSessionOnHandler, this, DUMMY_REQUEST_ID, routerRecordWithSession, sessionId)); } } } public void dump(@NonNull PrintWriter pw, @NonNull String prefix) { pw.println(prefix + "UserHandler"); Loading Loading @@ -3580,6 +3621,16 @@ class MediaRouter2ServiceImpl { } mSessionCreationRequests.remove(matchingRequest); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding() && !mUserRecord.isRouterRecordBinded(matchingRequest.mRouterRecord)) { Slog.w( TAG, "Ignoring session creation request for unbound router:" + matchingRequest.mRouterRecord.getDebugString()); return; } // Not to show old session MediaRoute2Provider oldProvider = findProvider(matchingRequest.mOldSession.getProviderId()); Loading Loading @@ -3650,8 +3701,11 @@ class MediaRouter2ServiceImpl { + sessionInfo); return; } if (!Flags.cleanUpDeadRouterRecordsAfterUnbinding() || mUserRecord.isRouterRecordBinded(routerRecord)) { notifySessionInfoChangedToRouters(Arrays.asList(routerRecord), sessionInfo); } } private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider, @NonNull RoutingSessionInfo sessionInfo) { Loading @@ -3666,8 +3720,16 @@ class MediaRouter2ServiceImpl { + sessionInfo); return; } if (Flags.cleanUpDeadRouterRecordsAfterUnbinding()) { if (mUserRecord.isRouterRecordBinded(routerRecord)) { routerRecord.notifySessionReleased(sessionInfo); } mSessionToRouterMap.remove(sessionInfo.getId()); } else { routerRecord.notifySessionReleased(sessionInfo); } } private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider, long uniqueRequestId, int reason) { Loading Loading @@ -3721,6 +3783,15 @@ class MediaRouter2ServiceImpl { mSessionCreationRequests.remove(matchingRequest); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding() && !mUserRecord.isRouterRecordBinded(matchingRequest.mRouterRecord)) { Slog.w( TAG, "handleSessionCreationRequestFailed | Ignoring with unbound router:" + matchingRequest.mRouterRecord.getDebugString()); return false; } // Notify the requester about the failure. // The call should be made by either MediaRouter2 or MediaRouter2Manager. if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) { Loading Loading @@ -3894,7 +3965,7 @@ class MediaRouter2ServiceImpl { } catch (RemoteException ex) { Slog.w( TAG, "Failed to notify preferred features changed." "Failed to notify route listing preference changed." + " Manager probably died.", ex); } Loading Loading
media/java/android/media/flags/media_better_together.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,16 @@ flag { bug: "275185436" } flag { name: "clean_up_dead_router_records_after_unbinding" namespace: "media_better_together" description: "Fixes a bug of notifying unbound router records that causes DeadObjectException." bug: "414836668" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "disable_set_bluetooth_ad2p_on_calls" namespace: "media_better_together" Loading
services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +84 −13 Original line number Diff line number Diff line Loading @@ -1295,7 +1295,7 @@ class MediaRouter2ServiceImpl { throw new RuntimeException("MediaRouter2 died prematurely.", ex); } userRecord.mRouterRecords.add(routerRecord); userRecord.addRouterRecord(routerRecord); mAllRouterRecords.put(binder, routerRecord); userRecord.mHandler.sendMessage( Loading Loading @@ -1328,11 +1328,10 @@ class MediaRouter2ServiceImpl { Slog.i( TAG, TextUtils.formatSimple( "unregisterRouter2 | package: %s, router id: %d, died: %b", routerRecord.mPackageName, routerRecord.mRouterId, died)); "unregisterRouter2 | %s, died: %b", routerRecord.getDebugString(), died)); UserRecord userRecord = routerRecord.mUserRecord; userRecord.mRouterRecords.remove(routerRecord); userRecord.removeRouterRecord(routerRecord); routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers, routerRecord.mUserRecord.mHandler, Loading Loading @@ -1899,11 +1898,8 @@ class MediaRouter2ServiceImpl { Slog.i( TAG, TextUtils.formatSimple( "unregisterManager | package: %s, user: %d, manager: %d, died: %b", managerRecord.mOwnerPackageName, userRecord.mUserId, managerRecord.mManagerId, died)); "unregisterManager | %s, user: %d, died: %b", managerRecord.getDebugString(), userRecord.mUserId, died)); userRecord.mManagerRecords.remove(managerRecord); managerRecord.dispose(); Loading Loading @@ -2330,7 +2326,7 @@ class MediaRouter2ServiceImpl { final class UserRecord { public final int mUserId; //TODO: make records private for thread-safety final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>(); private final ArrayList<RouterRecord> mRouterRecords = new ArrayList<>(); final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>(); // @GuardedBy("mLock") Loading @@ -2354,6 +2350,17 @@ class MediaRouter2ServiceImpl { mHandler.init(); } void addRouterRecord(RouterRecord routerRecord) { mRouterRecords.add(routerRecord); } void removeRouterRecord(RouterRecord routerRecord) { mRouterRecords.remove(routerRecord); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding()) { mHandler.removeRouterRecord(routerRecord); } } // TODO: This assumes that only one router exists in a package. // Do this in Android S or later. @GuardedBy("mLock") Loading @@ -2366,6 +2373,16 @@ class MediaRouter2ServiceImpl { return null; } /** Returns true if the given RouterRecord is binded to the service. */ boolean isRouterRecordBinded(RouterRecord routerRecordToCheck) { for (RouterRecord routerRecord : mRouterRecords) { if (routerRecord.mRouterId == routerRecordToCheck.mRouterId) { return true; } } return false; } // @GuardedBy("mLock") public void updateDeviceSuggestionsLocked( String packageName, Loading Loading @@ -3046,6 +3063,12 @@ class MediaRouter2ServiceImpl { @Override public void onSessionCreated(@NonNull MediaRoute2Provider provider, long uniqueRequestId, @NonNull RoutingSessionInfo sessionInfo) { Slog.i( TAG, "onSessionCreated with uniqueRequestId: " + uniqueRequestId + ", sessionInfo: " + sessionInfo); sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreatedOnHandler, this, provider, uniqueRequestId, sessionInfo)); } Loading Loading @@ -3112,6 +3135,24 @@ class MediaRouter2ServiceImpl { } } public void removeRouterRecord(RouterRecord routerRecord) { for (String sessionId : mSessionToRouterMap.keySet()) { RouterRecord routerRecordWithSession = mSessionToRouterMap.get(sessionId); if (routerRecordWithSession.mRouterId == routerRecord.mRouterId) { // Release the session associated with the RouterRecord being removed. The // onSessionReleasedOnHandler callback will then remove the RouterRecord from // mSessionToRouterMap. sendMessage( PooledLambda.obtainMessage( UserHandler::releaseSessionOnHandler, this, DUMMY_REQUEST_ID, routerRecordWithSession, sessionId)); } } } public void dump(@NonNull PrintWriter pw, @NonNull String prefix) { pw.println(prefix + "UserHandler"); Loading Loading @@ -3580,6 +3621,16 @@ class MediaRouter2ServiceImpl { } mSessionCreationRequests.remove(matchingRequest); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding() && !mUserRecord.isRouterRecordBinded(matchingRequest.mRouterRecord)) { Slog.w( TAG, "Ignoring session creation request for unbound router:" + matchingRequest.mRouterRecord.getDebugString()); return; } // Not to show old session MediaRoute2Provider oldProvider = findProvider(matchingRequest.mOldSession.getProviderId()); Loading Loading @@ -3650,8 +3701,11 @@ class MediaRouter2ServiceImpl { + sessionInfo); return; } if (!Flags.cleanUpDeadRouterRecordsAfterUnbinding() || mUserRecord.isRouterRecordBinded(routerRecord)) { notifySessionInfoChangedToRouters(Arrays.asList(routerRecord), sessionInfo); } } private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider, @NonNull RoutingSessionInfo sessionInfo) { Loading @@ -3666,8 +3720,16 @@ class MediaRouter2ServiceImpl { + sessionInfo); return; } if (Flags.cleanUpDeadRouterRecordsAfterUnbinding()) { if (mUserRecord.isRouterRecordBinded(routerRecord)) { routerRecord.notifySessionReleased(sessionInfo); } mSessionToRouterMap.remove(sessionInfo.getId()); } else { routerRecord.notifySessionReleased(sessionInfo); } } private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider, long uniqueRequestId, int reason) { Loading Loading @@ -3721,6 +3783,15 @@ class MediaRouter2ServiceImpl { mSessionCreationRequests.remove(matchingRequest); if (Flags.cleanUpDeadRouterRecordsAfterUnbinding() && !mUserRecord.isRouterRecordBinded(matchingRequest.mRouterRecord)) { Slog.w( TAG, "handleSessionCreationRequestFailed | Ignoring with unbound router:" + matchingRequest.mRouterRecord.getDebugString()); return false; } // Notify the requester about the failure. // The call should be made by either MediaRouter2 or MediaRouter2Manager. if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) { Loading Loading @@ -3894,7 +3965,7 @@ class MediaRouter2ServiceImpl { } catch (RemoteException ex) { Slog.w( TAG, "Failed to notify preferred features changed." "Failed to notify route listing preference changed." + " Manager probably died.", ex); } Loading