• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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