From a67c3eb3bc2a76df0be1cd5e98b0a22c3000e6a9 Mon Sep 17 00:00:00 2001
From: Sam Dubey <dubeyshubham@google.com>
Date: Tue, 17 Oct 2023 10:04:56 +0000
Subject: [PATCH] Revert "Move RingtoneTest to media/tests/ringtone"

This reverts commit addff744edc1df08ff1eab9aefd7ae2488a03c7e.

Reason for revert: Likely causing b/305726574 b/305901414, will verify
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd57a938c6d0f1c7af20a1dd4f84e32360e9d292)
Merged-In: Iacaab00ffe18b2fd6b5aeba6b5baf0794767430c
Change-Id: Iacaab00ffe18b2fd6b5aeba6b5baf0794767430c
---
 media/java/android/media/RingtoneV1.java      |  43 ++-
 .../unit/RingtoneTest.java}                   | 285 +++++++++++++++---
 media/tests/ringtone/Android.bp               |  15 +-
 media/tests/ringtone/OWNERS                   |   3 -
 .../media/testing/MediaPlayerTestHelper.java  |  75 -----
 .../RingtoneInjectablesTrackingTestRule.java  | 225 --------------
 6 files changed, 277 insertions(+), 369 deletions(-)
 rename media/tests/{ringtone/src/com/android/media/RingtoneBuilderTest.java => MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java} (70%)
 delete mode 100644 media/tests/ringtone/OWNERS
 delete mode 100644 media/tests/ringtone/src/com/android/media/testing/MediaPlayerTestHelper.java
 delete mode 100644 media/tests/ringtone/src/com/android/media/testing/RingtoneInjectablesTrackingTestRule.java

diff --git a/media/java/android/media/RingtoneV1.java b/media/java/android/media/RingtoneV1.java
index b761afaeaa67..3c54d4a0d166 100644
--- a/media/java/android/media/RingtoneV1.java
+++ b/media/java/android/media/RingtoneV1.java
@@ -16,14 +16,15 @@
 
 package android.media;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources.NotFoundException;
 import android.media.audiofx.HapticGenerator;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.os.VibrationEffect;
