Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81ac077e authored by tanaykhemani's avatar tanaykhemani
Browse files

Add entry point info for MR2 transfer calls

Bug: 427967405
Flag: EXEMPT passing a new parameter for logging
Test: atest LocalMediaManagerTest
Test: atest MediaSwitchingControllerTest
Change-Id: I842e751284344164ef7a86b9ae9a6d7ebc74508f
parent 52bdf8e9
Loading
Loading
Loading
Loading
+18 −59
Original line number Diff line number Diff line
@@ -127,65 +127,6 @@ public final class MediaRouter2 {
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScanningState {}

    /**
     * Indicates that a routing session started as the result of selecting a route from the output
     * switcher where the route is not amongst the suggested routes.
     *
     * @hide
     */
    public static final int ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER_NOT_SUGGESTED = 0;

    /**
     * Indicates that a routing session started as the result of selecting a route from the output
     * switcher where the route is amongst the suggested routes.
     *
     * @hide
     */
    public static final int ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER_SUGGESTED_DEVICE = 1;

    /**
     * Indicates that a routing session started as the result of selecting the device suggestion
     * pill in the UMO notification.
     *
     * @hide
     */
    public static final int ENTRY_POINT_SYSTEM_UMO_SUGGESTED_DEVICE = 2;

    /**
     * Indicates that a routing session was started from a local media router instance where the
     * entry point was not specified.
     *
     * <p>This entry point is marked when {@link MediaRouter2#transferTo(MediaRoute2Info)} is called
     * on a local media router instance.
     *
     * @hide
     */
    public static final int ENTRY_POINT_LOCAL_ROUTER_UNSPECIFIED = 3;

    /**
     * Indicates that a routing session was started from a proxy media router instance where the
     * entry point was not specified.
     *
     * <p>This entry point is marked when {@link MediaRouter2#transferTo(MediaRoute2Info)} is called
     * on a proxy media router instance.
     *
     * @hide
     */
    public static final int ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED = 4;

    /** @hide */
    @IntDef(
            prefix = "ENTRY_POINT",
            value = {
                ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER_NOT_SUGGESTED,
                ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER_SUGGESTED_DEVICE,
                ENTRY_POINT_SYSTEM_UMO_SUGGESTED_DEVICE,
                ENTRY_POINT_LOCAL_ROUTER_UNSPECIFIED,
                ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED
            })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EntryPoint {}

    private static final String TAG = "MR2";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final Object sSystemRouterLock = new Object();
@@ -1161,6 +1102,24 @@ public final class MediaRouter2 {
        mImpl.transferTo(route);
    }

    /**
     * Transfers the current media to the given route. If it's necessary a new {@link
     * RoutingController} is created or it is handled within the current routing controller.
     *
     * @param route the route you want to transfer the current media to. Pass {@code null} to stop
     *     routing of the current media.
     * @param routingChangeInfo information about the start of the media routing session. See {@link
     *     RoutingChangeInfo}
     * @see TransferCallback#onTransfer
     * @see TransferCallback#onTransferFailure
     * @hide
     */
    public void transferTo(
            @NonNull MediaRoute2Info route, @NonNull RoutingChangeInfo routingChangeInfo) {
        // TODO: b/427964326 - Pass the entry point of media routing session to MediaRouterService
        mImpl.transferTo(route);
    }

    /**
     * Stops the current media routing. If the {@link #getSystemController() system controller}
     * controls the media routing, this method is a no-op.
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
 * Captures information about the change in media routing for logging purposes.
 *
 * @hide
 */
public final class RoutingChangeInfo implements Parcelable {

    // Indicates the start point of a media session.
    private final @EntryPoint int mEntryPoint;

    // Indicates that the route was a suggested route.
    private final boolean mIsSuggested;

    /**
     * Unspecified default value.
     *
     * @hide
     */
    public static final int ENTRY_POINT_UNSPECIFIED = 0;

    /**
     * Indicates that a routing session started as the result of selecting a route from the output
     * switcher.
     *
     * @hide
     */
    public static final int ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER = 1;

    /**
     * Indicates that a routing session started as the result of selecting the device suggestion
     * pill in the system media controls.
     *
     * @hide
     */
    public static final int ENTRY_POINT_SYSTEM_MEDIA_CONTROLS = 2;

    /**
     * Indicates that a routing session was started from a local media router instance where the
     * entry point was not specified.
     *
     * <p>This entry point is marked when {@link MediaRouter2#transferTo(MediaRoute2Info)} is called
     * on a local media router instance.
     *
     * @hide
     */
    public static final int ENTRY_POINT_LOCAL_ROUTER_UNSPECIFIED = 3;

    /**
     * Indicates that a routing session was started from a proxy media router instance where the
     * entry point was not specified.
     *
     * <p>This entry point is marked when {@link MediaRouter2#transferTo(MediaRoute2Info)} is called
     * on a proxy media router instance.
     *
     * @hide
     */
    public static final int ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED = 4;

    /**
     * Indicates that a routing session started as the result of selecting a route from the output
     * switcher in TV.
     *
     * @hide
     */
    public static final int ENTRY_POINT_TV_OUTPUT_SWITCHER = 5;

    /** @hide */
    @IntDef(
            prefix = "ENTRY_POINT",
            value = {
                ENTRY_POINT_UNSPECIFIED,
                ENTRY_POINT_SYSTEM_OUTPUT_SWITCHER,
                ENTRY_POINT_SYSTEM_MEDIA_CONTROLS,
                ENTRY_POINT_LOCAL_ROUTER_UNSPECIFIED,
                ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED,
                ENTRY_POINT_TV_OUTPUT_SWITCHER
            })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EntryPoint {}

    @NonNull
    public static final Creator<RoutingChangeInfo> CREATOR =
            new Creator<>() {
                @Override
                public RoutingChangeInfo createFromParcel(Parcel in) {
                    return new RoutingChangeInfo(in);
                }

                @Override
                public RoutingChangeInfo[] newArray(int size) {
                    return new RoutingChangeInfo[size];
                }
            };

    public RoutingChangeInfo(@EntryPoint int entryPoint, boolean isSuggested) {
        mEntryPoint = entryPoint;
        mIsSuggested = isSuggested;
    }

    private RoutingChangeInfo(Parcel in) {
        mEntryPoint = in.readInt();
        mIsSuggested = in.readBoolean();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
        dest.writeInt(mEntryPoint);
        dest.writeBoolean(mIsSuggested);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (!(obj instanceof RoutingChangeInfo other)) {
            return false;
        }

        if (obj == this) {
            return true;
        }

        return other.getEntryPoint() == this.getEntryPoint()
                && other.isSuggested() == this.mIsSuggested;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mEntryPoint, mIsSuggested);
    }

    public @EntryPoint int getEntryPoint() {
        return mEntryPoint;
    }

    public boolean isSuggested() {
        return mIsSuggested;
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.RouteListingPreference;
import android.media.RoutingChangeInfo;
import android.media.RoutingSessionInfo;
import android.media.SuggestedDeviceInfo;
import android.media.session.MediaController;
@@ -315,7 +316,8 @@ public abstract class InfoMediaManager {

    protected abstract void unregisterRouter();

    protected abstract void transferToRoute(@NonNull MediaRoute2Info route);
    protected abstract void transferToRoute(
            @NonNull MediaRoute2Info route, @NonNull RoutingChangeInfo routingChangeInfo);

    protected abstract void selectRoute(
            @NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info);
@@ -475,7 +477,7 @@ public abstract class InfoMediaManager {
        return mCurrentConnectedDevice;
    }

    /* package */ void connectToDevice(MediaDevice device) {
    /* package */ void connectToDevice(MediaDevice device, RoutingChangeInfo routingChangeInfo) {
        Log.i(TAG, "connectToDevice(), device = " + device.getName() + "/" + device.getId());
        if (device.mRouteInfo == null) {
            Log.w(TAG, "Unable to connect. RouteInfo is empty");
@@ -483,7 +485,7 @@ public abstract class InfoMediaManager {
        }

        device.setConnectedRecord();
        transferToRoute(device.mRouteInfo);
        transferToRoute(device.mRouteInfo, routingChangeInfo);
    }

    /**
+41 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.settingslib.media;

import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
import static android.media.RoutingChangeInfo.ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -25,6 +26,8 @@ import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.RoutingChangeInfo;
import android.media.RoutingChangeInfo.EntryPoint;
import android.media.RoutingSessionInfo;
import android.os.Build;
import android.os.Handler;
@@ -189,10 +192,29 @@ public class LocalMediaManager implements BluetoothCallback {

    /**
     * Connect the MediaDevice to transfer media
     *
     * @param connectDevice the MediaDevice
     * @return {@code true} if successfully call, otherwise return {@code false}
     * @deprecated Use {@link #connectDevice(MediaDevice, RoutingChangeInfo)} instead.
     */
    @Deprecated
    public boolean connectDevice(MediaDevice connectDevice) {
        return connectDevice(
                connectDevice,
                new RoutingChangeInfo(
                        ENTRY_POINT_PROXY_ROUTER_UNSPECIFIED, /* isSuggested= */ false));
    }

    /**
     * Connect the MediaDevice to transfer media
     *
     * @param connectDevice the MediaDevice
     * @param routingChangeInfo the invocation details of the connect device request. See {@link
     *     RoutingChangeInfo}
     * @return {@code true} if successfully call, otherwise return {@code false}
     */
    public boolean connectDevice(
            @NonNull MediaDevice connectDevice, @NonNull RoutingChangeInfo routingChangeInfo) {
        MediaDevice device = getMediaDeviceById(connectDevice.getId());
        if (device == null) {
            Log.w(TAG, "connectDevice() connectDevice not in the list!");
@@ -215,7 +237,7 @@ public class LocalMediaManager implements BluetoothCallback {
        }

        mInfoMediaManager.setDeviceState(device, MediaDeviceState.STATE_CONNECTING);
        mInfoMediaManager.connectToDevice(device);
        mInfoMediaManager.connectToDevice(device, routingChangeInfo);
        return true;
    }

@@ -224,10 +246,14 @@ public class LocalMediaManager implements BluetoothCallback {
     * to attempt to discover the device.
     *
     * @param suggestion the suggested device to connect to.
     * @param routingChangeInfo the invocation details of the connect device request. See {@link
     *     RoutingChangeInfo}
     */
    public void connectSuggestedDevice(SuggestedDeviceState suggestion) {
    public void connectSuggestedDevice(
            @NonNull SuggestedDeviceState suggestion,
            @NonNull RoutingChangeInfo routingChangeInfo) {
        synchronized (mMediaDevicesLock) {
            if (suggestion == null || mConnectingSuggestedDeviceState != null) {
            if (mConnectingSuggestedDeviceState != null) {
                return;
            }
            SuggestedDeviceState currentSuggestion = mInfoMediaManager.getSuggestedDevice();
@@ -239,11 +265,13 @@ public class LocalMediaManager implements BluetoothCallback {
                if (suggestion.getSuggestedDeviceInfo().getRouteId().equals(device.getId())) {
                    Log.i(TAG, "Suggestion: device is available, connecting. deviceId = "
                            + device.getId());
                    connectDevice(device);
                    connectDevice(device, routingChangeInfo);
                    return;
                }
            }
            mConnectingSuggestedDeviceState = new ConnectingSuggestedDeviceState(currentSuggestion);
            mConnectingSuggestedDeviceState =
                    new ConnectingSuggestedDeviceState(
                            currentSuggestion, routingChangeInfo.getEntryPoint());
            mConnectingSuggestedDeviceState.tryConnect();
        }
    }
@@ -860,7 +888,8 @@ public class LocalMediaManager implements BluetoothCallback {
        boolean mIsConnectionAttemptActive = false;
        boolean mDidAttemptCompleteSuccessfully = false;

        ConnectingSuggestedDeviceState(@NonNull SuggestedDeviceState suggestedDeviceState) {
        ConnectingSuggestedDeviceState(
                @NonNull SuggestedDeviceState suggestedDeviceState, @EntryPoint int entryPoint) {
            mSuggestedDeviceState = suggestedDeviceState;
            mDeviceCallback =
                    new DeviceCallback() {
@@ -869,11 +898,15 @@ public class LocalMediaManager implements BluetoothCallback {
                            synchronized (mMediaDevicesLock) {
                                for (MediaDevice mediaDevice : mediaDevices) {
                                    if (isSuggestedDevice(mediaDevice)) {
                                        Log.i(TAG,
                                        Log.i(
                                                TAG,
                                                "Suggestion: scan found matched device, "
                                                        + "connecting. deviceId = "
                                                        + mediaDevice.getId());
                                        connectDevice(mediaDevice);
                                        connectDevice(
                                                mediaDevice,
                                                new RoutingChangeInfo(
                                                        entryPoint, /* isSuggested= */ true));
                                        mIsConnectionAttemptActive = true;
                                        break;
                                    }
+3 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.settingslib.media;
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.RouteListingPreference;
import android.media.RoutingChangeInfo;
import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.os.UserHandle;
@@ -87,7 +88,8 @@ import java.util.List;
    }

    @Override
    protected void transferToRoute(@NonNull MediaRoute2Info route) {
    protected void transferToRoute(
            @NonNull MediaRoute2Info route, @NonNull RoutingChangeInfo routingChangeInfo) {
        // Do nothing.
    }

Loading