diff options
| author | 2022-11-28 22:39:51 +0000 | |
|---|---|---|
| committer | 2022-11-28 22:39:51 +0000 | |
| commit | c218ba0da3f703b7513d51f15ccf0c69e78c871c (patch) | |
| tree | 1c34e2bf0d370beb20534e5c9642ae3bb739dd1c | |
| parent | a40fb53567553125f88e606810bc451ef2c7ceb0 (diff) | |
| parent | dcb271056004e17d0c2f9ba5ec4184e03188840c (diff) | |
Merge "AudioDeviceVolumeManager and VolumeInfo API changes" into tm-qpr-dev am: dcb2710560
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20568529
Change-Id: I3dce7756a12fbd885c7f7ab1b989715ab7f1be05
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
8 files changed, 202 insertions, 61 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 00ed56c8a995..9730013b1849 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -114,6 +114,7 @@ import android.location.CountryDetector; import android.location.ICountryDetector; import android.location.ILocationManager; import android.location.LocationManager; +import android.media.AudioDeviceVolumeManager; import android.media.AudioManager; import android.media.MediaFrameworkInitializer; import android.media.MediaFrameworkPlatformInitializer; @@ -338,6 +339,13 @@ public final class SystemServiceRegistry { return new AudioManager(ctx); }}); + registerService(Context.AUDIO_DEVICE_VOLUME_SERVICE, AudioDeviceVolumeManager.class, + new CachedServiceFetcher<AudioDeviceVolumeManager>() { + @Override + public AudioDeviceVolumeManager createService(ContextImpl ctx) { + return new AudioDeviceVolumeManager(ctx); + }}); + registerService(Context.MEDIA_ROUTER_SERVICE, MediaRouter.class, new CachedServiceFetcher<MediaRouter>() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index cc42a4c11036..445c4d7c6e3f 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3845,6 +3845,7 @@ public abstract class Context { WIFI_RTT_RANGING_SERVICE, NSD_SERVICE, AUDIO_SERVICE, + AUDIO_DEVICE_VOLUME_SERVICE, AUTH_SERVICE, FINGERPRINT_SERVICE, //@hide: FACE_SERVICE, @@ -4687,6 +4688,17 @@ public abstract class Context { public static final String AUDIO_SERVICE = "audio"; /** + * @hide + * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.media.AudioDeviceVolumeManager} for handling management of audio device + * (e.g. speaker, USB headset) volume. + * + * @see #getSystemService(String) + * @see android.media.AudioDeviceVolumeManager + */ + public static final String AUDIO_DEVICE_VOLUME_SERVICE = "audio_device_volume"; + + /** * Use with {@link #getSystemService(String)} to retrieve a {@link * android.media.MediaTranscodingManager} for transcoding media. * diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java index c70887672f9e..4aee9eb0488e 100644 --- a/media/java/android/media/AudioDeviceVolumeManager.java +++ b/media/java/android/media/AudioDeviceVolumeManager.java @@ -41,8 +41,7 @@ import java.util.concurrent.Executor; */ public class AudioDeviceVolumeManager { - // define when using Log.* - //private static final String TAG = "AudioDeviceVolumeManager"; + private static final String TAG = "AudioDeviceVolumeManager"; /** Indicates no special treatment in the handling of the volume adjustment */ public static final int ADJUST_MODE_NORMAL = 0; @@ -62,11 +61,15 @@ public class AudioDeviceVolumeManager { private static IAudioService sService; private final @NonNull String mPackageName; - private final @Nullable String mAttributionTag; - public AudioDeviceVolumeManager(Context context) { + /** + * @hide + * Constructor + * @param context the Context for the device volume operations + */ + public AudioDeviceVolumeManager(@NonNull Context context) { + Objects.requireNonNull(context); mPackageName = context.getApplicationContext().getOpPackageName(); - mAttributionTag = context.getApplicationContext().getAttributionTag(); } /** @@ -308,13 +311,36 @@ public class AudioDeviceVolumeManager { @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolume(@NonNull VolumeInfo vi, @NonNull AudioDeviceAttributes ada) { try { - getService().setDeviceVolume(vi, ada, mPackageName, mAttributionTag); + getService().setDeviceVolume(vi, ada, mPackageName); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * @hide + * Returns the volume on the given audio device for the given volume information. + * For instance if using a {@link VolumeInfo} configured for {@link AudioManager#STREAM_ALARM}, + * it will return the alarm volume. When no volume index has ever been set for the given + * device, the default volume will be returned (the volume setting that would have been + * applied if playback for that use case had started). + * @param vi the volume information, only stream-based volumes are supported. Information + * other than the stream type is ignored. + * @param ada the device for which volume is to be retrieved + */ + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public @NonNull VolumeInfo getDeviceVolume(@NonNull VolumeInfo vi, + @NonNull AudioDeviceAttributes ada) { + try { + return getService().getDeviceVolume(vi, ada, mPackageName); } catch (RemoteException e) { e.rethrowFromSystemServer(); } + return VolumeInfo.getDefaultVolumeInfo(); } /** + * @hide * Return human-readable name for volume behavior * @param behavior one of the volume behaviors defined in AudioManager * @return a string for the given behavior diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index c3e605e396f3..6516eab6e1b3 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1212,7 +1212,13 @@ public class AudioManager { } } - private static boolean isPublicStreamType(int streamType) { + /** + * @hide + * Checks whether a stream type is part of the public SDK + * @param streamType + * @return true if the stream type is available in SDK + */ + public static boolean isPublicStreamType(int streamType) { switch (streamType) { case STREAM_VOICE_CALL: case STREAM_SYSTEM: diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 90eb9e644f26..ad933e02c0d5 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -99,7 +99,10 @@ interface IAudioService { in String callingPackage, in String attributionTag); void setDeviceVolume(in VolumeInfo vi, in AudioDeviceAttributes ada, - in String callingPackage, in String attributionTag); + in String callingPackage); + + VolumeInfo getDeviceVolume(in VolumeInfo vi, in AudioDeviceAttributes ada, + in String callingPackage); oneway void handleVolumeKey(in KeyEvent event, boolean isOnTv, String callingPackage, String caller); diff --git a/media/java/android/media/VolumeInfo.java b/media/java/android/media/VolumeInfo.java index c61b0e57db1a..bc91a09cf681 100644 --- a/media/java/android/media/VolumeInfo.java +++ b/media/java/android/media/VolumeInfo.java @@ -27,7 +27,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; -import java.util.List; import java.util.Objects; /** @@ -35,8 +34,9 @@ import java.util.Objects; * A class to represent type of volume information. * Can be used to represent volume associated with a stream type or {@link AudioVolumeGroup}. * Volume index is optional when used to represent a category of volume. - * Index ranges are supported too, making the representation of volume changes agnostic to the - * range (e.g. can be used to map BT A2DP absolute volume range to internal range). + * Volume ranges are supported too, making the representation of volume changes agnostic + * regarding the range of values that are supported (e.g. can be used to map BT A2DP absolute + * volume range to internal range). * * Note: this class is not yet part of the SystemApi but is intended to be gradually introduced * particularly in parts of the audio framework that suffer from code ambiguity when @@ -46,25 +46,27 @@ public final class VolumeInfo implements Parcelable { private static final String TAG = "VolumeInfo"; private final boolean mUsesStreamType; // false implies AudioVolumeGroup is used + private final boolean mHasMuteCommand; private final boolean mIsMuted; private final int mVolIndex; private final int mMinVolIndex; private final int mMaxVolIndex; - private final int mVolGroupId; - private final int mStreamType; + private final @Nullable AudioVolumeGroup mVolGroup; + private final @AudioManager.PublicStreamTypes int mStreamType; private static IAudioService sService; private static VolumeInfo sDefaultVolumeInfo; - private VolumeInfo(boolean usesStreamType, boolean isMuted, int volIndex, - int minVolIndex, int maxVolIndex, - int volGroupId, int streamType) { + private VolumeInfo(boolean usesStreamType, boolean hasMuteCommand, boolean isMuted, + int volIndex, int minVolIndex, int maxVolIndex, + AudioVolumeGroup volGroup, int streamType) { mUsesStreamType = usesStreamType; + mHasMuteCommand = hasMuteCommand; mIsMuted = isMuted; mVolIndex = volIndex; mMinVolIndex = minVolIndex; mMaxVolIndex = maxVolIndex; - mVolGroupId = volGroupId; + mVolGroup = volGroup; mStreamType = streamType; } @@ -81,8 +83,10 @@ public final class VolumeInfo implements Parcelable { /** * Returns the associated stream type, or will throw if {@link #hasStreamType()} returned false. * @return a stream type value, see AudioManager.STREAM_* + * @throws IllegalStateException when called on a VolumeInfo not configured for + * stream types. */ - public int getStreamType() { + public @AudioManager.PublicStreamTypes int getStreamType() { if (!mUsesStreamType) { throw new IllegalStateException("VolumeInfo doesn't use stream types"); } @@ -101,24 +105,28 @@ public final class VolumeInfo implements Parcelable { /** * Returns the associated volume group, or will throw if {@link #hasVolumeGroup()} returned * false. - * @return the volume group corresponding to this VolumeInfo, or null if an error occurred - * in the volume group management + * @return the volume group corresponding to this VolumeInfo + * @throws IllegalStateException when called on a VolumeInfo not configured for + * volume groups. */ - public @Nullable AudioVolumeGroup getVolumeGroup() { + public @NonNull AudioVolumeGroup getVolumeGroup() { if (mUsesStreamType) { throw new IllegalStateException("VolumeInfo doesn't use AudioVolumeGroup"); } - List<AudioVolumeGroup> volGroups = AudioVolumeGroup.getAudioVolumeGroups(); - for (AudioVolumeGroup group : volGroups) { - if (group.getId() == mVolGroupId) { - return group; - } - } - return null; + return mVolGroup; + } + + /** + * Return whether this instance is conveying a mute state + * @return true if the muted state was explicitly set for this instance + */ + public boolean hasMuteCommand() { + return mHasMuteCommand; } /** - * Returns whether this instance is conveying a mute state. + * Returns whether this instance is conveying a mute state that was explicitly set + * by {@link Builder#setMuted(boolean)}, false otherwise * @return true if the volume state is muted */ public boolean isMuted() { @@ -185,18 +193,21 @@ public final class VolumeInfo implements Parcelable { */ public static final class Builder { private boolean mUsesStreamType = true; // false implies AudioVolumeGroup is used - private int mStreamType = AudioManager.STREAM_MUSIC; + private @AudioManager.PublicStreamTypes int mStreamType = AudioManager.STREAM_MUSIC; + private boolean mHasMuteCommand = false; private boolean mIsMuted = false; private int mVolIndex = INDEX_NOT_SET; private int mMinVolIndex = INDEX_NOT_SET; private int mMaxVolIndex = INDEX_NOT_SET; - private int mVolGroupId = -Integer.MIN_VALUE; + private @Nullable AudioVolumeGroup mVolGroup; /** * Builder constructor for stream type-based VolumeInfo */ - public Builder(int streamType) { - // TODO validate stream type + public Builder(@AudioManager.PublicStreamTypes int streamType) { + if (!AudioManager.isPublicStreamType(streamType)) { + throw new IllegalArgumentException("Not a valid public stream type " + streamType); + } mUsesStreamType = true; mStreamType = streamType; } @@ -208,7 +219,7 @@ public final class VolumeInfo implements Parcelable { Objects.requireNonNull(volGroup); mUsesStreamType = false; mStreamType = -Integer.MIN_VALUE; - mVolGroupId = volGroup.getId(); + mVolGroup = volGroup; } /** @@ -219,11 +230,12 @@ public final class VolumeInfo implements Parcelable { Objects.requireNonNull(info); mUsesStreamType = info.mUsesStreamType; mStreamType = info.mStreamType; + mHasMuteCommand = info.mHasMuteCommand; mIsMuted = info.mIsMuted; mVolIndex = info.mVolIndex; mMinVolIndex = info.mMinVolIndex; mMaxVolIndex = info.mMaxVolIndex; - mVolGroupId = info.mVolGroupId; + mVolGroup = info.mVolGroup; } /** @@ -232,6 +244,7 @@ public final class VolumeInfo implements Parcelable { * @return the same builder instance */ public @NonNull Builder setMuted(boolean isMuted) { + mHasMuteCommand = true; mIsMuted = isMuted; return this; } @@ -241,7 +254,6 @@ public final class VolumeInfo implements Parcelable { * @param volIndex a 0 or greater value, or {@link #INDEX_NOT_SET} if unknown * @return the same builder instance */ - // TODO should we allow muted true + volume index set? (useful when toggling mute on/off?) public @NonNull Builder setVolumeIndex(int volIndex) { if (volIndex != INDEX_NOT_SET && volIndex < 0) { throw new IllegalArgumentException("Volume index cannot be negative"); @@ -296,9 +308,9 @@ public final class VolumeInfo implements Parcelable { throw new IllegalArgumentException("Min volume index:" + mMinVolIndex + " greater than max index:" + mMaxVolIndex); } - return new VolumeInfo(mUsesStreamType, mIsMuted, + return new VolumeInfo(mUsesStreamType, mHasMuteCommand, mIsMuted, mVolIndex, mMinVolIndex, mMaxVolIndex, - mVolGroupId, mStreamType); + mVolGroup, mStreamType); } } @@ -306,8 +318,8 @@ public final class VolumeInfo implements Parcelable { // Parcelable @Override public int hashCode() { - return Objects.hash(mUsesStreamType, mStreamType, mIsMuted, - mVolIndex, mMinVolIndex, mMaxVolIndex, mVolGroupId); + return Objects.hash(mUsesStreamType, mHasMuteCommand, mStreamType, mIsMuted, + mVolIndex, mMinVolIndex, mMaxVolIndex, mVolGroup); } @Override @@ -318,19 +330,20 @@ public final class VolumeInfo implements Parcelable { VolumeInfo that = (VolumeInfo) o; return ((mUsesStreamType == that.mUsesStreamType) && (mStreamType == that.mStreamType) - && (mIsMuted == that.mIsMuted) - && (mVolIndex == that.mVolIndex) - && (mMinVolIndex == that.mMinVolIndex) - && (mMaxVolIndex == that.mMaxVolIndex) - && (mVolGroupId == that.mVolGroupId)); + && (mHasMuteCommand == that.mHasMuteCommand) + && (mIsMuted == that.mIsMuted) + && (mVolIndex == that.mVolIndex) + && (mMinVolIndex == that.mMinVolIndex) + && (mMaxVolIndex == that.mMaxVolIndex) + && Objects.equals(mVolGroup, that.mVolGroup)); } @Override public String toString() { return new String("VolumeInfo:" + (mUsesStreamType ? (" streamType:" + mStreamType) - : (" volGroupId" + mVolGroupId)) - + " muted:" + mIsMuted + : (" volGroup:" + mVolGroup)) + + (mHasMuteCommand ? (" muted:" + mIsMuted) : ("[no mute cmd]")) + ((mVolIndex != INDEX_NOT_SET) ? (" volIndex:" + mVolIndex) : "") + ((mMinVolIndex != INDEX_NOT_SET) ? (" min:" + mMinVolIndex) : "") + ((mMaxVolIndex != INDEX_NOT_SET) ? (" max:" + mMaxVolIndex) : "")); @@ -345,21 +358,29 @@ public final class VolumeInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeBoolean(mUsesStreamType); dest.writeInt(mStreamType); + dest.writeBoolean(mHasMuteCommand); dest.writeBoolean(mIsMuted); dest.writeInt(mVolIndex); dest.writeInt(mMinVolIndex); dest.writeInt(mMaxVolIndex); - dest.writeInt(mVolGroupId); + if (!mUsesStreamType) { + mVolGroup.writeToParcel(dest, 0 /*ignored*/); + } } private VolumeInfo(@NonNull Parcel in) { mUsesStreamType = in.readBoolean(); mStreamType = in.readInt(); + mHasMuteCommand = in.readBoolean(); mIsMuted = in.readBoolean(); mVolIndex = in.readInt(); mMinVolIndex = in.readInt(); mMaxVolIndex = in.readInt(); - mVolGroupId = in.readInt(); + if (!mUsesStreamType) { + mVolGroup = AudioVolumeGroup.CREATOR.createFromParcel(in); + } else { + mVolGroup = null; + } } public static final @NonNull Parcelable.Creator<VolumeInfo> CREATOR = diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index f3f75d603a34..d7759902ce0b 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3599,6 +3599,18 @@ public class AudioService extends IAudioService.Stub } } + // TODO enforce MODIFY_AUDIO_SYSTEM_SETTINGS when defined + private void enforceModifyAudioRoutingOrSystemSettingsPermission() { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + != PackageManager.PERMISSION_GRANTED + /*&& mContext.checkCallingOrSelfPermission( + android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) + != PackageManager.PERMISSION_DENIED*/) { + throw new SecurityException( + "Missing MODIFY_AUDIO_ROUTING or MODIFY_AUDIO_SYSTEM_SETTINGS permission"); + } + } + private void enforceAccessUltrasoundPermission() { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_ULTRASOUND) != PackageManager.PERMISSION_GRANTED) { @@ -3703,10 +3715,12 @@ public class AudioService extends IAudioService.Stub } /** @see AudioDeviceVolumeManager#setDeviceVolume(VolumeInfo, AudioDeviceAttributes) - * Part of service interface, check permissions and parameters here */ + * Part of service interface, check permissions and parameters here + * Note calling package is for logging purposes only, not to be trusted + */ public void setDeviceVolume(@NonNull VolumeInfo vi, @NonNull AudioDeviceAttributes ada, - @NonNull String callingPackage, @Nullable String attributionTag) { - enforceModifyAudioRoutingPermission(); + @NonNull String callingPackage) { + enforceModifyAudioRoutingOrSystemSettingsPermission(); Objects.requireNonNull(vi); Objects.requireNonNull(ada); Objects.requireNonNull(callingPackage); @@ -3719,8 +3733,20 @@ public class AudioService extends IAudioService.Stub return; } int index = vi.getVolumeIndex(); - if (index == VolumeInfo.INDEX_NOT_SET) { - throw new IllegalArgumentException("changing device volume requires a volume index"); + if (index == VolumeInfo.INDEX_NOT_SET && !vi.hasMuteCommand()) { + throw new IllegalArgumentException( + "changing device volume requires a volume index or mute command"); + } + + // TODO handle unmuting of current audio device + // if a stream is not muted but the VolumeInfo is for muting, set the volume index + // for the device to min volume + if (vi.hasMuteCommand() && vi.isMuted() && !isStreamMute(vi.getStreamType())) { + setStreamVolumeWithAttributionInt(vi.getStreamType(), + mStreamStates[vi.getStreamType()].getMinIndex(), + /*flags*/ 0, + ada, callingPackage, null); + return; } if (vi.getMinVolumeIndex() == VolumeInfo.INDEX_NOT_SET @@ -3742,7 +3768,7 @@ public class AudioService extends IAudioService.Stub } } setStreamVolumeWithAttributionInt(vi.getStreamType(), index, /*flags*/ 0, - ada, callingPackage, attributionTag); + ada, callingPackage, null); } /** Retain API for unsupported app usage */ @@ -4648,6 +4674,40 @@ public class AudioService extends IAudioService.Stub } } + /** + * @see AudioDeviceVolumeManager#getDeviceVolume(VolumeInfo, AudioDeviceAttributes) + */ + public @NonNull VolumeInfo getDeviceVolume(@NonNull VolumeInfo vi, + @NonNull AudioDeviceAttributes ada, @NonNull String callingPackage) { + enforceModifyAudioRoutingOrSystemSettingsPermission(); + Objects.requireNonNull(vi); + Objects.requireNonNull(ada); + Objects.requireNonNull(callingPackage); + if (!vi.hasStreamType()) { + Log.e(TAG, "Unsupported non-stream type based VolumeInfo", new Exception()); + return getDefaultVolumeInfo(); + } + + int streamType = vi.getStreamType(); + final VolumeInfo.Builder vib = new VolumeInfo.Builder(vi); + vib.setMinVolumeIndex((mStreamStates[streamType].mIndexMin + 5) / 10); + vib.setMaxVolumeIndex((mStreamStates[streamType].mIndexMax + 5) / 10); + synchronized (VolumeStreamState.class) { + final int index; + if (isFixedVolumeDevice(ada.getInternalType())) { + index = (mStreamStates[streamType].mIndexMax + 5) / 10; + } else { + index = (mStreamStates[streamType].getIndex(ada.getInternalType()) + 5) / 10; + } + vib.setVolumeIndex(index); + // only set as a mute command if stream muted + if (mStreamStates[streamType].mIsMuted) { + vib.setMuted(true); + } + return vib.build(); + } + } + /** @see AudioManager#getStreamMaxVolume(int) */ public int getStreamMaxVolume(int streamType) { ensureValidStreamType(streamType); @@ -4686,7 +4746,6 @@ public class AudioService extends IAudioService.Stub sDefaultVolumeInfo = new VolumeInfo.Builder(AudioSystem.STREAM_MUSIC) .setMinVolumeIndex(getStreamMinVolume(AudioSystem.STREAM_MUSIC)) .setMaxVolumeIndex(getStreamMaxVolume(AudioSystem.STREAM_MUSIC)) - .setMuted(false) .build(); } return sDefaultVolumeInfo; diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceVolumeManagerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceVolumeManagerTest.java index 7acb6d66c834..64af2969b67c 100644 --- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceVolumeManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceVolumeManagerTest.java @@ -27,18 +27,18 @@ import android.media.AudioManager; import android.media.AudioSystem; import android.media.VolumeInfo; import android.os.test.TestLooper; +import android.util.Log; import androidx.test.InstrumentationRegistry; +import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; public class AudioDeviceVolumeManagerTest { private static final String TAG = "AudioDeviceVolumeManagerTest"; - private static final AudioDeviceAttributes DEVICE_SPEAKER_OUT = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, ""); - private Context mContext; private String mPackageName; private AudioSystemAdapter mSpyAudioSystem; @@ -84,14 +84,20 @@ public class AudioDeviceVolumeManagerTest { final AudioDeviceAttributes usbDevice = new AudioDeviceAttributes( /*native type*/ AudioSystem.DEVICE_OUT_USB_DEVICE, /*address*/ "bla"); - mAudioService.setDeviceVolume(volMin, usbDevice, mPackageName, TAG); + mAudioService.setDeviceVolume(volMin, usbDevice, mPackageName); mTestLooper.dispatchAll(); verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( AudioManager.STREAM_MUSIC, minIndex, AudioSystem.DEVICE_OUT_USB_DEVICE); - mAudioService.setDeviceVolume(volMid, usbDevice, mPackageName, TAG); + mAudioService.setDeviceVolume(volMid, usbDevice, mPackageName); mTestLooper.dispatchAll(); verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( AudioManager.STREAM_MUSIC, midIndex, AudioSystem.DEVICE_OUT_USB_DEVICE); + + final VolumeInfo vi = mAudioService.getDeviceVolume(volMin, usbDevice, mPackageName); + Assert.assertEquals("getDeviceVolume doesn't return expected value in " + vi + + " after setting " + volMid, + (volMid.getMaxVolumeIndex() - volMid.getMinVolumeIndex()) / 2, + (vi.getMaxVolumeIndex() - vi.getMinVolumeIndex()) / 2); } } |