1 /* 2 * Copyright (C) 2022 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.settingslib.bluetooth; 18 19 import android.annotation.IntDef; 20 import android.bluetooth.BluetoothHearingAid; 21 import android.bluetooth.BluetoothLeAudio; 22 import android.util.SparseIntArray; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.Objects; 27 28 /** Hearing aids information and constants that shared within hearing aids related profiles */ 29 public class HearingAidInfo { 30 31 @Retention(RetentionPolicy.SOURCE) 32 @IntDef({ 33 DeviceSide.SIDE_INVALID, 34 DeviceSide.SIDE_LEFT, 35 DeviceSide.SIDE_RIGHT, 36 DeviceSide.SIDE_LEFT_AND_RIGHT, 37 }) 38 39 /** Side definition for hearing aids. */ 40 public @interface DeviceSide { 41 int SIDE_INVALID = -1; 42 int SIDE_LEFT = 0; 43 int SIDE_RIGHT = 1; 44 int SIDE_LEFT_AND_RIGHT = 2; 45 } 46 47 @Retention(java.lang.annotation.RetentionPolicy.SOURCE) 48 @IntDef({ 49 DeviceMode.MODE_INVALID, 50 DeviceMode.MODE_MONAURAL, 51 DeviceMode.MODE_BINAURAL, 52 DeviceMode.MODE_BANDED, 53 }) 54 55 /** Mode definition for hearing aids. */ 56 public @interface DeviceMode { 57 int MODE_INVALID = -1; 58 int MODE_MONAURAL = 0; 59 int MODE_BINAURAL = 1; 60 int MODE_BANDED = 2; 61 } 62 63 private final int mSide; 64 private final int mMode; 65 private final long mHiSyncId; 66 HearingAidInfo(int side, int mode, long hiSyncId)67 private HearingAidInfo(int side, int mode, long hiSyncId) { 68 mSide = side; 69 mMode = mode; 70 mHiSyncId = hiSyncId; 71 } 72 73 @DeviceSide getSide()74 public int getSide() { 75 return mSide; 76 } 77 78 @DeviceMode getMode()79 public int getMode() { 80 return mMode; 81 } 82 getHiSyncId()83 public long getHiSyncId() { 84 return mHiSyncId; 85 } 86 87 @Override equals(Object o)88 public boolean equals(Object o) { 89 if (this == o) { 90 return true; 91 } 92 if (!(o instanceof HearingAidInfo)) { 93 return false; 94 } 95 HearingAidInfo that = (HearingAidInfo) o; 96 return mSide == that.mSide && mMode == that.mMode && mHiSyncId == that.mHiSyncId; 97 } 98 99 @Override hashCode()100 public int hashCode() { 101 return Objects.hash(mSide, mMode, mHiSyncId); 102 } 103 104 @Override toString()105 public String toString() { 106 return "HearingAidInfo{" 107 + "mSide=" + mSide 108 + ", mMode=" + mMode 109 + ", mHiSyncId=" + mHiSyncId 110 + '}'; 111 } 112 113 @DeviceSide convertAshaDeviceSideToInternalSide(int ashaDeviceSide)114 private static int convertAshaDeviceSideToInternalSide(int ashaDeviceSide) { 115 return ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.get( 116 ashaDeviceSide, DeviceSide.SIDE_INVALID); 117 } 118 119 @DeviceMode convertAshaDeviceModeToInternalMode(int ashaDeviceMode)120 private static int convertAshaDeviceModeToInternalMode(int ashaDeviceMode) { 121 return ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.get( 122 ashaDeviceMode, DeviceMode.MODE_INVALID); 123 } 124 125 @DeviceSide convertLeAudioLocationToInternalSide(int leAudioLocation)126 private static int convertLeAudioLocationToInternalSide(int leAudioLocation) { 127 boolean isLeft = (leAudioLocation & LE_AUDIO_LOCATION_LEFT) != 0; 128 boolean isRight = (leAudioLocation & LE_AUDIO_LOCATION_RIGHT) != 0; 129 if (isLeft && isRight) { 130 return DeviceSide.SIDE_LEFT_AND_RIGHT; 131 } else if (isLeft) { 132 return DeviceSide.SIDE_LEFT; 133 } else if (isRight) { 134 return DeviceSide.SIDE_RIGHT; 135 } 136 return DeviceSide.SIDE_INVALID; 137 } 138 139 @DeviceMode convertHapDeviceTypeToInternalMode(int hapDeviceType)140 private static int convertHapDeviceTypeToInternalMode(int hapDeviceType) { 141 return HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.get(hapDeviceType, DeviceMode.MODE_INVALID); 142 } 143 144 /** Builder class for constructing {@link HearingAidInfo} objects. */ 145 public static final class Builder { 146 private int mSide = DeviceSide.SIDE_INVALID; 147 private int mMode = DeviceMode.MODE_INVALID; 148 private long mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; 149 150 /** 151 * Configure the hearing device mode. 152 * @param ashaDeviceMode one of the hearing aid device modes defined in HearingAidProfile 153 * {@link HearingAidProfile.DeviceMode} 154 */ setAshaDeviceMode(int ashaDeviceMode)155 public Builder setAshaDeviceMode(int ashaDeviceMode) { 156 mMode = convertAshaDeviceModeToInternalMode(ashaDeviceMode); 157 return this; 158 } 159 160 /** 161 * Configure the hearing device mode. 162 * @param hapDeviceType one of the hearing aid device types defined in HapClientProfile 163 * {@link HapClientProfile.HearingAidType} 164 */ setHapDeviceType(int hapDeviceType)165 public Builder setHapDeviceType(int hapDeviceType) { 166 mMode = convertHapDeviceTypeToInternalMode(hapDeviceType); 167 return this; 168 } 169 170 /** 171 * Configure the hearing device side. 172 * @param ashaDeviceSide one of the hearing aid device sides defined in HearingAidProfile 173 * {@link HearingAidProfile.DeviceSide} 174 */ setAshaDeviceSide(int ashaDeviceSide)175 public Builder setAshaDeviceSide(int ashaDeviceSide) { 176 mSide = convertAshaDeviceSideToInternalSide(ashaDeviceSide); 177 return this; 178 } 179 180 /** 181 * Configure the hearing device side. 182 * @param leAudioLocation one of the audio location defined in BluetoothLeAudio 183 * {@link BluetoothLeAudio.AudioLocation} 184 */ setLeAudioLocation(int leAudioLocation)185 public Builder setLeAudioLocation(int leAudioLocation) { 186 mSide = convertLeAudioLocationToInternalSide(leAudioLocation); 187 return this; 188 } 189 190 /** 191 * Configure the hearing aid hiSyncId. 192 * @param hiSyncId the ASHA hearing aid id 193 */ setHiSyncId(long hiSyncId)194 public Builder setHiSyncId(long hiSyncId) { 195 mHiSyncId = hiSyncId; 196 return this; 197 } 198 199 /** Build the configured {@link HearingAidInfo} */ build()200 public HearingAidInfo build() { 201 return new HearingAidInfo(mSide, mMode, mHiSyncId); 202 } 203 } 204 205 private static final int LE_AUDIO_LOCATION_LEFT = 206 BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT 207 | BluetoothLeAudio.AUDIO_LOCATION_BACK_LEFT 208 | BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT_OF_CENTER 209 | BluetoothLeAudio.AUDIO_LOCATION_SIDE_LEFT 210 | BluetoothLeAudio.AUDIO_LOCATION_TOP_FRONT_LEFT 211 | BluetoothLeAudio.AUDIO_LOCATION_TOP_BACK_LEFT 212 | BluetoothLeAudio.AUDIO_LOCATION_TOP_SIDE_LEFT 213 | BluetoothLeAudio.AUDIO_LOCATION_BOTTOM_FRONT_LEFT 214 | BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT_WIDE 215 | BluetoothLeAudio.AUDIO_LOCATION_LEFT_SURROUND; 216 217 private static final int LE_AUDIO_LOCATION_RIGHT = 218 BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT 219 | BluetoothLeAudio.AUDIO_LOCATION_BACK_RIGHT 220 | BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER 221 | BluetoothLeAudio.AUDIO_LOCATION_SIDE_RIGHT 222 | BluetoothLeAudio.AUDIO_LOCATION_TOP_FRONT_RIGHT 223 | BluetoothLeAudio.AUDIO_LOCATION_TOP_BACK_RIGHT 224 | BluetoothLeAudio.AUDIO_LOCATION_TOP_SIDE_RIGHT 225 | BluetoothLeAudio.AUDIO_LOCATION_BOTTOM_FRONT_RIGHT 226 | BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT_WIDE 227 | BluetoothLeAudio.AUDIO_LOCATION_RIGHT_SURROUND; 228 229 private static final SparseIntArray ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING; 230 private static final SparseIntArray ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING; 231 private static final SparseIntArray HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING; 232 233 static { 234 ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING = new SparseIntArray(); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_INVALID, DeviceSide.SIDE_INVALID)235 ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( 236 HearingAidProfile.DeviceSide.SIDE_INVALID, DeviceSide.SIDE_INVALID); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_LEFT, DeviceSide.SIDE_LEFT)237 ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( 238 HearingAidProfile.DeviceSide.SIDE_LEFT, DeviceSide.SIDE_LEFT); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_RIGHT, DeviceSide.SIDE_RIGHT)239 ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( 240 HearingAidProfile.DeviceSide.SIDE_RIGHT, DeviceSide.SIDE_RIGHT); 241 242 ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING = new SparseIntArray(); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_INVALID, DeviceMode.MODE_INVALID)243 ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( 244 HearingAidProfile.DeviceMode.MODE_INVALID, DeviceMode.MODE_INVALID); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_MONAURAL, DeviceMode.MODE_MONAURAL)245 ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( 246 HearingAidProfile.DeviceMode.MODE_MONAURAL, DeviceMode.MODE_MONAURAL); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_BINAURAL, DeviceMode.MODE_BINAURAL)247 ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( 248 HearingAidProfile.DeviceMode.MODE_BINAURAL, DeviceMode.MODE_BINAURAL); 249 250 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING = new SparseIntArray(); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_INVALID, DeviceMode.MODE_INVALID)251 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( 252 HapClientProfile.HearingAidType.TYPE_INVALID, DeviceMode.MODE_INVALID); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_BINAURAL, DeviceMode.MODE_BINAURAL)253 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( 254 HapClientProfile.HearingAidType.TYPE_BINAURAL, DeviceMode.MODE_BINAURAL); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_MONAURAL, DeviceMode.MODE_MONAURAL)255 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( 256 HapClientProfile.HearingAidType.TYPE_MONAURAL, DeviceMode.MODE_MONAURAL); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_BANDED, DeviceMode.MODE_BANDED)257 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( 258 HapClientProfile.HearingAidType.TYPE_BANDED, DeviceMode.MODE_BANDED); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_RFU, DeviceMode.MODE_INVALID)259 HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( 260 HapClientProfile.HearingAidType.TYPE_RFU, DeviceMode.MODE_INVALID); 261 262 } 263 } 264