From 063a35ae62aae6084df3b2e1e5a413646d50c082 Mon Sep 17 00:00:00 2001 From: hughchen Date: Wed, 4 Mar 2020 17:51:57 +0800 Subject: [PATCH] Implement transfer fail callback - Implement fail callback to notify caller that transfer media is failed. - Do not update UI immediately when user doing transfer. Update the UI when onTransferred() is called. - Add test case Bug: 150752219 Test: make -j42 RunSettingsLibRoboTests Change-Id: I431cfdcfa1efb95115fd83dfd81e4135e7085ad3 --- .../settingslib/media/InfoMediaManager.java | 42 ++++++++++++++++- .../settingslib/media/LocalMediaManager.java | 47 +++++++++++++------ .../settingslib/media/MediaManager.java | 18 +++++++ .../media/InfoMediaManagerTest.java | 29 ++++++++++++ .../media/LocalMediaManagerTest.java | 9 ++++ .../settingslib/media/MediaManagerTest.java | 10 ++++ 6 files changed, 138 insertions(+), 17 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 7e78a78852a87..eb0ddfb492cbf 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -24,6 +24,7 @@ import static android.media.MediaRoute2Info.TYPE_REMOTE_TV; import static android.media.MediaRoute2Info.TYPE_UNKNOWN; import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES; import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET; +import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR; import android.app.Notification; import android.bluetooth.BluetoothAdapter; @@ -50,6 +51,7 @@ import java.util.concurrent.Executors; public class InfoMediaManager extends MediaManager { private static final String TAG = "InfoMediaManager"; + private static final boolean DEBUG = false; @VisibleForTesting final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback(); @@ -339,6 +341,9 @@ public class InfoMediaManager extends MediaManager { private void buildAllRoutes() { for (MediaRoute2Info route : mRouterManager.getAllRoutes()) { + if (DEBUG) { + Log.d(TAG, "buildAllRoutes() route : " + route.getName()); + } if (route.isSystemRoute()) { addMediaDevice(route); } @@ -347,6 +352,9 @@ public class InfoMediaManager extends MediaManager { private void buildAvailableRoutes() { for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) { + if (DEBUG) { + Log.d(TAG, "buildAvailableRoutes() route : " + route.getName()); + } addMediaDevice(route); } } @@ -363,7 +371,8 @@ public class InfoMediaManager extends MediaManager { mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route, mPackageName); if (!TextUtils.isEmpty(mPackageName) - && TextUtils.equals(route.getClientPackageName(), mPackageName)) { + && TextUtils.equals(route.getClientPackageName(), mPackageName) + && mCurrentConnectedDevice == null) { mCurrentConnectedDevice = mediaDevice; } break; @@ -409,12 +418,41 @@ public class InfoMediaManager extends MediaManager { @Override public void onRoutesChanged(List routes) { - refreshDevices(); + mMediaDevices.clear(); + mCurrentConnectedDevice = null; + if (TextUtils.isEmpty(mPackageName)) { + buildAllRoutes(); + } else { + buildAvailableRoutes(); + } + + final String id = mCurrentConnectedDevice != null + ? mCurrentConnectedDevice.getId() + : null; + dispatchConnectedDeviceChanged(id); } @Override public void onRoutesRemoved(List routes) { refreshDevices(); } + + @Override + public void onTransferred(RoutingSessionInfo oldSession, RoutingSessionInfo newSession) { + if (DEBUG) { + Log.d(TAG, "onTransferred() oldSession : " + oldSession.getName() + + ", newSession : " + newSession.getName()); + } + } + + @Override + public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) { + dispatchOnRequestFailed(REASON_UNKNOWN_ERROR); + } + + @Override + public void onRequestFailed(int reason) { + dispatchOnRequestFailed(reason); + } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index adb3c1170f8f0..90f55dd6f38d6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -142,20 +142,11 @@ public class LocalMediaManager implements BluetoothCallback { mCurrentConnectedDevice.disconnect(); } - boolean isConnected = false; if (TextUtils.isEmpty(mPackageName)) { - isConnected = mInfoMediaManager.connectDeviceWithoutPackageName(device); + mInfoMediaManager.connectDeviceWithoutPackageName(device); } else { - isConnected = device.connect(); + device.connect(); } - if (isConnected) { - mCurrentConnectedDevice = device; - } - - final int state = isConnected - ? MediaDeviceState.STATE_CONNECTED - : MediaDeviceState.STATE_DISCONNECTED; - dispatchSelectedDeviceStateChanged(device, state); } void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) { @@ -186,6 +177,12 @@ public class LocalMediaManager implements BluetoothCallback { } } + void dispatchOnRequestFailed(int reason) { + for (DeviceCallback callback : getCallbacks()) { + callback.onRequestFailed(reason); + } + } + /** * Stop scan MediaDevice */ @@ -337,7 +334,7 @@ public class LocalMediaManager implements BluetoothCallback { MediaDevice phoneMediaDevice = null; for (MediaDevice device : mMediaDevices) { if (device instanceof BluetoothMediaDevice) { - if (isConnected(((BluetoothMediaDevice) device).getCachedDevice())) { + if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) { return device; } } else if (device instanceof PhoneMediaDevice) { @@ -347,7 +344,7 @@ public class LocalMediaManager implements BluetoothCallback { return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null; } - private boolean isConnected(CachedBluetoothDevice device) { + private boolean isActiveDevice(CachedBluetoothDevice device) { return device.isActiveDevice(BluetoothProfile.A2DP) || device.isActiveDevice(BluetoothProfile.HEARING_AID); } @@ -423,20 +420,28 @@ public class LocalMediaManager implements BluetoothCallback { @Override public void onConnectedDeviceChanged(String id) { - final MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id); + MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id); + connectDevice = connectDevice != null + ? connectDevice : updateCurrentConnectedDevice(); if (connectDevice == mCurrentConnectedDevice) { Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!"); return; } mCurrentConnectedDevice = connectDevice; - dispatchDeviceAttributesChanged(); + dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice, + MediaDeviceState.STATE_CONNECTED); } @Override public void onDeviceAttributesChanged() { dispatchDeviceAttributesChanged(); } + + @Override + public void onRequestFailed(int reason) { + dispatchOnRequestFailed(reason); + } } @@ -467,6 +472,18 @@ public class LocalMediaManager implements BluetoothCallback { * Callback for notifying the device attributes is changed. */ default void onDeviceAttributesChanged() {}; + + /** + * Callback for notifying that transferring is failed. + * + * @param reason the reason that the request has failed. Can be one of followings: + * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR}, + * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED}, + * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR}, + * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE}, + * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND}, + */ + default void onRequestFailed(int reason){}; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java index 73551f60c462b..e8cbab8197b2a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java @@ -110,6 +110,12 @@ public abstract class MediaManager { } } + protected void dispatchOnRequestFailed(int reason) { + for (MediaDeviceCallback callback : getCallbacks()) { + callback.onRequestFailed(reason); + } + } + private Collection getCallbacks() { return new CopyOnWriteArrayList<>(mCallbacks); } @@ -158,5 +164,17 @@ public abstract class MediaManager { * (e.g: device name, connection state, subtitle) is changed. */ void onDeviceAttributesChanged(); + + /** + * Callback for notifying that transferring is failed. + * + * @param reason the reason that the request has failed. Can be one of followings: + * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR}, + * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED}, + * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR}, + * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE}, + * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND}, + */ + void onRequestFailed(int reason); } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java index 7cd0a7ce04379..7f93f697152c7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java @@ -16,6 +16,9 @@ package com.android.settingslib.media; +import static android.media.MediaRoute2ProviderService.REASON_NETWORK_ERROR; +import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -54,6 +57,8 @@ public class InfoMediaManagerTest { private MediaRouter2Manager mRouterManager; @Mock private LocalBluetoothManager mLocalBluetoothManager; + @Mock + private MediaManager.MediaDeviceCallback mCallback; private InfoMediaManager mInfoMediaManager; private Context mContext; @@ -144,6 +149,8 @@ public class InfoMediaManagerTest { @Test public void onRoutesChanged_getAvailableRoutes_shouldAddMediaDevice() { final MediaRoute2Info info = mock(MediaRoute2Info.class); + mInfoMediaManager.registerCallback(mCallback); + when(info.getId()).thenReturn(TEST_ID); when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME); @@ -160,11 +167,14 @@ public class InfoMediaManagerTest { assertThat(infoDevice.getId()).isEqualTo(TEST_ID); assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice); assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size()); + verify(mCallback).onConnectedDeviceChanged(TEST_ID); } @Test public void onRoutesChanged_buildAllRoutes_shouldAddMediaDevice() { final MediaRoute2Info info = mock(MediaRoute2Info.class); + mInfoMediaManager.registerCallback(mCallback); + when(info.getId()).thenReturn(TEST_ID); when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME); when(info.isSystemRoute()).thenReturn(true); @@ -182,6 +192,7 @@ public class InfoMediaManagerTest { final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0); assertThat(infoDevice.getId()).isEqualTo(TEST_ID); assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size()); + verify(mCallback).onConnectedDeviceChanged(null); } @Test @@ -493,4 +504,22 @@ public class InfoMediaManagerTest { assertThat(mInfoMediaManager.getSessionName()).isEqualTo(TEST_NAME); } + + @Test + public void onTransferFailed_shouldDispatchOnRequestFailed() { + mInfoMediaManager.registerCallback(mCallback); + + mInfoMediaManager.mMediaRouterCallback.onTransferFailed(null, null); + + verify(mCallback).onRequestFailed(REASON_UNKNOWN_ERROR); + } + + @Test + public void onRequestFailed_shouldDispatchOnRequestFailed() { + mInfoMediaManager.registerCallback(mCallback); + + mInfoMediaManager.mMediaRouterCallback.onRequestFailed(REASON_NETWORK_ERROR); + + verify(mCallback).onRequestFailed(REASON_NETWORK_ERROR); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java index 3611dfefbb7f9..1e888da6468eb 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java @@ -477,4 +477,13 @@ public class LocalMediaManagerTest { assertThat(mLocalMediaManager.mMediaDevices).hasSize(3); verify(mCallback).onDeviceListUpdate(any()); } + + @Test + public void onRequestFailed_shouldDispatchOnRequestFailed() { + mLocalMediaManager.registerCallback(mCallback); + + mLocalMediaManager.mMediaDeviceCallback.onRequestFailed(1); + + verify(mCallback).onRequestFailed(1); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java index ead2be4d7b267..a50965ab2619b 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java @@ -136,4 +136,14 @@ public class MediaManagerTest { assertThat(device).isNull(); } + + @Test + public void dispatchOnRequestFailed_registerCallback_shouldDispatchCallback() { + mMediaManager.registerCallback(mCallback); + + mMediaManager.dispatchOnRequestFailed(1); + + verify(mCallback).onRequestFailed(1); + } + }