• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 android.media;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.Objects;
32 
33 /**
34  * @hide
35  * Class to represent the attributes of an audio device: its type (speaker, headset...), address
36  * (if known) and role (input, output).
37  * <p>Unlike {@link AudioDeviceInfo}, the device
38  * doesn't need to be connected to be uniquely identified, it can
39  * for instance represent a specific A2DP headset even after a
40  * disconnection, whereas the corresponding <code>AudioDeviceInfo</code>
41  * would then be invalid.
42  * <p>While creating / obtaining an instance is not protected by a
43  * permission, APIs using one rely on MODIFY_AUDIO_ROUTING.
44  */
45 @SystemApi
46 public final class AudioDeviceAttributes implements Parcelable {
47 
48     /**
49      * A role identifying input devices, such as microphones.
50      */
51     public static final int ROLE_INPUT = AudioPort.ROLE_SOURCE;
52     /**
53      * A role identifying output devices, such as speakers or headphones.
54      */
55     public static final int ROLE_OUTPUT = AudioPort.ROLE_SINK;
56 
57     /** @hide */
58     @IntDef(flag = false, prefix = "ROLE_", value = {
59             ROLE_INPUT, ROLE_OUTPUT }
60     )
61     @Retention(RetentionPolicy.SOURCE)
62     public @interface Role {}
63 
64     /**
65      * The audio device type, as defined in {@link AudioDeviceInfo}
66      */
67     private final @AudioDeviceInfo.AudioDeviceType int mType;
68     /**
69      * The unique address of the device. Some devices don't have addresses, only an empty string.
70      */
71     private final @NonNull String mAddress;
72     /**
73      * The non-unique name of the device. Some devices don't have names, only an empty string.
74      * Should not be used as a unique identifier for a device.
75      */
76     private final @NonNull String mName;
77     /**
78      * Is input or output device
79      */
80     private final @Role int mRole;
81     /**
82      * The internal audio device type
83      */
84     private final int mNativeType;
85     /**
86      * List of AudioProfiles supported by the device
87      */
88     private final @NonNull List<AudioProfile> mAudioProfiles;
89     /**
90      * List of AudioDescriptors supported by the device
91      */
92     private final @NonNull List<AudioDescriptor> mAudioDescriptors;
93 
94     /**
95      * @hide
96      * Constructor from a valid {@link AudioDeviceInfo}
97      * @param deviceInfo the connected audio device from which to obtain the device-identifying
98      *                   type and address.
99      */
100     @SystemApi
AudioDeviceAttributes(@onNull AudioDeviceInfo deviceInfo)101     public AudioDeviceAttributes(@NonNull AudioDeviceInfo deviceInfo) {
102         Objects.requireNonNull(deviceInfo);
103         mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
104         mType = deviceInfo.getType();
105         mAddress = deviceInfo.getAddress();
106         mName = String.valueOf(deviceInfo.getProductName());
107         mNativeType = deviceInfo.getInternalType();
108         mAudioProfiles = deviceInfo.getAudioProfiles();
109         mAudioDescriptors = deviceInfo.getAudioDescriptors();
110     }
111 
112     /**
113      * @hide
114      * Constructor from role, device type and address
115      * @param role indicates input or output role
116      * @param type the device type, as defined in {@link AudioDeviceInfo}
117      * @param address the address of the device, or an empty string for devices without one
118      */
119     @SystemApi
AudioDeviceAttributes(@ole int role, @AudioDeviceInfo.AudioDeviceType int type, @NonNull String address)120     public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
121             @NonNull String address) {
122         this(role, type, address, "", new ArrayList<>(), new ArrayList<>());
123     }
124 
125     /**
126      * @hide
127      * Constructor with specification of all attributes
128      * @param role indicates input or output role
129      * @param type the device type, as defined in {@link AudioDeviceInfo}
130      * @param address the address of the device, or an empty string for devices without one
131      * @param name the name of the device, or an empty string for devices without one
132      * @param profiles the list of AudioProfiles supported by the device
133      * @param descriptors the list of AudioDescriptors supported by the device
134      */
135     @SystemApi
AudioDeviceAttributes(@ole int role, @AudioDeviceInfo.AudioDeviceType int type, @NonNull String address, @NonNull String name, @NonNull List<AudioProfile> profiles, @NonNull List<AudioDescriptor> descriptors)136     public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
137             @NonNull String address, @NonNull String name, @NonNull List<AudioProfile> profiles,
138             @NonNull List<AudioDescriptor> descriptors) {
139         Objects.requireNonNull(address);
140         if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
141             throw new IllegalArgumentException("Invalid role " + role);
142         }
143         if (role == ROLE_OUTPUT) {
144             AudioDeviceInfo.enforceValidAudioDeviceTypeOut(type);
145             mNativeType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(type);
146         } else if (role == ROLE_INPUT) {
147             AudioDeviceInfo.enforceValidAudioDeviceTypeIn(type);
148             mNativeType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(type, address);
149         } else {
150             mNativeType = AudioSystem.DEVICE_NONE;
151         }
152 
153         mRole = role;
154         mType = type;
155         mAddress = address;
156         mName = name;
157         mAudioProfiles = profiles;
158         mAudioDescriptors = descriptors;
159     }
160 
161     /**
162      * @hide
163      * Constructor called from AudioSystem JNI when creating an AudioDeviceAttributes from a native
164      * AudioDeviceTypeAddr instance.
165      * @param nativeType the internal device type, as defined in {@link AudioSystem}
166      * @param address the address of the device, or an empty string for devices without one
167      */
AudioDeviceAttributes(int nativeType, @NonNull String address)168     public AudioDeviceAttributes(int nativeType, @NonNull String address) {
169         this(nativeType, address, "");
170     }
171 
172     /**
173      * @hide
174      * Constructor called from BtHelper to connect or disconnect a Bluetooth device.
175      * @param nativeType the internal device type, as defined in {@link AudioSystem}
176      * @param address the address of the device, or an empty string for devices without one
177      * @param name the name of the device, or an empty string for devices without one
178      */
AudioDeviceAttributes(int nativeType, @NonNull String address, @NonNull String name)179     public AudioDeviceAttributes(int nativeType, @NonNull String address, @NonNull String name) {
180         mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
181         mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
182         mAddress = address;
183         mName = name;
184         mNativeType = nativeType;
185         mAudioProfiles = new ArrayList<>();
186         mAudioDescriptors = new ArrayList<>();
187     }
188 
189     /**
190      * @hide
191      * Returns the role of a device
192      * @return the role
193      */
194     @SystemApi
getRole()195     public @Role int getRole() {
196         return mRole;
197     }
198 
199     /**
200      * @hide
201      * Returns the audio device type of a device
202      * @return the type, as defined in {@link AudioDeviceInfo}
203      */
204     @SystemApi
getType()205     public @AudioDeviceInfo.AudioDeviceType int getType() {
206         return mType;
207     }
208 
209     /**
210      * @hide
211      * Returns the address of the audio device, or an empty string for devices without one
212      * @return the device address
213      */
214     @SystemApi
getAddress()215     public @NonNull String getAddress() {
216         return mAddress;
217     }
218 
219     /**
220      * @hide
221      * Returns the name of the audio device, or an empty string for devices without one
222      * @return the device name
223      */
224     @SystemApi
getName()225     public @NonNull String getName() {
226         return mName;
227     }
228 
229     /**
230      * @hide
231      * Returns the internal device type of a device
232      * @return the internal device type
233      */
getInternalType()234     public int getInternalType() {
235         return mNativeType;
236     }
237 
238     /**
239      * @hide
240      * Returns the list of AudioProfiles supported by the device
241      * @return the list of AudioProfiles
242      */
243     @SystemApi
getAudioProfiles()244     public @NonNull List<AudioProfile> getAudioProfiles() {
245         return mAudioProfiles;
246     }
247 
248     /**
249      * @hide
250      * Returns the list of AudioDescriptors supported by the device
251      * @return the list of AudioDescriptors
252      */
253     @SystemApi
getAudioDescriptors()254     public @NonNull List<AudioDescriptor> getAudioDescriptors() {
255         return mAudioDescriptors;
256     }
257 
258     @Override
hashCode()259     public int hashCode() {
260         return Objects.hash(mRole, mType, mAddress, mName, mAudioProfiles, mAudioDescriptors);
261     }
262 
263     @Override
equals(Object o)264     public boolean equals(Object o) {
265         if (this == o) return true;
266         if (o == null || getClass() != o.getClass()) return false;
267 
268         AudioDeviceAttributes that = (AudioDeviceAttributes) o;
269         return ((mRole == that.mRole)
270                 && (mType == that.mType)
271                 && mAddress.equals(that.mAddress)
272                 && mName.equals(that.mName)
273                 && mAudioProfiles.equals(that.mAudioProfiles)
274                 && mAudioDescriptors.equals(that.mAudioDescriptors));
275     }
276 
277     /**
278      * Returns true if the role, type and address are equal. Called to compare with an
279      * AudioDeviceAttributes that was created from a native AudioDeviceTypeAddr instance.
280      * @param o object to compare with
281      * @return whether role, type and address are equal
282      */
equalTypeAddress(@ullable Object o)283     public boolean equalTypeAddress(@Nullable Object o) {
284         if (this == o) return true;
285         if (o == null || getClass() != o.getClass()) return false;
286 
287         AudioDeviceAttributes that = (AudioDeviceAttributes) o;
288         return ((mRole == that.mRole)
289                 && (mType == that.mType)
290                 && mAddress.equals(that.mAddress));
291     }
292 
293     /** @hide */
roleToString(@ole int role)294     public static String roleToString(@Role int role) {
295         return (role == ROLE_OUTPUT ? "output" : "input");
296     }
297 
298     @Override
toString()299     public String toString() {
300         return new String("AudioDeviceAttributes:"
301                 + " role:" + roleToString(mRole)
302                 + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
303                         : AudioSystem.getInputDeviceName(mNativeType))
304                 + " addr:" + mAddress
305                 + " name:" + mName
306                 + " profiles:" + mAudioProfiles.toString()
307                 + " descriptors:" + mAudioDescriptors.toString());
308     }
309 
310     @Override
describeContents()311     public int describeContents() {
312         return 0;
313     }
314 
315     @Override
writeToParcel(@onNull Parcel dest, int flags)316     public void writeToParcel(@NonNull Parcel dest, int flags) {
317         dest.writeInt(mRole);
318         dest.writeInt(mType);
319         dest.writeString(mAddress);
320         dest.writeString(mName);
321         dest.writeInt(mNativeType);
322         dest.writeParcelableArray(
323                 mAudioProfiles.toArray(new AudioProfile[mAudioProfiles.size()]), flags);
324         dest.writeParcelableArray(
325                 mAudioDescriptors.toArray(new AudioDescriptor[mAudioDescriptors.size()]), flags);
326     }
327 
AudioDeviceAttributes(@onNull Parcel in)328     private AudioDeviceAttributes(@NonNull Parcel in) {
329         mRole = in.readInt();
330         mType = in.readInt();
331         mAddress = in.readString();
332         mName = in.readString();
333         mNativeType = in.readInt();
334         AudioProfile[] audioProfilesArray =
335                 in.readParcelableArray(AudioProfile.class.getClassLoader(), AudioProfile.class);
336         mAudioProfiles = new ArrayList<AudioProfile>(Arrays.asList(audioProfilesArray));
337         AudioDescriptor[] audioDescriptorsArray = in.readParcelableArray(
338                 AudioDescriptor.class.getClassLoader(), AudioDescriptor.class);
339         mAudioDescriptors = new ArrayList<AudioDescriptor>(Arrays.asList(audioDescriptorsArray));
340     }
341 
342     public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR =
343             new Parcelable.Creator<AudioDeviceAttributes>() {
344         /**
345          * Rebuilds an AudioDeviceAttributes previously stored with writeToParcel().
346          * @param p Parcel object to read the AudioDeviceAttributes from
347          * @return a new AudioDeviceAttributes created from the data in the parcel
348          */
349         public AudioDeviceAttributes createFromParcel(Parcel p) {
350             return new AudioDeviceAttributes(p);
351         }
352 
353         public AudioDeviceAttributes[] newArray(int size) {
354             return new AudioDeviceAttributes[size];
355         }
356     };
357 }
358