blob: 44b481dea77dda43ce1ed46a0bba49587fa32b57 [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
98 public LocalMediaManager(Context context, String packageName, Notification notification) {
99 mContext = context;
hughchene6a4f482019-10-18 17:34:15 +0800100 mPackageName = packageName;
hughchena73686f2018-11-12 17:42:08 +0800101 mLocalBluetoothManager =
102 LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
hughchenb3d68f62020-02-11 14:30:14 +0800103 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
hughchena73686f2018-11-12 17:42:08 +0800104 if (mLocalBluetoothManager == null) {
105 Log.e(TAG, "Bluetooth is not supported on this device");
106 return;
107 }
108
hughchen491b9fc2020-02-05 18:31:36 +0800109 mInfoMediaManager =
110 new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager);
hughchena73686f2018-11-12 17:42:08 +0800111 }
112
Fabian Kozynskicc4c6c32020-03-09 15:11:33 -0400113 public LocalMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
hughchendf7b8382020-02-03 17:48:49 +0800114 InfoMediaManager infoMediaManager, String packageName) {
hughchenbd0dd492019-01-08 14:34:10 +0800115 mContext = context;
116 mLocalBluetoothManager = localBluetoothManager;
hughchene6a4f482019-10-18 17:34:15 +0800117 mInfoMediaManager = infoMediaManager;
hughchendf7b8382020-02-03 17:48:49 +0800118 mPackageName = packageName;
hughchenbd0dd492019-01-08 14:34:10 +0800119 }
120
hughchena73686f2018-11-12 17:42:08 +0800121 /**
122 * Connect the MediaDevice to transfer media
123 * @param connectDevice the MediaDevice
124 */
125 public void connectDevice(MediaDevice connectDevice) {
hughchenbd0dd492019-01-08 14:34:10 +0800126 final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
hughchenc0c11632019-03-07 16:21:17 +0800127 if (device instanceof BluetoothMediaDevice) {
128 final CachedBluetoothDevice cachedDevice =
129 ((BluetoothMediaDevice) device).getCachedDevice();
130 if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
Tim Pengdbdfaef2020-03-11 11:30:01 +0800131 device.setState(MediaDeviceState.STATE_CONNECTING);
hughchen4ae21862020-01-14 15:55:29 +0800132 cachedDevice.connect();
hughchenc0c11632019-03-07 16:21:17 +0800133 return;
134 }
135 }
136
hughchenbd0dd492019-01-08 14:34:10 +0800137 if (device == mCurrentConnectedDevice) {
138 Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
hughchena73686f2018-11-12 17:42:08 +0800139 return;
140 }
141
hughchene6a4f482019-10-18 17:34:15 +0800142 if (mCurrentConnectedDevice != null) {
hughchenbd0dd492019-01-08 14:34:10 +0800143 mCurrentConnectedDevice.disconnect();
hughchena73686f2018-11-12 17:42:08 +0800144 }
145
Tim Pengdbdfaef2020-03-11 11:30:01 +0800146 device.setState(MediaDeviceState.STATE_CONNECTING);
hughchendf7b8382020-02-03 17:48:49 +0800147 if (TextUtils.isEmpty(mPackageName)) {
hughchen063a35a2020-03-04 17:51:57 +0800148 mInfoMediaManager.connectDeviceWithoutPackageName(device);
hughchendf7b8382020-02-03 17:48:49 +0800149 } else {
hughchen063a35a2020-03-04 17:51:57 +0800150 device.connect();
hughchendf7b8382020-02-03 17:48:49 +0800151 }
hughchena73686f2018-11-12 17:42:08 +0800152 }
153
timhypeng97c6cf62018-12-27 15:40:32 +0800154 void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
hughchen8175bf22020-02-12 18:52:34 +0800155 for (DeviceCallback callback : getCallbacks()) {
156 callback.onSelectedDeviceStateChanged(device, state);
hughchena73686f2018-11-12 17:42:08 +0800157 }
158 }
159
160 /**
161 * Start scan connected MediaDevice
162 */
163 public void startScan() {
164 mMediaDevices.clear();
hughchen0d202042020-01-17 18:30:03 +0800165 mInfoMediaManager.registerCallback(mMediaDeviceCallback);
166 mInfoMediaManager.startScan();
hughchena73686f2018-11-12 17:42:08 +0800167 }
168
hughchena73686f2018-11-12 17:42:08 +0800169 void dispatchDeviceListUpdate() {
hughchenb3d68f62020-02-11 14:30:14 +0800170 //TODO(b/149260820): Use new rule to rank device once device type api is ready.
hughchen8175bf22020-02-12 18:52:34 +0800171 for (DeviceCallback callback : getCallbacks()) {
172 callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
hughchena73686f2018-11-12 17:42:08 +0800173 }
174 }
175
hughchene572b832020-01-08 18:07:18 +0800176 void dispatchDeviceAttributesChanged() {
hughchen8175bf22020-02-12 18:52:34 +0800177 for (DeviceCallback callback : getCallbacks()) {
178 callback.onDeviceAttributesChanged();
hughchene572b832020-01-08 18:07:18 +0800179 }
180 }
181
hughchen063a35a2020-03-04 17:51:57 +0800182 void dispatchOnRequestFailed(int reason) {
183 for (DeviceCallback callback : getCallbacks()) {
184 callback.onRequestFailed(reason);
185 }
186 }
187
hughchena73686f2018-11-12 17:42:08 +0800188 /**
189 * Stop scan MediaDevice
190 */
191 public void stopScan() {
hughchen0d202042020-01-17 18:30:03 +0800192 mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
193 mInfoMediaManager.stopScan();
hughchena73686f2018-11-12 17:42:08 +0800194 }
195
hughchen04872632018-12-24 14:41:20 +0800196 /**
197 * Find the MediaDevice through id.
198 *
199 * @param devices the list of MediaDevice
200 * @param id the unique id of MediaDevice
201 * @return MediaDevice
202 */
203 public MediaDevice getMediaDeviceById(List<MediaDevice> devices, String id) {
204 for (MediaDevice mediaDevice : devices) {
205 if (mediaDevice.getId().equals(id)) {
206 return mediaDevice;
207 }
208 }
209 Log.i(TAG, "getMediaDeviceById() can't found device");
210 return null;
211 }
212
hughchenbd0dd492019-01-08 14:34:10 +0800213 /**
timhypengd37d70b2020-02-05 13:52:37 +0800214 * Find the MediaDevice from all media devices by id.
215 *
216 * @param id the unique id of MediaDevice
217 * @return MediaDevice
218 */
219 public MediaDevice getMediaDeviceById(String id) {
220 for (MediaDevice mediaDevice : mMediaDevices) {
221 if (mediaDevice.getId().equals(id)) {
222 return mediaDevice;
223 }
224 }
225 Log.i(TAG, "Unable to find device " + id);
226 return null;
227 }
228
229 /**
hughchenbd0dd492019-01-08 14:34:10 +0800230 * Find the current connected MediaDevice.
231 *
232 * @return MediaDevice
233 */
234 public MediaDevice getCurrentConnectedDevice() {
235 return mCurrentConnectedDevice;
236 }
237
timhypenga812e882020-02-04 17:15:48 +0800238 /**
239 * Find the active MediaDevice.
240 *
241 * @param type the media device type.
242 * @return MediaDevice list
243 */
244 public List<MediaDevice> getActiveMediaDevice(@MediaDevice.MediaDeviceType int type) {
245 final List<MediaDevice> devices = new ArrayList<>();
246 for (MediaDevice device : mMediaDevices) {
247 if (type == device.mType && device.getClientPackageName() != null) {
248 devices.add(device);
249 }
250 }
251 return devices;
252 }
253
hughchen6ab62ca2020-02-12 10:40:04 +0800254 /**
255 * Add a MediaDevice to let it play current media.
256 *
257 * @param device MediaDevice
258 * @return If add device successful return {@code true}, otherwise return {@code false}
259 */
260 public boolean addDeviceToPlayMedia(MediaDevice device) {
261 return mInfoMediaManager.addDeviceToPlayMedia(device);
262 }
263
264 /**
265 * Remove a {@code device} from current media.
266 *
267 * @param device MediaDevice
268 * @return If device stop successful return {@code true}, otherwise return {@code false}
269 */
270 public boolean removeDeviceFromPlayMedia(MediaDevice device) {
271 return mInfoMediaManager.removeDeviceFromPlayMedia(device);
272 }
273
274 /**
275 * Get the MediaDevice list that can be added to current media.
276 *
277 * @return list of MediaDevice
278 */
279 public List<MediaDevice> getSelectableMediaDevice() {
280 return mInfoMediaManager.getSelectableMediaDevice();
281 }
282
283 /**
hughchen61bced02020-02-20 18:46:32 +0800284 * Release session to stop playing media on MediaDevice.
285 */
286 public boolean releaseSession() {
287 return mInfoMediaManager.releaseSession();
288 }
289
290 /**
timhypeng6bbd5552020-02-17 14:53:45 +0800291 * Get the MediaDevice list that has been selected to current media.
292 *
293 * @return list of MediaDevice
294 */
295 public List<MediaDevice> getSelectedMediaDevice() {
296 return mInfoMediaManager.getSelectedMediaDevice();
297 }
298
299 /**
hughchen6ab62ca2020-02-12 10:40:04 +0800300 * Adjust the volume of session.
301 *
302 * @param volume the value of volume
303 */
304 public void adjustSessionVolume(int volume) {
305 mInfoMediaManager.adjustSessionVolume(volume);
306 }
307
308 /**
309 * Gets the maximum volume of the {@link android.media.RoutingSessionInfo}.
310 *
311 * @return maximum volume of the session, and return -1 if not found.
312 */
313 public int getSessionVolumeMax() {
314 return mInfoMediaManager.getSessionVolumeMax();
315 }
316
317 /**
318 * Gets the current volume of the {@link android.media.RoutingSessionInfo}.
319 *
320 * @return current volume of the session, and return -1 if not found.
321 */
322 public int getSessionVolume() {
323 return mInfoMediaManager.getSessionVolume();
324 }
325
Tim Peng635b04a2020-03-05 13:08:02 +0800326 /**
327 * Gets the user-visible name of the {@link android.media.RoutingSessionInfo}.
328 *
329 * @return current name of the session, and return {@code null} if not found.
330 */
331 public CharSequence getSessionName() {
332 return mInfoMediaManager.getSessionName();
333 }
334
hughchenbd0dd492019-01-08 14:34:10 +0800335 private MediaDevice updateCurrentConnectedDevice() {
hughchen491b9fc2020-02-05 18:31:36 +0800336 MediaDevice phoneMediaDevice = null;
hughchenbd0dd492019-01-08 14:34:10 +0800337 for (MediaDevice device : mMediaDevices) {
338 if (device instanceof BluetoothMediaDevice) {
hughchen063a35a2020-03-04 17:51:57 +0800339 if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) {
hughchenbd0dd492019-01-08 14:34:10 +0800340 return device;
341 }
hughchen491b9fc2020-02-05 18:31:36 +0800342 } else if (device instanceof PhoneMediaDevice) {
343 phoneMediaDevice = device;
hughchenbd0dd492019-01-08 14:34:10 +0800344 }
345 }
hughchen491b9fc2020-02-05 18:31:36 +0800346 return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null;
hughchenbd0dd492019-01-08 14:34:10 +0800347 }
348
hughchen063a35a2020-03-04 17:51:57 +0800349 private boolean isActiveDevice(CachedBluetoothDevice device) {
hughchenbd0dd492019-01-08 14:34:10 +0800350 return device.isActiveDevice(BluetoothProfile.A2DP)
351 || device.isActiveDevice(BluetoothProfile.HEARING_AID);
352 }
353
hughchen8175bf22020-02-12 18:52:34 +0800354 private Collection<DeviceCallback> getCallbacks() {
355 return new CopyOnWriteArrayList<>(mCallbacks);
356 }
357
hughchena73686f2018-11-12 17:42:08 +0800358 class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
359 @Override
360 public void onDeviceAdded(MediaDevice device) {
361 if (!mMediaDevices.contains(device)) {
362 mMediaDevices.add(device);
hughchena73686f2018-11-12 17:42:08 +0800363 dispatchDeviceListUpdate();
364 }
365 }
366
367 @Override
368 public void onDeviceListAdded(List<MediaDevice> devices) {
hughchendf7b8382020-02-03 17:48:49 +0800369 mMediaDevices.clear();
370 mMediaDevices.addAll(devices);
hughchenb3d68f62020-02-11 14:30:14 +0800371 mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
372
hughchene6a4f482019-10-18 17:34:15 +0800373 final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
374 mCurrentConnectedDevice = infoMediaDevice != null
375 ? infoMediaDevice : updateCurrentConnectedDevice();
hughchena73686f2018-11-12 17:42:08 +0800376 dispatchDeviceListUpdate();
377 }
378
hughchenb3d68f62020-02-11 14:30:14 +0800379 private List<MediaDevice> buildDisconnectedBluetoothDevice() {
380 for (MediaDevice device : mDisconnectedMediaDevices) {
381 ((BluetoothMediaDevice) device).getCachedDevice()
382 .unregisterCallback(mDeviceAttributeChangeCallback);
383 }
384 mDisconnectedMediaDevices.clear();
385 final List<BluetoothDevice> bluetoothDevices =
386 mBluetoothAdapter.getMostRecentlyConnectedDevices();
387 final CachedBluetoothDeviceManager cachedDeviceManager =
388 mLocalBluetoothManager.getCachedDeviceManager();
389
390 for (BluetoothDevice device : bluetoothDevices) {
391 final CachedBluetoothDevice cachedDevice =
392 cachedDeviceManager.findDevice(device);
393 if (cachedDevice != null) {
394 if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
395 && !cachedDevice.isConnected()) {
396 final MediaDevice mediaDevice = new BluetoothMediaDevice(mContext,
397 cachedDevice,
398 null, null, mPackageName);
399 if (!mMediaDevices.contains(mediaDevice)) {
400 cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
401 mDisconnectedMediaDevices.add(mediaDevice);
402 }
403 }
404 }
405 }
406 return new ArrayList<>(mDisconnectedMediaDevices);
407 }
408
hughchena73686f2018-11-12 17:42:08 +0800409 @Override
410 public void onDeviceRemoved(MediaDevice device) {
411 if (mMediaDevices.contains(device)) {
412 mMediaDevices.remove(device);
hughchena73686f2018-11-12 17:42:08 +0800413 dispatchDeviceListUpdate();
414 }
415 }
416
417 @Override
418 public void onDeviceListRemoved(List<MediaDevice> devices) {
419 mMediaDevices.removeAll(devices);
hughchena73686f2018-11-12 17:42:08 +0800420 dispatchDeviceListUpdate();
421 }
422
423 @Override
hughchenbd0dd492019-01-08 14:34:10 +0800424 public void onConnectedDeviceChanged(String id) {
hughchen063a35a2020-03-04 17:51:57 +0800425 MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
426 connectDevice = connectDevice != null
427 ? connectDevice : updateCurrentConnectedDevice();
Tim Pengdbdfaef2020-03-11 11:30:01 +0800428 connectDevice.setState(MediaDeviceState.STATE_CONNECTED);
hughchenbd0dd492019-01-08 14:34:10 +0800429
430 if (connectDevice == mCurrentConnectedDevice) {
hughchenc0c11632019-03-07 16:21:17 +0800431 Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!");
hughchenbd0dd492019-01-08 14:34:10 +0800432 return;
433 }
434 mCurrentConnectedDevice = connectDevice;
hughchen063a35a2020-03-04 17:51:57 +0800435 dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
436 MediaDeviceState.STATE_CONNECTED);
hughchenc0c11632019-03-07 16:21:17 +0800437 }
hughchenbd0dd492019-01-08 14:34:10 +0800438
hughchenc0c11632019-03-07 16:21:17 +0800439 @Override
440 public void onDeviceAttributesChanged() {
hughchene572b832020-01-08 18:07:18 +0800441 dispatchDeviceAttributesChanged();
hughchenbd0dd492019-01-08 14:34:10 +0800442 }
hughchen063a35a2020-03-04 17:51:57 +0800443
444 @Override
445 public void onRequestFailed(int reason) {
Tim Pengdbdfaef2020-03-11 11:30:01 +0800446 for (MediaDevice device : mMediaDevices) {
447 if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
448 device.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
449 }
450 }
hughchen063a35a2020-03-04 17:51:57 +0800451 dispatchOnRequestFailed(reason);
452 }
hughchena73686f2018-11-12 17:42:08 +0800453 }
454
455
456 /**
457 * Callback for notifying device information updating
458 */
459 public interface DeviceCallback {
460 /**
461 * Callback for notifying device list updated.
462 *
463 * @param devices MediaDevice list
464 */
hughchene572b832020-01-08 18:07:18 +0800465 default void onDeviceListUpdate(List<MediaDevice> devices) {};
hughchena73686f2018-11-12 17:42:08 +0800466
467 /**
468 * Callback for notifying the connected device is changed.
469 *
470 * @param device the changed connected MediaDevice
471 * @param state the current MediaDevice state, the possible values are:
472 * {@link MediaDeviceState#STATE_CONNECTED},
473 * {@link MediaDeviceState#STATE_CONNECTING},
474 * {@link MediaDeviceState#STATE_DISCONNECTED}
475 */
hughchene572b832020-01-08 18:07:18 +0800476 default void onSelectedDeviceStateChanged(MediaDevice device,
477 @MediaDeviceState int state) {};
478
479 /**
480 * Callback for notifying the device attributes is changed.
481 */
482 default void onDeviceAttributesChanged() {};
hughchen063a35a2020-03-04 17:51:57 +0800483
484 /**
485 * Callback for notifying that transferring is failed.
486 *
487 * @param reason the reason that the request has failed. Can be one of followings:
488 * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR},
489 * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED},
490 * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR},
491 * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE},
492 * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND},
493 */
494 default void onRequestFailed(int reason){};
hughchena73686f2018-11-12 17:42:08 +0800495 }
hughchenb3d68f62020-02-11 14:30:14 +0800496
497 /**
498 * This callback is for update {@link BluetoothMediaDevice} summary when
499 * {@link CachedBluetoothDevice} connection state is changed.
500 */
501 @VisibleForTesting
502 class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
503
504 @Override
505 public void onDeviceAttributesChanged() {
506 dispatchDeviceAttributesChanged();
507 }
508 }
hughchena73686f2018-11-12 17:42:08 +0800509}