Merge "Implement LocalMediaManager for seamless transfer"
This commit is contained in:
committed by
Android (Google) Code Review
commit
c09f4ee42e
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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 android.app.Notification;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.bluetooth.A2dpProfile;
|
||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BluetoothMediaManager provide interface to get Bluetooth device list.
|
||||
*/
|
||||
public class BluetoothMediaManager extends MediaManager implements BluetoothCallback {
|
||||
|
||||
private static final String TAG = "BluetoothMediaManager";
|
||||
|
||||
private final DeviceAttributeChangeCallback mCachedDeviceCallback =
|
||||
new DeviceAttributeChangeCallback();
|
||||
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
|
||||
private MediaDevice mLastAddedDevice;
|
||||
private MediaDevice mLastRemovedDevice;
|
||||
|
||||
BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
|
||||
Notification notification) {
|
||||
super(context, notification);
|
||||
|
||||
mLocalBluetoothManager = localBluetoothManager;
|
||||
mProfileManager = mLocalBluetoothManager.getProfileManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
mMediaDevices.clear();
|
||||
mLocalBluetoothManager.getEventManager().registerCallback(this);
|
||||
buildBluetoothDeviceList();
|
||||
dispatchDeviceListAdded();
|
||||
}
|
||||
|
||||
private void buildBluetoothDeviceList() {
|
||||
addConnectedA2dpDevices();
|
||||
addConnectedHearingAidDevices();
|
||||
}
|
||||
|
||||
private void addConnectedA2dpDevices() {
|
||||
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
|
||||
if (a2dpProfile == null) {
|
||||
Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
|
||||
return;
|
||||
}
|
||||
final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
|
||||
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
|
||||
mLocalBluetoothManager.getCachedDeviceManager();
|
||||
|
||||
for (BluetoothDevice device : devices) {
|
||||
final CachedBluetoothDevice cachedDevice =
|
||||
cachedBluetoothDeviceManager.findDevice(device);
|
||||
|
||||
if (cachedDevice == null) {
|
||||
Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
|
||||
+ ", is connected : " + cachedDevice.isConnected());
|
||||
|
||||
if (cachedDevice.isConnected()) {
|
||||
addMediaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addConnectedHearingAidDevices() {
|
||||
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
|
||||
if (hapProfile == null) {
|
||||
Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
|
||||
return;
|
||||
}
|
||||
final List<Long> devicesHiSyncIds = new ArrayList<>();
|
||||
final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
|
||||
final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
|
||||
mLocalBluetoothManager.getCachedDeviceManager();
|
||||
|
||||
for (BluetoothDevice device : devices) {
|
||||
final CachedBluetoothDevice cachedDevice =
|
||||
cachedBluetoothDeviceManager.findDevice(device);
|
||||
|
||||
if (cachedDevice == null) {
|
||||
Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
|
||||
+ ", is connected : " + cachedDevice.isConnected());
|
||||
final long hiSyncId = hapProfile.getHiSyncId(device);
|
||||
|
||||
// device with same hiSyncId should not be shown in the UI.
|
||||
// So do not add it into connectedDevices.
|
||||
if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
|
||||
devicesHiSyncIds.add(hiSyncId);
|
||||
addMediaDevice(cachedDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
|
||||
MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
|
||||
if (mediaDevice == null) {
|
||||
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
|
||||
cachedDevice.registerCallback(mCachedDeviceCallback);
|
||||
mLastAddedDevice = mediaDevice;
|
||||
mMediaDevices.add(mediaDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopScan() {
|
||||
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
|
||||
unregisterCachedDeviceCallback();
|
||||
}
|
||||
|
||||
private void unregisterCachedDeviceCallback() {
|
||||
for (MediaDevice device : mMediaDevices) {
|
||||
if (device instanceof BluetoothMediaDevice) {
|
||||
((BluetoothMediaDevice) device).getCachedDevice()
|
||||
.unregisterCallback(mCachedDeviceCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
if (BluetoothAdapter.STATE_ON == bluetoothState) {
|
||||
buildBluetoothDeviceList();
|
||||
dispatchDeviceListAdded();
|
||||
} else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
|
||||
final List<MediaDevice> removeDevicesList = new ArrayList<>();
|
||||
for (MediaDevice device : mMediaDevices) {
|
||||
if (device instanceof BluetoothMediaDevice) {
|
||||
((BluetoothMediaDevice) device).getCachedDevice()
|
||||
.unregisterCallback(mCachedDeviceCallback);
|
||||
removeDevicesList.add(device);
|
||||
}
|
||||
}
|
||||
mMediaDevices.removeAll(removeDevicesList);
|
||||
dispatchDeviceListRemoved(removeDevicesList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
|
||||
if (isCachedDeviceConnected(cachedDevice)) {
|
||||
addMediaDevice(cachedDevice);
|
||||
dispatchDeviceAdded(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCachedDeviceConnected(CachedBluetoothDevice cachedDevice) {
|
||||
final boolean isConnectedHearingAidDevice = cachedDevice.isConnectedHearingAidDevice();
|
||||
final boolean isConnectedA2dpDevice = cachedDevice.isConnectedA2dpDevice();
|
||||
Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice.getName()
|
||||
+ ", is hearing aid connected : " + isConnectedHearingAidDevice
|
||||
+ ", is a2dp connected : " + isConnectedA2dpDevice);
|
||||
|
||||
return isConnectedHearingAidDevice || isConnectedA2dpDevice;
|
||||
}
|
||||
|
||||
private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
|
||||
if (mLastAddedDevice != null
|
||||
&& MediaDeviceUtils.getId(cachedDevice) == mLastAddedDevice.getId()) {
|
||||
dispatchDeviceAdded(mLastAddedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
|
||||
if (!isCachedDeviceConnected(cachedDevice)) {
|
||||
removeMediaDevice(cachedDevice);
|
||||
dispatchDeviceRemoved(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
|
||||
final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
|
||||
if (mediaDevice != null) {
|
||||
cachedDevice.unregisterCallback(mCachedDeviceCallback);
|
||||
mLastRemovedDevice = mediaDevice;
|
||||
mMediaDevices.remove(mediaDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
|
||||
if (mLastRemovedDevice != null
|
||||
&& MediaDeviceUtils.getId(cachedDevice) == mLastRemovedDevice.getId()) {
|
||||
dispatchDeviceRemoved(mLastRemovedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
|
||||
int bluetoothProfile) {
|
||||
Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice.getName()
|
||||
+ ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
|
||||
|
||||
if (isCachedDeviceConnected(cachedDevice)) {
|
||||
addMediaDevice(cachedDevice);
|
||||
dispatchDeviceAdded(cachedDevice);
|
||||
} else {
|
||||
removeMediaDevice(cachedDevice);
|
||||
dispatchDeviceRemoved(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice.getName()
|
||||
+ ", state: " + state);
|
||||
|
||||
if (isCachedDeviceConnected(cachedDevice)) {
|
||||
addMediaDevice(cachedDevice);
|
||||
dispatchDeviceAdded(cachedDevice);
|
||||
} else {
|
||||
removeMediaDevice(cachedDevice);
|
||||
dispatchDeviceRemoved(cachedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
|
||||
@Override
|
||||
public void onDeviceAttributesChanged() {
|
||||
dispatchDeviceAttributesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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 android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.mediarouter.media.MediaRouteSelector;
|
||||
import androidx.mediarouter.media.MediaRouter;
|
||||
|
||||
/**
|
||||
* InfoMediaManager provide interface to get InfoMediaDevice list.
|
||||
*/
|
||||
public class InfoMediaManager extends MediaManager {
|
||||
|
||||
private static final String TAG = "InfoMediaManager";
|
||||
|
||||
private final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
|
||||
|
||||
private MediaRouter mMediaRouter;
|
||||
private String mPackageName;
|
||||
|
||||
InfoMediaManager(Context context, String packageName, Notification notification) {
|
||||
super(context, notification);
|
||||
|
||||
mMediaRouter = MediaRouter.getInstance(context);
|
||||
mPackageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
mMediaDevices.clear();
|
||||
startScanCastDevice();
|
||||
}
|
||||
|
||||
private void startScanCastDevice() {
|
||||
final MediaRouteSelector selector = new MediaRouteSelector.Builder()
|
||||
.addControlCategory(getControlCategoryByPackageName(mPackageName))
|
||||
.build();
|
||||
|
||||
mMediaRouter.addCallback(selector, mMediaRouterCallback,
|
||||
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
|
||||
}
|
||||
|
||||
private 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";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopScan() {
|
||||
mMediaRouter.removeCallback(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);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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 android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
|
||||
*/
|
||||
public class LocalMediaManager implements BluetoothCallback {
|
||||
|
||||
private static final String TAG = "LocalMediaManager";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({MediaDeviceState.STATE_CONNECTED,
|
||||
MediaDeviceState.STATE_CONNECTING,
|
||||
MediaDeviceState.STATE_DISCONNECTED})
|
||||
public @interface MediaDeviceState {
|
||||
int STATE_CONNECTED = 1;
|
||||
int STATE_CONNECTING = 2;
|
||||
int STATE_DISCONNECTED = 3;
|
||||
}
|
||||
|
||||
private final Collection<DeviceCallback> mCallbacks = new ArrayList<>();
|
||||
private final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
|
||||
|
||||
private Context mContext;
|
||||
private List<MediaDevice> mMediaDevices = new ArrayList<>();
|
||||
private BluetoothMediaManager mBluetoothMediaManager;
|
||||
private InfoMediaManager mInfoMediaManager;
|
||||
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private MediaDevice mLastConnectedDevice;
|
||||
private MediaDevice mPhoneDevice;
|
||||
|
||||
/**
|
||||
* Register to start receiving callbacks for MediaDevice events.
|
||||
*/
|
||||
public void registerCallback(DeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister to stop receiving callbacks for MediaDevice events
|
||||
*/
|
||||
public void unregisterCallback(DeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalMediaManager(Context context, String packageName, Notification notification) {
|
||||
mContext = context;
|
||||
mLocalBluetoothManager =
|
||||
LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
|
||||
if (mLocalBluetoothManager == null) {
|
||||
Log.e(TAG, "Bluetooth is not supported on this device");
|
||||
return;
|
||||
}
|
||||
|
||||
mBluetoothMediaManager =
|
||||
new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
|
||||
mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the MediaDevice to transfer media
|
||||
* @param connectDevice the MediaDevice
|
||||
*/
|
||||
public void connectDevice(MediaDevice connectDevice) {
|
||||
if (connectDevice == mLastConnectedDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLastConnectedDevice != null) {
|
||||
mLastConnectedDevice.disconnect();
|
||||
}
|
||||
|
||||
connectDevice.connect();
|
||||
if (connectDevice.isConnected()) {
|
||||
mLastConnectedDevice = connectDevice;
|
||||
}
|
||||
|
||||
final int state = connectDevice.isConnected()
|
||||
? MediaDeviceState.STATE_CONNECTED
|
||||
: MediaDeviceState.STATE_DISCONNECTED;
|
||||
dispatchSelectedDeviceStateChanged(connectDevice, state);
|
||||
}
|
||||
|
||||
void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
|
||||
synchronized (mCallbacks) {
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onSelectedDeviceStateChanged(device, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start scan connected MediaDevice
|
||||
*/
|
||||
public void startScan() {
|
||||
mMediaDevices.clear();
|
||||
mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
|
||||
mInfoMediaManager.registerCallback(mMediaDeviceCallback);
|
||||
mBluetoothMediaManager.startScan();
|
||||
mInfoMediaManager.startScan();
|
||||
}
|
||||
|
||||
private void addPhoneDeviceIfNecessary() {
|
||||
// add phone device to list if there have any Bluetooth device and cast device.
|
||||
if (mMediaDevices.size() > 0 && !mMediaDevices.contains(mPhoneDevice)) {
|
||||
if (mPhoneDevice == null) {
|
||||
mPhoneDevice = new PhoneMediaDevice(mContext, mLocalBluetoothManager);
|
||||
}
|
||||
mMediaDevices.add(mPhoneDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void removePhoneMediaDeviceIfNecessary() {
|
||||
// if PhoneMediaDevice is the last item in the list, remove it.
|
||||
if (mMediaDevices.size() == 1 && mMediaDevices.contains(mPhoneDevice)) {
|
||||
mMediaDevices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchDeviceListUpdate() {
|
||||
synchronized (mCallbacks) {
|
||||
for (DeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop scan MediaDevice
|
||||
*/
|
||||
public void stopScan() {
|
||||
mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
|
||||
mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
|
||||
mBluetoothMediaManager.stopScan();
|
||||
mInfoMediaManager.stopScan();
|
||||
}
|
||||
|
||||
class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
|
||||
@Override
|
||||
public void onDeviceAdded(MediaDevice device) {
|
||||
if (!mMediaDevices.contains(device)) {
|
||||
mMediaDevices.add(device);
|
||||
addPhoneDeviceIfNecessary();
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceListAdded(List<MediaDevice> devices) {
|
||||
mMediaDevices.addAll(devices);
|
||||
addPhoneDeviceIfNecessary();
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceRemoved(MediaDevice device) {
|
||||
if (mMediaDevices.contains(device)) {
|
||||
mMediaDevices.remove(device);
|
||||
removePhoneMediaDeviceIfNecessary();
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceListRemoved(List<MediaDevice> devices) {
|
||||
mMediaDevices.removeAll(devices);
|
||||
removePhoneMediaDeviceIfNecessary();
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAttributesChanged() {
|
||||
dispatchDeviceListUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for notifying device information updating
|
||||
*/
|
||||
public interface DeviceCallback {
|
||||
/**
|
||||
* Callback for notifying device list updated.
|
||||
*
|
||||
* @param devices MediaDevice list
|
||||
*/
|
||||
void onDeviceListUpdate(List<MediaDevice> devices);
|
||||
|
||||
/**
|
||||
* Callback for notifying the connected device is changed.
|
||||
*
|
||||
* @param device the changed connected MediaDevice
|
||||
* @param state the current MediaDevice state, the possible values are:
|
||||
* {@link MediaDeviceState#STATE_CONNECTED},
|
||||
* {@link MediaDeviceState#STATE_CONNECTING},
|
||||
* {@link MediaDeviceState#STATE_DISCONNECTED}
|
||||
*/
|
||||
void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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 android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MediaManager provide interface to get MediaDevice list.
|
||||
*/
|
||||
public abstract class MediaManager {
|
||||
|
||||
private static final String TAG = "MediaManager";
|
||||
|
||||
protected final Collection<MediaDeviceCallback> mCallbacks = new ArrayList<>();
|
||||
protected final List<MediaDevice> mMediaDevices = new ArrayList<>();
|
||||
|
||||
protected Context mContext;
|
||||
protected Notification mNotification;
|
||||
|
||||
MediaManager(Context context, Notification notification) {
|
||||
mContext = context;
|
||||
mNotification = notification;
|
||||
}
|
||||
|
||||
protected void registerCallback(MediaDeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
if (!mCallbacks.contains(callback)) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void unregisterCallback(MediaDeviceCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
if (mCallbacks.contains(callback)) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start scan connected MediaDevice
|
||||
*/
|
||||
public abstract void startScan();
|
||||
|
||||
/**
|
||||
* Stop scan MediaDevice
|
||||
*/
|
||||
public abstract void stopScan();
|
||||
|
||||
protected MediaDevice findMediaDevice(String id) {
|
||||
for (MediaDevice mediaDevice : mMediaDevices) {
|
||||
if (mediaDevice.getId().equals(id)) {
|
||||
return mediaDevice;
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "findMediaDevice() can't found device");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceAdded(mediaDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceRemoved(MediaDevice mediaDevice) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceRemoved(mediaDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceListAdded() {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListAdded(mMediaDevices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceListRemoved(List<MediaDevice> devices) {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceListRemoved(devices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void dispatchDeviceAttributesChanged() {
|
||||
synchronized (mCallbacks) {
|
||||
for (MediaDeviceCallback callback : mCallbacks) {
|
||||
callback.onDeviceAttributesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for notifying device is added, removed and attributes changed.
|
||||
*/
|
||||
public interface MediaDeviceCallback {
|
||||
/**
|
||||
* Callback for notifying MediaDevice is added.
|
||||
*
|
||||
* @param device the MediaDevice
|
||||
*/
|
||||
void onDeviceAdded(MediaDevice device);
|
||||
|
||||
/**
|
||||
* Callback for notifying MediaDevice list is added.
|
||||
*
|
||||
* @param devices the MediaDevice list
|
||||
*/
|
||||
void onDeviceListAdded(List<MediaDevice> devices);
|
||||
|
||||
/**
|
||||
* Callback for notifying MediaDevice is removed.
|
||||
*
|
||||
* @param device the MediaDevice
|
||||
*/
|
||||
void onDeviceRemoved(MediaDevice device);
|
||||
|
||||
/**
|
||||
* Callback for notifying MediaDevice list is removed.
|
||||
*
|
||||
* @param devices the MediaDevice list
|
||||
*/
|
||||
void onDeviceListRemoved(List<MediaDevice> devices);
|
||||
|
||||
/**
|
||||
* Callback for notifying MediaDevice attributes is changed.
|
||||
*/
|
||||
void onDeviceAttributesChanged();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user