@@ -61,7 +62,6 @@ class RingtoneV1 implements Ringtone.ApiInterface {
 
     private final Context mContext;
     private final AudioManager mAudioManager;
-    private final Ringtone.Injectables mInjectables;
     private VolumeShaper.Configuration mVolumeShaperConfig;
     private VolumeShaper mVolumeShaper;
 
@@ -74,10 +74,12 @@ class RingtoneV1 implements Ringtone.ApiInterface {
     private final IRingtonePlayer mRemotePlayer;
     private final Binder mRemoteToken;
 
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private MediaPlayer mLocalPlayer;
     private final MyOnCompletionListener mCompletionListener = new MyOnCompletionListener();
     private HapticGenerator mHapticGenerator;
 
+    @UnsupportedAppUsage
     private Uri mUri;
     private String mTitle;
 
@@ -92,15 +94,10 @@ class RingtoneV1 implements Ringtone.ApiInterface {
     private boolean mHapticGeneratorEnabled = false;
     private final Object mPlaybackSettingsLock = new Object();
 
-    /** @hide */
+    /** {@hide} */
+    @UnsupportedAppUsage
     public RingtoneV1(Context context, boolean allowRemote) {
-        this(context, new Ringtone.Injectables(), allowRemote);
-    }
-
-    /** @hide */
-    RingtoneV1(Context context, @NonNull Ringtone.Injectables injectables, boolean allowRemote) {
         mContext = context;
-        mInjectables = injectables;
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         mAllowRemote = allowRemote;
         mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
@@ -203,7 +200,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
         }
         destroyLocalPlayer();
         // try opening uri locally before delegating to remote player
-        mLocalPlayer = mInjectables.newMediaPlayer();
+        mLocalPlayer = new MediaPlayer();
         try {
             mLocalPlayer.setDataSource(mContext, mUri);
             mLocalPlayer.setAudioAttributes(mAudioAttributes);
@@ -243,7 +240,19 @@ class RingtoneV1 implements Ringtone.ApiInterface {
      */
     public boolean hasHapticChannels() {
         // FIXME: support remote player, or internalize haptic channels support and remove entirely.
-        return mInjectables.hasHapticChannels(mLocalPlayer);
+        try {
+            android.os.Trace.beginSection("Ringtone.hasHapticChannels");
+            if (mLocalPlayer != null) {
+                for(MediaPlayer.TrackInfo trackInfo : mLocalPlayer.getTrackInfo()) {
+                    if (trackInfo.hasHapticChannels()) {
+                        return true;
+                    }
+                }
+            }
+        } finally {
+            android.os.Trace.endSection();
+        }
+        return false;
     }
 
     /**
@@ -325,7 +334,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
      * @see android.media.audiofx.HapticGenerator#isAvailable()
      */
     public boolean setHapticGeneratorEnabled(boolean enabled) {
-        if (!mInjectables.isHapticGeneratorAvailable()) {
+        if (!HapticGenerator.isAvailable()) {
             return false;
         }
         synchronized (mPlaybackSettingsLock) {
@@ -353,7 +362,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
             mLocalPlayer.setVolume(mVolume);
             mLocalPlayer.setLooping(mIsLooping);
             if (mHapticGenerator == null && mHapticGeneratorEnabled) {
-                mHapticGenerator = mInjectables.createHapticGenerator(mLocalPlayer);
+                mHapticGenerator = HapticGenerator.create(mLocalPlayer.getAudioSessionId());
             }
             if (mHapticGenerator != null) {
                 mHapticGenerator.setEnabled(mHapticGeneratorEnabled);
@@ -388,6 +397,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUri(Uri uri) {
         setUri(uri, null);
     }
@@ -415,6 +425,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public Uri getUri() {
         return mUri;
     }
@@ -545,7 +556,7 @@ class RingtoneV1 implements Ringtone.ApiInterface {
                 Log.e(TAG, "Could not load fallback ringtone");
                 return false;
             }
-            mLocalPlayer = mInjectables.newMediaPlayer();
+            mLocalPlayer = new MediaPlayer();
             if (afd.getDeclaredLength() < 0) {
                 mLocalPlayer.setDataSource(afd.getFileDescriptor());
             } else {
@@ -583,12 +594,12 @@ class RingtoneV1 implements Ringtone.ApiInterface {
     }
 
     public boolean isLocalOnly() {
-        return !mAllowRemote;
+        return mAllowRemote;
     }
 
     public boolean isUsingRemotePlayer() {
         // V2 testing api, but this is the v1 approximation.
-        return (mLocalPlayer == null) && mAllowRemote && (mRemotePlayer != null) && (mUri != null);
+        return (mLocalPlayer == null) && mAllowRemote && (mRemotePlayer != null);
     }
 
     class MyOnCompletionListener implements MediaPlayer.OnCompletionListener {
diff --git a/media/tests/ringtone/src/com/android/media/RingtoneBuilderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
similarity index 70%
rename from media/tests/ringtone/src/com/android/media/RingtoneBuilderTest.java
rename to media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
index 2c8daba86d19..3c0c6847f557 100644
--- a/media/tests/ringtone/src/com/android/media/RingtoneBuilderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
@@ -14,22 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.media;
+package com.android.mediaframeworktest.unit;
 
 import static android.media.Ringtone.MEDIA_SOUND;
 import static android.media.Ringtone.MEDIA_SOUND_AND_VIBRATION;
 import static android.media.Ringtone.MEDIA_VIBRATION;
 
-import static com.android.media.testing.MediaPlayerTestHelper.verifyPlayerFallbackSetup;
-import static com.android.media.testing.MediaPlayerTestHelper.verifyPlayerSetup;
-import static com.android.media.testing.MediaPlayerTestHelper.verifyPlayerStarted;
-import static com.android.media.testing.MediaPlayerTestHelper.verifyPlayerStopped;
-
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.never;
@@ -55,29 +53,34 @@ import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.testing.TestableContext;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.framework.base.media.ringtone.tests.R;
-import com.android.media.testing.RingtoneInjectablesTrackingTestRule;
+import com.android.mediaframeworktest.R;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
 import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Queue;
 
-/**
- * Test behavior of {@link Ringtone} when it's created via {@link Ringtone.Builder}.
- */
 @RunWith(AndroidJUnit4.class)
-public class RingtoneBuilderTest {
+public class RingtoneTest {
 
     private static final Uri SOUND_URI = Uri.parse("content://fake-sound-uri");
 
@@ -90,8 +93,11 @@ public class RingtoneBuilderTest {
 
     private static final VibrationEffect VIBRATION_EFFECT =
             VibrationEffect.createWaveform(new long[] { 0, 100, 50, 100}, -1);
+    private static final VibrationEffect VIBRATION_EFFECT_REPEATING =
+            VibrationEffect.createWaveform(new long[] { 0, 100, 50, 100, 50}, 1);
 
-    @Rule public final RingtoneInjectablesTrackingTestRule
+    @Rule
+    public final RingtoneInjectablesTrackingTestRule
             mMediaPlayerRule = new RingtoneInjectablesTrackingTestRule();
 
     @Captor private ArgumentCaptor<IBinder> mIBinderCaptor;
@@ -116,7 +122,6 @@ public class RingtoneBuilderTest {
         mContext = spy(testContext);
     }
 
-
     @Test
     public void testRingtone_fullLifecycleUsingLocalMediaPlayer() throws Exception {
         MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
@@ -137,14 +142,14 @@ public class RingtoneBuilderTest {
         assertThat(ringtone.isLocalOnly()).isFalse();
 
         // Prepare
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES);
         verify(mockMediaPlayer).setVolume(1.0f);
         verify(mockMediaPlayer).setLooping(false);
         verify(mockMediaPlayer).prepare();
 
         // Play
         ringtone.play();
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
 
         // Verify dynamic controls.
         ringtone.setVolume(0.8f);
@@ -160,7 +165,7 @@ public class RingtoneBuilderTest {
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
 
         // This test is intended to strictly verify all interactions with MediaPlayer in a local
         // playback case. This shouldn't be necessary in other tests that have the same basic
@@ -194,16 +199,16 @@ public class RingtoneBuilderTest {
         assertThat(ringtone.getAudioAttributes()).isEqualTo(audioAttributes);
 
         // Prepare
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, audioAttributes);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, audioAttributes);
         verify(mockMediaPlayer).prepare();
 
         // Play
         ringtone.play();
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
 
         verifyZeroInteractions(mMockRemotePlayer);
         verifyZeroInteractions(mMockVibrator);
@@ -215,8 +220,8 @@ public class RingtoneBuilderTest {
         setupFileNotFound(mockMediaPlayer, SOUND_URI);
         Ringtone ringtone =
                 newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
-                        .setUri(SOUND_URI)
-                        .build();
+                .setUri(SOUND_URI)
+                .build();
         assertThat(ringtone).isNotNull();
         assertThat(ringtone.isUsingRemotePlayer()).isTrue();
 
@@ -279,7 +284,7 @@ public class RingtoneBuilderTest {
         // Prepare
         // Uses attributes with haptic channels enabled, but will use the effect when there aren't
         // any present.
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
         verify(mockMediaPlayer).setVolume(1.0f);
         verify(mockMediaPlayer).setLooping(false);
         verify(mockMediaPlayer).prepare();
@@ -287,7 +292,7 @@ public class RingtoneBuilderTest {
         // Play
         ringtone.play();
 
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
         verify(mMockVibrator).vibrate(VIBRATION_EFFECT, RINGTONE_VIB_ATTRIBUTES);
 
         // Verify dynamic controls.
@@ -305,7 +310,7 @@ public class RingtoneBuilderTest {
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
         verify(mMockVibrator).cancel(VibrationAttributes.USAGE_RINGTONE);
 
         // This test is intended to strictly verify all interactions with MediaPlayer in a local
@@ -383,7 +388,7 @@ public class RingtoneBuilderTest {
         // Prepare
         // Uses attributes with haptic channels enabled, but will abandon the MediaPlayer when it
         // knows there aren't any.
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
         verify(mockMediaPlayer).setVolume(0.0f);  // Vibration-only: sound muted.
         verify(mockMediaPlayer).setLooping(false);
         verify(mockMediaPlayer).prepare();
@@ -438,7 +443,7 @@ public class RingtoneBuilderTest {
         // Prepare
         // Uses attributes with haptic channels enabled, but will use the effect when there aren't
         // any present.
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
         verify(mockMediaPlayer).setVolume(0.0f);  // Vibration-only: sound muted.
         verify(mockMediaPlayer).setLooping(false);
         verify(mockMediaPlayer).prepare();
@@ -446,7 +451,7 @@ public class RingtoneBuilderTest {
         // Play
         ringtone.play();
         // Vibrator.vibrate isn't called because the vibration comes from the sound.
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
 
         // Verify dynamic controls (no-op without sound)
         ringtone.setVolume(0.8f);
@@ -461,7 +466,7 @@ public class RingtoneBuilderTest {
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
 
         // This test is intended to strictly verify all interactions with MediaPlayer in a local
         // playback case. This shouldn't be necessary in other tests that have the same basic
@@ -491,17 +496,17 @@ public class RingtoneBuilderTest {
 
         // Prepare
         // The attributes here have haptic channels enabled (unlike above)
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
         verify(mockMediaPlayer).prepare();
 
         // Play
         ringtone.play();
         when(mockMediaPlayer.isPlaying()).thenReturn(true);
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
 
         verifyZeroInteractions(mMockRemotePlayer);
         // Nothing after the initial hasVibrator - it uses audio-coupled.
@@ -531,7 +536,7 @@ public class RingtoneBuilderTest {
 
         // Prepare
         // The attributes here have haptic channels enabled (unlike above)
-        verifyPlayerSetup(mContext, mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
         verify(mockMediaPlayer).prepare();
 
         // Play
@@ -554,7 +559,7 @@ public class RingtoneBuilderTest {
     @Test
     public void testRingtone_nullMediaOnBuilderUsesFallback() throws Exception {
         AssetFileDescriptor testResourceFd =
-                mContext.getResources().openRawResourceFd(R.raw.test_sound_file);
+                mContext.getResources().openRawResourceFd(R.raw.shortmp3);
         // Ensure it will flow as expected.
         assertThat(testResourceFd).isNotNull();
         assertThat(testResourceFd.getDeclaredLength()).isAtLeast(0);
@@ -570,18 +575,18 @@ public class RingtoneBuilderTest {
 
         // Delegates straight to fallback in local player.
         // Prepare
-        verifyPlayerFallbackSetup(mockMediaPlayer, testResourceFd, RINGTONE_ATTRIBUTES);
+        verifyLocalPlayerFallbackSetup(mockMediaPlayer, testResourceFd, RINGTONE_ATTRIBUTES);
         verify(mockMediaPlayer).setVolume(1.0f);
         verify(mockMediaPlayer).setLooping(false);
         verify(mockMediaPlayer).prepare();
 
         // Play
         ringtone.play();
-        verifyPlayerStarted(mockMediaPlayer);
+        verifyLocalPlay(mockMediaPlayer);
 
         // Release
         ringtone.stop();
-        verifyPlayerStopped(mockMediaPlayer);
+        verifyLocalStop(mockMediaPlayer);
 
         verifyNoMoreInteractions(mockMediaPlayer);
         verifyNoMoreInteractions(mMockRemotePlayer);
@@ -610,10 +615,24 @@ public class RingtoneBuilderTest {
         verifyNoMoreInteractions(mMockRemotePlayer);
     }
 
+    @Test
+    public void testRingtone_noMediaSetOnBuilderFallbackFailsAndNoRemote() throws Exception {
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, null);
+        Ringtone ringtone = newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .setLocalOnly()
+                .build();
+        // Local player fallback fails as the resource isn't found (no media player creation is
+        // attempted), and since there is no local player, the ringtone ends up having nothing to
+        // do.
+        assertThat(ringtone).isNull();
+    }
+
     private Ringtone.Builder newBuilder(@Ringtone.RingtoneMedia int ringtoneMedia,
             AudioAttributes audioAttributes) {
         return new Ringtone.Builder(mContext, ringtoneMedia, audioAttributes)
-                .setInjectables(mMediaPlayerRule.getRingtoneTestInjectables());
+                .setInjectables(mMediaPlayerRule.injectables);
     }
 
     private static AudioAttributes audioAttributes(int audioUsage) {
@@ -628,4 +647,194 @@ public class RingtoneBuilderTest {
         doThrow(new FileNotFoundException("Fake file not found"))
                 .when(mockMediaPlayer).setDataSource(any(Context.class), eq(uri));
     }
+
+    private void verifyLocalPlayerSetup(MediaPlayer mockPlayer, Uri expectedUri,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        verify(mockPlayer).setDataSource(mContext, expectedUri);
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlayerFallbackSetup(MediaPlayer mockPlayer, AssetFileDescriptor afd,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        // This is very specific but it's a simple way to test that the test resource matches.
+        if (afd.getDeclaredLength() < 0) {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor());
+        } else {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor(),
+                    afd.getStartOffset(),
+                    afd.getDeclaredLength());
+        }
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlay(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).setOnCompletionListener(any());
+        verify(mockMediaPlayer).start();
+    }
+
+    private void verifyLocalStop(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).stop();
+        verify(mockMediaPlayer).setOnCompletionListener(isNull());
+        verify(mockMediaPlayer).reset();
+        verify(mockMediaPlayer).release();
+    }
+
+    /**
+     * This rule ensures that all expected media player creations from the factory do actually
+     * occur. The reason for this level of control is that creating a media player is fairly
+     * expensive and blocking, so we do want unit tests of this class to "declare" interactions
+     * of all created media players.
+     *
+     * This needs to be a TestRule so that the teardown assertions can be skipped if the test has
+     * failed (and media player assertions may just be a distracting side effect). Otherwise, the
+     * teardown failures hide the real test ones.
+     */
+    public static class RingtoneInjectablesTrackingTestRule implements TestRule {
+        public Ringtone.Injectables injectables = new TestInjectables();
+        public boolean hapticGeneratorAvailable = true;
+
+        // Queue of (local) media players, in order of expected creation. Enqueue using
+        // expectNewMediaPlayer(), dequeued by the media player factory passed to Ringtone.
+        // This queue is asserted to be empty at the end of the test.
+        private Queue<MediaPlayer> mMockMediaPlayerQueue = new ArrayDeque<>();
+
+        // Similar to media players, but for haptic generator, which also needs releasing.
+        private Map<MediaPlayer, HapticGenerator> mMockHapticGeneratorMap = new ArrayMap<>();
+
+        // Media players with haptic channels.
+        private ArraySet<MediaPlayer> mHapticChannels = new ArraySet<>();
+
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    base.evaluate();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage("Test setup an expectLocalMediaPlayer but it wasn't consumed")
+                            .that(mMockMediaPlayerQueue).isEmpty();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage(
+                            "Test setup an expectLocalHapticGenerator but it wasn't consumed")
+                            .that(mMockHapticGeneratorMap).isEmpty();
+                }
+            };
+        }
+
+        private TestMediaPlayer expectLocalMediaPlayer() {
+            TestMediaPlayer mockMediaPlayer = Mockito.mock(TestMediaPlayer.class);
+            // Delegate to simulated methods. This means they can be verified but also reflect
+            // realistic transitions from the TestMediaPlayer.
+            doCallRealMethod().when(mockMediaPlayer).start();
+            doCallRealMethod().when(mockMediaPlayer).stop();
+            doCallRealMethod().when(mockMediaPlayer).setLooping(anyBoolean());
+            when(mockMediaPlayer.isLooping()).thenCallRealMethod();
+            when(mockMediaPlayer.isLooping()).thenCallRealMethod();
+            mMockMediaPlayerQueue.add(mockMediaPlayer);
+            return mockMediaPlayer;
+        }
+
+        private HapticGenerator expectHapticGenerator(MediaPlayer mockMediaPlayer) {
+            HapticGenerator mockHapticGenerator = Mockito.mock(HapticGenerator.class);
+            // A test should never want this.
+            assertWithMessage("Can't expect a second haptic generator created "
+                    + "for one media player")
+                    .that(mMockHapticGeneratorMap.put(mockMediaPlayer, mockHapticGenerator))
+                    .isNull();
+            return mockHapticGenerator;
+        }
+
+        private void setHasHapticChannels(MediaPlayer mp, boolean hasHapticChannels) {
+            if (hasHapticChannels) {
+                mHapticChannels.add(mp);
+            } else {
+                mHapticChannels.remove(mp);
+            }
+        }
+
+        private class TestInjectables extends Ringtone.Injectables {
+            @Override
+            public MediaPlayer newMediaPlayer() {
+                assertWithMessage(
+                        "Unexpected MediaPlayer creation. Bug or need expectNewMediaPlayer")
+                        .that(mMockMediaPlayerQueue)
+                        .isNotEmpty();
+                return mMockMediaPlayerQueue.remove();
+            }
+
+            @Override
+            public boolean isHapticGeneratorAvailable() {
+                return hapticGeneratorAvailable;
+            }
+
+            @Override
+            public HapticGenerator createHapticGenerator(MediaPlayer mediaPlayer) {
+                HapticGenerator mockHapticGenerator = mMockHapticGeneratorMap.remove(mediaPlayer);
+                assertWithMessage("Unexpected HapticGenerator creation. "
+                        + "Bug or need expectHapticGenerator")
+                        .that(mockHapticGenerator)
+                        .isNotNull();
+                return mockHapticGenerator;
+            }
+
+            @Override
+            public boolean isHapticPlaybackSupported() {
+                return true;
+            }
+
+            @Override
+            public boolean hasHapticChannels(MediaPlayer mp) {
+                return mHapticChannels.contains(mp);
+            }
+        }
+    }
+
+    /**
+     * MediaPlayer relies on a native backend and so its necessary to intercept calls from
+     * fake usage hitting them.
+     *
+     * Mocks don't work directly on native calls, but if they're overridden then it does work.
+     * Some basic state faking is also done to make the mocks more realistic.
+     */
+    private static class TestMediaPlayer extends MediaPlayer {
+        private boolean mIsPlaying = false;
+        private boolean mIsLooping = false;
+
+        @Override
+        public void start() {
+            mIsPlaying = true;
+        }
+
+        @Override
+        public void stop() {
+            mIsPlaying = false;
+        }
+
+        @Override
+        public void setLooping(boolean value) {
+            mIsLooping = value;
+        }
+
+        @Override
+        public boolean isLooping() {
+            return mIsLooping;
+        }
+
+        @Override
+        public boolean isPlaying() {
+            return mIsPlaying;
+        }
+
+        void simulatePlayingFinished() {
+            if (!mIsPlaying) {
+                throw new IllegalStateException(
+                        "Attempted to pretend playing finished when not playing");
+            }
+            mIsPlaying = false;
+        }
+    }
 }
diff --git a/media/tests/ringtone/Android.bp b/media/tests/ringtone/Android.bp
index 8d1e5e3a5bab..55b98c4704b1 100644
--- a/media/tests/ringtone/Android.bp
+++ b/media/tests/ringtone/Android.bp
@@ -9,24 +9,15 @@ android_test {
     srcs: ["src/**/*.java"],
 
     libs: [
-        "android.test.base",
-        "android.test.mock",
         "android.test.runner",
+        "android.test.base",
     ],
 
     static_libs: [
-        "androidx.test.ext.junit",
-        "androidx.test.ext.truth",
         "androidx.test.rules",
-        "frameworks-base-testutils",
-        "mockito-target-inline-minus-junit4",
-        "testables",
         "testng",
-    ],
-
-    jni_libs: [
-        "libdexmakerjvmtiagent",
-        "libstaticjvmtiagent",
+        "androidx.test.ext.truth",
+        "frameworks-base-testutils",
     ],
 
     test_suites: [
diff --git a/media/tests/ringtone/OWNERS b/media/tests/ringtone/OWNERS
deleted file mode 100644
index 93b44f4788c5..000000000000
--- a/media/tests/ringtone/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 345036
-
-include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/media/tests/ringtone/src/com/android/media/testing/MediaPlayerTestHelper.java b/media/tests/ringtone/src/com/android/media/testing/MediaPlayerTestHelper.java
deleted file mode 100644
index e97e1173a1ea..000000000000
--- a/media/tests/ringtone/src/com/android/media/testing/MediaPlayerTestHelper.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.testing;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.media.AudioAttributes;
-import android.media.MediaPlayer;
-import android.net.Uri;
-
-/**
- * Helper class with assertion methods on mock {@link MediaPlayer} instances.
- */
-public final class MediaPlayerTestHelper {
-
-    /** Verify this local media player mock instance was started. */
-    public static void verifyPlayerStarted(MediaPlayer mockMediaPlayer) {
-        verify(mockMediaPlayer).setOnCompletionListener(any());
-        verify(mockMediaPlayer).start();
-    }
-
-    /** Verify this local media player mock instance was stopped and released. */
-    public static void verifyPlayerStopped(MediaPlayer mockMediaPlayer) {
-        verify(mockMediaPlayer).stop();
-        verify(mockMediaPlayer).setOnCompletionListener(isNull());
-        verify(mockMediaPlayer).reset();
-        verify(mockMediaPlayer).release();
-    }
-
-    /** Verify this local media player mock instance was setup with given attributes. */
-    public static void verifyPlayerSetup(Context context, MediaPlayer mockPlayer,
-            Uri expectedUri, AudioAttributes expectedAudioAttributes) throws Exception {
-        verify(mockPlayer).setDataSource(context, expectedUri);
-        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
-        verify(mockPlayer).setPreferredDevice(null);
-        verify(mockPlayer).prepare();
-    }
-
-    /** Verify this local media player mock instance was setup with given fallback attributes. */
-    public static void verifyPlayerFallbackSetup(MediaPlayer mockPlayer,
-            AssetFileDescriptor afd, AudioAttributes expectedAudioAttributes) throws Exception {
-        // This is very specific but it's a simple way to test that the test resource matches.
-        if (afd.getDeclaredLength() < 0) {
-            verify(mockPlayer).setDataSource(afd.getFileDescriptor());
-        } else {
-            verify(mockPlayer).setDataSource(afd.getFileDescriptor(),
-                    afd.getStartOffset(),
-                    afd.getDeclaredLength());
-        }
-        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
-        verify(mockPlayer).setPreferredDevice(null);
-        verify(mockPlayer).prepare();
-    }
-
-    private MediaPlayerTestHelper() {
-    }
-}
diff --git a/media/tests/ringtone/src/com/android/media/testing/RingtoneInjectablesTrackingTestRule.java b/media/tests/ringtone/src/com/android/media/testing/RingtoneInjectablesTrackingTestRule.java
deleted file mode 100644
index 25752ce83e5c..000000000000
--- a/media/tests/ringtone/src/com/android/media/testing/RingtoneInjectablesTrackingTestRule.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.testing;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.doCallRealMethod;
-import static org.mockito.Mockito.when;
-
-import android.media.MediaPlayer;
-import android.media.Ringtone;
-import android.media.audiofx.HapticGenerator;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.mockito.Mockito;
-
-import java.util.ArrayDeque;
-import java.util.Map;
-import java.util.Queue;
-
-/**
- * This rule ensures that all expected media player creations from the factory do actually
- * occur. The reason for this level of control is that creating a media player is fairly
- * expensive and blocking, so we do want unit tests of this class to "declare" interactions
- * of all created media players.
- * <p>
- * This needs to be a TestRule so that the teardown assertions can be skipped if the test has
- * failed (and media player assertions may just be a distracting side effect). Otherwise, the
- * teardown failures hide the real test ones.
- */
-public class RingtoneInjectablesTrackingTestRule implements TestRule {
-
-    private final Ringtone.Injectables mRingtoneTestInjectables = new TestInjectables();
-
-    // Queue of (local) media players, in order of expected creation. Enqueue using
-    // expectNewMediaPlayer(), dequeued by the media player factory passed to Ringtone.
-    // This queue is asserted to be empty at the end of the test.
-    private final Queue<MediaPlayer> mMockMediaPlayerQueue = new ArrayDeque<>();
-
-    // Similar to media players, but for haptic generator, which also needs releasing.
-    private final Map<MediaPlayer, HapticGenerator> mMockHapticGeneratorMap = new ArrayMap<>();
-
-    // Media players with haptic channels.
-    private final ArraySet<MediaPlayer> mHapticChannels = new ArraySet<>();
-
-    private boolean mHapticGeneratorAvailable = true;
-
-    @Override
-    public Statement apply(Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                base.evaluate();
-                // Only assert if the test didn't fail (base.evaluate() would throw).
-                assertWithMessage("Test setup an expectLocalMediaPlayer but it wasn't consumed")
-                        .that(mMockMediaPlayerQueue).isEmpty();
-                // Only assert if the test didn't fail (base.evaluate() would throw).
-                assertWithMessage(
-                        "Test setup an expectLocalHapticGenerator but it wasn't consumed")
-                        .that(mMockHapticGeneratorMap).isEmpty();
-            }
-        };
-    }
-
-    /** The {@link Ringtone.Injectables} to be used for creating a testable {@link Ringtone}. */
-    public Ringtone.Injectables getRingtoneTestInjectables() {
-        return mRingtoneTestInjectables;
-    }
-
-    /**
-     * Create a test {@link MediaPlayer} that will be provided to the {@link Ringtone} instance
-     * created with {@link #getRingtoneTestInjectables()}.
-     *
-     * <p>If a media player is not created during the test execution after this method is called
-     * then the test will fail. It will also fail if the ringtone attempts to create one without
-     * this method being called first.
-     */
-    public TestMediaPlayer expectLocalMediaPlayer() {
-        TestMediaPlayer mockMediaPlayer = Mockito.mock(TestMediaPlayer.class);
-        // Delegate to simulated methods. This means they can be verified but also reflect
-        // realistic transitions from the TestMediaPlayer.
-        doCallRealMethod().when(mockMediaPlayer).start();
-        doCallRealMethod().when(mockMediaPlayer).stop();
-        doCallRealMethod().when(mockMediaPlayer).setLooping(anyBoolean());
-        when(mockMediaPlayer.isLooping()).thenCallRealMethod();
-        mMockMediaPlayerQueue.add(mockMediaPlayer);
-        return mockMediaPlayer;
-    }
-
-    /**
-     * Create a test {@link HapticGenerator} that will be provided to the {@link Ringtone} instance
-     * created with {@link #getRingtoneTestInjectables()}.
-     *
-     * <p>If a haptic generator is not created during the test execution after this method is called
-     * then the test will fail. It will also fail if the ringtone attempts to create one without
-     * this method being called first.
-     */
-    public HapticGenerator expectHapticGenerator(MediaPlayer mediaPlayer) {
-        HapticGenerator mockHapticGenerator = Mockito.mock(HapticGenerator.class);
-        // A test should never want this.
-        assertWithMessage("Can't expect a second haptic generator created "
-                + "for one media player")
-                .that(mMockHapticGeneratorMap.put(mediaPlayer, mockHapticGenerator))
-                .isNull();
-        return mockHapticGenerator;
-    }
-
-    /**
-     * Configures the {@link MediaPlayer} to always return given flag when
-     * {@link Ringtone.Injectables#hasHapticChannels(MediaPlayer)} is called.
-     */
-    public void setHasHapticChannels(MediaPlayer mp, boolean hasHapticChannels) {
-        if (hasHapticChannels) {
-            mHapticChannels.add(mp);
-        } else {
-            mHapticChannels.remove(mp);
-        }
-    }
-
-    /** Test implementation of {@link Ringtone.Injectables} that uses the test rule setup. */
-    private class TestInjectables extends Ringtone.Injectables {
-        @Override
-        public MediaPlayer newMediaPlayer() {
-            assertWithMessage(
-                    "Unexpected MediaPlayer creation. Bug or need expectNewMediaPlayer")
-                    .that(mMockMediaPlayerQueue)
-                    .isNotEmpty();
-            return mMockMediaPlayerQueue.remove();
-        }
-
-        @Override
-        public boolean isHapticGeneratorAvailable() {
-            return mHapticGeneratorAvailable;
-        }
-
-        @Override
-        public HapticGenerator createHapticGenerator(MediaPlayer mediaPlayer) {
-            HapticGenerator mockHapticGenerator = mMockHapticGeneratorMap.remove(mediaPlayer);
-            assertWithMessage("Unexpected HapticGenerator creation. "
-                    + "Bug or need expectHapticGenerator")
-                    .that(mockHapticGenerator)
-                    .isNotNull();
-            return mockHapticGenerator;
-        }
-
-        @Override
-        public boolean isHapticPlaybackSupported() {
-            return true;
-        }
-
-        @Override
-        public boolean hasHapticChannels(MediaPlayer mp) {
-            return mHapticChannels.contains(mp);
-        }
-    }
-
-    /**
-     * MediaPlayer relies on a native backend and so its necessary to intercept calls from
-     * fake usage hitting them.
-     * <p>
-     * Mocks don't work directly on native calls, but if they're overridden then it does work.
-     * Some basic state faking is also done to make the mocks more realistic.
-     */
-    public static class TestMediaPlayer extends MediaPlayer {
-        private boolean mIsPlaying = false;
-        private boolean mIsLooping = false;
-
-        @Override
-        public void start() {
-            mIsPlaying = true;
-        }
-
-        @Override
-        public void stop() {
-            mIsPlaying = false;
-        }
-
-        @Override
-        public void setLooping(boolean value) {
-            mIsLooping = value;
-        }
-
-        @Override
-        public boolean isLooping() {
-            return mIsLooping;
-        }
-
-        @Override
-        public boolean isPlaying() {
-            return mIsPlaying;
-        }
-
-        /**
-         * Updates {@link #isPlaying()} result to false, if it's set to true.
-         *
-         * @throws IllegalStateException is {@link #isPlaying()} is already false
-         */
-        public void simulatePlayingFinished() {
-            if (!mIsPlaying) {
-                throw new IllegalStateException(
-                        "Attempted to pretend playing finished when not playing");
-            }
-            mIsPlaying = false;
-        }
-    }
-}
-- 
GitLab