• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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.le_audio;
19 
20 import android.bluetooth.BluetoothDevice;
21 import android.bluetooth.BluetoothLeAudioCodecConfig;
22 import android.bluetooth.BluetoothLeBroadcastMetadata;
23 
24 import java.util.List;
25 /**
26  * Stack event sent via a callback from JNI to Java, or generated
27  * internally by the LeAudio State Machine.
28  */
29 public class LeAudioStackEvent {
30     // Event types for STACK_EVENT message (coming from native in bt_le_audio.h)
31     private static final int EVENT_TYPE_NONE = 0;
32     public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1;
33     public static final int EVENT_TYPE_GROUP_STATUS_CHANGED = 2;
34     public static final int EVENT_TYPE_GROUP_NODE_STATUS_CHANGED = 3;
35     public static final int EVENT_TYPE_AUDIO_CONF_CHANGED = 4;
36     public static final int EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE = 5;
37     public static final int EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED = 6;
38     public static final int EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED = 7;
39     public static final int EVENT_TYPE_NATIVE_INITIALIZED = 8;
40         // -------- DO NOT PUT ANY NEW UNICAST EVENTS BELOW THIS LINE-------------
41     public static final int EVENT_TYPE_UNICAST_MAX = 9;
42 
43     // Broadcast related events
44     public static final int EVENT_TYPE_BROADCAST_CREATED = EVENT_TYPE_UNICAST_MAX + 1;
45     public static final int EVENT_TYPE_BROADCAST_DESTROYED = EVENT_TYPE_UNICAST_MAX + 2;
46     public static final int EVENT_TYPE_BROADCAST_STATE = EVENT_TYPE_UNICAST_MAX + 3;
47     public static final int EVENT_TYPE_BROADCAST_METADATA_CHANGED = EVENT_TYPE_UNICAST_MAX + 4;
48 
49     // Do not modify without updating the HAL bt_le_audio.h files.
50     // Match up with GroupStatus enum of bt_le_audio.h
51     static final int CONNECTION_STATE_DISCONNECTED = 0;
52     static final int CONNECTION_STATE_CONNECTING = 1;
53     static final int CONNECTION_STATE_CONNECTED = 2;
54     static final int CONNECTION_STATE_DISCONNECTING = 3;
55 
56     static final int GROUP_STATUS_INACTIVE = 0;
57     static final int GROUP_STATUS_ACTIVE = 1;
58     static final int GROUP_STATUS_TURNED_IDLE_DURING_CALL = 2;
59 
60     static final int GROUP_NODE_ADDED = 1;
61     static final int GROUP_NODE_REMOVED = 2;
62 
63     // Do not modify without updating the HAL bt_le_audio.h files.
64     // Match up with BroadcastState enum of bt_le_audio.h
65     static final int BROADCAST_STATE_STOPPED = 0;
66     static final int BROADCAST_STATE_CONFIGURING = 1;
67     static final int BROADCAST_STATE_PAUSED = 2;
68     static final int BROADCAST_STATE_STOPPING = 3;
69     static final int BROADCAST_STATE_STREAMING = 4;
70 
71     public int type = EVENT_TYPE_NONE;
72     public BluetoothDevice device;
73     public int valueInt1 = 0;
74     public int valueInt2 = 0;
75     public int valueInt3 = 0;
76     public int valueInt4 = 0;
77     public int valueInt5 = 0;
78     public boolean valueBool1 = false;
79     public BluetoothLeAudioCodecConfig valueCodec1;
80     public BluetoothLeAudioCodecConfig valueCodec2;
81     public List<BluetoothLeAudioCodecConfig> valueCodecList1;
82     public List<BluetoothLeAudioCodecConfig> valueCodecList2;
83     public BluetoothLeBroadcastMetadata broadcastMetadata;
84 
LeAudioStackEvent(int type)85     LeAudioStackEvent(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("LeAudioStackEvent {type:" + eventTypeToString(type));
94         result.append(", device:" + device);
95         result.append(", value1:" + eventTypeValue1ToString(type, valueInt1));
96         result.append(", value2:" + eventTypeValue2ToString(type, valueInt2));
97         result.append(", value3:" + eventTypeValue3ToString(type, valueInt3));
98         result.append(", value4:" + eventTypeValue4ToString(type, valueInt4));
99         result.append(", value5:" + eventTypeValue5ToString(type, valueInt5));
100         result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1));
101         result.append(", valueCodec1:" + eventTypeValueCodec1ToString(type, valueCodec1));
102         result.append(", valueCodec2:" + eventTypeValueCodec2ToString(type, valueCodec2));
103         result.append(", valueCodecList1:"
104                 + eventTypeValueCodecList1ToString(type, valueCodecList1));
105         result.append(", valueCodecList2:"
106                 + eventTypeValueCodecList2ToString(type, valueCodecList2));
107         if (type == EVENT_TYPE_BROADCAST_METADATA_CHANGED) {
108             result.append(", broadcastMetadata:"
109                     + eventTypeValueBroadcastMetadataToString(broadcastMetadata));
110         }
111         result.append("}");
112         return result.toString();
113     }
114 
eventTypeToString(int type)115     private static String eventTypeToString(int type) {
116         switch (type) {
117             case EVENT_TYPE_NONE:
118                 return "EVENT_TYPE_NONE";
119             case EVENT_TYPE_CONNECTION_STATE_CHANGED:
120                 return "EVENT_TYPE_CONNECTION_STATE_CHANGED";
121             case EVENT_TYPE_GROUP_STATUS_CHANGED:
122                 return "EVENT_TYPE_GROUP_STATUS_CHANGED";
123             case EVENT_TYPE_GROUP_NODE_STATUS_CHANGED:
124                 return "EVENT_TYPE_GROUP_NODE_STATUS_CHANGED";
125             case EVENT_TYPE_AUDIO_CONF_CHANGED:
126                 return "EVENT_TYPE_AUDIO_CONF_CHANGED";
127             case EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE:
128                 return "EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE";
129             case EVENT_TYPE_BROADCAST_CREATED:
130                 return "EVENT_TYPE_BROADCAST_CREATED";
131             case EVENT_TYPE_BROADCAST_DESTROYED:
132                 return "EVENT_TYPE_BROADCAST_DESTROYED";
133             case EVENT_TYPE_BROADCAST_STATE:
134                 return "EVENT_TYPE_BROADCAST_STATE";
135             case EVENT_TYPE_BROADCAST_METADATA_CHANGED:
136                 return "EVENT_TYPE_BROADCAST_METADATA_CHANGED";
137             case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
138                 return "EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED";
139             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
140                 return "EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED";
141             case EVENT_TYPE_NATIVE_INITIALIZED:
142                 return "EVENT_TYPE_NATIVE_INITIALIZED";
143             default:
144                 return "EVENT_TYPE_UNKNOWN:" + type;
145         }
146     }
147 
eventTypeValue1ToString(int type, int value)148     private static String eventTypeValue1ToString(int type, int value) {
149         switch (type) {
150             case EVENT_TYPE_CONNECTION_STATE_CHANGED:
151                 switch (value) {
152                     case CONNECTION_STATE_DISCONNECTED:
153                         return  "CONNECTION_STATE_DISCONNECTED";
154                     case CONNECTION_STATE_CONNECTING:
155                         return  "CONNECTION_STATE_CONNECTING";
156                     case CONNECTION_STATE_CONNECTED:
157                         return  "CONNECTION_STATE_CONNECTED";
158                     case CONNECTION_STATE_DISCONNECTING:
159                         return  "CONNECTION_STATE_DISCONNECTING";
160                     default:
161                         return "UNKNOWN";
162                 }
163             case EVENT_TYPE_GROUP_NODE_STATUS_CHANGED:
164                 // same as EVENT_TYPE_GROUP_STATUS_CHANGED
165             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
166                 // same as EVENT_TYPE_GROUP_STATUS_CHANGED
167             case EVENT_TYPE_GROUP_STATUS_CHANGED:
168                 return "{group_id:" + Integer.toString(value) + "}";
169             case EVENT_TYPE_AUDIO_CONF_CHANGED:
170                 // FIXME: It should have proper direction names here
171                 return "{direction:" + value + "}";
172             case EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE:
173                 return "{sink_audio_location:" + value + "}";
174             case EVENT_TYPE_BROADCAST_CREATED:
175                 // same as EVENT_TYPE_BROADCAST_STATE
176             case EVENT_TYPE_BROADCAST_DESTROYED:
177                 // same as EVENT_TYPE_BROADCAST_STATE
178             case EVENT_TYPE_BROADCAST_METADATA_CHANGED:
179                 // same as EVENT_TYPE_BROADCAST_STATE
180             case EVENT_TYPE_BROADCAST_STATE:
181                 return "{broadcastId:" + value + "}";
182             default:
183                 break;
184         }
185         return Integer.toString(value);
186     }
187 
eventTypeValue2ToString(int type, int value)188     private static String eventTypeValue2ToString(int type, int value) {
189         switch (type) {
190             case EVENT_TYPE_GROUP_STATUS_CHANGED:
191                 switch (value) {
192                     case GROUP_STATUS_ACTIVE:
193                         return "GROUP_STATUS_ACTIVE";
194                     case GROUP_STATUS_INACTIVE:
195                         return "GROUP_STATUS_INACTIVE";
196                     case GROUP_STATUS_TURNED_IDLE_DURING_CALL:
197                         return "GROUP_STATUS_TURNED_IDLE_DURING_CALL";
198                     default:
199                         break;
200                 }
201                 break;
202             case EVENT_TYPE_GROUP_NODE_STATUS_CHANGED:
203                 switch (value) {
204                     case GROUP_NODE_ADDED:
205                         return "GROUP_NODE_ADDED";
206                     case GROUP_NODE_REMOVED:
207                         return "GROUP_NODE_REMOVED";
208                     default:
209                         return "UNKNOWN";
210                 }
211             case EVENT_TYPE_AUDIO_CONF_CHANGED:
212                 return "{group_id:" + Integer.toString(value) + "}";
213             case EVENT_TYPE_BROADCAST_STATE:
214                 return "{state:" + broadcastStateToString(value) + "}";
215             default:
216                 break;
217         }
218         return Integer.toString(value);
219     }
220 
eventTypeValue3ToString(int type, int value)221     private static String eventTypeValue3ToString(int type, int value) {
222         switch (type) {
223             case EVENT_TYPE_AUDIO_CONF_CHANGED:
224                 // FIXME: It should have proper location names here
225                 return "{snk_audio_loc:" + value + "}";
226             default:
227                 break;
228         }
229         return Integer.toString(value);
230     }
231 
eventTypeValue4ToString(int type, int value)232     private static String eventTypeValue4ToString(int type, int value) {
233         switch (type) {
234             case EVENT_TYPE_AUDIO_CONF_CHANGED:
235                 // FIXME: It should have proper location names here
236                 return "{src_audio_loc:" + value + "}";
237             default:
238                 break;
239         }
240         return Integer.toString(value);
241     }
242 
eventTypeValue5ToString(int type, int value)243     private static String eventTypeValue5ToString(int type, int value) {
244         switch (type) {
245             case EVENT_TYPE_AUDIO_CONF_CHANGED:
246                 return "{available_contexts:" + Integer.toBinaryString(value) + "}";
247             default:
248                 break;
249         }
250         return Integer.toString(value);
251     }
252 
eventTypeValueBool1ToString(int type, boolean value)253     private static String eventTypeValueBool1ToString(int type, boolean value) {
254         switch (type) {
255             case EVENT_TYPE_BROADCAST_CREATED:
256                 return "{success:" + value + "}";
257             default:
258                 return "<unused>";
259         }
260     }
261 
eventTypeValueCodec1ToString(int type, BluetoothLeAudioCodecConfig value)262     private static String eventTypeValueCodec1ToString(int type,
263                                     BluetoothLeAudioCodecConfig value) {
264         switch (type) {
265             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
266                 return "{input codec = " + value + "}";
267             default:
268                 return "<unused>";
269         }
270     }
271 
eventTypeValueCodec2ToString(int type, BluetoothLeAudioCodecConfig value)272     private static String eventTypeValueCodec2ToString(int type,
273                                     BluetoothLeAudioCodecConfig value) {
274         switch (type) {
275             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
276                 return "{output codec = " + value + "}";
277             default:
278                 return "<unused>";
279         }
280     }
281 
eventTypeValueCodecList1ToString(int type, List<BluetoothLeAudioCodecConfig> value)282     private static String eventTypeValueCodecList1ToString(int type,
283                                     List<BluetoothLeAudioCodecConfig> value) {
284         switch (type) {
285             case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
286                 return "{input local capa codec = " + value + "}";
287             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
288                 return "{input selectable codec = " + value + "}";
289             default:
290                 return "<unused>";
291         }
292     }
293 
eventTypeValueCodecList2ToString(int type, List<BluetoothLeAudioCodecConfig> value)294     private static String eventTypeValueCodecList2ToString(int type,
295                                     List<BluetoothLeAudioCodecConfig> value) {
296         switch (type) {
297             case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
298                 return "{output local capa codec = " + value + "}";
299             case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
300                 return "{output selectable codec = " + value + "}";
301             default:
302                 return "<unused>";
303         }
304     }
305 
broadcastStateToString(int state)306     private static String broadcastStateToString(int state) {
307         switch (state) {
308             case BROADCAST_STATE_STOPPED:
309                 return "BROADCAST_STATE_STOPPED";
310             case BROADCAST_STATE_CONFIGURING:
311                 return "BROADCAST_STATE_CONFIGURING";
312             case BROADCAST_STATE_PAUSED:
313                 return "BROADCAST_STATE_PAUSED";
314             case BROADCAST_STATE_STOPPING:
315                 return "BROADCAST_STATE_STOPPING";
316             case BROADCAST_STATE_STREAMING:
317                 return "BROADCAST_STATE_STREAMING";
318             default:
319                 return "UNKNOWN";
320         }
321     }
322 
eventTypeValueBroadcastMetadataToString( BluetoothLeBroadcastMetadata meta)323     private static String eventTypeValueBroadcastMetadataToString(
324             BluetoothLeBroadcastMetadata meta) {
325         return meta.toString();
326     }
327 
encodeHexString(byte[] pduData)328     protected static String encodeHexString(byte[] pduData) {
329         StringBuilder out = new StringBuilder(pduData.length * 2);
330         for (int i = 0; i < pduData.length; i++) {
331             // MS-nibble first
332             out.append(Integer.toString((pduData[i] >> 4) & 0x0f, 16));
333             out.append(Integer.toString(pduData[i] & 0x0f, 16));
334         }
335         return out.toString();
336     }
337 }
338