diff options
| author | 2022-11-28 22:09:30 +0000 | |
|---|---|---|
| committer | 2022-11-28 22:09:30 +0000 | |
| commit | dcb271056004e17d0c2f9ba5ec4184e03188840c (patch) | |
| tree | 65ff1744088d5dbc66baf301a5c821610d0cfe5c | |
| parent | b272ead9bbc939aabaff721d3195d0c64ed3e349 (diff) | |
| parent | 7ec3e248161f3dce5939c010a0ae63bbcdf5b155 (diff) | |
Merge "AudioDeviceVolumeManager and VolumeInfo API changes" into tm-qpr-dev
8 files changed, 202 insertions, 61 deletions
| diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index b6189692107e..ec100c2fa0c0 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -115,6 +115,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; @@ -339,6 +340,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 fce23cf6819a..77ca48a8ed1d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3846,6 +3846,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 e7eda3ea4552..798688ea7b46 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 4a01c61830d0..83a77bd71c4a 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);      }  } |