diff options
| author | 2019-04-04 13:10:13 -0700 | |
|---|---|---|
| committer | 2019-04-11 16:56:34 -0700 | |
| commit | 6d69bde308f8ea6c04f54b0b3cb807d310ae8ccb (patch) | |
| tree | 9c4a5e2c29bd9540a9314f65b9b8c51f7f8718f4 | |
| parent | 5c7c6a4b7dc3e161ad77f3b239aa1cef728c9bd9 (diff) | |
Replacing AudioProductStrategies with List
- Removed AudioProductStrategies and updated usages to work with
List<AudioProductStrategy>
- ditributed looping logic to the respective callers
Test: built successfully with make and ran on device
Bug: 129265140
Change-Id: If95ba9c2418a1fda29590ca1af2d04e7395c2130
| -rw-r--r-- | api/system-current.txt | 18 | ||||
| -rw-r--r-- | core/java/android/preference/SeekBarVolumizer.java | 62 | ||||
| -rw-r--r-- | core/jni/android_media_AudioProductStrategies.cpp | 24 | ||||
| -rw-r--r-- | media/java/android/media/AudioAttributes.java | 14 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 5 | ||||
| -rw-r--r-- | media/java/android/media/IAudioService.aidl | 4 | ||||
| -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 | 91 | ||||
| -rw-r--r-- | media/java/android/media/audiopolicy/AudioVolumeGroup.java | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 49 |
11 files changed, 191 insertions, 373 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 282f6f749128..648a97d5c0d1 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3497,7 +3497,7 @@ 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 static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.audiopolicy.AudioVolumeGroups 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); @@ -3677,22 +3677,6 @@ 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(); diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 847b8e48b296..aa930c8dcb1e 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,7 +28,7 @@ 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.AudioProductStrategy; import android.media.audiopolicy.AudioVolumeGroups; import android.net.Uri; import android.os.Handler; @@ -44,6 +45,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.SomeArgs; +import com.android.internal.util.Preconditions; /** * Turns a {@link SeekBar} into a volume control. @@ -67,7 +69,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 +162,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 (AudioManager.getAudioProductStrategies().size() > 0) { + mVolumeGroupId = getVolumeGroupIdForLegacyStreamType(mStreamType); + mAttributes = getAudioAttributesForLegacyStreamType( mStreamType); } @@ -190,6 +189,44 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba mDefaultUri = defaultUri; } + private int getVolumeGroupIdForLegacyStreamType(int streamType) { + for (final AudioProductStrategy productStrategy : + AudioManager.getAudioProductStrategies()) { + 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); + } + + private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) { + Preconditions.checkNotNull(attributes, "attributes must not be null"); + for (final AudioProductStrategy productStrategy : + AudioManager.getAudioProductStrategies()) { + int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes); + if (volumeGroupId != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + } + return AudioVolumeGroups.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 +366,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba postStopSample(); mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); mReceiver.setListening(false); - if (mAudioProductStrategies.size() > 0) { + if (AudioManager.getAudioProductStrategies().size() > 0) { unregisterVolumeGroupCb(); } mSeekBar.setOnSeekBarChangeListener(null); @@ -349,7 +386,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 (AudioManager.getAudioProductStrategies().size() > 0) { registerVolumeGroupCb(); } } @@ -507,7 +544,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 (AudioManager.getAudioProductStrategies().size() == 0) { updateVolumeSlider(streamType, streamValue); } } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { @@ -519,12 +556,11 @@ 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 (AudioManager.getAudioProductStrategies().size() == 0) { int streamVolume = mAudioManager.getStreamVolume(streamType); updateVolumeSlider(streamType, streamVolume); } else { - int volumeGroup = mAudioProductStrategies.getVolumeGroupIdForLegacyStreamType( - streamType); + int volumeGroup = getVolumeGroupIdForLegacyStreamType(streamType); if (volumeGroup != AudioVolumeGroups.DEFAULT_VOLUME_GROUP && volumeGroup == mVolumeGroupId) { int streamVolume = mAudioManager.getStreamVolume(streamType); 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/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..f80c8c61cec9 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -37,7 +37,7 @@ 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.AudioVolumeGroupChangeHandler; import android.media.audiopolicy.AudioVolumeGroups; import android.media.projection.MediaProjection; @@ -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(); diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 980cb0459821..36c9b5a9dbb8 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -33,7 +33,7 @@ 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.AudioProductStrategy; import android.media.audiopolicy.AudioVolumeGroups; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; @@ -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..578186353402 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.name() + " 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; @@ -200,7 +288,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..964de95932c5 100644 --- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java +++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java @@ -49,7 +49,7 @@ public final class AudioVolumeGroup implements Parcelable { /** * @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/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d58888a7c67b..832cd877d0ad 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -90,7 +90,7 @@ 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; @@ -281,8 +281,6 @@ public class AudioService extends IAudioService.Stub private SettingsObserver mSettingsObserver; - /** @see AudioProductStrategies */ - private static AudioProductStrategies sAudioProductStrategies; /** @see AudioVolumeGroups */ private static AudioVolumeGroups sAudioVolumeGroups; @@ -636,19 +634,19 @@ 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,11 +1021,12 @@ 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(); } /** @@ -1947,14 +1946,14 @@ 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 int volumeGroup = getVolumeGroupIdForAttributes(attr); final AudioVolumeGroup avg = sAudioVolumeGroups.getById(volumeGroup); if (avg == null) { return; @@ -1969,7 +1968,7 @@ public class AudioService extends IAudioService.Stub 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 +2143,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 != 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); + } + + 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 != AudioVolumeGroups.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + } + return AudioVolumeGroups.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()) { |