mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Move DefaultSuitableOutputChecker operations to playback thread
PiperOrigin-RevId: 726879236 (cherry picked from commit e0ef6e51829dd1627d952d2677f532230cb2dbc9)
This commit is contained in:
parent
41af00f100
commit
8bd1db5f2c
@ -31,8 +31,11 @@ import android.media.MediaRouter2.RoutingController;
|
||||
import android.media.RouteDiscoveryPreference;
|
||||
import android.media.RoutingSessionInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.media3.common.util.BackgroundThreadStateHandler;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.concurrent.Executor;
|
||||
@ -43,26 +46,26 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
@Nullable private final SuitableOutputChecker impl;
|
||||
|
||||
/**
|
||||
* Creates the default {@link SuitableOutputChecker}.
|
||||
*
|
||||
* @param context A {@link Context}.
|
||||
* @param eventHandler A {@link Handler} to trigger {@link Callback} methods on.
|
||||
*/
|
||||
public DefaultSuitableOutputChecker(Context context, Handler eventHandler) {
|
||||
/** Creates the default {@link SuitableOutputChecker}. */
|
||||
public DefaultSuitableOutputChecker() {
|
||||
if (Util.SDK_INT >= 35) {
|
||||
impl = new ImplApi35(context, eventHandler);
|
||||
impl = new ImplApi35();
|
||||
} else if (Util.SDK_INT >= 23) {
|
||||
impl = new ImplApi23(context, eventHandler);
|
||||
impl = new ImplApi23();
|
||||
} else {
|
||||
impl = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable(Callback callback) {
|
||||
public void enable(
|
||||
Callback callback,
|
||||
Context context,
|
||||
Looper callbackLooper,
|
||||
Looper backgroundLooper,
|
||||
Clock clock) {
|
||||
if (impl != null) {
|
||||
impl.enable(callback);
|
||||
impl.enable(callback, context, callbackLooper, backgroundLooper, clock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,61 +88,63 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
/* preferredFeatures= */ ImmutableList.of(), /* activeScan= */ false)
|
||||
.build();
|
||||
|
||||
private final Context applicationContext;
|
||||
private final Handler eventHandler;
|
||||
|
||||
private @MonotonicNonNull MediaRouter2 router;
|
||||
private @MonotonicNonNull RouteCallback routeCallback;
|
||||
@Nullable private ControllerCallback controllerCallback;
|
||||
private boolean isSelectedOutputSuitableForPlayback;
|
||||
|
||||
public ImplApi35(Context context, Handler eventHandler) {
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.eventHandler = eventHandler;
|
||||
}
|
||||
private @MonotonicNonNull BackgroundThreadStateHandler<Boolean> isSuitableForPlaybackState;
|
||||
|
||||
@SuppressLint("ThreadSafe") // Handler is thread-safe, but not annotated.
|
||||
@Override
|
||||
public void enable(Callback callback) {
|
||||
router = MediaRouter2.getInstance(applicationContext);
|
||||
routeCallback = new RouteCallback() {};
|
||||
Executor executor =
|
||||
new Executor() {
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
Util.postOrRun(eventHandler, command);
|
||||
}
|
||||
};
|
||||
router.registerRouteCallback(executor, routeCallback, EMPTY_DISCOVERY_PREFERENCE);
|
||||
controllerCallback =
|
||||
new ControllerCallback() {
|
||||
@Override
|
||||
public void onControllerUpdated(RoutingController controller) {
|
||||
boolean isCurrentSelectedOutputSuitableForPlayback =
|
||||
isSelectedOutputSuitableForPlayback(router);
|
||||
if (isSelectedOutputSuitableForPlayback
|
||||
!= isCurrentSelectedOutputSuitableForPlayback) {
|
||||
isSelectedOutputSuitableForPlayback = isCurrentSelectedOutputSuitableForPlayback;
|
||||
callback.onSelectedOutputSuitabilityChanged(
|
||||
isCurrentSelectedOutputSuitableForPlayback);
|
||||
}
|
||||
}
|
||||
};
|
||||
router.registerControllerCallback(executor, controllerCallback);
|
||||
isSelectedOutputSuitableForPlayback = isSelectedOutputSuitableForPlayback(router);
|
||||
public void enable(
|
||||
Callback callback,
|
||||
Context context,
|
||||
Looper callbackLooper,
|
||||
Looper backgroundLooper,
|
||||
Clock clock) {
|
||||
isSuitableForPlaybackState =
|
||||
new BackgroundThreadStateHandler<>(
|
||||
/* initialState= */ true,
|
||||
backgroundLooper,
|
||||
callbackLooper,
|
||||
clock,
|
||||
/* onStateChanged= */ (oldState, newState) ->
|
||||
callback.onSelectedOutputSuitabilityChanged(newState));
|
||||
isSuitableForPlaybackState.runInBackground(
|
||||
() -> {
|
||||
checkNotNull(isSuitableForPlaybackState);
|
||||
router = MediaRouter2.getInstance(context);
|
||||
routeCallback = new RouteCallback() {};
|
||||
Executor backgroundExecutor = isSuitableForPlaybackState::runInBackground;
|
||||
router.registerRouteCallback(
|
||||
backgroundExecutor, routeCallback, EMPTY_DISCOVERY_PREFERENCE);
|
||||
controllerCallback =
|
||||
new ControllerCallback() {
|
||||
@Override
|
||||
public void onControllerUpdated(RoutingController controller) {
|
||||
isSuitableForPlaybackState.setStateInBackground(
|
||||
isSelectedOutputSuitableForPlayback(router));
|
||||
}
|
||||
};
|
||||
router.registerControllerCallback(backgroundExecutor, controllerCallback);
|
||||
isSuitableForPlaybackState.setStateInBackground(
|
||||
isSelectedOutputSuitableForPlayback(router));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
checkStateNotNull(controllerCallback, "SuitableOutputChecker is not enabled");
|
||||
checkNotNull(router).unregisterControllerCallback(controllerCallback);
|
||||
controllerCallback = null;
|
||||
router.unregisterRouteCallback(checkNotNull(routeCallback));
|
||||
checkStateNotNull(isSuitableForPlaybackState)
|
||||
.runInBackground(
|
||||
() -> {
|
||||
checkNotNull(router).unregisterControllerCallback(checkNotNull(controllerCallback));
|
||||
controllerCallback = null;
|
||||
router.unregisterRouteCallback(checkNotNull(routeCallback));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectedOutputSuitableForPlayback() {
|
||||
return isSelectedOutputSuitableForPlayback;
|
||||
return isSuitableForPlaybackState == null ? true : isSuitableForPlaybackState.get();
|
||||
}
|
||||
|
||||
private static boolean isSelectedOutputSuitableForPlayback(MediaRouter2 router) {
|
||||
@ -173,67 +178,72 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@RequiresApi(23)
|
||||
private static final class ImplApi23 implements SuitableOutputChecker {
|
||||
|
||||
private final Context applicationContext;
|
||||
private final Handler eventHandler;
|
||||
|
||||
@Nullable private AudioManager audioManager;
|
||||
private @MonotonicNonNull AudioDeviceCallback audioDeviceCallback;
|
||||
private boolean isSelectedOutputSuitableForPlayback;
|
||||
|
||||
public ImplApi23(Context context, Handler eventHandler) {
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.eventHandler = eventHandler;
|
||||
}
|
||||
private @MonotonicNonNull BackgroundThreadStateHandler<Boolean> isSuitableForPlaybackState;
|
||||
|
||||
@Override
|
||||
public void enable(Callback callback) {
|
||||
AudioManager audioManager =
|
||||
(AudioManager) applicationContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (audioManager == null) {
|
||||
isSelectedOutputSuitableForPlayback = true;
|
||||
return;
|
||||
}
|
||||
this.audioManager = audioManager;
|
||||
audioDeviceCallback =
|
||||
new AudioDeviceCallback() {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
|
||||
updateIsSelectedOutputSuitableForPlayback(callback);
|
||||
public void enable(
|
||||
Callback callback,
|
||||
Context context,
|
||||
Looper callbackLooper,
|
||||
Looper backgroundLooper,
|
||||
Clock clock) {
|
||||
isSuitableForPlaybackState =
|
||||
new BackgroundThreadStateHandler<>(
|
||||
/* initialState= */ true,
|
||||
backgroundLooper,
|
||||
callbackLooper,
|
||||
clock,
|
||||
/* onStateChanged= */ (oldState, newState) ->
|
||||
callback.onSelectedOutputSuitabilityChanged(newState));
|
||||
isSuitableForPlaybackState.runInBackground(
|
||||
() -> {
|
||||
checkNotNull(isSuitableForPlaybackState);
|
||||
if (!Util.isWear(context)) {
|
||||
return;
|
||||
}
|
||||
AudioManager audioManager =
|
||||
(AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (audioManager == null) {
|
||||
return;
|
||||
}
|
||||
this.audioManager = audioManager;
|
||||
audioDeviceCallback =
|
||||
new AudioDeviceCallback() {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
|
||||
isSuitableForPlaybackState.setStateInBackground(hasSupportedAudioOutput());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
|
||||
updateIsSelectedOutputSuitableForPlayback(callback);
|
||||
}
|
||||
};
|
||||
audioManager.registerAudioDeviceCallback(audioDeviceCallback, eventHandler);
|
||||
isSelectedOutputSuitableForPlayback = hasSupportedAudioOutput();
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
|
||||
isSuitableForPlaybackState.setStateInBackground(hasSupportedAudioOutput());
|
||||
}
|
||||
};
|
||||
audioManager.registerAudioDeviceCallback(
|
||||
audioDeviceCallback, new Handler(checkNotNull(Looper.myLooper())));
|
||||
isSuitableForPlaybackState.setStateInBackground(hasSupportedAudioOutput());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
if (audioManager != null) {
|
||||
audioManager.unregisterAudioDeviceCallback(checkNotNull(audioDeviceCallback));
|
||||
}
|
||||
checkNotNull(isSuitableForPlaybackState)
|
||||
.runInBackground(
|
||||
() -> {
|
||||
if (audioManager != null) {
|
||||
audioManager.unregisterAudioDeviceCallback(checkNotNull(audioDeviceCallback));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectedOutputSuitableForPlayback() {
|
||||
return isSelectedOutputSuitableForPlayback;
|
||||
}
|
||||
|
||||
private void updateIsSelectedOutputSuitableForPlayback(Callback callback) {
|
||||
boolean isSelectedOutputSuitableForPlayback = hasSupportedAudioOutput();
|
||||
if (this.isSelectedOutputSuitableForPlayback != isSelectedOutputSuitableForPlayback) {
|
||||
this.isSelectedOutputSuitableForPlayback = isSelectedOutputSuitableForPlayback;
|
||||
callback.onSelectedOutputSuitabilityChanged(isSelectedOutputSuitableForPlayback);
|
||||
}
|
||||
return isSuitableForPlaybackState == null ? true : isSuitableForPlaybackState.get();
|
||||
}
|
||||
|
||||
private boolean hasSupportedAudioOutput() {
|
||||
if (!Util.isWear(applicationContext)) {
|
||||
return true;
|
||||
}
|
||||
AudioDeviceInfo[] audioDeviceInfos =
|
||||
checkStateNotNull(audioManager).getDevices(AudioManager.GET_DEVICES_OUTPUTS);
|
||||
for (AudioDeviceInfo device : audioDeviceInfos) {
|
||||
|
@ -24,7 +24,6 @@ import android.content.Context;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioTrack;
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.view.Surface;
|
||||
@ -460,7 +459,7 @@ public interface ExoPlayer extends Player {
|
||||
usePlatformDiagnostics = true;
|
||||
playerName = "";
|
||||
priority = C.PRIORITY_PLAYBACK;
|
||||
suitableOutputChecker = new DefaultSuitableOutputChecker(context, new Handler(looper));
|
||||
suitableOutputChecker = new DefaultSuitableOutputChecker();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,7 +413,12 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
if (builder.suppressPlaybackOnUnsuitableOutput) {
|
||||
suitableOutputChecker = builder.suitableOutputChecker;
|
||||
suitableOutputChecker.enable(this::onSelectedOutputSuitabilityChanged);
|
||||
suitableOutputChecker.enable(
|
||||
this::onSelectedOutputSuitabilityChanged,
|
||||
applicationContext,
|
||||
applicationLooper,
|
||||
playbackLooper,
|
||||
clock);
|
||||
} else {
|
||||
suitableOutputChecker = null;
|
||||
}
|
||||
|
@ -17,7 +17,10 @@ package androidx.media3.exoplayer;
|
||||
|
||||
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.RestrictTo;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
|
||||
/** Provides methods to check the suitability of selected media outputs. */
|
||||
@ -45,8 +48,17 @@ public interface SuitableOutputChecker {
|
||||
* #disable()}.
|
||||
*
|
||||
* @param callback To receive notifications of changes in suitable media output changes.
|
||||
* @param context A {@link Context}.
|
||||
* @param callbackLooper The {@link Looper} to call {@link Callback} methods on.
|
||||
* @param backgroundLooper The {@link Looper} to run background operations on.
|
||||
* @param clock The {@link Clock}.
|
||||
*/
|
||||
void enable(Callback callback);
|
||||
void enable(
|
||||
Callback callback,
|
||||
Context context,
|
||||
Looper callbackLooper,
|
||||
Looper backgroundLooper,
|
||||
Clock clock);
|
||||
|
||||
/**
|
||||
* Disables the current instance to receive updates on the selected media outputs and clears the
|
||||
|
@ -15035,6 +15035,7 @@ public class ExoPlayerTest {
|
||||
parameterizeTestExoPlayerBuilder(
|
||||
new TestExoPlayerBuilder(context).setSuppressPlaybackOnUnsuitableOutput(true))
|
||||
.build();
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.setMediaItem(
|
||||
MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4"));
|
||||
player.addListener(
|
||||
@ -15051,7 +15052,7 @@ public class ExoPlayerTest {
|
||||
|
||||
player.play();
|
||||
player.stop();
|
||||
runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||
advance(player).untilState(Player.STATE_IDLE);
|
||||
|
||||
assertThat(playbackSuppressionList)
|
||||
.containsExactly(Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT);
|
||||
@ -15113,6 +15114,7 @@ public class ExoPlayerTest {
|
||||
parameterizeTestExoPlayerBuilder(
|
||||
new TestExoPlayerBuilder(context).setSuppressPlaybackOnUnsuitableOutput(true))
|
||||
.build();
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.setMediaItem(
|
||||
MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4"));
|
||||
player.addListener(
|
||||
@ -15131,7 +15133,7 @@ public class ExoPlayerTest {
|
||||
player.play();
|
||||
player.play();
|
||||
player.stop();
|
||||
runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||
advance(player).untilState(Player.STATE_IDLE);
|
||||
|
||||
assertThat(playbackSuppressionList)
|
||||
.containsExactly(
|
||||
@ -15241,12 +15243,13 @@ public class ExoPlayerTest {
|
||||
player.prepare();
|
||||
player.play();
|
||||
player.pause();
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
advance(player).untilState(Player.STATE_READY);
|
||||
|
||||
addConnectedAudioOutput(
|
||||
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, /* notifyAudioDeviceCallbacks= */ true);
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.stop();
|
||||
runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||
advance(player).untilState(Player.STATE_IDLE);
|
||||
|
||||
assertThat(playbackSuppressionList)
|
||||
.containsExactly(
|
||||
@ -15298,11 +15301,12 @@ public class ExoPlayerTest {
|
||||
public void addSuitableOutputWhenPlaybackNotSuppressed_shouldNotRemovePlaybackSuppression()
|
||||
throws Exception {
|
||||
addWatchAsSystemFeature();
|
||||
setupConnectedAudioOutput(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
|
||||
setupConnectedAudioOutput(AudioDeviceInfo.TYPE_USB_DEVICE);
|
||||
ExoPlayer player =
|
||||
parameterizeTestExoPlayerBuilder(
|
||||
new TestExoPlayerBuilder(context).setSuppressPlaybackOnUnsuitableOutput(true))
|
||||
.build();
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.setMediaItem(
|
||||
MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4"));
|
||||
PlaybackSuppressionReasonChangedListener playbackSuppressionReasonChangedListener =
|
||||
@ -15313,8 +15317,9 @@ public class ExoPlayerTest {
|
||||
|
||||
addConnectedAudioOutput(
|
||||
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, /* notifyAudioDeviceCallbacks= */ true);
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.stop();
|
||||
runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||
advance(player).untilState(Player.STATE_IDLE);
|
||||
|
||||
assertThat(playbackSuppressionReasonChangedListener.getReasonChangedList()).isEmpty();
|
||||
player.release();
|
||||
@ -15341,14 +15346,15 @@ public class ExoPlayerTest {
|
||||
MediaItem.fromUri("asset:///media/mp4/sample_with_increasing_timestamps_360p.mp4"));
|
||||
player.prepare();
|
||||
player.play();
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
advance(player).untilState(Player.STATE_READY);
|
||||
PlaybackSuppressionReasonChangedListener playbackSuppressionReasonChangedListener =
|
||||
new PlaybackSuppressionReasonChangedListener();
|
||||
player.addListener(playbackSuppressionReasonChangedListener);
|
||||
|
||||
removeConnectedAudioOutput(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP);
|
||||
advance(player).untilPendingCommandsAreFullyHandled();
|
||||
player.stop();
|
||||
runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||
advance(player).untilState(Player.STATE_IDLE);
|
||||
|
||||
assertThat(playbackSuppressionReasonChangedListener.getReasonChangedList())
|
||||
.containsExactly(Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT);
|
||||
|
@ -18,8 +18,11 @@ package androidx.media3.test.utils;
|
||||
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
|
||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RestrictTo;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.SuitableOutputChecker;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
@ -64,7 +67,12 @@ public final class FakeSuitableOutputChecker implements SuitableOutputChecker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable(Callback callback) {
|
||||
public void enable(
|
||||
Callback callback,
|
||||
Context context,
|
||||
Looper callbackLooper,
|
||||
Looper backgroundLooper,
|
||||
Clock clock) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package androidx.media3.ui;
|
||||
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.advance;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPlayWhenReady;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPlaybackState;
|
||||
import static androidx.test.ext.truth.content.IntentSubject.assertThat;
|
||||
@ -38,6 +39,7 @@ import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.Player.PlayWhenReadyChangeReason;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.test.utils.FakeClock;
|
||||
import androidx.media3.test.utils.FakeSuitableOutputChecker;
|
||||
import androidx.media3.test.utils.TestExoPlayerBuilder;
|
||||
@ -75,11 +77,11 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest {
|
||||
|
||||
private ShadowPackageManager shadowPackageManager;
|
||||
private ShadowApplication shadowApplication;
|
||||
private Player testPlayer;
|
||||
private ExoPlayer testPlayer;
|
||||
private FakeSuitableOutputChecker suitableMediaOutputChecker;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setUp() throws Exception {
|
||||
shadowPackageManager =
|
||||
shadowOf(ApplicationProvider.getApplicationContext().getPackageManager());
|
||||
shadowPackageManager.setSystemFeature(PackageManager.FEATURE_WATCH, /* supported= */ true);
|
||||
@ -95,6 +97,7 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest {
|
||||
builder.setSuitableOutputChecker(suitableMediaOutputChecker);
|
||||
}
|
||||
testPlayer = builder.build();
|
||||
advance(testPlayer).untilPendingCommandsAreFullyHandled();
|
||||
|
||||
shadowApplication = shadowOf((Application) ApplicationProvider.getApplicationContext());
|
||||
}
|
||||
@ -816,8 +819,7 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest {
|
||||
|
||||
addConnectedAudioOutput(
|
||||
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, /* notifyAudioDeviceCallbacks= */ true);
|
||||
runUntilPlayWhenReady(testPlayer, /* expectedPlayWhenReady= */ false);
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
advance(testPlayer).untilPendingCommandsAreFullyHandled();
|
||||
|
||||
assertThat(ShadowPowerManager.getLatestWakeLock()).isNotNull();
|
||||
assertThat(ShadowPowerManager.getLatestWakeLock().isHeld()).isFalse();
|
||||
@ -959,7 +961,7 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest {
|
||||
fakeComponentName, new IntentFilter(fakeActionName));
|
||||
}
|
||||
|
||||
private void setupConnectedAudioOutput(int... deviceTypes) {
|
||||
private void setupConnectedAudioOutput(int... deviceTypes) throws TimeoutException {
|
||||
ShadowAudioManager shadowAudioManager =
|
||||
shadowOf(ApplicationProvider.getApplicationContext().getSystemService(AudioManager.class));
|
||||
for (int deviceType : deviceTypes) {
|
||||
@ -967,6 +969,7 @@ public class WearUnsuitableOutputPlaybackSuppressionResolverListenerTest {
|
||||
AudioDeviceInfoBuilder.newBuilder().setType(deviceType).build(),
|
||||
/* notifyAudioDeviceCallbacks= */ true);
|
||||
}
|
||||
advance(testPlayer).untilPendingCommandsAreFullyHandled();
|
||||
}
|
||||
|
||||
private void addConnectedAudioOutput(int deviceTypes, boolean notifyAudioDeviceCallbacks) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user