Loading media/java/android/media/RoutingChangeInfo.java +72 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ public final class RoutingChangeInfo implements Parcelable { // Indicates that the route was a suggested route. private final boolean mIsSuggested; // Indicates the suggestion providers for a route. private final @SuggestionProviderFlags int mSuggestionProviderFlags; /** * Indicates that a routing session started as the result of selecting a route from the output * switcher. Loading Loading @@ -97,6 +100,40 @@ public final class RoutingChangeInfo implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface EntryPoint {} /** * Flag indicating that the route was suggested by {@link RouteListingPreference}. * * @hide */ public static final int SUGGESTION_PROVIDER_RLP = 1; /** * Flag indicating that the route was suggested by the app as a device suggestion. * * @hide */ public static final int SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP = 1 << 1; /** * Flag indicating that the route was suggested as a device suggestion by an app not playing the * media. * * @hide */ public static final int SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER = 1 << 2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "SUGGESTION_PROVIDER", flag = true, value = { SUGGESTION_PROVIDER_RLP, SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP, SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER }) public @interface SuggestionProviderFlags {} @NonNull public static final Creator<RoutingChangeInfo> CREATOR = new Creator<>() { Loading @@ -112,13 +149,22 @@ public final class RoutingChangeInfo implements Parcelable { }; public RoutingChangeInfo(@EntryPoint int entryPoint, boolean isSuggested) { this(entryPoint, isSuggested, /* suggestionProviderFlags= */ 0); } public RoutingChangeInfo( @EntryPoint int entryPoint, boolean isSuggested, @SuggestionProviderFlags int suggestionProviderFlags) { mEntryPoint = entryPoint; mIsSuggested = isSuggested; mSuggestionProviderFlags = suggestionProviderFlags; } private RoutingChangeInfo(Parcel in) { mEntryPoint = in.readInt(); mIsSuggested = in.readBoolean(); mSuggestionProviderFlags = in.readInt(); } @Override Loading @@ -130,6 +176,7 @@ public final class RoutingChangeInfo implements Parcelable { public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) { dest.writeInt(mEntryPoint); dest.writeBoolean(mIsSuggested); dest.writeInt(mSuggestionProviderFlags); } @Override Loading @@ -146,13 +193,14 @@ public final class RoutingChangeInfo implements Parcelable { return true; } return other.getEntryPoint() == this.getEntryPoint() && other.isSuggested() == this.mIsSuggested; return other.getEntryPoint() == this.mEntryPoint && other.isSuggested() == this.mIsSuggested && other.mSuggestionProviderFlags == this.mSuggestionProviderFlags; } @Override public int hashCode() { return Objects.hash(mEntryPoint, mIsSuggested); return Objects.hash(mEntryPoint, mIsSuggested, mSuggestionProviderFlags); } public @EntryPoint int getEntryPoint() { Loading @@ -162,4 +210,25 @@ public final class RoutingChangeInfo implements Parcelable { public boolean isSuggested() { return mIsSuggested; } public @SuggestionProviderFlags int getSuggestionProviderFlags() { return mSuggestionProviderFlags; } /** * Returns whether the route had an active suggestion from the active route listing preference. */ public boolean isSuggestedByRlp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_RLP) != 0; } /** Returns whether the route had an active device suggestion from the media app. */ public boolean isSuggestedByMediaApp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP) != 0; } /** Whether the route had an active device suggestion from an app other than the media app. */ public boolean isSuggestedByAnotherApp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER) != 0; } } services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +53 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ import static android.media.MediaRouter2.SCANNING_STATE_SCANNING_FULL; import static android.media.MediaRouter2.SCANNING_STATE_WHILE_INTERACTIVE; import static android.media.MediaRouter2Utils.getOriginalId; import static android.media.MediaRouter2Utils.getProviderId; import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_RLP; import static android.media.RoutingChangeInfo.SuggestionProviderFlags; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.media.MediaRouterMetricLogger.EVENT_TYPE_CREATE_SESSION; Loading Loading @@ -1629,9 +1634,16 @@ class MediaRouter2ServiceImpl { } long uniqueRequestId = toUniqueRequestId(routerRecord.mRouterId, requestId); @SuggestionProviderFlags int suggestionProviderFlags = getSuggestionProviderFlags(routerRecord, route); RoutingChangeInfo updatedInfo = new RoutingChangeInfo( routingChangeInfo.getEntryPoint(), routingChangeInfo.isSuggested(), suggestionProviderFlags); mMediaRouterMetricLogger.addRequestInfo( uniqueRequestId, EVENT_TYPE_CREATE_SESSION, routingChangeInfo); mMediaRouterMetricLogger.notifyRoutingChangeRequested(uniqueRequestId, routingChangeInfo); uniqueRequestId, EVENT_TYPE_CREATE_SESSION, updatedInfo); mMediaRouterMetricLogger.notifyRoutingChangeRequested(uniqueRequestId, updatedInfo); userHandler.sendMessage( obtainMessage( UserHandler::requestCreateSessionWithRouter2OnHandler, Loading Loading @@ -2465,6 +2477,45 @@ class MediaRouter2ServiceImpl { } } private static @SuggestionProviderFlags int getSuggestionProviderFlags( RouterRecord routerRecord, MediaRoute2Info mediaRoute2Info) { String routeId = mediaRoute2Info.getId(); int result = 0; if (routerRecord.mRouteListingPreference != null) { List<RouteListingPreference.Item> routeListingPreferenceItems = routerRecord.mRouteListingPreference.getItems(); if (routeListingPreferenceItems.stream() .anyMatch( item -> (item.getRouteId().equals(routeId)) && (item.getFlags() & FLAG_SUGGESTED) != 0)) { result |= SUGGESTION_PROVIDER_RLP; } } Map<String, List<SuggestedDeviceInfo>> suggestionsMap = routerRecord.mDeviceSuggestions; List<SuggestedDeviceInfo> suggestionsByApp = suggestionsMap.get(routerRecord.mPackageName); if (suggestionsByApp != null && suggestionsByApp.stream() .anyMatch( suggestedDeviceInfo -> suggestedDeviceInfo.getRouteId().equals(routeId))) { result |= SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP; } if (suggestionsMap.entrySet().stream() .filter(entry -> !entry.getKey().equals(routerRecord.mPackageName)) .anyMatch( entry -> entry.getValue().stream() .anyMatch( suggestedDeviceInfo -> suggestedDeviceInfo .getRouteId() .equals(routeId)))) { result |= SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER; } return result; } /** Invoked when {@link MediaRouterService#systemRunning()} is invoked. */ /* package */ void systemRunning() { sInstance.set(this); Loading services/core/java/com/android/server/media/MediaRouterMetricLogger.java +36 −3 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Map; /** Loading Loading @@ -314,6 +315,9 @@ final class MediaRouterMetricLogger { routingSessionInfo.isSystemSession(), routingSessionInfo.getTransferReason(), routingChangeInfo.isSuggested(), routingChangeInfo.isSuggestedByRlp(), routingChangeInfo.isSuggestedByMediaApp(), routingChangeInfo.isSuggestedByAnotherApp(), getElapsedRealTime()); mOngoingRoutingChangeCache.put(routingSessionInfo.getOriginalId(), ongoingRoutingChange); mRoutingChangeInfoCache.remove(uniqueRequestId); Loading @@ -338,12 +342,13 @@ final class MediaRouterMetricLogger { TextUtils.formatSimple( "notifySessionEnd | EntryPoint: %d, ClientPackageUid: %d," + " IsSystemSession: %b, TransferReason: %d, IsSuggested: %b," + " SessionLengthInMillis: %d", + " SuggestionProviders: %s, SessionLengthInMillis: %d", ongoingRoutingChange.entryPoint, ongoingRoutingChange.clientPackageUid, ongoingRoutingChange.isSystemSession, ongoingRoutingChange.transferReason, ongoingRoutingChange.isSuggested, ongoingRoutingChange.getSuggestionProvidersDebugString(), sessionLengthInMillis)); } Loading @@ -354,7 +359,10 @@ final class MediaRouterMetricLogger { ongoingRoutingChange.isSystemSession, convertTransferReasonForLogging(ongoingRoutingChange.transferReason), ongoingRoutingChange.isSuggested, sessionLengthInMillis); sessionLengthInMillis, ongoingRoutingChange.isSuggestedByRlp, ongoingRoutingChange.isSuggestedByMediaApp, ongoingRoutingChange.isSuggestedByAnotherApp); mOngoingRoutingChangeCache.remove(sessionId); } Loading Loading @@ -745,7 +753,32 @@ final class MediaRouterMetricLogger { boolean isSystemSession, @TransferReason int transferReason, boolean isSuggested, long startTimeInMillis) {} boolean isSuggestedByRlp, boolean isSuggestedByMediaApp, boolean isSuggestedByAnotherApp, long startTimeInMillis) { /** * Returns a human-readable representation of the suggestion provider for logging purposes. */ public String getSuggestionProvidersDebugString() { var providerStrings = new ArrayList<String>(); if (isSuggestedByRlp) { providerStrings.add("RLP"); } if (isSuggestedByMediaApp) { providerStrings.add("MEDIA_APP"); } if (isSuggestedByAnotherApp) { providerStrings.add("ANOTHER_APP"); } if (providerStrings.isEmpty()) { return "NONE"; } else { return String.join("|", providerStrings); } } } /** Tracks the count of changes in route listing preference */ private record RlpCount(long rlpTotalCount, long rlpWithSuggestionCount) {} Loading services/tests/media/mediarouterservicetest/src/com/android/server/media/MediaRouterMetricLoggerTest.java +8 −2 Original line number Diff line number Diff line Loading @@ -402,7 +402,10 @@ public class MediaRouterMetricLoggerTest { anyBoolean(), anyInt(), anyBoolean(), anyLong()), anyLong(), anyBoolean(), anyBoolean(), anyBoolean()), never()); } Loading Loading @@ -449,7 +452,10 @@ public class MediaRouterMetricLoggerTest { eq( ROUTING_CHANGE_REPORTED__TRANSFER_REASON__TRANSFER_REASON_SYSTEM_REQUEST), eq(/* isSuggested= */ false), sessionLengthCaptor.capture())); sessionLengthCaptor.capture(), eq(/* isSuggestedByRlp= */ false), eq(/* isSuggestedByMediaApp= */ false), eq(/* isSuggestedByOtherApp= */ false))); assertThat(sessionLengthCaptor.getValue()).isEqualTo(sessionTimeInMillis); } Loading Loading
media/java/android/media/RoutingChangeInfo.java +72 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ public final class RoutingChangeInfo implements Parcelable { // Indicates that the route was a suggested route. private final boolean mIsSuggested; // Indicates the suggestion providers for a route. private final @SuggestionProviderFlags int mSuggestionProviderFlags; /** * Indicates that a routing session started as the result of selecting a route from the output * switcher. Loading Loading @@ -97,6 +100,40 @@ public final class RoutingChangeInfo implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface EntryPoint {} /** * Flag indicating that the route was suggested by {@link RouteListingPreference}. * * @hide */ public static final int SUGGESTION_PROVIDER_RLP = 1; /** * Flag indicating that the route was suggested by the app as a device suggestion. * * @hide */ public static final int SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP = 1 << 1; /** * Flag indicating that the route was suggested as a device suggestion by an app not playing the * media. * * @hide */ public static final int SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER = 1 << 2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "SUGGESTION_PROVIDER", flag = true, value = { SUGGESTION_PROVIDER_RLP, SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP, SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER }) public @interface SuggestionProviderFlags {} @NonNull public static final Creator<RoutingChangeInfo> CREATOR = new Creator<>() { Loading @@ -112,13 +149,22 @@ public final class RoutingChangeInfo implements Parcelable { }; public RoutingChangeInfo(@EntryPoint int entryPoint, boolean isSuggested) { this(entryPoint, isSuggested, /* suggestionProviderFlags= */ 0); } public RoutingChangeInfo( @EntryPoint int entryPoint, boolean isSuggested, @SuggestionProviderFlags int suggestionProviderFlags) { mEntryPoint = entryPoint; mIsSuggested = isSuggested; mSuggestionProviderFlags = suggestionProviderFlags; } private RoutingChangeInfo(Parcel in) { mEntryPoint = in.readInt(); mIsSuggested = in.readBoolean(); mSuggestionProviderFlags = in.readInt(); } @Override Loading @@ -130,6 +176,7 @@ public final class RoutingChangeInfo implements Parcelable { public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) { dest.writeInt(mEntryPoint); dest.writeBoolean(mIsSuggested); dest.writeInt(mSuggestionProviderFlags); } @Override Loading @@ -146,13 +193,14 @@ public final class RoutingChangeInfo implements Parcelable { return true; } return other.getEntryPoint() == this.getEntryPoint() && other.isSuggested() == this.mIsSuggested; return other.getEntryPoint() == this.mEntryPoint && other.isSuggested() == this.mIsSuggested && other.mSuggestionProviderFlags == this.mSuggestionProviderFlags; } @Override public int hashCode() { return Objects.hash(mEntryPoint, mIsSuggested); return Objects.hash(mEntryPoint, mIsSuggested, mSuggestionProviderFlags); } public @EntryPoint int getEntryPoint() { Loading @@ -162,4 +210,25 @@ public final class RoutingChangeInfo implements Parcelable { public boolean isSuggested() { return mIsSuggested; } public @SuggestionProviderFlags int getSuggestionProviderFlags() { return mSuggestionProviderFlags; } /** * Returns whether the route had an active suggestion from the active route listing preference. */ public boolean isSuggestedByRlp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_RLP) != 0; } /** Returns whether the route had an active device suggestion from the media app. */ public boolean isSuggestedByMediaApp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP) != 0; } /** Whether the route had an active device suggestion from an app other than the media app. */ public boolean isSuggestedByAnotherApp() { return (mSuggestionProviderFlags & SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER) != 0; } }
services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +53 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ import static android.media.MediaRouter2.SCANNING_STATE_SCANNING_FULL; import static android.media.MediaRouter2.SCANNING_STATE_WHILE_INTERACTIVE; import static android.media.MediaRouter2Utils.getOriginalId; import static android.media.MediaRouter2Utils.getProviderId; import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER; import static android.media.RoutingChangeInfo.SUGGESTION_PROVIDER_RLP; import static android.media.RoutingChangeInfo.SuggestionProviderFlags; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.media.MediaRouterMetricLogger.EVENT_TYPE_CREATE_SESSION; Loading Loading @@ -1629,9 +1634,16 @@ class MediaRouter2ServiceImpl { } long uniqueRequestId = toUniqueRequestId(routerRecord.mRouterId, requestId); @SuggestionProviderFlags int suggestionProviderFlags = getSuggestionProviderFlags(routerRecord, route); RoutingChangeInfo updatedInfo = new RoutingChangeInfo( routingChangeInfo.getEntryPoint(), routingChangeInfo.isSuggested(), suggestionProviderFlags); mMediaRouterMetricLogger.addRequestInfo( uniqueRequestId, EVENT_TYPE_CREATE_SESSION, routingChangeInfo); mMediaRouterMetricLogger.notifyRoutingChangeRequested(uniqueRequestId, routingChangeInfo); uniqueRequestId, EVENT_TYPE_CREATE_SESSION, updatedInfo); mMediaRouterMetricLogger.notifyRoutingChangeRequested(uniqueRequestId, updatedInfo); userHandler.sendMessage( obtainMessage( UserHandler::requestCreateSessionWithRouter2OnHandler, Loading Loading @@ -2465,6 +2477,45 @@ class MediaRouter2ServiceImpl { } } private static @SuggestionProviderFlags int getSuggestionProviderFlags( RouterRecord routerRecord, MediaRoute2Info mediaRoute2Info) { String routeId = mediaRoute2Info.getId(); int result = 0; if (routerRecord.mRouteListingPreference != null) { List<RouteListingPreference.Item> routeListingPreferenceItems = routerRecord.mRouteListingPreference.getItems(); if (routeListingPreferenceItems.stream() .anyMatch( item -> (item.getRouteId().equals(routeId)) && (item.getFlags() & FLAG_SUGGESTED) != 0)) { result |= SUGGESTION_PROVIDER_RLP; } } Map<String, List<SuggestedDeviceInfo>> suggestionsMap = routerRecord.mDeviceSuggestions; List<SuggestedDeviceInfo> suggestionsByApp = suggestionsMap.get(routerRecord.mPackageName); if (suggestionsByApp != null && suggestionsByApp.stream() .anyMatch( suggestedDeviceInfo -> suggestedDeviceInfo.getRouteId().equals(routeId))) { result |= SUGGESTION_PROVIDER_DEVICE_SUGGESTION_APP; } if (suggestionsMap.entrySet().stream() .filter(entry -> !entry.getKey().equals(routerRecord.mPackageName)) .anyMatch( entry -> entry.getValue().stream() .anyMatch( suggestedDeviceInfo -> suggestedDeviceInfo .getRouteId() .equals(routeId)))) { result |= SUGGESTION_PROVIDER_DEVICE_SUGGESTION_OTHER; } return result; } /** Invoked when {@link MediaRouterService#systemRunning()} is invoked. */ /* package */ void systemRunning() { sInstance.set(this); Loading
services/core/java/com/android/server/media/MediaRouterMetricLogger.java +36 −3 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Map; /** Loading Loading @@ -314,6 +315,9 @@ final class MediaRouterMetricLogger { routingSessionInfo.isSystemSession(), routingSessionInfo.getTransferReason(), routingChangeInfo.isSuggested(), routingChangeInfo.isSuggestedByRlp(), routingChangeInfo.isSuggestedByMediaApp(), routingChangeInfo.isSuggestedByAnotherApp(), getElapsedRealTime()); mOngoingRoutingChangeCache.put(routingSessionInfo.getOriginalId(), ongoingRoutingChange); mRoutingChangeInfoCache.remove(uniqueRequestId); Loading @@ -338,12 +342,13 @@ final class MediaRouterMetricLogger { TextUtils.formatSimple( "notifySessionEnd | EntryPoint: %d, ClientPackageUid: %d," + " IsSystemSession: %b, TransferReason: %d, IsSuggested: %b," + " SessionLengthInMillis: %d", + " SuggestionProviders: %s, SessionLengthInMillis: %d", ongoingRoutingChange.entryPoint, ongoingRoutingChange.clientPackageUid, ongoingRoutingChange.isSystemSession, ongoingRoutingChange.transferReason, ongoingRoutingChange.isSuggested, ongoingRoutingChange.getSuggestionProvidersDebugString(), sessionLengthInMillis)); } Loading @@ -354,7 +359,10 @@ final class MediaRouterMetricLogger { ongoingRoutingChange.isSystemSession, convertTransferReasonForLogging(ongoingRoutingChange.transferReason), ongoingRoutingChange.isSuggested, sessionLengthInMillis); sessionLengthInMillis, ongoingRoutingChange.isSuggestedByRlp, ongoingRoutingChange.isSuggestedByMediaApp, ongoingRoutingChange.isSuggestedByAnotherApp); mOngoingRoutingChangeCache.remove(sessionId); } Loading Loading @@ -745,7 +753,32 @@ final class MediaRouterMetricLogger { boolean isSystemSession, @TransferReason int transferReason, boolean isSuggested, long startTimeInMillis) {} boolean isSuggestedByRlp, boolean isSuggestedByMediaApp, boolean isSuggestedByAnotherApp, long startTimeInMillis) { /** * Returns a human-readable representation of the suggestion provider for logging purposes. */ public String getSuggestionProvidersDebugString() { var providerStrings = new ArrayList<String>(); if (isSuggestedByRlp) { providerStrings.add("RLP"); } if (isSuggestedByMediaApp) { providerStrings.add("MEDIA_APP"); } if (isSuggestedByAnotherApp) { providerStrings.add("ANOTHER_APP"); } if (providerStrings.isEmpty()) { return "NONE"; } else { return String.join("|", providerStrings); } } } /** Tracks the count of changes in route listing preference */ private record RlpCount(long rlpTotalCount, long rlpWithSuggestionCount) {} Loading
services/tests/media/mediarouterservicetest/src/com/android/server/media/MediaRouterMetricLoggerTest.java +8 −2 Original line number Diff line number Diff line Loading @@ -402,7 +402,10 @@ public class MediaRouterMetricLoggerTest { anyBoolean(), anyInt(), anyBoolean(), anyLong()), anyLong(), anyBoolean(), anyBoolean(), anyBoolean()), never()); } Loading Loading @@ -449,7 +452,10 @@ public class MediaRouterMetricLoggerTest { eq( ROUTING_CHANGE_REPORTED__TRANSFER_REASON__TRANSFER_REASON_SYSTEM_REQUEST), eq(/* isSuggested= */ false), sessionLengthCaptor.capture())); sessionLengthCaptor.capture(), eq(/* isSuggestedByRlp= */ false), eq(/* isSuggestedByMediaApp= */ false), eq(/* isSuggestedByOtherApp= */ false))); assertThat(sessionLengthCaptor.getValue()).isEqualTo(sessionTimeInMillis); } Loading