blob: 9ae9b4a462277cabf5a140158036c1b05998b0ee [file] [log] [blame]
hughchena73686f2018-11-12 17:42:08 +08001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.settingslib.media;
17
18import android.app.Notification;
hughchenb3d68f62020-02-11 14:30:14 +080019import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothDevice;
hughchenbd0dd492019-01-08 14:34:10 +080021import android.bluetooth.BluetoothProfile;
hughchena73686f2018-11-12 17:42:08 +080022import android.content.Context;
hughchendf7b8382020-02-03 17:48:49 +080023import android.text.TextUtils;
hughchena73686f2018-11-12 17:42:08 +080024import android.util.Log;
25
26import androidx.annotation.IntDef;
27
hughchenbd0dd492019-01-08 14:34:10 +080028import com.android.internal.annotations.VisibleForTesting;
hughchena73686f2018-11-12 17:42:08 +080029import com.android.settingslib.bluetooth.BluetoothCallback;
hughchenbd0dd492019-01-08 14:34:10 +080030import com.android.settingslib.bluetooth.CachedBluetoothDevice;
hughchenb3d68f62020-02-11 14:30:14 +080031import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
hughchena73686f2018-11-12 17:42:08 +080032import com.android.settingslib.bluetooth.LocalBluetoothManager;
33
34import java.lang.annotation.Retention;
35import java.lang.annotation.RetentionPolicy;
36import java.util.ArrayList;
37import java.util.Collection;
timhypenga8b826c2018-11-14 15:33:53 +080038import java.util.Comparator;
hughchena73686f2018-11-12 17:42:08 +080039import java.util.List;
hughchen8175bf22020-02-12 18:52:34 +080040import java.util.concurrent.CopyOnWriteArrayList;
hughchena73686f2018-11-12 17:42:08 +080041
42/**
43 * LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
44 */
45public class LocalMediaManager implements BluetoothCallback {
timhypenga8b826c2018-11-14 15:33:53 +080046 private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
hughchena73686f2018-11-12 17:42:08 +080047 private static final String TAG = "LocalMediaManager";
48
49 @Retention(RetentionPolicy.SOURCE)
50 @IntDef({MediaDeviceState.STATE_CONNECTED,
51 MediaDeviceState.STATE_CONNECTING,
Tim Pengdbdfaef2020-03-11 11:30:01 +080052 MediaDeviceState.STATE_DISCONNECTED,
53 MediaDeviceState.STATE_CONNECTING_FAILED})
hughchena73686f2018-11-12 17:42:08 +080054 public @interface MediaDeviceState {
Tim Pengdbdfaef2020-03-11 11:30:01 +080055 int STATE_CONNECTED = 0;
56 int STATE_CONNECTING = 1;
57 int STATE_DISCONNECTED = 2;
58 int STATE_CONNECTING_FAILED = 3;
hughchena73686f2018-11-12 17:42:08 +080059 }
60
hughchen8175bf22020-02-12 18:52:34 +080061 private final Collection<DeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
hughchenbd0dd492019-01-08 14:34:10 +080062 @VisibleForTesting
63 final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
hughchena73686f2018-11-12 17:42:08 +080064
65 private Context mContext;
hughchena73686f2018-11-12 17:42:08 +080066 private LocalBluetoothManager mLocalBluetoothManager;
hughchene6a4f482019-10-18 17:34:15 +080067 private InfoMediaManager mInfoMediaManager;
68 private String mPackageName;
hughchenbd0dd492019-01-08 14:34:10 +080069
70 @VisibleForTesting
71 List<MediaDevice> mMediaDevices = new ArrayList<>();
72 @VisibleForTesting
hughchenb3d68f62020-02-11 14:30:14 +080073 List<MediaDevice> mDisconnectedMediaDevices = new ArrayList<>();
74 @VisibleForTesting
hughchenbd0dd492019-01-08 14:34:10 +080075 MediaDevice mPhoneDevice;
76 @VisibleForTesting
77 MediaDevice mCurrentConnectedDevice;
hughchenb3d68f62020-02-11 14:30:14 +080078 @VisibleForTesting
79 DeviceAttributeChangeCallback mDeviceAttributeChangeCallback =
80 new DeviceAttributeChangeCallback();
81 @VisibleForTesting
82 BluetoothAdapter mBluetoothAdapter;
hughchena73686f2018-11-12 17:42:08 +080083
84 /**
85 * Register to start receiving callbacks for MediaDevice events.
86 */
87 public void registerCallback(DeviceCallback callback) {
hughchen8175bf22020-02-12 18:52:34 +080088 mCallbacks.add(callback);
hughchena73686f2018-11-12 17:42:08 +080089 }
90
91 /**
92 * Unregister to stop receiving callbacks for MediaDevice events
93 */
94 public void unregisterCallback(DeviceCallback callback) {
hughchen8175bf22020-02-12 18:52:34 +080095 mCallbacks.remove(callback);
hughchena73686f2018-11-12 17:42:08 +080096 }
97
Fabian Kozynskie7316342020-03-16 13:31:06 -040098 /**
99 * Creates a LocalMediaManager with references to given managers.
100 *
101 * It will obtain a {@link LocalBluetoothManager} by calling
102 * {@link LocalBluetoothManager#getInstance} and create an {@link InfoMediaManager} passing
103 * that bluetooth manager.
104 *
105 * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter.
106 */
hughchena73686f2018-11-12 17:42:08 +0800107 public LocalMediaManager(Context context, String packageName, Notification notification) {
108 mContext = context;
hughchene6a4f482019-10-18 17:34:15 +0800109 mPackageName = packageName;
hughchena73686f2018-11-12 17:42:08 +0800110 mLocalBluetoothManager =
111 LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
hughchenb3d68f62020-02-11 14:30:14 +0800112 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
hughchena73686f2018-11-12 17:42:08 +0800113 if (mLocalBluetoothManager == null) {
114 Log.e(TAG, "Bluetooth is not supported on this device");
115 return;
116 }
117
hughchen491b9fc2020-02-05 18:31:36 +0800118 mInfoMediaManager =
119 new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager);
hughchena73686f2018-11-12 17:42:08 +0800120 }
121
Fabian Kozynskie7316342020-03-16 13:31:06 -0400122 /**
123 * Creates a LocalMediaManager with references to given managers.
124 *
125 * It will use {@link BluetoothAdapter#getDefaultAdapter()] for setting the bluetooth adapter.
126 */
Fabian Kozynskicc4c6c32020-03-09 15:11:33 -0400127 public LocalMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
hughchendf7b8382020-02-03 17:48:49 +0800128 InfoMediaManager infoMediaManager, String packageName) {
hughchenbd0dd492019-01-08 14:34:10 +0800129 mContext = context;
130 mLocalBluetoothManager = localBluetoothManager;
hughchene6a4f482019-10-18 17:34:15 +0800131 mInfoMediaManager = infoMediaManager;
hughchendf7b8382020-02-03 17:48:49 +0800132 mPackageName = packageName;
Fabian Kozynskie7316342020-03-16 13:31:06 -0400133 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
hughchenbd0dd492019-01-08 14:34:10 +0800134 }
135
hughchena73686f2018-11-12 17:42:08 +0800136 /**
137 * Connect the MediaDevice to transfer media
138 * @param connectDevice the MediaDevice
139 */
140 public void connectDevice(MediaDevice connectDevice) {
hughchenbd0dd492019-01-08 14:34:10 +0800141 final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
hughchenc0c11632019-03-07 16:21:17 +0800142 if (device instanceof BluetoothMediaDevice) {
143 final CachedBluetoothDevice cachedDevice =
144 ((BluetoothMediaDevice) device).getCachedDevice();
145 if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
Tim Pengdbdfaef2020-03-11 11:30:01 +0800146 device.setState(MediaDeviceState.STATE_CONNECTING);
hughchen4ae21862020-01-14 15:55:29 +0800147 cachedDevice.connect();
hughchenc0c11632019-03-07 16:21:17 +0800148 return;
149 }
150 }
151
hughchenbd0dd492019-01-08 14:34:10 +0800152 if (device == mCurrentConnectedDevice) {
153 Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
hughchena73686f2018-11-12 17:42:08 +0800154 return;
155 }
156
hughchene6a4f482019-10-18 17:34:15 +0800157 if (mCurrentConnectedDevice != null) {
hughchenbd0dd492019-01-08 14:34:10 +0800158 mCurrentConnectedDevice.disconnect();
hughchena73686f2018-11-12 17:42:08 +0800159 }
160
Tim Pengdbdfaef2020-03-11 11:30:01 +0800161 device.setState(MediaDeviceState.STATE_CONNECTING);
hughchendf7b8382020-02-03 17:48:49 +0800162 if (TextUtils.isEmpty(mPackageName)) {
hughchen063a35a2020-03-04 17:51:57 +0800163 mInfoMediaManager.connectDeviceWithoutPackageName(device);
hughchendf7b8382020-02-03 17:48:49 +0800164 } else {
hughchen063a35a2020-03-04 17:51:57 +0800165 device.connect();
hughchendf7b8382020-02-03 17:48:49 +0800166 }
hughchena73686f2018-11-12 17:42:08 +0800167 }
168
timhypeng97c6cf62018-12-27 15:40:32 +0800169 void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
hughchen8175bf22020-02-12 18:52:34 +0800170 for (DeviceCallback callback : getCallbacks()) {
171 callback.onSelectedDeviceStateChanged(device, state);
hughchena73686f2018-11-12 17:42:08 +0800172 }
173 }
174
175 /**
176 * Start scan connected MediaDevice
177 */
178 public void startScan() {
179 mMediaDevices.clear();
hughchen0d202042020-01-17 18:30:03 +0800180 mInfoMediaManager.registerCallback(mMediaDeviceCallback);
181 mInfoMediaManager.startScan();
hughchena73686f2018-11-12 17:42:08 +0800182 }
183
hughchena73686f2018-11-12 17:42:08 +0800184 void dispatchDeviceListUpdate() {
hughchenb3d68f62020-02-11 14:30:14 +0800185 //TODO(b/149260820): Use new rule to rank device once device type api is ready.
hughchen8175bf22020-02-12 18:52:34 +0800186 for (DeviceCallback callback : getCallbacks()) {
187 callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
hughchena73686f2018-11-12 17:42:08 +0800188 }
189 }
190
hughchene572b832020-01-08 18:07:18 +0800191 void dispatchDeviceAttributesChanged() {
hughchen8175bf22020-02-12 18:52:34 +0800192 for (DeviceCallback callback : getCallbacks()) {
193 callback.onDeviceAttributesChanged();
hughchene572b832020-01-08 18:07:18 +0800194 }
195 }
196
hughchen063a35a2020-03-04 17:51:57 +0800197 void dispatchOnRequestFailed(int reason) {
198 for (DeviceCallback callback : getCallbacks()) {
199 callback.onRequestFailed(reason);
200 }
201 }
202
hughchena73686f2018-11-12 17:42:08 +0800203 /**
204 * Stop scan MediaDevice
205 */
206 public void stopScan() {
hughchen0d202042020-01-17 18:30:03 +0800207 mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
208 mInfoMediaManager.stopScan();
hughchena73686f2018-11-12 17:42:08 +0800209 }
210
hughchen04872632018-12-24 14:41:20 +0800211 /**
212 * Find the MediaDevice through id.
213 *
214 * @param devices the list of MediaDevice
215 * @param id the unique id of MediaDevice
216 * @return MediaDevice
217 */
218 public MediaDevice getMediaDeviceById(List<MediaDevice> devices, String id) {
219 for (MediaDevice mediaDevice : devices) {
220 if (mediaDevice.getId().equals(id)) {
221 return mediaDevice;
222 }
223 }
224 Log.i(TAG, "getMediaDeviceById() can't found device");
225 return null;
226 }
227
hughchenbd0dd492019-01-08 14:34:10 +0800228 /**
timhypengd37d70b2020-02-05 13:52:37 +0800229 * Find the MediaDevice from all media devices by id.
230 *
231 * @param id the unique id of MediaDevice
232 * @return MediaDevice
233 */
234 public MediaDevice getMediaDeviceById(String id) {
235 for (MediaDevice mediaDevice : mMediaDevices) {
236 if (mediaDevice.getId().equals(id)) {
237 return mediaDevice;
238 }
239 }
240 Log.i(TAG, "Unable to find device " + id);
241 return null;
242 }
243
244 /**
hughchenbd0dd492019-01-08 14:34:10 +0800245 * Find the current connected MediaDevice.
246 *
247 * @return MediaDevice
248 */
249 public MediaDevice getCurrentConnectedDevice() {
250 return mCurrentConnectedDevice;
251 }
252
timhypenga812e882020-02-04 17:15:48 +0800253 /**
254 * Find the active MediaDevice.
255 *
256 * @param type the media device type.
257 * @return MediaDevice list
258 */
259 public List<MediaDevice> getActiveMediaDevice(@MediaDevice.MediaDeviceType int type) {
260 final List<MediaDevice> devices = new ArrayList<>();
261 for (MediaDevice device : mMediaDevices) {
262 if (type == device.mType && device.getClientPackageName() != null) {
263 devices.add(device);
264 }
265 }
266 return devices;
267 }
268
hughchen6ab62ca2020-02-12 10:40:04 +0800269 /**
270 * Add a MediaDevice to let it play current media.
271 *
272 * @param device MediaDevice
273 * @return If add device successful return {@code true}, otherwise return {@code false}
274 */
275 public boolean addDeviceToPlayMedia(MediaDevice device) {
276 return mInfoMediaManager.addDeviceToPlayMedia(device);
277 }
278
279 /**
280 * Remove a {@code device} from current media.
281 *
282 * @param device MediaDevice
283 * @return If device stop successful return {@code true}, otherwise return {@code false}
284 */
285 public boolean removeDeviceFromPlayMedia(MediaDevice device) {
286 return mInfoMediaManager.removeDeviceFromPlayMedia(device);
287 }
288
289 /**
290 * Get the MediaDevice list that can be added to current media.
291 *
292 * @return list of MediaDevice
293 */
294 public List<MediaDevice> getSelectableMediaDevice() {
295 return mInfoMediaManager.getSelectableMediaDevice();
296 }
297
298 /**
hughchen61bced02020-02-20 18:46:32 +0800299 * Release session to stop playing media on MediaDevice.
300 */
301 public boolean releaseSession() {
302 return mInfoMediaManager.releaseSession();
303 }
304
305 /**
timhypeng6bbd5552020-02-17 14:53:45 +0800306 * Get the MediaDevice list that has been selected to current media.
307 *
308 * @return list of MediaDevice
309 */
310 public List<MediaDevice> getSelectedMediaDevice() {
311 return mInfoMediaManager.getSelectedMediaDevice();
312 }
313
314 /**
hughchen6ab62ca2020-02-12 10:40:04 +0800315 * Adjust the volume of session.
316 *
317 * @param volume the value of volume
318 */
319 public void adjustSessionVolume(int volume) {
320 mInfoMediaManager.adjustSessionVolume(volume);
321 }
322
323 /**
324 * Gets the maximum volume of the {@link android.media.RoutingSessionInfo}.
325 *
326 * @return maximum volume of the session, and return -1 if not found.
327 */
328 public int getSessionVolumeMax() {
329 return mInfoMediaManager.getSessionVolumeMax();
330 }
331
332 /**
333 * Gets the current volume of the {@link android.media.RoutingSessionInfo}.
334 *
335 * @return current volume of the session, and return -1 if not found.
336 */
337 public int getSessionVolume() {
338 return mInfoMediaManager.getSessionVolume();
339 }
340
Tim Peng635b04a2020-03-05 13:08:02 +0800341 /**
342 * Gets the user-visible name of the {@link android.media.RoutingSessionInfo}.
343 *
344 * @return current name of the session, and return {@code null} if not found.
345 */
346 public CharSequence getSessionName() {
347 return mInfoMediaManager.getSessionName();
348 }
349
hughchenbd0dd492019-01-08 14:34:10 +0800350 private MediaDevice updateCurrentConnectedDevice() {
hughchen491b9fc2020-02-05 18:31:36 +0800351 MediaDevice phoneMediaDevice = null;
hughchenbd0dd492019-01-08 14:34:10 +0800352 for (MediaDevice device : mMediaDevices) {
353 if (device instanceof BluetoothMediaDevice) {
hughchen063a35a2020-03-04 17:51:57 +0800354 if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) {
hughchenbd0dd492019-01-08 14:34:10 +0800355 return device;
356 }
hughchen491b9fc2020-02-05 18:31:36 +0800357 } else if (device instanceof PhoneMediaDevice) {
358 phoneMediaDevice = device;
hughchenbd0dd492019-01-08 14:34:10 +0800359 }
360 }
hughchen491b9fc2020-02-05 18:31:36 +0800361 return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null;
hughchenbd0dd492019-01-08 14:34:10 +0800362 }
363
hughchen063a35a2020-03-04 17:51:57 +0800364 private boolean isActiveDevice(CachedBluetoothDevice device) {
hughchenbd0dd492019-01-08 14:34:10 +0800365 return device.isActiveDevice(BluetoothProfile.A2DP)
366 || device.isActiveDevice(BluetoothProfile.HEARING_AID);
367 }
368
hughchen8175bf22020-02-12 18:52:34 +0800369 private Collection<DeviceCallback> getCallbacks() {
370 return new CopyOnWriteArrayList<>(mCallbacks);
371 }
372
hughchena73686f2018-11-12 17:42:08 +0800373 class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
374 @Override
375 public void onDeviceAdded(MediaDevice device) {
376 if (!mMediaDevices.contains(device)) {
377 mMediaDevices.add(device);
hughchena73686f2018-11-12 17:42:08 +0800378 dispatchDeviceListUpdate();
379 }
380 }
381
382 @Override
383 public void onDeviceListAdded(List<MediaDevice> devices) {
hughchendf7b8382020-02-03 17:48:49 +0800384 mMediaDevices.clear();
385 mMediaDevices.addAll(devices);
hughchenb3d68f62020-02-11 14:30:14 +0800386 mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
387
hughchene6a4f482019-10-18 17:34:15 +0800388 final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
389 mCurrentConnectedDevice = infoMediaDevice != null
390 ? infoMediaDevice : updateCurrentConnectedDevice();
hughchena73686f2018-11-12 17:42:08 +0800391 dispatchDeviceListUpdate();
392 }
393
hughchenb3d68f62020-02-11 14:30:14 +0800394 private List<MediaDevice> buildDisconnectedBluetoothDevice() {
395 for (MediaDevice device : mDisconnectedMediaDevices) {
396 ((BluetoothMediaDevice) device).getCachedDevice()
397 .unregisterCallback(mDeviceAttributeChangeCallback);
398 }
399 mDisconnectedMediaDevices.clear();
400 final List<BluetoothDevice> bluetoothDevices =
401 mBluetoothAdapter.getMostRecentlyConnectedDevices();
402 final CachedBluetoothDeviceManager cachedDeviceManager =
403 mLocalBluetoothManager.getCachedDeviceManager();
404
405 for (BluetoothDevice device : bluetoothDevices) {
406 final CachedBluetoothDevice cachedDevice =
407 cachedDeviceManager.findDevice(device);
408 if (cachedDevice != null) {
409 if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
410 && !cachedDevice.isConnected()) {
411 final MediaDevice mediaDevice = new BluetoothMediaDevice(mContext,
412 cachedDevice,
413 null, null, mPackageName);
414 if (!mMediaDevices.contains(mediaDevice)) {
415 cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
416 mDisconnectedMediaDevices.add(mediaDevice);
417 }
418 }
419 }
420 }
421 return new ArrayList<>(mDisconnectedMediaDevices);
422 }
423
hughchena73686f2018-11-12 17:42:08 +0800424 @Override
425 public void onDeviceRemoved(MediaDevice device) {
426 if (mMediaDevices.contains(device)) {
427 mMediaDevices.remove(device);
hughchena73686f2018-11-12 17:42:08 +0800428 dispatchDeviceListUpdate();
429 }
430 }
431
432 @Override
433 public void onDeviceListRemoved(List<MediaDevice> devices) {
434 mMediaDevices.removeAll(devices);
hughchena73686f2018-11-12 17:42:08 +0800435 dispatchDeviceListUpdate();
436 }
437
438 @Override
hughchenbd0dd492019-01-08 14:34:10 +0800439 public void onConnectedDeviceChanged(String id) {
hughchen063a35a2020-03-04 17:51:57 +0800440 MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
441 connectDevice = connectDevice != null
442 ? connectDevice : updateCurrentConnectedDevice();
Tim Pengdbdfaef2020-03-11 11:30:01 +0800443 connectDevice.setState(MediaDeviceState.STATE_CONNECTED);
hughchenbd0dd492019-01-08 14:34:10 +0800444
445 if (connectDevice == mCurrentConnectedDevice) {
hughchenc0c11632019-03-07 16:21:17 +0800446 Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!");
hughchenbd0dd492019-01-08 14:34:10 +0800447 return;
448 }
449 mCurrentConnectedDevice = connectDevice;
hughchen063a35a2020-03-04 17:51:57 +0800450 dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
451 MediaDeviceState.STATE_CONNECTED);
hughchenc0c11632019-03-07 16:21:17 +0800452 }
hughchenbd0dd492019-01-08 14:34:10 +0800453
hughchenc0c11632019-03-07 16:21:17 +0800454 @Override
455 public void onDeviceAttributesChanged() {
hughchene572b832020-01-08 18:07:18 +0800456 dispatchDeviceAttributesChanged();
hughchenbd0dd492019-01-08 14:34:10 +0800457 }
hughchen063a35a2020-03-04 17:51:57 +0800458
459 @Override
460 public void onRequestFailed(int reason) {
Tim Pengdbdfaef2020-03-11 11:30:01 +0800461 for (MediaDevice device : mMediaDevices) {
462 if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
463 device.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
464 }
465 }
hughchen063a35a2020-03-04 17:51:57 +0800466 dispatchOnRequestFailed(reason);
467 }
hughchena73686f2018-11-12 17:42:08 +0800468 }
469
470
471 /**
472 * Callback for notifying device information updating
473 */
474 public interface DeviceCallback {
475 /**
476 * Callback for notifying device list updated.
477 *
478 * @param devices MediaDevice list
479 */
hughchene572b832020-01-08 18:07:18 +0800480 default void onDeviceListUpdate(List<MediaDevice> devices) {};
hughchena73686f2018-11-12 17:42:08 +0800481
482 /**
483 * Callback for notifying the connected device is changed.
484 *
485 * @param device the changed connected MediaDevice
486 * @param state the current MediaDevice state, the possible values are:
487 * {@link MediaDeviceState#STATE_CONNECTED},
488 * {@link MediaDeviceState#STATE_CONNECTING},
489 * {@link MediaDeviceState#STATE_DISCONNECTED}
490 */
hughchene572b832020-01-08 18:07:18 +0800491 default void onSelectedDeviceStateChanged(MediaDevice device,
492 @MediaDeviceState int state) {};
493
494 /**
495 * Callback for notifying the device attributes is changed.
496 */
497 default void onDeviceAttributesChanged() {};
hughchen063a35a2020-03-04 17:51:57 +0800498
499 /**
500 * Callback for notifying that transferring is failed.
501 *
502 * @param reason the reason that the request has failed. Can be one of followings:
503 * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR},
504 * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED},
505 * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR},
506 * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE},
507 * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND},
508 */
509 default void onRequestFailed(int reason){};
hughchena73686f2018-11-12 17:42:08 +0800510 }
hughchenb3d68f62020-02-11 14:30:14 +0800511
512 /**
513 * This callback is for update {@link BluetoothMediaDevice} summary when
514 * {@link CachedBluetoothDevice} connection state is changed.
515 */
516 @VisibleForTesting
517 class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
518
519 @Override
520 public void onDeviceAttributesChanged() {
521 dispatchDeviceAttributesChanged();
522 }
523 }
hughchena73686f2018-11-12 17:42:08 +0800524}