/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.bluetooth; import android.annotation.IntDef; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.util.SparseIntArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** Hearing aids information and constants that shared within hearing aids related profiles */ public class HearingAidInfo { @Retention(RetentionPolicy.SOURCE) @IntDef({ DeviceSide.SIDE_INVALID, DeviceSide.SIDE_LEFT, DeviceSide.SIDE_RIGHT, DeviceSide.SIDE_LEFT_AND_RIGHT, }) /** Side definition for hearing aids. */ public @interface DeviceSide { int SIDE_INVALID = -1; int SIDE_LEFT = 0; int SIDE_RIGHT = 1; int SIDE_LEFT_AND_RIGHT = 2; } @Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({ DeviceMode.MODE_INVALID, DeviceMode.MODE_MONAURAL, DeviceMode.MODE_BINAURAL, DeviceMode.MODE_BANDED, }) /** Mode definition for hearing aids. */ public @interface DeviceMode { int MODE_INVALID = -1; int MODE_MONAURAL = 0; int MODE_BINAURAL = 1; int MODE_BANDED = 2; } private final int mSide; private final int mMode; private final long mHiSyncId; private HearingAidInfo(int side, int mode, long hiSyncId) { mSide = side; mMode = mode; mHiSyncId = hiSyncId; } @DeviceSide public int getSide() { return mSide; } @DeviceMode public int getMode() { return mMode; } public long getHiSyncId() { return mHiSyncId; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof HearingAidInfo)) { return false; } HearingAidInfo that = (HearingAidInfo) o; return mSide == that.mSide && mMode == that.mMode && mHiSyncId == that.mHiSyncId; } @Override public int hashCode() { return Objects.hash(mSide, mMode, mHiSyncId); } @Override public String toString() { return "HearingAidInfo{" + "mSide=" + mSide + ", mMode=" + mMode + ", mHiSyncId=" + mHiSyncId + '}'; } @DeviceSide private static int convertAshaDeviceSideToInternalSide(int ashaDeviceSide) { return ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.get( ashaDeviceSide, DeviceSide.SIDE_INVALID); } @DeviceMode private static int convertAshaDeviceModeToInternalMode(int ashaDeviceMode) { return ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.get( ashaDeviceMode, DeviceMode.MODE_INVALID); } @DeviceSide private static int convertLeAudioLocationToInternalSide(int leAudioLocation) { boolean isLeft = (leAudioLocation & LE_AUDIO_LOCATION_LEFT) != 0; boolean isRight = (leAudioLocation & LE_AUDIO_LOCATION_RIGHT) != 0; if (isLeft && isRight) { return DeviceSide.SIDE_LEFT_AND_RIGHT; } else if (isLeft) { return DeviceSide.SIDE_LEFT; } else if (isRight) { return DeviceSide.SIDE_RIGHT; } return DeviceSide.SIDE_INVALID; } @DeviceMode private static int convertHapDeviceTypeToInternalMode(int hapDeviceType) { return HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.get(hapDeviceType, DeviceMode.MODE_INVALID); } /** Builder class for constructing {@link HearingAidInfo} objects. */ public static final class Builder { private int mSide = DeviceSide.SIDE_INVALID; private int mMode = DeviceMode.MODE_INVALID; private long mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; /** * Configure the hearing device mode. * @param ashaDeviceMode one of the hearing aid device modes defined in HearingAidProfile * {@link HearingAidProfile.DeviceMode} */ public Builder setAshaDeviceMode(int ashaDeviceMode) { mMode = convertAshaDeviceModeToInternalMode(ashaDeviceMode); return this; } /** * Configure the hearing device mode. * @param hapDeviceType one of the hearing aid device types defined in HapClientProfile * {@link HapClientProfile.HearingAidType} */ public Builder setHapDeviceType(int hapDeviceType) { mMode = convertHapDeviceTypeToInternalMode(hapDeviceType); return this; } /** * Configure the hearing device side. * @param ashaDeviceSide one of the hearing aid device sides defined in HearingAidProfile * {@link HearingAidProfile.DeviceSide} */ public Builder setAshaDeviceSide(int ashaDeviceSide) { mSide = convertAshaDeviceSideToInternalSide(ashaDeviceSide); return this; } /** * Configure the hearing device side. * @param leAudioLocation one of the audio location defined in BluetoothLeAudio * {@link BluetoothLeAudio.AudioLocation} */ public Builder setLeAudioLocation(int leAudioLocation) { mSide = convertLeAudioLocationToInternalSide(leAudioLocation); return this; } /** * Configure the hearing aid hiSyncId. * @param hiSyncId the ASHA hearing aid id */ public Builder setHiSyncId(long hiSyncId) { mHiSyncId = hiSyncId; return this; } /** Build the configured {@link HearingAidInfo} */ public HearingAidInfo build() { return new HearingAidInfo(mSide, mMode, mHiSyncId); } } private static final int LE_AUDIO_LOCATION_LEFT = BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT | BluetoothLeAudio.AUDIO_LOCATION_BACK_LEFT | BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT_OF_CENTER | BluetoothLeAudio.AUDIO_LOCATION_SIDE_LEFT | BluetoothLeAudio.AUDIO_LOCATION_TOP_FRONT_LEFT | BluetoothLeAudio.AUDIO_LOCATION_TOP_BACK_LEFT | BluetoothLeAudio.AUDIO_LOCATION_TOP_SIDE_LEFT | BluetoothLeAudio.AUDIO_LOCATION_BOTTOM_FRONT_LEFT | BluetoothLeAudio.AUDIO_LOCATION_FRONT_LEFT_WIDE | BluetoothLeAudio.AUDIO_LOCATION_LEFT_SURROUND; private static final int LE_AUDIO_LOCATION_RIGHT = BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_BACK_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER | BluetoothLeAudio.AUDIO_LOCATION_SIDE_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_TOP_FRONT_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_TOP_BACK_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_TOP_SIDE_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_BOTTOM_FRONT_RIGHT | BluetoothLeAudio.AUDIO_LOCATION_FRONT_RIGHT_WIDE | BluetoothLeAudio.AUDIO_LOCATION_RIGHT_SURROUND; private static final SparseIntArray ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING; private static final SparseIntArray ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING; private static final SparseIntArray HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING; static { ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING = new SparseIntArray(); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_INVALID, DeviceSide.SIDE_INVALID); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_LEFT, DeviceSide.SIDE_LEFT); ASHA_DEVICE_SIDE_TO_INTERNAL_SIDE_MAPPING.put( HearingAidProfile.DeviceSide.SIDE_RIGHT, DeviceSide.SIDE_RIGHT); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING = new SparseIntArray(); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_INVALID, DeviceMode.MODE_INVALID); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_MONAURAL, DeviceMode.MODE_MONAURAL); ASHA_DEVICE_MODE_TO_INTERNAL_MODE_MAPPING.put( HearingAidProfile.DeviceMode.MODE_BINAURAL, DeviceMode.MODE_BINAURAL); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING = new SparseIntArray(); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_INVALID, DeviceMode.MODE_INVALID); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_BINAURAL, DeviceMode.MODE_BINAURAL); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_MONAURAL, DeviceMode.MODE_MONAURAL); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_BANDED, DeviceMode.MODE_BANDED); HAP_DEVICE_TYPE_TO_INTERNAL_MODE_MAPPING.put( HapClientProfile.HearingAidType.TYPE_RFU, DeviceMode.MODE_INVALID); } }