blob: 79be922144556f50c2d0134381933c16a1280dda [file] [log] [blame]
/*
* 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.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;
/**
* A class to create the association between different playback attributes
* (e.g. media, mapping direction) to a single volume control.
* @hide
*/
@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.
*/
private int mId;
/**
* human-readable name of this volume group.
*/
private final String mName;
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 legacyStreamTypes of volume group
*/
AudioVolumeGroup(@NonNull String name, int id,
@NonNull AudioAttributes[] audioAttributes,
@NonNull int[] legacyStreamTypes) {
Preconditions.checkNotNull(name, "name must not be null");
Preconditions.checkNotNull(audioAttributes, "audioAttributes must not be null");
Preconditions.checkNotNull(legacyStreamTypes, "legacyStreamTypes must not be null");
mName = name;
mId = id;
mAudioAttributes = audioAttributes;
mLegacyStreamTypes = legacyStreamTypes;
}
@Override
public boolean equals(@NonNull Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AudioVolumeGroup thatAvg = (AudioVolumeGroup) o;
return mName == thatAvg.mName && mId == thatAvg.mId
&& mAudioAttributes.equals(thatAvg.mAudioAttributes);
}
/**
* @return List of {@link AudioAttributes} involved in this {@link AudioVolumeGroup}.
*/
public @NonNull List<AudioAttributes> getAudioAttributes() {
return Arrays.asList(mAudioAttributes);
}
/**
* @return the stream types involved in this {@link AudioVolumeGroup}.
*/
public @NonNull int[] getLegacyStreamTypes() {
return mLegacyStreamTypes;
}
/**
* @return human-readable name of this volume group.
*/
public @NonNull String name() {
return mName;
}
/**
* @return the volume group unique identifier id.
*/
public int getId() {
return mId;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mName);
dest.writeInt(mId);
dest.writeInt(mAudioAttributes.length);
for (AudioAttributes attributes : mAudioAttributes) {
attributes.writeToParcel(dest, flags | AudioAttributes.FLATTEN_TAGS/*flags*/);
}
dest.writeInt(mLegacyStreamTypes.length);
for (int streamType : mLegacyStreamTypes) {
dest.writeInt(streamType);
}
}
public static final Parcelable.Creator<AudioVolumeGroup> CREATOR =
new Parcelable.Creator<AudioVolumeGroup>() {
@Override
public @NonNull AudioVolumeGroup createFromParcel(@NonNull Parcel in) {
Preconditions.checkNotNull(in, "in Parcel must not be null");
String name = in.readString();
int id = in.readInt();
int nbAttributes = in.readInt();
AudioAttributes[] audioAttributes = new AudioAttributes[nbAttributes];
for (int index = 0; index < nbAttributes; index++) {
audioAttributes[index] = AudioAttributes.CREATOR.createFromParcel(in);
}
int nbStreamTypes = in.readInt();
int[] streamTypes = new int[nbStreamTypes];
for (int index = 0; index < nbStreamTypes; index++) {
streamTypes[index] = in.readInt();
}
return new AudioVolumeGroup(name, id, audioAttributes, streamTypes);
}
@Override
public @NonNull AudioVolumeGroup[] newArray(int size) {
return new AudioVolumeGroup[size];
}
};
@Override
public @NonNull String toString() {
StringBuilder s = new StringBuilder();
s.append("\n Name: ");
s.append(mName);
s.append(" Id: ");
s.append(Integer.toString(mId));
s.append("\n Supported Audio Attributes:");
for (AudioAttributes attribute : mAudioAttributes) {
s.append("\n -");
s.append(attribute.toString());
}
s.append("\n Supported Legacy Stream Types: { ");
for (int legacyStreamType : mLegacyStreamTypes) {
s.append(Integer.toString(legacyStreamType));
s.append(" ");
}
s.append("}");
return s.toString();
}
}