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

Commit e6a4f48a authored by hughchen's avatar hughchen
Browse files

Use new media router2 api to get info media device list

1. Use new media router2 api to get info device list
2. Use new media router2 api to tranfer media to info device

Bug: 144535188
Test: make -j50 RunSettingsLibRoboTests
Change-Id: I682dc53f659180cdef434b2063668ee0fcd1f9c3
parent 0c2469bb
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -17,9 +17,8 @@ package com.android.settingslib.media;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.Toast;

import androidx.mediarouter.media.MediaRouter;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;

import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -31,22 +30,28 @@ public class InfoMediaDevice extends MediaDevice {

    private static final String TAG = "InfoMediaDevice";

    private MediaRouter.RouteInfo mRouteInfo;
    private final MediaRoute2Info mRouteInfo;
    private final MediaRouter2Manager mRouterManager;
    private final String mPackageName;

    InfoMediaDevice(Context context, MediaRouter.RouteInfo info) {
    InfoMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
            String packageName) {
        super(context, MediaDeviceType.TYPE_CAST_DEVICE);
        mRouterManager = routerManager;
        mRouteInfo = info;
        mPackageName = packageName;
        initDeviceRecord();
    }

    @Override
    public String getName() {
        return mRouteInfo.getName();
        return mRouteInfo.getName().toString();
    }

    @Override
    public String getSummary() {
        return null;
        return mRouteInfo.getClientPackageName() != null
                ? mContext.getString(R.string.bluetooth_active_no_battery_level) : null;
    }

    @Override
@@ -63,15 +68,14 @@ public class InfoMediaDevice extends MediaDevice {

    @Override
    public boolean connect() {
        //TODO(b/121083246): use SystemApi to transfer media
        setConnectedRecord();
        Toast.makeText(mContext, "This is cast device !", Toast.LENGTH_SHORT).show();
        return false;
        mRouterManager.selectRoute(mPackageName, mRouteInfo);
        return true;
    }

    @Override
    public void disconnect() {
        //TODO(b/121083246): disconnected last select device
        //TODO(b/144535188): disconnected last select device
    }

    @Override
+48 −32
Original line number Diff line number Diff line
@@ -17,13 +17,16 @@ package com.android.settingslib.media;

import android.app.Notification;
import android.content.Context;
import android.util.Log;

import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;

import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * InfoMediaManager provide interface to get InfoMediaDevice list.
 */
@@ -32,62 +35,75 @@ public class InfoMediaManager extends MediaManager {
    private static final String TAG = "InfoMediaManager";

    @VisibleForTesting
    final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
    final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
    @VisibleForTesting
    MediaRouteSelector mSelector;
    final Executor mExecutor = Executors.newSingleThreadExecutor();
    @VisibleForTesting
    MediaRouter mMediaRouter;
    MediaRouter2Manager mRouterManager;

    private String mPackageName;
    private MediaDevice mCurrentConnectedDevice;

    InfoMediaManager(Context context, String packageName, Notification notification) {
    public InfoMediaManager(Context context, String packageName, Notification notification) {
        super(context, notification);

        mMediaRouter = MediaRouter.getInstance(context);
        mRouterManager = MediaRouter2Manager.getInstance(context);
        if (packageName != null) {
            mPackageName = packageName;
        mSelector = new MediaRouteSelector.Builder()
                .addControlCategory(getControlCategoryByPackageName(mPackageName))
                .build();
        }
    }

    @Override
    public void startScan() {
        mMediaDevices.clear();
        mMediaRouter.addCallback(mSelector, mMediaRouterCallback,
                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
        mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
    }

    @VisibleForTesting
    String getControlCategoryByPackageName(String packageName) {
        //TODO(b/117129183): Use package name to get ControlCategory.
        //Since api not ready, return fixed ControlCategory for prototype.
        return "com.google.android.gms.cast.CATEGORY_CAST/4F8B3483";
        return "com.google.android.gms.cast.CATEGORY_CAST";
    }

    @Override
    public void stopScan() {
        mMediaRouter.removeCallback(mMediaRouterCallback);
        mRouterManager.unregisterCallback(mMediaRouterCallback);
    }

    class MediaRouterCallback extends MediaRouter.Callback {
        @Override
        public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
            MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
            if (mediaDevice == null) {
                mediaDevice = new InfoMediaDevice(mContext, route);
                Log.d(TAG, "onRouteAdded() route : " + route.getName());
                mMediaDevices.add(mediaDevice);
                dispatchDeviceAdded(mediaDevice);
    /**
     * Get current device that played media.
     * @return MediaDevice
     */
    public MediaDevice getCurrentConnectedDevice() {
        return mCurrentConnectedDevice;
    }

    class RouterManagerCallback extends MediaRouter2Manager.Callback {

        private void refreshDevices() {
            mMediaDevices.clear();
            mCurrentConnectedDevice = null;
            for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) {
                final MediaDevice device = new InfoMediaDevice(mContext, mRouterManager, route,
                        mPackageName);
                if (TextUtils.equals(route.getClientPackageName(), mPackageName)) {
                    mCurrentConnectedDevice = device;
                }
                mMediaDevices.add(device);
            }
            dispatchDeviceListAdded();
        }

        @Override
        public void onRoutesAdded(List<MediaRoute2Info> routes) {
            refreshDevices();
        }

        @Override
        public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
            final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
            if (mediaDevice != null) {
                Log.d(TAG, "onRouteRemoved() route : " + route.getName());
                mMediaDevices.remove(mediaDevice);
                dispatchDeviceRemoved(mediaDevice);
        public void onControlCategoriesChanged(String packageName, List<String> controlCategories) {
            if (TextUtils.equals(mPackageName, packageName)) {
                refreshDevices();
            }
        }
    }
+18 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settingslib.media;
import android.app.Notification;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.IntDef;
@@ -59,6 +60,8 @@ public class LocalMediaManager implements BluetoothCallback {
    private Context mContext;
    private BluetoothMediaManager mBluetoothMediaManager;
    private LocalBluetoothManager mLocalBluetoothManager;
    private InfoMediaManager mInfoMediaManager;
    private String mPackageName;

    @VisibleForTesting
    List<MediaDevice> mMediaDevices = new ArrayList<>();
@@ -87,6 +90,7 @@ public class LocalMediaManager implements BluetoothCallback {

    public LocalMediaManager(Context context, String packageName, Notification notification) {
        mContext = context;
        mPackageName = packageName;
        mLocalBluetoothManager =
                LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
        if (mLocalBluetoothManager == null) {
@@ -96,6 +100,7 @@ public class LocalMediaManager implements BluetoothCallback {

        mBluetoothMediaManager =
                new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
        mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
    }

    @VisibleForTesting
@@ -104,6 +109,7 @@ public class LocalMediaManager implements BluetoothCallback {
        mContext = context;
        mLocalBluetoothManager = localBluetoothManager;
        mBluetoothMediaManager = bluetoothMediaManager;
        mInfoMediaManager = infoMediaManager;
    }

    /**
@@ -126,8 +132,7 @@ public class LocalMediaManager implements BluetoothCallback {
            return;
        }

        //TODO(b/121083246): Update it once remote media API is ready.
        if (mCurrentConnectedDevice != null && !(connectDevice instanceof InfoMediaDevice)) {
        if (mCurrentConnectedDevice != null) {
            mCurrentConnectedDevice.disconnect();
        }

@@ -157,6 +162,10 @@ public class LocalMediaManager implements BluetoothCallback {
        mMediaDevices.clear();
        mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
        mBluetoothMediaManager.startScan();
        if (!TextUtils.isEmpty(mPackageName)) {
            mInfoMediaManager.registerCallback(mMediaDeviceCallback);
            mInfoMediaManager.startScan();
        }
    }

    private void addPhoneDeviceIfNecessary() {
@@ -191,6 +200,10 @@ public class LocalMediaManager implements BluetoothCallback {
    public void stopScan() {
        mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
        mBluetoothMediaManager.stopScan();
        if (!TextUtils.isEmpty(mPackageName)) {
            mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
            mInfoMediaManager.stopScan();
        }
    }

    /**
@@ -253,7 +266,9 @@ public class LocalMediaManager implements BluetoothCallback {
                }
            }
            addPhoneDeviceIfNecessary();
            mCurrentConnectedDevice = updateCurrentConnectedDevice();
            final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
            mCurrentConnectedDevice = infoMediaDevice != null
                    ? infoMediaDevice : updateCurrentConnectedDevice();
            updatePhoneMediaDeviceSummary();
            dispatchDeviceListUpdate();
        }
+5 −6
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@
package com.android.settingslib.media;

import android.bluetooth.BluetoothDevice;

import androidx.mediarouter.media.MediaRouter;
import android.media.MediaRoute2Info;

import com.android.settingslib.bluetooth.CachedBluetoothDevice;

@@ -49,12 +48,12 @@ public class MediaDeviceUtils {
    }

    /**
     * Use RouteInfo id to represent unique id
     * Use MediaRoute2Info id to represent unique id
     *
     * @param route the RouteInfo
     * @return RouteInfo id
     * @param route the MediaRoute2Info
     * @return MediaRoute2Info id
     */
    public static String getId(MediaRouter.RouteInfo route) {
    public static String getId(MediaRoute2Info route) {
        return route.getId();
    }
}
+98 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 com.android.settingslib.media;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;

import com.android.settingslib.R;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@RunWith(RobolectricTestRunner.class)
public class InfoMediaDeviceTest {

    private static final String TEST_PACKAGE_NAME = "com.test.packagename";
    private static final String TEST_ID = "test_id";
    private static final String TEST_NAME = "test_name";

    @Mock
    private MediaRouter2Manager mRouterManager;
    @Mock
    private MediaRoute2Info mRouteInfo;


    private Context mContext;
    private InfoMediaDevice mInfoMediaDevice;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;

        mInfoMediaDevice = new InfoMediaDevice(mContext, mRouterManager, mRouteInfo,
                TEST_PACKAGE_NAME);
    }

    @Test
    public void getName_shouldReturnName() {
        when(mRouteInfo.getName()).thenReturn(TEST_NAME);

        assertThat(mInfoMediaDevice.getName()).isEqualTo(TEST_NAME);
    }

    @Test
    public void getSummary_clientPackageNameIsNull_returnNull() {
        when(mRouteInfo.getClientPackageName()).thenReturn(null);

        assertThat(mInfoMediaDevice.getSummary()).isEqualTo(null);
    }

    @Test
    public void getSummary_clientPackageNameIsNotNull_returnActive() {
        when(mRouteInfo.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);

        assertThat(mInfoMediaDevice.getSummary())
                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
    }

    @Test
    public void getId_shouldReturnId() {
        when(mRouteInfo.getId()).thenReturn(TEST_ID);

        assertThat(mInfoMediaDevice.getId()).isEqualTo(TEST_ID);
    }

    @Test
    public void connect_shouldSelectRoute() {
        mInfoMediaDevice.connect();

        verify(mRouterManager).selectRoute(TEST_PACKAGE_NAME, mRouteInfo);
    }
}
Loading