1 /* 2 * Copyright 2021 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.bluetooth.hap; 19 20 import static android.bluetooth.BluetoothProfile.getConnectionStateName; 21 22 import android.bluetooth.BluetoothDevice; 23 import android.bluetooth.IBluetoothHapClient; 24 25 import java.math.BigInteger; 26 import java.util.ArrayList; 27 import java.util.List; 28 29 /** 30 * Stack event sent via a callback from GATT Service client to main service module, or generated 31 * internally by the Hearing Access Profile State Machine. 32 */ 33 public class HapClientStackEvent { 34 // Event types for STACK_EVENT message (coming from native HAS client) 35 private static final int EVENT_TYPE_NONE = 0; 36 public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; 37 public static final int EVENT_TYPE_DEVICE_AVAILABLE = 2; 38 public static final int EVENT_TYPE_DEVICE_FEATURES = 3; 39 public static final int EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED = 4; 40 public static final int EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR = 5; 41 public static final int EVENT_TYPE_ON_PRESET_INFO = 6; 42 public static final int EVENT_TYPE_ON_PRESET_NAME_SET_ERROR = 7; 43 public static final int EVENT_TYPE_ON_PRESET_INFO_ERROR = 8; 44 45 // Possible operation results 46 /* WARNING: Matches status codes defined in bta_has.h */ 47 static final int STATUS_NO_ERROR = 0; 48 static final int STATUS_SET_NAME_NOT_ALLOWED = 1; 49 static final int STATUS_OPERATION_NOT_SUPPORTED = 2; 50 static final int STATUS_OPERATION_NOT_POSSIBLE = 3; 51 static final int STATUS_INVALID_PRESET_NAME_LENGTH = 4; 52 static final int STATUS_INVALID_PRESET_INDEX = 5; 53 static final int STATUS_GROUP_OPERATION_NOT_SUPPORTED = 6; 54 static final int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = 7; 55 56 // Supported features 57 public static final int FEATURE_BIT_NUM_TYPE_MONAURAL = 58 IBluetoothHapClient.FEATURE_BIT_NUM_TYPE_MONAURAL; 59 public static final int FEATURE_BIT_NUM_TYPE_BANDED = 60 IBluetoothHapClient.FEATURE_BIT_NUM_TYPE_BANDED; 61 public static final int FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS = 62 IBluetoothHapClient.FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS; 63 public static final int FEATURE_BIT_NUM_INDEPENDENT_PRESETS = 64 IBluetoothHapClient.FEATURE_BIT_NUM_INDEPENDENT_PRESETS; 65 public static final int FEATURE_BIT_NUM_DYNAMIC_PRESETS = 66 IBluetoothHapClient.FEATURE_BIT_NUM_DYNAMIC_PRESETS; 67 public static final int FEATURE_BIT_NUM_WRITABLE_PRESETS = 68 IBluetoothHapClient.FEATURE_BIT_NUM_WRITABLE_PRESETS; 69 70 // Preset Info notification reason 71 /* WARNING: Matches status codes defined in bta_has.h */ 72 public static final int PRESET_INFO_REASON_ALL_PRESET_INFO = 0; 73 public static final int PRESET_INFO_REASON_PRESET_INFO_UPDATE = 1; 74 public static final int PRESET_INFO_REASON_PRESET_DELETED = 2; 75 public static final int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = 3; 76 public static final int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = 4; 77 78 public int type; 79 public BluetoothDevice device; 80 public int valueInt1; 81 public int valueInt2; 82 public int valueInt3; 83 public ArrayList valueList; 84 HapClientStackEvent(int type)85 HapClientStackEvent(int type) { 86 this.type = type; 87 } 88 89 @Override toString()90 public String toString() { 91 // event dump 92 StringBuilder result = new StringBuilder(); 93 result.append("HearingAccessStackEvent {type:").append(eventTypeToString(type)); 94 result.append(", device: ").append(device); 95 result.append(", value1: ").append(eventTypeValueInt1ToString(type, valueInt1)); 96 result.append(", value2: ").append(eventTypeValueInt2ToString(type, valueInt2)); 97 result.append(", value3: ").append(eventTypeValueInt3ToString(type, valueInt3)); 98 result.append(", list: ").append(eventTypeValueListToString(type, valueList)); 99 100 result.append("}"); 101 return result.toString(); 102 } 103 eventTypeValueListToString(int type, List value)104 private static String eventTypeValueListToString(int type, List value) { 105 switch (type) { 106 case EVENT_TYPE_ON_PRESET_INFO: 107 return "{presets count: " + (value == null ? 0 : value.size()) + "}"; 108 default: 109 return "{list: empty}"; 110 } 111 } 112 eventTypeValueInt1ToString(int type, int value)113 private static String eventTypeValueInt1ToString(int type, int value) { 114 switch (type) { 115 case EVENT_TYPE_CONNECTION_STATE_CHANGED: 116 return "{state: " + getConnectionStateName(value) + "}"; 117 case EVENT_TYPE_DEVICE_AVAILABLE: 118 return "{features: " + featuresToString(value) + "}"; 119 case EVENT_TYPE_DEVICE_FEATURES: 120 return "{features: " + featuresToString(value) + "}"; 121 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 122 return "{statusCode: " + statusCodeValueToString(value) + "}"; 123 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 124 return "{statusCode: " + statusCodeValueToString(value) + "}"; 125 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 126 return "{presetIndex: " + value + "}"; 127 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 128 return "{statusCode: " + statusCodeValueToString(value) + "}"; 129 case EVENT_TYPE_ON_PRESET_INFO: 130 default: 131 return "{unused: " + value + "}"; 132 } 133 } 134 infoReasonToString(int value)135 private static String infoReasonToString(int value) { 136 switch (value) { 137 case PRESET_INFO_REASON_ALL_PRESET_INFO: 138 return "PRESET_INFO_REASON_ALL_PRESET_INFO"; 139 case PRESET_INFO_REASON_PRESET_INFO_UPDATE: 140 return "PRESET_INFO_REASON_PRESET_INFO_UPDATE"; 141 case PRESET_INFO_REASON_PRESET_DELETED: 142 return "PRESET_INFO_REASON_PRESET_DELETED"; 143 case PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: 144 return "PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED"; 145 case PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: 146 return "PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE"; 147 default: 148 return "UNKNOWN"; 149 } 150 } 151 eventTypeValueInt2ToString(int type, int value)152 private static String eventTypeValueInt2ToString(int type, int value) { 153 switch (type) { 154 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 155 return "{presetIndex: " + value + "}"; 156 case EVENT_TYPE_ON_PRESET_INFO: 157 return "{info_reason: " + infoReasonToString(value) + "}"; 158 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 159 return "{presetIndex: " + value + "}"; 160 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 161 return "{groupId: " + value + "}"; 162 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 163 return "{groupId: " + value + "}"; 164 default: 165 return "{unused: " + value + "}"; 166 } 167 } 168 eventTypeValueInt3ToString(int type, int value)169 private static String eventTypeValueInt3ToString(int type, int value) { 170 switch (type) { 171 case EVENT_TYPE_ON_PRESET_INFO: 172 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 173 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 174 return "{groupId: " + value + "}"; 175 default: 176 return "{unused: " + value + "}"; 177 } 178 } 179 statusCodeValueToString(int value)180 private static String statusCodeValueToString(int value) { 181 switch (value) { 182 case STATUS_NO_ERROR: 183 return "STATUS_NO_ERROR"; 184 case STATUS_SET_NAME_NOT_ALLOWED: 185 return "STATUS_SET_NAME_NOT_ALLOWED"; 186 case STATUS_OPERATION_NOT_SUPPORTED: 187 return "STATUS_OPERATION_NOT_SUPPORTED"; 188 case STATUS_OPERATION_NOT_POSSIBLE: 189 return "STATUS_OPERATION_NOT_POSSIBLE"; 190 case STATUS_INVALID_PRESET_NAME_LENGTH: 191 return "STATUS_INVALID_PRESET_NAME_LENGTH"; 192 case STATUS_INVALID_PRESET_INDEX: 193 return "STATUS_INVALID_PRESET_INDEX"; 194 case STATUS_GROUP_OPERATION_NOT_SUPPORTED: 195 return "STATUS_GROUP_OPERATION_NOT_SUPPORTED"; 196 case STATUS_PROCEDURE_ALREADY_IN_PROGRESS: 197 return "STATUS_PROCEDURE_ALREADY_IN_PROGRESS"; 198 default: 199 return "ERROR_UNKNOWN"; 200 } 201 } 202 featuresToString(int value)203 private static String featuresToString(int value) { 204 StringBuilder features_sb = new StringBuilder(); 205 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_TYPE_MONAURAL)) { 206 features_sb.append("TYPE_MONAURAL"); 207 } else if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_TYPE_BANDED)) { 208 features_sb.append("TYPE_BANDED"); 209 } else { 210 features_sb.append("TYPE_BINAURAL"); 211 } 212 213 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS)) { 214 features_sb.append(", SYNCHRONIZATED_PRESETS"); 215 } 216 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_INDEPENDENT_PRESETS)) { 217 features_sb.append(", INDEPENDENT_PRESETS"); 218 } 219 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_DYNAMIC_PRESETS)) { 220 features_sb.append(", DYNAMIC_PRESETS"); 221 } 222 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_WRITABLE_PRESETS)) { 223 features_sb.append(", WRITABLE_PRESETS"); 224 } 225 226 return features_sb.toString(); 227 } 228 eventTypeToString(int type)229 private static String eventTypeToString(int type) { 230 switch (type) { 231 case EVENT_TYPE_NONE: 232 return "EVENT_TYPE_NONE"; 233 case EVENT_TYPE_CONNECTION_STATE_CHANGED: 234 return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; 235 case EVENT_TYPE_DEVICE_AVAILABLE: 236 return "EVENT_TYPE_DEVICE_AVAILABLE"; 237 case EVENT_TYPE_DEVICE_FEATURES: 238 return "EVENT_TYPE_DEVICE_FEATURES"; 239 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 240 return "EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED"; 241 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 242 return "EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR"; 243 case EVENT_TYPE_ON_PRESET_INFO: 244 return "EVENT_TYPE_ON_PRESET_INFO"; 245 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 246 return "EVENT_TYPE_ON_PRESET_NAME_SET_ERROR"; 247 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 248 return "EVENT_TYPE_ON_PRESET_INFO_ERROR"; 249 default: 250 return "EVENT_TYPE_UNKNOWN:" + type; 251 } 252 } 253 } 254