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 android.bluetooth.BluetoothDevice; 21 import android.bluetooth.IBluetoothHapClient; 22 23 import java.math.BigInteger; 24 import java.util.ArrayList; 25 import java.util.List; 26 27 /** 28 * Stack event sent via a callback from GATT Service client to main service module, or generated 29 * internally by the Hearing Access Profile State Machine. 30 */ 31 public class HapClientStackEvent { 32 // Event types for STACK_EVENT message (coming from native HAS client) 33 private static final int EVENT_TYPE_NONE = 0; 34 public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; 35 public static final int EVENT_TYPE_DEVICE_AVAILABLE = 2; 36 public static final int EVENT_TYPE_DEVICE_FEATURES = 3; 37 public static final int EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED = 4; 38 public static final int EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR = 5; 39 public static final int EVENT_TYPE_ON_PRESET_INFO = 6; 40 public static final int EVENT_TYPE_ON_PRESET_NAME_SET_ERROR = 7; 41 public static final int EVENT_TYPE_ON_PRESET_INFO_ERROR = 8; 42 43 // Connection state values as defined in bt_has.h 44 static final int CONNECTION_STATE_DISCONNECTED = 0; 45 static final int CONNECTION_STATE_CONNECTING = 1; 46 static final int CONNECTION_STATE_CONNECTED = 2; 47 static final int CONNECTION_STATE_DISCONNECTING = 3; 48 49 // Possible operation results 50 /* WARNING: Matches status codes defined in bta_has.h */ 51 static final int STATUS_NO_ERROR = 0; 52 static final int STATUS_SET_NAME_NOT_ALLOWED = 1; 53 static final int STATUS_OPERATION_NOT_SUPPORTED = 2; 54 static final int STATUS_OPERATION_NOT_POSSIBLE = 3; 55 static final int STATUS_INVALID_PRESET_NAME_LENGTH = 4; 56 static final int STATUS_INVALID_PRESET_INDEX = 5; 57 static final int STATUS_GROUP_OPERATION_NOT_SUPPORTED = 6; 58 static final int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = 7; 59 60 // Supported features 61 public static final int FEATURE_BIT_NUM_TYPE_MONAURAL = 62 IBluetoothHapClient.FEATURE_BIT_NUM_TYPE_MONAURAL; 63 public static final int FEATURE_BIT_NUM_TYPE_BANDED = 64 IBluetoothHapClient.FEATURE_BIT_NUM_TYPE_BANDED; 65 public static final int FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS = 66 IBluetoothHapClient.FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS; 67 public static final int FEATURE_BIT_NUM_INDEPENDENT_PRESETS = 68 IBluetoothHapClient.FEATURE_BIT_NUM_INDEPENDENT_PRESETS; 69 public static final int FEATURE_BIT_NUM_DYNAMIC_PRESETS = 70 IBluetoothHapClient.FEATURE_BIT_NUM_DYNAMIC_PRESETS; 71 public static final int FEATURE_BIT_NUM_WRITABLE_PRESETS = 72 IBluetoothHapClient.FEATURE_BIT_NUM_WRITABLE_PRESETS; 73 74 // Preset Info notification reason 75 /* WARNING: Matches status codes defined in bta_has.h */ 76 public static final int PRESET_INFO_REASON_ALL_PRESET_INFO = 0; 77 public static final int PRESET_INFO_REASON_PRESET_INFO_UPDATE = 1; 78 public static final int PRESET_INFO_REASON_PRESET_DELETED = 2; 79 public static final int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = 3; 80 public static final int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = 4; 81 82 public int type; 83 public BluetoothDevice device; 84 public int valueInt1; 85 public int valueInt2; 86 public int valueInt3; 87 public ArrayList valueList; 88 HapClientStackEvent(int type)89 HapClientStackEvent(int type) { 90 this.type = type; 91 } 92 93 @Override toString()94 public String toString() { 95 // event dump 96 StringBuilder result = new StringBuilder(); 97 result.append("HearingAccessStackEvent {type:" + eventTypeToString(type)); 98 result.append(", device: " + device); 99 result.append(", value1: " + eventTypeValueInt1ToString(type, valueInt1)); 100 result.append(", value2: " + eventTypeValueInt2ToString(type, valueInt2)); 101 result.append(", value3: " + eventTypeValueInt3ToString(type, valueInt3)); 102 result.append(", list: " + eventTypeValueListToString(type, valueList)); 103 104 result.append("}"); 105 return result.toString(); 106 } 107 eventTypeValueListToString(int type, List value)108 private String eventTypeValueListToString(int type, List value) { 109 switch (type) { 110 case EVENT_TYPE_ON_PRESET_INFO: 111 return "{presets count: " + (value == null ? 0 : value.size()) + "}"; 112 default: 113 return "{list: empty}"; 114 } 115 } 116 eventTypeValueInt1ToString(int type, int value)117 private String eventTypeValueInt1ToString(int type, int value) { 118 switch (type) { 119 case EVENT_TYPE_CONNECTION_STATE_CHANGED: 120 return "{state: " + connectionStateValueToString(value) + "}"; 121 case EVENT_TYPE_DEVICE_AVAILABLE: 122 return "{features: " + featuresToString(value) + "}"; 123 case EVENT_TYPE_DEVICE_FEATURES: 124 return "{features: " + featuresToString(value) + "}"; 125 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 126 return "{statusCode: " + statusCodeValueToString(value) + "}"; 127 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 128 return "{statusCode: " + statusCodeValueToString(value) + "}"; 129 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 130 return "{presetIndex: " + value + "}"; 131 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 132 return "{statusCode: " + statusCodeValueToString(value) + "}"; 133 case EVENT_TYPE_ON_PRESET_INFO: 134 default: 135 return "{unused: " + value + "}"; 136 } 137 } 138 infoReasonToString(int value)139 private String infoReasonToString(int value) { 140 switch (value) { 141 case PRESET_INFO_REASON_ALL_PRESET_INFO: 142 return "PRESET_INFO_REASON_ALL_PRESET_INFO"; 143 case PRESET_INFO_REASON_PRESET_INFO_UPDATE: 144 return "PRESET_INFO_REASON_PRESET_INFO_UPDATE"; 145 case PRESET_INFO_REASON_PRESET_DELETED: 146 return "PRESET_INFO_REASON_PRESET_DELETED"; 147 case PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: 148 return "PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED"; 149 case PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: 150 return "PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE"; 151 default: 152 return "UNKNOWN"; 153 } 154 } 155 eventTypeValueInt2ToString(int type, int value)156 private String eventTypeValueInt2ToString(int type, int value) { 157 switch (type) { 158 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 159 return "{presetIndex: " + value + "}"; 160 case EVENT_TYPE_ON_PRESET_INFO: 161 return "{info_reason: " + infoReasonToString(value) + "}"; 162 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 163 return "{presetIndex: " + value + "}"; 164 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 165 return "{groupId: " + value + "}"; 166 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 167 return "{groupId: " + value + "}"; 168 default: 169 return "{unused: " + value + "}"; 170 } 171 } 172 eventTypeValueInt3ToString(int type, int value)173 private String eventTypeValueInt3ToString(int type, int value) { 174 switch (type) { 175 case EVENT_TYPE_ON_PRESET_INFO: 176 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 177 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 178 return "{groupId: " + value + "}"; 179 default: 180 return "{unused: " + value + "}"; 181 } 182 } 183 connectionStateValueToString(int value)184 private String connectionStateValueToString(int value) { 185 switch (value) { 186 case CONNECTION_STATE_DISCONNECTED: 187 return "CONNECTION_STATE_DISCONNECTED"; 188 case CONNECTION_STATE_CONNECTING: 189 return "CONNECTION_STATE_CONNECTING"; 190 case CONNECTION_STATE_CONNECTED: 191 return "CONNECTION_STATE_CONNECTED"; 192 case CONNECTION_STATE_DISCONNECTING: 193 return "CONNECTION_STATE_DISCONNECTING"; 194 default: 195 return "CONNECTION_STATE_UNKNOWN!"; 196 } 197 } 198 statusCodeValueToString(int value)199 private String statusCodeValueToString(int value) { 200 switch (value) { 201 case STATUS_NO_ERROR: 202 return "STATUS_NO_ERROR"; 203 case STATUS_SET_NAME_NOT_ALLOWED: 204 return "STATUS_SET_NAME_NOT_ALLOWED"; 205 case STATUS_OPERATION_NOT_SUPPORTED: 206 return "STATUS_OPERATION_NOT_SUPPORTED"; 207 case STATUS_OPERATION_NOT_POSSIBLE: 208 return "STATUS_OPERATION_NOT_POSSIBLE"; 209 case STATUS_INVALID_PRESET_NAME_LENGTH: 210 return "STATUS_INVALID_PRESET_NAME_LENGTH"; 211 case STATUS_INVALID_PRESET_INDEX: 212 return "STATUS_INVALID_PRESET_INDEX"; 213 case STATUS_GROUP_OPERATION_NOT_SUPPORTED: 214 return "STATUS_GROUP_OPERATION_NOT_SUPPORTED"; 215 case STATUS_PROCEDURE_ALREADY_IN_PROGRESS: 216 return "STATUS_PROCEDURE_ALREADY_IN_PROGRESS"; 217 default: 218 return "ERROR_UNKNOWN"; 219 } 220 } 221 featuresToString(int value)222 private String featuresToString(int value) { 223 String features_str = ""; 224 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_TYPE_MONAURAL)) { 225 features_str += "TYPE_MONAURAL"; 226 } else if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_TYPE_BANDED)) { 227 features_str += "TYPE_BANDED"; 228 } else { 229 features_str += "TYPE_BINAURAL"; 230 } 231 232 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS)) { 233 features_str += ", SYNCHRONIZATED_PRESETS"; 234 } 235 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_INDEPENDENT_PRESETS)) { 236 features_str += ", INDEPENDENT_PRESETS"; 237 } 238 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_DYNAMIC_PRESETS)) { 239 features_str += ", DYNAMIC_PRESETS"; 240 } 241 if (BigInteger.valueOf(value).testBit(FEATURE_BIT_NUM_WRITABLE_PRESETS)) { 242 features_str += ", WRITABLE_PRESETS"; 243 } 244 245 return features_str; 246 } 247 eventTypeToString(int type)248 private static String eventTypeToString(int type) { 249 switch (type) { 250 case EVENT_TYPE_NONE: 251 return "EVENT_TYPE_NONE"; 252 case EVENT_TYPE_CONNECTION_STATE_CHANGED: 253 return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; 254 case EVENT_TYPE_DEVICE_AVAILABLE: 255 return "EVENT_TYPE_DEVICE_AVAILABLE"; 256 case EVENT_TYPE_DEVICE_FEATURES: 257 return "EVENT_TYPE_DEVICE_FEATURES"; 258 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED: 259 return "EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED"; 260 case EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR: 261 return "EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR"; 262 case EVENT_TYPE_ON_PRESET_INFO: 263 return "EVENT_TYPE_ON_PRESET_INFO"; 264 case EVENT_TYPE_ON_PRESET_NAME_SET_ERROR: 265 return "EVENT_TYPE_ON_PRESET_NAME_SET_ERROR"; 266 case EVENT_TYPE_ON_PRESET_INFO_ERROR: 267 return "EVENT_TYPE_ON_PRESET_INFO_ERROR"; 268 default: 269 return "EVENT_TYPE_UNKNOWN:" + type; 270 } 271 } 272 } 273