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);