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
This commit is contained in:
Hayden Gomes
2019-04-04 13:10:13 -07:00
parent 5c7c6a4b7d
commit 6d69bde308
11 changed files with 191 additions and 373 deletions

View File

@@ -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();

View File

@@ -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);

View File

@@ -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)

View File

@@ -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()) {

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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()) {