• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.audio.hal;
18 
19 import static android.media.audio.common.AudioDeviceDescription.CONNECTION_BUS;
20 import static android.media.audio.common.AudioDeviceType.IN_DEVICE;
21 import static android.media.audio.common.AudioDeviceType.OUT_DEVICE;
22 import static android.media.audio.common.AudioGainMode.JOINT;
23 
24 import android.annotation.NonNull;
25 import android.media.audio.common.AudioDevice;
26 import android.media.audio.common.AudioGain;
27 import android.media.audio.common.AudioPort;
28 
29 import com.android.internal.util.Preconditions;
30 
31 import java.util.Objects;
32 
33 /**
34  * Audio Device info received from HAL as part of dynamic gain stage configration
35  */
36 public final class HalAudioDeviceInfo {
37     private final int mId;
38     private final String mName;
39     private final AudioGain mAudioGain;
40     private final int mType;
41     private final String mConnection;
42     private final String mAddress;
43     private static final int AUDIO_PORT_EXT_DEVICE = 1;
44 
HalAudioDeviceInfo(AudioPort port)45     public HalAudioDeviceInfo(AudioPort port) {
46         Objects.requireNonNull(port, "Audio port can not be null");
47 
48         Preconditions.checkArgument(port.ext.getTag() == AUDIO_PORT_EXT_DEVICE,
49                 "Invalid audio port ext setting: %d", port.ext.getTag());
50         AudioDevice device = Objects.requireNonNull(port.ext.getDevice().device,
51                 "Audio device can not be null");
52         checkIfAudioDeviceIsValidOutputBus(device);
53 
54         mId = port.id;
55         mName = port.name;
56         mAudioGain = getAudioGain(port.gains);
57         mType = device.type.type;
58         mConnection = device.type.connection;
59         mAddress = device.address.getId();
60     }
61 
getId()62     public int getId() {
63         return mId;
64     }
65 
getName()66     public String getName() {
67         return mName;
68     }
69 
getGainMinValue()70     public int getGainMinValue() {
71         return mAudioGain.minValue;
72     }
73 
getGainMaxValue()74     public int getGainMaxValue() {
75         return mAudioGain.maxValue;
76     }
77 
getGainDefaultValue()78     public int getGainDefaultValue() {
79         return mAudioGain.defaultValue;
80     }
81 
getGainStepValue()82     public int getGainStepValue() {
83         return mAudioGain.stepValue;
84     }
85 
getType()86     public int getType() {
87         return mType;
88     }
89 
getConnection()90     public String getConnection() {
91         return mConnection;
92     }
93 
getAddress()94     public String getAddress() {
95         return mAddress;
96     }
97 
isOutputDevice()98     public boolean isOutputDevice() {
99         return mType == OUT_DEVICE;
100     }
101 
isInputDevice()102     public boolean isInputDevice() {
103         return mType == IN_DEVICE;
104     }
105 
106     @Override
toString()107     public String toString() {
108         return new StringBuilder()
109                 .append("{mId: ").append(mId).append(", mName: ").append(mName)
110                 .append(", mAudioGain: ").append(Objects.toString(mAudioGain))
111                 .append(", mType: ").append(mType).append(", mConnection: ").append(mConnection)
112                 .append(", mAddress: ").append(mAddress).append("}").toString();
113     }
114 
115     @Override
equals(Object o)116     public boolean equals(Object o) {
117         if (this == o) {
118             return true;
119         }
120 
121         if (!(o instanceof HalAudioDeviceInfo)) {
122             return false;
123         }
124 
125         HalAudioDeviceInfo rhs = (HalAudioDeviceInfo) o;
126 
127         // mId is not reliable until Audio HAL migrates to AIDL
128         return mType == rhs.mType && mName.equals(rhs.mName) && mConnection.equals(rhs.mConnection)
129                 && mAddress.equals(rhs.mAddress) && Objects.equals(mAudioGain, rhs.mAudioGain);
130     }
131 
132     @Override
hashCode()133     public int hashCode() {
134         // mId is not reliable until Audio HAL migrates to AIDL
135         return Objects.hash(mName, mAudioGain, mType, mConnection, mAddress);
136     }
137 
checkIfAudioDeviceIsValidOutputBus(AudioDevice device)138     private void checkIfAudioDeviceIsValidOutputBus(AudioDevice device) {
139         Preconditions.checkArgument((device.type.type == OUT_DEVICE)
140                         || (device.type.type == IN_DEVICE),
141                 "Invalid audio device type (expecting IN/OUT_DEVICE): %d", device.type.type);
142 
143         Preconditions.checkArgument(device.type.connection.equals(CONNECTION_BUS),
144                 "Invalid audio device connection (expecting CONNECTION_BUS): %s",
145                 device.type.connection);
146 
147         Preconditions.checkStringNotEmpty(device.address.getId(),
148                 "Audio device address cannot be empty");
149     }
150 
getAudioGain(@onNull AudioGain[] gains)151     private static AudioGain getAudioGain(@NonNull AudioGain[] gains) {
152         Objects.requireNonNull(gains, "Audio gains can not be null");
153         Preconditions.checkArgument(gains.length > 0, "Audio port must have gains defined");
154         for (int index = 0; index < gains.length; index++) {
155             AudioGain gain = Objects.requireNonNull(gains[index], "Audio gain can not be null");
156             if (gain.mode == JOINT) {
157                 return checkAudioGainConfiguration(gain);
158             }
159         }
160         throw new IllegalStateException("Audio port does not have a valid audio gain");
161     }
162 
checkAudioGainConfiguration(AudioGain gain)163     private static AudioGain checkAudioGainConfiguration(AudioGain gain) {
164         Preconditions.checkArgument(gain.maxValue >= gain.minValue,
165                 "Max gain %d is lower than min gain %d",
166                 gain.maxValue, gain.minValue);
167         Preconditions.checkArgument((gain.defaultValue >= gain.minValue)
168                         && (gain.defaultValue <= gain.maxValue),
169                 "Default gain %d not in range (%d,%d)", gain.defaultValue,
170                 gain.minValue, gain.maxValue);
171         Preconditions.checkArgument(gain.stepValue > 0,
172                 "Gain step value must be greater than zero: %d", gain.stepValue);
173         Preconditions.checkArgument(
174                 ((gain.maxValue - gain.minValue) % gain.stepValue) == 0,
175                 "Gain step value %d greater than min gain to max gain range %d",
176                 gain.stepValue, gain.maxValue - gain.minValue);
177         Preconditions.checkArgument(
178                 ((gain.defaultValue - gain.minValue) % gain.stepValue) == 0,
179                 "Gain step value %d greater than min gain to default gain range %d",
180                 gain.stepValue, gain.defaultValue - gain.minValue);
181         return gain;
182     }
183 }
184