Use MediaSource from Car api instead of ContentProvider
Bug: 124451543
Test: Manual
Change-Id: If9fef12b8156671989418de2f6bef312a6ad0728
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
index 8bed455..2f85537 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
@@ -22,10 +22,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Application;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.media.CarMediaManager;
import android.content.ComponentName;
import android.content.ContentValues;
-import android.database.ContentObserver;
-import android.database.Cursor;
import android.media.session.MediaController;
import android.os.Handler;
import android.os.RemoteException;
@@ -51,6 +52,8 @@
private static final String TAG = "MediaSourceViewModel";
private static MediaSourceViewModel sInstance;
+ private final Car mCar;
+ private CarMediaManager mCarMediaManager;
// Primary media source.
private final MutableLiveData<MediaSource> mPrimaryMediaSource = dataOf(null);
@@ -59,6 +62,9 @@
// Media controller for the connected browser.
private final MutableLiveData<MediaControllerCompat> mMediaController = dataOf(null);
+ private final Handler mHandler;
+ private final CarMediaManager.MediaSourceChangedListener mMediaSourceListener;
+
/**
* Factory for creating dependencies. Can be swapped out for testing.
*/
@@ -69,7 +75,11 @@
MediaControllerCompat getControllerForSession(@Nullable MediaSessionCompat.Token session);
- MediaSource getSelectedSourceFromContentProvider();
+ Car getCarApi();
+
+ CarMediaManager getCarMediaManager(Car carApi) throws CarNotConnectedException;
+
+ MediaSource getMediaSource(String packageName);
}
/** Returns the MediaSourceViewModel singleton tied to the application. */
@@ -107,19 +117,18 @@
}
@Override
- public MediaSource getSelectedSourceFromContentProvider() {
- Cursor cursor = application.getContentResolver().query(
- MediaConstants.URI_MEDIA_SOURCE, null, null, null);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- return new MediaSource(application, cursor.getString(0));
- }
- return null;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
+ public Car getCarApi() {
+ return Car.createCar(application);
+ }
+
+ @Override
+ public CarMediaManager getCarMediaManager(Car carApi) throws CarNotConnectedException {
+ return (CarMediaManager) carApi.getCarManager(Car.CAR_MEDIA_SERVICE);
+ }
+
+ @Override
+ public MediaSource getMediaSource(String packageName) {
+ return packageName == null ? null : new MediaSource(application, packageName);
}
});
}
@@ -133,6 +142,7 @@
super(application);
mInputFactory = inputFactory;
+ mCar = inputFactory.getCarApi();
mConnectedBrowserCallback = browser -> {
mConnectedMediaBrowser.setValue(browser);
@@ -152,22 +162,17 @@
mBrowserConnector = inputFactory.createMediaBrowserConnector(application,
mConnectedBrowserCallback);
- updateModelState();
- application.getContentResolver().registerContentObserver(MediaConstants.URI_MEDIA_SOURCE,
- false, mMediaSourceObserver);
+ mHandler = new Handler(application.getMainLooper());
+ mMediaSourceListener = packageName -> mHandler.post(
+ () -> updateModelState(mInputFactory.getMediaSource(packageName)));
- }
-
- private final ContentObserver mMediaSourceObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- updateModelState();
+ try {
+ mCarMediaManager = mInputFactory.getCarMediaManager(mCar);
+ mCarMediaManager.registerMediaSourceListener(mMediaSourceListener);
+ updateModelState(mInputFactory.getMediaSource(mCarMediaManager.getMediaSource()));
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car not connected", e);
}
- };
-
- @VisibleForTesting
- ContentObserver getMediaSourceObserver() {
- return mMediaSourceObserver;
}
@VisibleForTesting
@@ -188,8 +193,8 @@
public void setPrimaryMediaSource(MediaSource mediaSource) {
ContentValues values = new ContentValues();
values.put(MediaConstants.KEY_PACKAGE_NAME, mediaSource.getPackageName());
- getApplication().getContentResolver().update(
- MediaConstants.URI_MEDIA_SOURCE, values, null, null);
+
+ mCarMediaManager.setMediaSource(mediaSource.getPackageName());
}
/**
@@ -210,9 +215,9 @@
return mMediaController;
}
- private void updateModelState() {
+ private void updateModelState(MediaSource newMediaSource) {
MediaSource oldMediaSource = mPrimaryMediaSource.getValue();
- MediaSource newMediaSource = mInputFactory.getSelectedSourceFromContentProvider();
+
if (Objects.equals(oldMediaSource, newMediaSource)) {
return;
}
diff --git a/car-media-common/tests/robotests/Android.mk b/car-media-common/tests/robotests/Android.mk
index ff270b4..2af1561 100644
--- a/car-media-common/tests/robotests/Android.mk
+++ b/car-media-common/tests/robotests/Android.mk
@@ -35,6 +35,7 @@
# Include the testing libraries
LOCAL_JAVA_LIBRARIES := \
+ android.car \
androidx.arch.core_core-runtime \
androidx.arch.core_core-common \
robolectric_android-all-stub \
@@ -57,6 +58,7 @@
LOCAL_MODULE := RunCarMediaCommonRoboTests
LOCAL_JAVA_LIBRARIES := \
+ android.car \
CarMediaCommonRoboTests \
robolectric_android-all-stub \
Robolectric_all-target \
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
index b3f04ea..3cc4cc3 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
@@ -18,11 +18,14 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application;
import android.annotation.NonNull;
import android.app.Application;
+import android.car.Car;
+import android.car.media.CarMediaManager;
import android.content.ComponentName;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.session.MediaControllerCompat;
@@ -59,19 +62,21 @@
public final TestLifecycleOwner mLifecycleOwner = new TestLifecycleOwner();
@Mock
- public MediaSource mMediaSource;
- @Mock
public MediaBrowserCompat mMediaBrowser;
@Mock
public MediaControllerCompat mMediaControllerFromBrowser;
@Mock
public MediaControllerCompat mMediaControllerFromSessionManager;
+ @Mock
+ public Car mCar;
+ @Mock
+ public CarMediaManager mCarMediaManager;
+
private MediaSourceViewModel mViewModel;
private ComponentName mRequestedBrowseService;
-
- private MediaSource mMediaSourceFromProvider;
+ private MediaSource mMediaSource;
@Before
public void setUp() {
@@ -81,7 +86,10 @@
.thenReturn(SESSION_MANAGER_CONTROLLER_PACKAGE_NAME);
mRequestedBrowseService = null;
+ mMediaSource = null;
+ }
+ private void initializeViewModel() {
mViewModel = new MediaSourceViewModel(application, new MediaSourceViewModel.InputFactory() {
@Override
public MediaBrowserConnector createMediaBrowserConnector(
@@ -104,14 +112,25 @@
}
@Override
- public MediaSource getSelectedSourceFromContentProvider() {
- return mMediaSourceFromProvider;
+ public Car getCarApi() {
+ return mCar;
+ }
+
+ @Override
+ public CarMediaManager getCarMediaManager(Car carApi) {
+ return mCarMediaManager;
+ }
+
+ @Override
+ public MediaSource getMediaSource(String packageName) {
+ return mMediaSource;
}
});
}
@Test
public void testGetSelectedMediaSource_none() {
+ initializeViewModel();
CaptureObserver<MediaSource> observer = new CaptureObserver<>();
mViewModel.getPrimaryMediaSource().observe(mLifecycleOwner, observer);
@@ -123,11 +142,10 @@
public void testGetMediaController_connectedBrowser() {
CaptureObserver<MediaControllerCompat> observer = new CaptureObserver<>();
ComponentName testComponent = new ComponentName("test", "test");
+ mMediaSource = mock(MediaSource.class);
when(mMediaSource.getBrowseServiceComponentName()).thenReturn(testComponent);
when(mMediaBrowser.isConnected()).thenReturn(true);
-
- mMediaSourceFromProvider = mMediaSource;
- mViewModel.getMediaSourceObserver().onChange(true);
+ initializeViewModel();
mViewModel.getConnectedBrowserCallback().onConnectedBrowserChanged(mMediaBrowser);
mViewModel.getMediaController().observe(mLifecycleOwner, observer);
@@ -136,16 +154,14 @@
assertThat(mRequestedBrowseService).isEqualTo(testComponent);
}
-
@Test
public void testGetMediaController_noActiveSession_notConnected() {
CaptureObserver<MediaControllerCompat> observer = new CaptureObserver<>();
ComponentName testComponent = new ComponentName("test", "test");
+ mMediaSource = mock(MediaSource.class);
when(mMediaSource.getBrowseServiceComponentName()).thenReturn(testComponent);
when(mMediaBrowser.isConnected()).thenReturn(false);
-
- mMediaSourceFromProvider = mMediaSource;
- mViewModel.getMediaSourceObserver().onChange(true);
+ initializeViewModel();
mViewModel.getMediaController().observe(mLifecycleOwner, observer);