1 /*
2  * Copyright (C) 2014 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.NonNull;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.os.Build;
22 
23 import java.util.Arrays;
24 import java.util.List;
25 
26 /**
27  * The AudioDevicePort is a specialized type of AudioPort
28  * describing an input (e.g microphone) or output device (e.g speaker)
29  * of the system.
30  * An AudioDevicePort is an AudioPort controlled by the audio HAL, almost always a physical
31  * device at the boundary of the audio system.
32  * In addition to base audio port attributes, the device descriptor contains:
33  * - the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
34  * - the device address (e.g MAC adddress for AD2P sink).
35  * @see AudioPort
36  * @hide
37  */
38 
39 public class AudioDevicePort extends AudioPort {
40 
41     private final int mType;
42     private final String mAddress;
43     private final int[] mEncapsulationModes;
44     private final int[] mEncapsulationMetadataTypes;
45 
46     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
AudioDevicePort(AudioHandle handle, String deviceName, int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains, int type, String address, int[] encapsulationModes, @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes)47     AudioDevicePort(AudioHandle handle, String deviceName,
48             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
49             int[] formats, AudioGain[] gains, int type, String address, int[] encapsulationModes,
50             @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes) {
51         super(handle,
52              (AudioManager.isInputDevice(type) == true)  ?
53                         AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK,
54              deviceName, samplingRates, channelMasks, channelIndexMasks, formats, gains);
55         mType = type;
56         mAddress = address;
57         mEncapsulationModes = encapsulationModes;
58         mEncapsulationMetadataTypes = encapsulationMetadataTypes;
59     }
60 
AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles, AudioGain[] gains, int type, String address, int[] encapsulationModes, @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes, List<AudioDescriptor> descriptors)61     AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles,
62             AudioGain[] gains, int type, String address, int[] encapsulationModes,
63             @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes,
64             List<AudioDescriptor> descriptors) {
65         super(handle,
66                 AudioManager.isInputDevice(type) ? AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK,
67                 deviceName, profiles, gains, descriptors);
68         mType = type;
69         mAddress = address;
70         mEncapsulationModes = encapsulationModes;
71         mEncapsulationMetadataTypes = encapsulationMetadataTypes;
72     }
73 
74     /**
75      * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
76      */
77     @UnsupportedAppUsage
type()78     public int type() {
79         return mType;
80     }
81 
82     /**
83      * Get the device address. Address format varies with the device type.
84      * - USB devices ({@link AudioManager#DEVICE_OUT_USB_DEVICE},
85      * {@link AudioManager#DEVICE_IN_USB_DEVICE}) use an address composed of the ALSA card number
86      * and device number: "card=2;device=1"
87      * - Bluetooth devices ({@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
88      * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
89      * {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP}),
90      * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER})
91      * use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by
92      * {@link BluetoothDevice#getAddress()}.
93      * - Bluetooth LE broadcast group ({@link AudioManager#DEVICE_OUT_BLE_BROADCAST} use the group number.
94      * - Devices that do not have an address will indicate an empty string "".
95      */
address()96     public String address() {
97         return mAddress;
98     }
99 
100     /**
101      * Get supported encapsulation modes.
102      */
encapsulationModes()103     public @NonNull @AudioTrack.EncapsulationMode int[] encapsulationModes() {
104         if (mEncapsulationModes == null) {
105             return new int[0];
106         }
107         return Arrays.stream(mEncapsulationModes).boxed()
108                 .filter(mode -> mode != AudioTrack.ENCAPSULATION_MODE_HANDLE)
109                 .mapToInt(Integer::intValue).toArray();
110     }
111 
112     /**
113      * Get supported encapsulation metadata types.
114      */
encapsulationMetadataTypes()115     public @NonNull @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes() {
116         if (mEncapsulationMetadataTypes == null) {
117             return new int[0];
118         }
119         int[] encapsulationMetadataTypes = new int[mEncapsulationMetadataTypes.length];
120         System.arraycopy(mEncapsulationMetadataTypes, 0,
121                          encapsulationMetadataTypes, 0, mEncapsulationMetadataTypes.length);
122         return encapsulationMetadataTypes;
123     }
124 
125     /**
126      * Build a specific configuration of this audio device port for use by methods
127      * like AudioManager.connectAudioPatch().
128      */
buildConfig(int samplingRate, int channelMask, int format, AudioGainConfig gain)129     public AudioDevicePortConfig buildConfig(int samplingRate, int channelMask, int format,
130                                           AudioGainConfig gain) {
131         return new AudioDevicePortConfig(this, samplingRate, channelMask, format, gain);
132     }
133 
134     @Override
equals(Object o)135     public boolean equals(Object o) {
136         if (o == null || !(o instanceof AudioDevicePort)) {
137             return false;
138         }
139         AudioDevicePort other = (AudioDevicePort)o;
140         if (mType != other.type()) {
141             return false;
142         }
143         if (mAddress == null && other.address() != null) {
144             return false;
145         }
146         if (!mAddress.equals(other.address())) {
147             return false;
148         }
149         return super.equals(o);
150     }
151 
152     @Override
toString()153     public String toString() {
154         String type = (mRole == ROLE_SOURCE ?
155                             AudioSystem.getInputDeviceName(mType) :
156                             AudioSystem.getOutputDeviceName(mType));
157         return "{" + super.toString()
158                 + ", mType: " + type
159                 + ", mAddress: " + mAddress
160                 + "}";
161     }
162 }
163