diff options
| author | 2019-04-12 15:49:39 +0000 | |
|---|---|---|
| committer | 2019-04-12 15:49:39 +0000 | |
| commit | e98e90dca6b1700cd6197db75eb3bb00bb668c41 (patch) | |
| tree | d93860ec8df5b3c82af1a2b78129fcad43f9d715 | |
| parent | 40ec9664f618744c016c90e91a3fcbafbff52a63 (diff) | |
| parent | ebd6aaa4b0f7b302e9733dd5a801b01bc450af4f (diff) | |
Merge changes from topic "AudioProductStrategies-API" into qt-dev
* changes:
Replacing AudioVolumeGroups with List
Cleaning up SeekBarVolumizer
Removing name getter from AudioProductStrategy
Replacing AudioProductStrategies with List
| -rw-r--r-- | api/system-current.txt | 31 | ||||
| -rw-r--r-- | core/java/android/preference/SeekBarVolumizer.java | 67 | ||||
| -rw-r--r-- | core/jni/android_media_AudioProductStrategies.cpp | 24 | ||||
| -rw-r--r-- | core/jni/android_media_AudioVolumeGroups.cpp | 2 | ||||
| -rw-r--r-- | media/java/android/media/AudioAttributes.java | 14 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 16 | ||||
| -rw-r--r-- | media/java/android/media/IAudioService.aidl | 8 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioProductStrategies.aidl | 18 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioProductStrategies.java | 277 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioProductStrategy.java | 111 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioVolumeGroup.java | 45 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioVolumeGroups.aidl | 18 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioVolumeGroups.java | 135 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 76 |
14 files changed, 266 insertions, 576 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 026ce092ba85..efbb079e660d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3498,8 +3498,8 @@ package android.media { method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes); method public void clearAudioServerStateCallback(); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioProductStrategies getAudioProductStrategies(); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioVolumeGroups getAudioVolumeGroups(); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies(); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups(); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); @@ -3678,27 +3678,10 @@ package android.media.audiopolicy { method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException; } - public final class AudioProductStrategies implements java.lang.Iterable<android.media.audiopolicy.AudioProductStrategy> android.os.Parcelable { - ctor public AudioProductStrategies(); - method public int describeContents(); - method @NonNull public android.media.AudioAttributes getAudioAttributesForLegacyStreamType(int); - method @NonNull public android.media.AudioAttributes getAudioAttributesForProductStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); - method @Nullable public android.media.audiopolicy.AudioProductStrategy getById(int); - method public int getLegacyStreamTypeForAudioAttributes(@NonNull android.media.AudioAttributes); - method @Nullable public android.media.audiopolicy.AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes); - method public int getVolumeGroupIdForAttributes(@NonNull android.media.AudioAttributes); - method public int getVolumeGroupIdForLegacyStreamType(int); - method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator(); - method public int size(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategies> CREATOR; - } - public final class AudioProductStrategy implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.media.AudioAttributes getAudioAttributes(); method public int getId(); - method @NonNull public String name(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR; } @@ -3711,16 +3694,6 @@ package android.media.audiopolicy { method @NonNull public String name(); method public void writeToParcel(@NonNull android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroup> CREATOR; - } - - public final class AudioVolumeGroups implements java.lang.Iterable<android.media.audiopolicy.AudioVolumeGroup> android.os.Parcelable { - ctor public AudioVolumeGroups(); - method public int describeContents(); - method @Nullable public android.media.audiopolicy.AudioVolumeGroup getById(int); - method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioVolumeGroup> iterator(); - method public int size(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroups> CREATOR; field public static final int DEFAULT_VOLUME_GROUP = -1; // 0xffffffff } diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 847b8e48b296..02f99258395c 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -16,6 +16,7 @@ package android.preference; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.app.NotificationManager; import android.content.BroadcastReceiver; @@ -27,8 +28,8 @@ import android.media.AudioAttributes; import android.media.AudioManager; import android.media.Ringtone; import android.media.RingtoneManager; -import android.media.audiopolicy.AudioProductStrategies; -import android.media.audiopolicy.AudioVolumeGroups; +import android.media.audiopolicy.AudioProductStrategy; +import android.media.audiopolicy.AudioVolumeGroup; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; @@ -67,7 +68,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba private static final int MSG_GROUP_VOLUME_CHANGED = 1; private final Handler mVolumeHandler = new VolumeHandler(); - private final AudioProductStrategies mAudioProductStrategies; private AudioAttributes mAttributes; private int mVolumeGroupId; @@ -161,11 +161,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } mZenMode = mNotificationManager.getZenMode(); - mAudioProductStrategies = mAudioManager.getAudioProductStrategies(); - if (mAudioProductStrategies.size() > 0) { - mVolumeGroupId = mAudioProductStrategies.getVolumeGroupIdForLegacyStreamType( - mStreamType); - mAttributes = mAudioProductStrategies.getAudioAttributesForLegacyStreamType( + if (hasAudioProductStrategies()) { + mVolumeGroupId = getVolumeGroupIdForLegacyStreamType(mStreamType); + mAttributes = getAudioAttributesForLegacyStreamType( mStreamType); } @@ -190,6 +188,40 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba mDefaultUri = defaultUri; } + private boolean hasAudioProductStrategies() { + return AudioManager.getAudioProductStrategies().size() > 0; + } + + private int getVolumeGroupIdForLegacyStreamType(int streamType) { + for (final AudioProductStrategy productStrategy : + AudioManager.getAudioProductStrategies()) { + int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType); + if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + } + + return AudioManager.getAudioProductStrategies().stream() + .map(strategy -> strategy.getVolumeGroupIdForAudioAttributes( + AudioProductStrategy.sDefaultAttributes)) + .filter(volumeGroupId -> volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) + .findFirst() + .orElse(AudioVolumeGroup.DEFAULT_VOLUME_GROUP); + } + + private @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) { + for (final AudioProductStrategy productStrategy : + AudioManager.getAudioProductStrategies()) { + AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType); + if (aa != null) { + return aa; + } + } + return new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) + .setUsage(AudioAttributes.USAGE_UNKNOWN).build(); + } + private static boolean isNotificationOrRing(int stream) { return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION; } @@ -329,7 +361,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba postStopSample(); mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); mReceiver.setListening(false); - if (mAudioProductStrategies.size() > 0) { + if (hasAudioProductStrategies()) { unregisterVolumeGroupCb(); } mSeekBar.setOnSeekBarChangeListener(null); @@ -349,7 +381,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba System.getUriFor(System.VOLUME_SETTINGS_INT[mStreamType]), false, mVolumeObserver); mReceiver.setListening(true); - if (mAudioProductStrategies.size() > 0) { + if (hasAudioProductStrategies()) { registerVolumeGroupCb(); } } @@ -507,7 +539,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) { int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); - if (mAudioProductStrategies.size() == 0) { + if (hasAudioProductStrategies()) { updateVolumeSlider(streamType, streamValue); } } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { @@ -519,13 +551,12 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) { int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); - if (mAudioProductStrategies.size() == 0) { + if (hasAudioProductStrategies()) { int streamVolume = mAudioManager.getStreamVolume(streamType); updateVolumeSlider(streamType, streamVolume); } else { - int volumeGroup = mAudioProductStrategies.getVolumeGroupIdForLegacyStreamType( - streamType); - if (volumeGroup != AudioVolumeGroups.DEFAULT_VOLUME_GROUP + int volumeGroup = getVolumeGroupIdForLegacyStreamType(streamType); + if (volumeGroup != AudioVolumeGroup.DEFAULT_VOLUME_GROUP && volumeGroup == mVolumeGroupId) { int streamVolume = mAudioManager.getStreamVolume(streamType); updateVolumeSlider(streamType, streamVolume); @@ -558,14 +589,14 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } private void registerVolumeGroupCb() { - if (mVolumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { + if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { mAudioManager.registerVolumeGroupCallback(Runnable::run, mVolumeGroupCallback); mLastProgress = mAudioManager.getVolumeIndexForAttributes(mAttributes); } } private void unregisterVolumeGroupCb() { - if (mVolumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { + if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { mAudioManager.unregisterVolumeGroupCallback(mVolumeGroupCallback); } } @@ -578,7 +609,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba case MSG_GROUP_VOLUME_CHANGED: int group = (int) args.arg1; if (mVolumeGroupId != group - || mVolumeGroupId == AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { + || mVolumeGroupId == AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { return; } updateSlider(); diff --git a/core/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp index 822b74a6b990..17a02b24c697 100644 --- a/core/jni/android_media_AudioProductStrategies.cpp +++ b/core/jni/android_media_AudioProductStrategies.cpp @@ -39,7 +39,7 @@ using namespace android; // ---------------------------------------------------------------------------- -static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategies"; +static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategy"; static const char* const kAudioProductStrategyClassPathName = "android/media/audiopolicy/AudioProductStrategy"; @@ -194,34 +194,12 @@ exit: return jStatus; } -static jint -android_media_AudioSystem_getProductStrategyFromAudioAttributes(JNIEnv *env, jobject clazz, - jobject jAudioAttributes) -{ - JNIAudioAttributeHelper::UniqueAaPtr attributes = JNIAudioAttributeHelper::makeUnique(); - jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, - jAudioAttributes, - attributes.get()); - if (jStatus != (jint)AUDIO_JAVA_SUCCESS) { - return jStatus; - } - product_strategy_t psId; - status_t status = AudioSystem::getProductStrategyFromAudioAttributes( - AudioAttributes(*attributes.get()), psId); - if (status != NO_ERROR) { - return nativeToJavaStatus(status); - } - return psId; -} - /* * JNI registration. */ static const JNINativeMethod gMethods[] = { {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_listAudioProductStrategies}, - {"native_get_product_strategies_from_audio_attributes", "(Landroid/media/AudioAttributes;)I", - (void *)android_media_AudioSystem_getProductStrategyFromAudioAttributes}, }; int register_android_media_AudioProductStrategies(JNIEnv *env) diff --git a/core/jni/android_media_AudioVolumeGroups.cpp b/core/jni/android_media_AudioVolumeGroups.cpp index 64f0c1e33e1c..7098451901c4 100644 --- a/core/jni/android_media_AudioVolumeGroups.cpp +++ b/core/jni/android_media_AudioVolumeGroups.cpp @@ -39,7 +39,7 @@ using namespace android; // ---------------------------------------------------------------------------- -static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroups"; +static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroup"; static const char* const kAudioVolumeGroupClassPathName = "android/media/audiopolicy/AudioVolumeGroup"; diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 9d4bce7b4301..d8640967a30a 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -20,7 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; -import android.media.audiopolicy.AudioProductStrategies; +import android.media.audiopolicy.AudioProductStrategy; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -783,9 +783,10 @@ public final class AudioAttributes implements Parcelable { */ @UnsupportedAppUsage public Builder setInternalLegacyStreamType(int streamType) { - final AudioProductStrategies ps = new AudioProductStrategies(); - if (ps.size() > 0) { - AudioAttributes attributes = ps.getAudioAttributesForLegacyStreamType(streamType); + if (AudioProductStrategy.getAudioProductStrategies().size() > 0) { + AudioAttributes attributes = + AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( + streamType); if (attributes != null) { return new Builder(attributes); } @@ -1165,9 +1166,8 @@ public final class AudioAttributes implements Parcelable { AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS; } - final AudioProductStrategies ps = new AudioProductStrategies(); - if (ps.size() > 0) { - return ps.getLegacyStreamTypeForAudioAttributes(aa); + if (AudioProductStrategy.getAudioProductStrategies().size() > 0) { + return AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(aa); } // usage to stream type mapping switch (aa.getUsage()) { diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index a5a409286754..d5eee6308ae0 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -37,9 +37,9 @@ import android.content.Context; import android.content.Intent; import android.media.audiopolicy.AudioPolicy; import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener; -import android.media.audiopolicy.AudioProductStrategies; +import android.media.audiopolicy.AudioProductStrategy; +import android.media.audiopolicy.AudioVolumeGroup; import android.media.audiopolicy.AudioVolumeGroupChangeHandler; -import android.media.audiopolicy.AudioVolumeGroups; import android.media.projection.MediaProjection; import android.media.session.MediaController; import android.media.session.MediaSession; @@ -5406,8 +5406,9 @@ public class AudioManager { * {@see android.media.audiopolicy.AudioProductStrategy} objects. */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull AudioProductStrategies getAudioProductStrategies() { + public static List<AudioProductStrategy> getAudioProductStrategies() { final IAudioService service = getService(); try { return service.getAudioProductStrategies(); @@ -5421,15 +5422,16 @@ public class AudioManager { * Introspection API to retrieve audio volume groups. * When implementing {Car|Oem}AudioManager, use this method to retrieve the collection of * audio volume groups. - * @return a (possibly zero-length) array of - * {@see android.media.audiopolicy.AudioVolumeGroups} objects. + * @return a (possibly zero-length) List of + * {@see android.media.audiopolicy.AudioVolumeGroup} objects. */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull AudioVolumeGroups getAudioVolumeGroups() { + public static List<AudioVolumeGroup> getAudioVolumeGroups() { final IAudioService service = getService(); try { - return service.listAudioVolumeGroups(); + return service.getAudioVolumeGroups(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 980cb0459821..eddbee46252e 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -33,8 +33,8 @@ import android.media.IVolumeController; import android.media.PlayerBase; import android.media.VolumePolicy; import android.media.audiopolicy.AudioPolicyConfig; -import android.media.audiopolicy.AudioProductStrategies; -import android.media.audiopolicy.AudioVolumeGroups; +import android.media.audiopolicy.AudioProductStrategy; +import android.media.audiopolicy.AudioVolumeGroup; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; import android.net.Uri; @@ -86,7 +86,7 @@ interface IAudioService { @UnsupportedAppUsage int getStreamMaxVolume(int streamType); - AudioVolumeGroups listAudioVolumeGroups(); + List<AudioVolumeGroup> getAudioVolumeGroups(); void setVolumeIndexForAttributes(in AudioAttributes aa, int index, int flags, String callingPackage); @@ -98,7 +98,7 @@ interface IAudioService { int getLastAudibleStreamVolume(int streamType); - AudioProductStrategies getAudioProductStrategies(); + List<AudioProductStrategy> getAudioProductStrategies(); void setMicrophoneMute(boolean on, String callingPackage, int userId); diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.aidl b/media/java/android/media/audiopolicy/AudioProductStrategies.aidl deleted file mode 100644 index bec11bcfab5d..000000000000 --- a/media/java/android/media/audiopolicy/AudioProductStrategies.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2018, 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 android.media.audiopolicy; - -parcelable AudioProductStrategies; diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java deleted file mode 100644 index c305b683f136..000000000000 --- a/media/java/android/media/audiopolicy/AudioProductStrategies.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2018 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 android.media.audiopolicy; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.media.AudioAttributes; -import android.media.AudioSystem; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -import com.android.internal.util.Preconditions; - -import java.util.ArrayList; -import java.util.Iterator; - -/** - * @hide - * A class to encapsulate a collection of {@link AudioProductStrategy}. - * Provides helper functions to easily retrieve the {@link AudioAttributes} for a given product - * strategy or legacy stream type. - */ -@SystemApi -public final class AudioProductStrategies implements Iterable<AudioProductStrategy>, Parcelable { - - private final ArrayList<AudioProductStrategy> mAudioProductStrategyList; - - private static final String TAG = "AudioProductStrategies"; - - public AudioProductStrategies() { - ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>(); - int status = native_list_audio_product_strategies(apsList); - if (status != AudioSystem.SUCCESS) { - Log.w(TAG, ": createAudioProductStrategies failed"); - } - mAudioProductStrategyList = apsList; - } - - private AudioProductStrategies(ArrayList<AudioProductStrategy> audioProductStrategy) { - mAudioProductStrategyList = audioProductStrategy; - } - - /** - * @hide - * @return number of {@link AudioProductStrategy} objects - */ - @SystemApi - public int size() { - return mAudioProductStrategyList.size(); - } - - /** - * @hide - * @return the matching {@link AudioProductStrategy} objects with the given id, - * null object if not found. - */ - @SystemApi - public @Nullable AudioProductStrategy getById(int productStrategyId) { - for (final AudioProductStrategy avg : this) { - if (avg.getId() == productStrategyId) { - return avg; - } - } - Log.e(TAG, ": invalid product strategy id: " + productStrategyId + " requested"); - return null; - } - - /** - * Returns an {@link Iterator} - */ - @Override - public @NonNull Iterator<AudioProductStrategy> iterator() { - return mAudioProductStrategyList.iterator(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AudioProductStrategies that = (AudioProductStrategies) o; - - return mAudioProductStrategyList.equals(that.mAudioProductStrategyList); - } - - /** - * @hide - * @param aps {@link AudioProductStrategy} (which is the generalisation of Car Audio Usage / - * legacy routing_strategy linked to {@link AudioAttributes#getUsage()} ) - * @return the {@link AudioAttributes} relevant for the given product strategy. - * If none is found, it builds the default attributes. - * TODO: shall the helper collection be able to identify the platform default? - */ - @SystemApi - @NonNull - public AudioAttributes getAudioAttributesForProductStrategy(@NonNull AudioProductStrategy aps) { - Preconditions.checkNotNull(aps, "AudioProductStrategy must not be null"); - for (final AudioProductStrategy audioProductStrategy : this) { - if (audioProductStrategy.equals(aps)) { - return audioProductStrategy.getAudioAttributes(); - } - } - return new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) - .setUsage(AudioAttributes.USAGE_UNKNOWN).build(); - } - - /** - * @hide - * @param streamType legacy stream type used for volume operation only - * @return the {@link AudioAttributes} relevant for the given streamType. - * If none is found, it builds the default attributes. - */ - @SystemApi - public @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) { - for (final AudioProductStrategy productStrategy : this) { - AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType); - if (aa != null) { - return aa; - } - } - return new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) - .setUsage(AudioAttributes.USAGE_UNKNOWN).build(); - } - - /** - * @hide - * @param aa the {@link AudioAttributes} for which stream type is requested - * @return the legacy stream type relevant for the given {@link AudioAttributes}. - * If the product strategy is not associated to any stream, it returns - * {@link AudioSystem#STREAM_MUSIC}. - * If no product strategy supports the stream type, it returns - * {@link AudioSystem#STREAM_MUSIC}. - */ - @SystemApi - public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) { - Preconditions.checkNotNull(aa, "AudioAttributes must not be null"); - for (final AudioProductStrategy productStrategy : this) { - if (productStrategy.supportsAudioAttributes(aa)) { - int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes(aa); - if (streamType == AudioSystem.STREAM_DEFAULT) { - Log.w(TAG, "Attributes " + aa.toString() + " ported by strategy " - + productStrategy.name() + " has no stream type associated, " - + "DO NOT USE STREAM TO CONTROL THE VOLUME"); - return AudioSystem.STREAM_MUSIC; - } - return streamType; - } - } - return AudioSystem.STREAM_MUSIC; - } - - /** - * @hide - * @param aa the {@link AudioAttributes} to be considered - * @return {@link AudioProductStrategy} supporting the given {@link AudioAttributes}. - * null is returned if no match with given attributes. - */ - @SystemApi - @Nullable - public AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull AudioAttributes aa) { - Preconditions.checkNotNull(aa, "attributes must not be null"); - int productStrategyId = native_get_product_strategies_from_audio_attributes(aa); - if (productStrategyId < 0) { - Log.w(TAG, "no strategy found for Attributes " + aa.toString()); - return null; - } - return getById(productStrategyId); - } - - /** - * @hide - * @param attributes the {@link AudioAttributes} to be considered - * @return volume group associated to the given {@link AudioAttributes}. - * If no group supports the given {@link AudioAttributes}, it returns the volume group - * for the default attributes. - * If no group supports the default attributes, it returns {@link #DEFAULT_VOLUME_GROUP} - */ - @SystemApi - public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) { - Preconditions.checkNotNull(attributes, "attributes must not be null"); - int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes); - if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { - return volumeGroupId; - } - // The default volume group is the one hosted by default product strategy, i.e. - // supporting Default Attributes - return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes); - } - - /** - * @hide - * @param streamType to be considered - * @return volume group associated to the given stream type. - */ - @SystemApi - public int getVolumeGroupIdForLegacyStreamType(int streamType) { - for (final AudioProductStrategy productStrategy : this) { - int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType); - if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { - return volumeGroupId; - } - } - // The default volume group is the one hosted by default product strategy, i.e. - // supporting Default Attributes - return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(size()); - for (final AudioProductStrategy productStrategy : this) { - productStrategy.writeToParcel(dest, flags); - } - } - - /** - * @param attributes to be considered - * @return volume group associated to the given {@link AudioAttributes}. - */ - private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) { - Preconditions.checkNotNull(attributes, "attributes must not be null"); - for (final AudioProductStrategy productStrategy : this) { - int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes); - if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { - return volumeGroupId; - } - } - return AudioVolumeGroups.DEFAULT_VOLUME_GROUP; - } - - public static final @android.annotation.NonNull Parcelable.Creator<AudioProductStrategies> CREATOR = - new Parcelable.Creator<AudioProductStrategies>() { - @Override - public AudioProductStrategies createFromParcel(@NonNull Parcel in) { - ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>(); - int size = in.readInt(); - for (int index = 0; index < size; index++) { - apsList.add(AudioProductStrategy.CREATOR.createFromParcel(in)); - } - return new AudioProductStrategies(apsList); - } - - @Override - public @NonNull AudioProductStrategies[] newArray(int size) { - return new AudioProductStrategies[size]; - } - }; - - private static native int native_list_audio_product_strategies( - ArrayList<AudioProductStrategy> strategies); - - private static native int native_get_product_strategies_from_audio_attributes( - AudioAttributes attributes); -} diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java index c1c255f68996..9ac9411370ab 100644 --- a/media/java/android/media/audiopolicy/AudioProductStrategy.java +++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java @@ -25,9 +25,14 @@ import android.media.MediaRecorder; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; +import java.util.ArrayList; +import java.util.List; + /** * @hide * A class to encapsulate a collection of attributes associated to a given product strategy @@ -41,6 +46,9 @@ public final class AudioProductStrategy implements Parcelable { */ public static final int DEFAULT_GROUP = -1; + + private static final String TAG = "AudioProductStrategy"; + private final AudioAttributesGroup[] mAudioAttributesGroups; private final String mName; /** @@ -51,6 +59,86 @@ public final class AudioProductStrategy implements Parcelable { */ private int mId; + private static final Object sLock = new Object(); + + @GuardedBy("sLock") + private static List<AudioProductStrategy> sAudioProductStrategies; + + /** + * @hide + * @return the list of AudioProductStrategy discovered from platform configuration file. + */ + @NonNull + public static List<AudioProductStrategy> getAudioProductStrategies() { + if (sAudioProductStrategies == null) { + synchronized (sLock) { + if (sAudioProductStrategies == null) { + sAudioProductStrategies = initializeAudioProductStrategies(); + } + } + } + return sAudioProductStrategies; + } + + /** + * @hide + * @param streamType to match against AudioProductStrategy + * @return the AudioAttributes for the first strategy found with the associated stream type + * If no match is found, returns AudioAttributes with unknown content_type and usage + */ + @NonNull + public static AudioAttributes getAudioAttributesForStrategyWithLegacyStreamType( + int streamType) { + for (final AudioProductStrategy productStrategy : + AudioProductStrategy.getAudioProductStrategies()) { + AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType); + if (aa != null) { + return aa; + } + } + return new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) + .setUsage(AudioAttributes.USAGE_UNKNOWN).build(); + } + + /** + * @hide + * @param audioAttributes to identify AudioProductStrategy with + * @return legacy stream type associated with matched AudioProductStrategy + * Defaults to STREAM_MUSIC if no match is found, or if matches is STREAM_DEFAULT + */ + public static int getLegacyStreamTypeForStrategyWithAudioAttributes( + @NonNull AudioAttributes audioAttributes) { + Preconditions.checkNotNull(audioAttributes, "AudioAttributes must not be null"); + for (final AudioProductStrategy productStrategy : + AudioProductStrategy.getAudioProductStrategies()) { + if (productStrategy.supportsAudioAttributes(audioAttributes)) { + int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes( + audioAttributes); + if (streamType == AudioSystem.STREAM_DEFAULT) { + Log.w(TAG, "Attributes " + audioAttributes.toString() + " ported by strategy " + + productStrategy.getId() + " has no stream type associated, " + + "DO NOT USE STREAM TO CONTROL THE VOLUME"); + return AudioSystem.STREAM_MUSIC; + } + return streamType; + } + } + return AudioSystem.STREAM_MUSIC; + } + + private static List<AudioProductStrategy> initializeAudioProductStrategies() { + ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>(); + int status = native_list_audio_product_strategies(apsList); + if (status != AudioSystem.SUCCESS) { + Log.w(TAG, ": initializeAudioProductStrategies failed"); + } + return apsList; + } + + private static native int native_list_audio_product_strategies( + ArrayList<AudioProductStrategy> strategies); + @Override public boolean equals(@Nullable Object o) { if (this == o) return true; @@ -65,8 +153,7 @@ public final class AudioProductStrategy implements Parcelable { /** * @param name of the product strategy * @param id of the product strategy - * @param audioAttributes {@link AudioAttributes} associated to the given product strategy - * @param legacyStreamTypes associated to the given product strategy. + * @param aag {@link AudioAttributesGroup} associated to the given product strategy */ private AudioProductStrategy(@NonNull String name, int id, @NonNull AudioAttributesGroup[] aag) { @@ -79,15 +166,6 @@ public final class AudioProductStrategy implements Parcelable { /** * @hide - * @return human-readable name of this product strategy, which is similar to a usage - */ - @SystemApi - public @NonNull String name() { - return mName; - } - - /** - * @hide * @return the product strategy ID (which is the generalisation of Car Audio Usage / legacy * routing_strategy linked to {@link AudioAttributes#getUsage()}). */ @@ -158,7 +236,7 @@ public final class AudioProductStrategy implements Parcelable { * @hide * @param streamType legacy stream type used for volume operation only * @return the volume group id relevant for the given streamType. - * If none is found, {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} is returned. + * If none is found, {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} is returned. */ public int getVolumeGroupIdForLegacyStreamType(int streamType) { for (final AudioAttributesGroup aag : mAudioAttributesGroups) { @@ -166,14 +244,14 @@ public final class AudioProductStrategy implements Parcelable { return aag.getVolumeGroupId(); } } - return AudioVolumeGroups.DEFAULT_VOLUME_GROUP; + return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; } /** * @hide * @param aa the {@link AudioAttributes} to be considered * @return the volume group id associated with the given audio attributes if found, - * {@link AudioVolumeGroups#DEFAULT_VOLUME_GROUP} otherwise. + * {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} otherwise. */ public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) { Preconditions.checkNotNull(aa, "AudioAttributes must not be null"); @@ -182,7 +260,7 @@ public final class AudioProductStrategy implements Parcelable { return aag.getVolumeGroupId(); } } - return AudioVolumeGroups.DEFAULT_VOLUME_GROUP; + return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; } @Override @@ -200,7 +278,8 @@ public final class AudioProductStrategy implements Parcelable { } } - public static final @android.annotation.NonNull Parcelable.Creator<AudioProductStrategy> CREATOR = + @NonNull + public static final Parcelable.Creator<AudioProductStrategy> CREATOR = new Parcelable.Creator<AudioProductStrategy>() { @Override public AudioProductStrategy createFromParcel(@NonNull Parcel in) { diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java index b60947f13c1f..79be92214455 100644 --- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java +++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java @@ -19,11 +19,15 @@ package android.media.audiopolicy; import android.annotation.NonNull; import android.annotation.SystemApi; import android.media.AudioAttributes; +import android.media.AudioSystem; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -34,6 +38,12 @@ import java.util.List; */ @SystemApi public final class AudioVolumeGroup implements Parcelable { + private static final String TAG = "AudioVolumeGroup"; + /** + * Volume group value to use when introspection API fails. + */ + public static final int DEFAULT_VOLUME_GROUP = -1; + /** * Unique identifier of a volume group. */ @@ -46,10 +56,43 @@ public final class AudioVolumeGroup implements Parcelable { private final AudioAttributes[] mAudioAttributes; private int[] mLegacyStreamTypes; + private static final Object sLock = new Object(); + + @GuardedBy("sLock") + private static List<AudioVolumeGroup> sAudioVolumeGroups; + + /** + * @hide + * @return the List of AudioVolumeGroup discovered from platform configuration file. + */ + @NonNull + public static List<AudioVolumeGroup> getAudioVolumeGroups() { + if (sAudioVolumeGroups == null) { + synchronized (sLock) { + if (sAudioVolumeGroups == null) { + sAudioVolumeGroups = initializeAudioVolumeGroups(); + } + } + } + return sAudioVolumeGroups; + } + + private static List<AudioVolumeGroup> initializeAudioVolumeGroups() { + ArrayList<AudioVolumeGroup> avgList = new ArrayList<>(); + int status = native_list_audio_volume_groups(avgList); + if (status != AudioSystem.SUCCESS) { + Log.w(TAG, ": listAudioVolumeGroups failed"); + } + return avgList; + } + + private static native int native_list_audio_volume_groups( + ArrayList<AudioVolumeGroup> groups); + /** * @param name of the volume group * @param id of the volume group - * @param followers {@link AudioProductStrategies} strategy following this volume group + * @param legacyStreamTypes of volume group */ AudioVolumeGroup(@NonNull String name, int id, @NonNull AudioAttributes[] audioAttributes, diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl b/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl deleted file mode 100644 index 918cac39f19a..000000000000 --- a/media/java/android/media/audiopolicy/AudioVolumeGroups.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2018, 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 android.media.audiopolicy; - -parcelable AudioVolumeGroups; diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.java b/media/java/android/media/audiopolicy/AudioVolumeGroups.java deleted file mode 100644 index 2e56f846e574..000000000000 --- a/media/java/android/media/audiopolicy/AudioVolumeGroups.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2018 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 android.media.audiopolicy; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.media.AudioSystem; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -import com.android.internal.util.Preconditions; - -import java.util.ArrayList; -import java.util.Iterator; - -/** - * @hide - * A class to encapsulate a collection of {@link AudioVolumeGroup}. - */ -@SystemApi -public final class AudioVolumeGroups implements Iterable<AudioVolumeGroup>, Parcelable { - - private final ArrayList<AudioVolumeGroup> mAudioVolumeGroupList; - - private static final String TAG = "AudioVolumeGroups"; - - /** - * Volume group value to use when introspection API fails. - */ - public static final int DEFAULT_VOLUME_GROUP = -1; - - public AudioVolumeGroups() { - ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>(); - int status = native_list_audio_volume_groups(avgList); - if (status != AudioSystem.SUCCESS) { - Log.w(TAG, ": listAudioVolumeGroups failed"); - } - mAudioVolumeGroupList = avgList; - } - - private AudioVolumeGroups(@NonNull ArrayList<AudioVolumeGroup> audioVolumeGroupList) { - Preconditions.checkNotNull(audioVolumeGroupList, "audioVolumeGroupList must not be null"); - mAudioVolumeGroupList = audioVolumeGroupList; - } - - /** - * @return number of {@link AudioProductStrategy} objects - */ - public int size() { - return mAudioVolumeGroupList.size(); - } - - /** - * Returns an {@link Iterator} - */ - @Override - public @NonNull Iterator<AudioVolumeGroup> iterator() { - return mAudioVolumeGroupList.iterator(); - } - - @Override - public boolean equals(@NonNull Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AudioVolumeGroups that = (AudioVolumeGroups) o; - - return mAudioVolumeGroupList.equals(that.mAudioVolumeGroupList); - } - - /** - * @return the matching {@link AudioVolumeGroup} objects with the given id, - * null object if not found. - */ - public @Nullable AudioVolumeGroup getById(int volumeGroupId) { - for (final AudioVolumeGroup avg : this) { - if (avg.getId() == volumeGroupId) { - return avg; - } - } - Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested"); - return null; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(size()); - for (final AudioVolumeGroup volumeGroup : this) { - volumeGroup.writeToParcel(dest, flags); - } - } - - private static native int native_list_audio_volume_groups( - ArrayList<AudioVolumeGroup> groups); - - public static final Parcelable.Creator<AudioVolumeGroups> CREATOR = - new Parcelable.Creator<AudioVolumeGroups>() { - @Override - public @NonNull AudioVolumeGroups createFromParcel(@NonNull Parcel in) { - Preconditions.checkNotNull(in, "in Parcel must not be null"); - ArrayList<AudioVolumeGroup> avgList = new ArrayList<AudioVolumeGroup>(); - int size = in.readInt(); - for (int index = 0; index < size; index++) { - avgList.add(AudioVolumeGroup.CREATOR.createFromParcel(in)); - } - return new AudioVolumeGroups(avgList); - } - - @Override - public @NonNull AudioVolumeGroups[] newArray(int size) { - return new AudioVolumeGroups[size]; - } - }; -} diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d58888a7c67b..77472ed288c3 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -90,9 +90,8 @@ import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioPolicy; import android.media.audiopolicy.AudioPolicyConfig; -import android.media.audiopolicy.AudioProductStrategies; +import android.media.audiopolicy.AudioProductStrategy; import android.media.audiopolicy.AudioVolumeGroup; -import android.media.audiopolicy.AudioVolumeGroups; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; import android.media.projection.IMediaProjectionManager; @@ -281,11 +280,6 @@ public class AudioService extends IAudioService.Stub private SettingsObserver mSettingsObserver; - /** @see AudioProductStrategies */ - private static AudioProductStrategies sAudioProductStrategies; - /** @see AudioVolumeGroups */ - private static AudioVolumeGroups sAudioVolumeGroups; - private int mMode = AudioSystem.MODE_NORMAL; // protects mRingerMode private final Object mSettingsLock = new Object(); @@ -636,19 +630,17 @@ public class AudioService extends IAudioService.Stub mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator(); - sAudioProductStrategies = new AudioProductStrategies(); - sAudioVolumeGroups = new AudioVolumeGroups(); - // Initialize volume // Priority 1 - Android Property // Priority 2 - Audio Policy Service // Priority 3 - Default Value - if (sAudioProductStrategies.size() > 0) { + if (AudioProductStrategy.getAudioProductStrategies().size() > 0) { int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { AudioAttributes attr = - sAudioProductStrategies.getAudioAttributesForLegacyStreamType(streamType); + AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( + streamType); int maxVolume = AudioSystem.getMaxVolumeIndexForAttributes(attr); if (maxVolume != -1) { MAX_STREAM_VOLUME[streamType] = maxVolume; @@ -1023,19 +1015,21 @@ public class AudioService extends IAudioService.Stub } /** - * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the + * @return the {@link android.media.audiopolicy.AudioProductStrategy} discovered from the * platform configuration file. */ - public @NonNull AudioProductStrategies getAudioProductStrategies() { - return sAudioProductStrategies; + @NonNull + public List<AudioProductStrategy> getAudioProductStrategies() { + return AudioProductStrategy.getAudioProductStrategies(); } /** - * @return the {@link android.media.audiopolicy.AudioVolumeGroups} discovered from the + * @return the List of {@link android.media.audiopolicy.AudioVolumeGroup} discovered from the * platform configuration file. */ - public @NonNull AudioVolumeGroups listAudioVolumeGroups() { - return sAudioVolumeGroups; + @NonNull + public List<AudioVolumeGroup> getAudioVolumeGroups() { + return AudioVolumeGroup.getAudioVolumeGroups(); } private void checkAllAliasStreamVolumes() { @@ -1947,15 +1941,15 @@ public class AudioService extends IAudioService.Stub enforceModifyAudioRoutingPermission(); Preconditions.checkNotNull(attr, "attr must not be null"); // @todo not hold the caller context, post message - int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr); + int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr); final int device = getDeviceForStream(stream); int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device); AudioSystem.setVolumeIndexForAttributes(attr, index, device); - final int volumeGroup = sAudioProductStrategies.getVolumeGroupIdForAttributes(attr); - final AudioVolumeGroup avg = sAudioVolumeGroups.getById(volumeGroup); + final int volumeGroup = getVolumeGroupIdForAttributes(attr); + final AudioVolumeGroup avg = getAudioVolumeGroupById(volumeGroup); if (avg == null) { return; } @@ -1965,11 +1959,23 @@ public class AudioService extends IAudioService.Stub } } + @Nullable + private AudioVolumeGroup getAudioVolumeGroupById(int volumeGroupId) { + for (final AudioVolumeGroup avg : AudioVolumeGroup.getAudioVolumeGroups()) { + if (avg.getId() == volumeGroupId) { + return avg; + } + } + + Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested"); + return null; + } + /** @see AudioManager#getVolumeIndexForAttributes(attr) */ public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) { enforceModifyAudioRoutingPermission(); Preconditions.checkNotNull(attr, "attr must not be null"); - int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr); + int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr); final int device = getDeviceForStream(stream); return AudioSystem.getVolumeIndexForAttributes(attr, device); @@ -2144,6 +2150,32 @@ public class AudioService extends IAudioService.Stub sendVolumeUpdate(streamType, oldIndex, index, flags); } + + + private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) { + Preconditions.checkNotNull(attributes, "attributes must not be null"); + int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes); + if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + // The default volume group is the one hosted by default product strategy, i.e. + // supporting Default Attributes + return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes); + } + + private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) { + Preconditions.checkNotNull(attributes, "attributes must not be null"); + for (final AudioProductStrategy productStrategy : + AudioProductStrategy.getAudioProductStrategies()) { + int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes); + if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + } + return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; + } + + // No ringer or zen muted stream volumes can be changed unless it'll exit dnd private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) { switch (mNm.getZenMode()) { |