blob: e91096760180eea6b138cdb7c556ce6335112055 [file] [log] [blame]
/*
* Copyright 2018 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 android.media.MediaRoute2Info.DEVICE_TYPE_BLUETOOTH;
import static android.media.MediaRoute2Info.DEVICE_TYPE_REMOTE_TV;
import static android.media.MediaRoute2Info.DEVICE_TYPE_UNKNOWN;
import android.app.Notification;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* InfoMediaManager provide interface to get InfoMediaDevice list.
*/
public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
@VisibleForTesting
final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
@VisibleForTesting
final Executor mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting
MediaRouter2Manager mRouterManager;
@VisibleForTesting
String mPackageName;
private MediaDevice mCurrentConnectedDevice;
private LocalBluetoothManager mBluetoothManager;
public InfoMediaManager(Context context, String packageName, Notification notification,
LocalBluetoothManager localBluetoothManager) {
super(context, notification);
mRouterManager = MediaRouter2Manager.getInstance(context);
mBluetoothManager = localBluetoothManager;
if (!TextUtils.isEmpty(packageName)) {
mPackageName = packageName;
}
}
@Override
public void startScan() {
mMediaDevices.clear();
mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
refreshDevices();
}
@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";
}
@Override
public void stopScan() {
mRouterManager.unregisterCallback(mMediaRouterCallback);
}
/**
* Get current device that played media.
* @return MediaDevice
*/
public MediaDevice getCurrentConnectedDevice() {
return mCurrentConnectedDevice;
}
private void refreshDevices() {
mMediaDevices.clear();
mCurrentConnectedDevice = null;
if (TextUtils.isEmpty(mPackageName)) {
buildAllRoutes();
} else {
buildAvailableRoutes();
}
dispatchDeviceListAdded();
}
private void buildAllRoutes() {
for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
addMediaDevice(route);
}
}
private void buildAvailableRoutes() {
for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) {
addMediaDevice(route);
}
}
private void addMediaDevice(MediaRoute2Info route) {
final int deviceType = route.getDeviceType();
MediaDevice mediaDevice = null;
switch (deviceType) {
case DEVICE_TYPE_UNKNOWN:
//TODO(b/148765806): use correct device type once api is ready.
final String defaultRoute = "DEFAULT_ROUTE";
if (TextUtils.equals(defaultRoute, route.getOriginalId())) {
mediaDevice =
new PhoneMediaDevice(mContext, mRouterManager, route, mPackageName);
} else {
mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
if (!TextUtils.isEmpty(mPackageName)
&& TextUtils.equals(route.getClientPackageName(), mPackageName)) {
mCurrentConnectedDevice = mediaDevice;
}
}
break;
case DEVICE_TYPE_REMOTE_TV:
break;
case DEVICE_TYPE_BLUETOOTH:
final BluetoothDevice device =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice(route.getOriginalId());
final CachedBluetoothDevice cachedDevice =
mBluetoothManager.getCachedDeviceManager().findDevice(device);
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
route, mPackageName);
break;
default:
Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
break;
}
if (mediaDevice != null) {
mMediaDevices.add(mediaDevice);
}
}
/**
* Transfer MediaDevice for media without package name.
*/
public boolean connectDeviceWithoutPackageName(MediaDevice device) {
boolean isConnected = false;
final List<RoutingSessionInfo> infos = mRouterManager.getActiveSessions();
if (infos.size() > 0) {
final RoutingSessionInfo info = infos.get(0);
final MediaRouter2Manager.RoutingController controller =
mRouterManager.getControllerForSession(info);
controller.transferToRoute(device.mRouteInfo);
isConnected = true;
}
return isConnected;
}
class RouterManagerCallback extends MediaRouter2Manager.Callback {
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
refreshDevices();
}
@Override
public void onControlCategoriesChanged(String packageName, List<String> controlCategories) {
if (TextUtils.equals(mPackageName, packageName)) {
refreshDevices();
}
}
@Override
public void onRoutesChanged(List<MediaRoute2Info> routes) {
refreshDevices();
}
}
}