1 /* 2 * Copyright (C) 2020 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.libraries.tv.tvsystem.media; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.media.AudioDeviceInfo; 23 import android.media.AudioPort; 24 import android.media.AudioSystem; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 30 /** 31 * @hide 32 * Class to represent the attributes of an audio device: its type (speaker, headset...), address 33 * (if known) and role (input, output). 34 * <p>Unlike {@link AudioDeviceInfo}, the device 35 * doesn't need to be connected to be uniquely identified, it can 36 * for instance represent a specific A2DP headset even after a 37 * disconnection, whereas the corresponding <code>AudioDeviceInfo</code> 38 * would then be invalid. 39 * <p>While creating / obtaining an instance is not protected by a 40 * permission, APIs using one rely on MODIFY_AUDIO_ROUTING. 41 */ 42 @SystemApi 43 public final class AudioDeviceAttributes { 44 45 /** 46 * A role identifying input devices, such as microphones. 47 */ 48 public static final int ROLE_INPUT = AudioPort.ROLE_SOURCE; 49 /** 50 * A role identifying output devices, such as speakers or headphones. 51 */ 52 public static final int ROLE_OUTPUT = AudioPort.ROLE_SINK; 53 54 /** @hide */ 55 @IntDef(flag = false, prefix = "ROLE_", value = { 56 ROLE_INPUT, ROLE_OUTPUT } 57 ) 58 @Retention(RetentionPolicy.SOURCE) 59 public @interface Role {} 60 61 /** 62 * The audio device type, as defined in {@link AudioDeviceInfo} 63 */ 64 private final @AudioDeviceInfo.AudioDeviceType int mType; 65 /** 66 * The unique address of the device. Some devices don't have addresses, only an empty string. 67 */ 68 private final @NonNull String mAddress; 69 70 /** 71 * Is input or output device 72 */ 73 private final @AudioDeviceAttributes.Role 74 int mRole; 75 76 /** 77 * @hide 78 * Constructor from a valid {@link AudioDeviceInfo} 79 * @param deviceInfo the connected audio device from which to obtain the device-identifying 80 * type and address. 81 */ 82 @SystemApi AudioDeviceAttributes(@onNull AudioDeviceInfo deviceInfo)83 public AudioDeviceAttributes(@NonNull AudioDeviceInfo deviceInfo) { 84 Objects.requireNonNull(deviceInfo); 85 mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT; 86 mType = deviceInfo.getType(); 87 mAddress = deviceInfo.getAddress(); 88 } 89 90 /** 91 * @hide 92 * Constructor from role, device type and address 93 * @param role indicates input or output role 94 * @param type the device type, as defined in {@link AudioDeviceInfo} 95 * @param address the address of the device, or an empty string for devices without one 96 */ 97 @SystemApi AudioDeviceAttributes(@udioDeviceAttributes.Role int role, @AudioDeviceInfo.AudioDeviceType int type, @NonNull String address)98 public AudioDeviceAttributes(@AudioDeviceAttributes.Role int role, 99 @AudioDeviceInfo.AudioDeviceType int type, 100 @NonNull String address) { 101 Objects.requireNonNull(address); 102 if (role != ROLE_OUTPUT && role != ROLE_INPUT) { 103 throw new IllegalArgumentException("Invalid role " + role); 104 } 105 106 mRole = role; 107 mType = type; 108 mAddress = address; 109 } 110 AudioDeviceAttributes(int nativeType, @NonNull String address)111 /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) { 112 mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT; 113 mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType); 114 mAddress = address; 115 } 116 117 /** 118 * @hide 119 * Returns the role of a device 120 * @return the role 121 */ 122 @SystemApi 123 public @AudioDeviceAttributes.Role getRole()124 int getRole() { 125 return mRole; 126 } 127 128 /** 129 * @hide 130 * Returns the audio device type of a device 131 * @return the type, as defined in {@link AudioDeviceInfo} 132 */ 133 @SystemApi getType()134 public @AudioDeviceInfo.AudioDeviceType int getType() { 135 return mType; 136 } 137 138 /** 139 * @hide 140 * Returns the address of the audio device, or an empty string for devices without one 141 * @return the device address 142 */ 143 @SystemApi getAddress()144 public @NonNull String getAddress() { 145 return mAddress; 146 } 147 148 @Override hashCode()149 public int hashCode() { 150 return Objects.hash(mRole, mType, mAddress); 151 } 152 153 @Override equals(Object o)154 public boolean equals(Object o) { 155 if (this == o) return true; 156 if (o == null || getClass() != o.getClass()) return false; 157 158 AudioDeviceAttributes that = (AudioDeviceAttributes) o; 159 return ((mRole == that.mRole) 160 && (mType == that.mType) 161 && mAddress.equals(that.mAddress)); 162 } 163 164 /** @hide */ roleToString(@udioDeviceAttributes.Role int role)165 public static String roleToString(@AudioDeviceAttributes.Role int role) { 166 return (role == ROLE_OUTPUT ? "output" : "input"); 167 } 168 169 @Override toString()170 public String toString() { 171 return new String("AudioDeviceAttributes:" 172 + " role:" + roleToString(mRole) 173 + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName( 174 AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)) 175 : AudioSystem.getInputDeviceName( 176 AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))) 177 + " addr:" + mAddress); 178 } 179 } 180