• 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 /*
19  * Defines the native interface that is used by state machine/service to
20  * send or receive messages from the native stack. This file is registered
21  * for the native methods in the corresponding JNI C++ file.
22  */
23 package com.android.bluetooth.le_audio;
24 
25 import android.bluetooth.BluetoothAdapter;
26 import android.bluetooth.BluetoothDevice;
27 import android.bluetooth.BluetoothLeBroadcastMetadata;
28 import android.util.Log;
29 
30 import com.android.bluetooth.Utils;
31 import com.android.internal.annotations.GuardedBy;
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 /** LeAudio Native Interface to/from JNI. */
35 public class LeAudioBroadcasterNativeInterface {
36     private static final String TAG = LeAudioBroadcasterNativeInterface.class.getSimpleName();
37 
38     private final BluetoothAdapter mAdapter;
39 
40     @GuardedBy("INSTANCE_LOCK")
41     private static LeAudioBroadcasterNativeInterface sInstance;
42 
43     private static final Object INSTANCE_LOCK = new Object();
44 
LeAudioBroadcasterNativeInterface()45     private LeAudioBroadcasterNativeInterface() {
46         mAdapter = BluetoothAdapter.getDefaultAdapter();
47         if (mAdapter == null) {
48             Log.wtf(TAG, "No Bluetooth Adapter Available");
49         }
50     }
51 
52     /** Get singleton instance. */
getInstance()53     public static LeAudioBroadcasterNativeInterface getInstance() {
54         synchronized (INSTANCE_LOCK) {
55             if (sInstance == null) {
56                 sInstance = new LeAudioBroadcasterNativeInterface();
57             }
58             return sInstance;
59         }
60     }
61 
62     /** Set singleton instance. */
63     @VisibleForTesting
setInstance(LeAudioBroadcasterNativeInterface instance)64     static void setInstance(LeAudioBroadcasterNativeInterface instance) {
65         synchronized (INSTANCE_LOCK) {
66             sInstance = instance;
67         }
68     }
69 
sendMessageToService(LeAudioStackEvent event)70     private static void sendMessageToService(LeAudioStackEvent event) {
71         LeAudioService service = LeAudioService.getLeAudioService();
72         if (service != null) {
73             service.messageFromNative(event);
74         } else {
75             Log.e(TAG, "Event ignored, service not available: " + event);
76         }
77     }
78 
79     @VisibleForTesting
getDevice(byte[] address)80     public BluetoothDevice getDevice(byte[] address) {
81         return mAdapter.getRemoteDevice(address);
82     }
83 
84     // Callbacks from the native stack back into the Java framework.
85     @VisibleForTesting
onBroadcastCreated(int broadcastId, boolean success)86     public void onBroadcastCreated(int broadcastId, boolean success) {
87         Log.d(TAG, "onBroadcastCreated: broadcastId=" + broadcastId);
88         LeAudioStackEvent event =
89                 new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED);
90 
91         event.valueInt1 = broadcastId;
92         event.valueBool1 = success;
93         sendMessageToService(event);
94     }
95 
96     @VisibleForTesting
onBroadcastDestroyed(int broadcastId)97     public void onBroadcastDestroyed(int broadcastId) {
98         Log.d(TAG, "onBroadcastDestroyed: broadcastId=" + broadcastId);
99         LeAudioStackEvent event =
100                 new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED);
101 
102         event.valueInt1 = broadcastId;
103         sendMessageToService(event);
104     }
105 
106     @VisibleForTesting
onBroadcastStateChanged(int broadcastId, int state)107     public void onBroadcastStateChanged(int broadcastId, int state) {
108         Log.d(TAG, "onBroadcastStateChanged: broadcastId=" + broadcastId + " state=" + state);
109         LeAudioStackEvent event =
110                 new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE);
111 
112         /* NOTICE: This is a fake device to satisfy Audio Manager in the upper
113          * layers which needs a device instance to route audio streams to the
114          * proper module (here it's Bluetooth). Broadcast has no concept of a
115          * destination or peer device therefore this fake device was created.
116          * For now it's only important that this device is a Bluetooth device.
117          */
118         event.device = getDevice(Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF"));
119         event.valueInt1 = broadcastId;
120         event.valueInt2 = state;
121         sendMessageToService(event);
122     }
123 
124     @VisibleForTesting
onBroadcastMetadataChanged(int broadcastId, BluetoothLeBroadcastMetadata metadata)125     public void onBroadcastMetadataChanged(int broadcastId, BluetoothLeBroadcastMetadata metadata) {
126         Log.d(TAG, "onBroadcastMetadataChanged: broadcastId=" + broadcastId);
127         LeAudioStackEvent event =
128                 new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_METADATA_CHANGED);
129 
130         event.valueInt1 = broadcastId;
131         event.broadcastMetadata = metadata;
132         sendMessageToService(event);
133     }
134 
135     @VisibleForTesting
onBroadcastAudioSessionCreated(boolean success)136     public void onBroadcastAudioSessionCreated(boolean success) {
137         Log.d(TAG, "onBroadcastAudioSessionCreated: success=" + success);
138         LeAudioStackEvent event =
139                 new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED);
140 
141         event.valueBool1 = success;
142         sendMessageToService(event);
143     }
144 
145     /**
146      * Initializes the native interface.
147      *
148      * <p>priorities to configure.
149      */
150     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
init()151     public void init() {
152         initNative();
153     }
154 
155     /** Stop the Broadcast Service. */
156     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stop()157     public void stop() {
158         stopNative();
159     }
160 
161     /** Cleanup the native interface. */
162     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
cleanup()163     public void cleanup() {
164         cleanupNative();
165     }
166 
167     /**
168      * Creates LeAudio Broadcast instance.
169      *
170      * @param isPublicBroadcast this BIG is public broadcast
171      * @param broadcastName BIG broadcast name
172      * @param broadcastCode BIG broadcast code
173      * @param publicMetadata BIG public broadcast meta data
174      * @param qualityArray BIG sub group audio quality array
175      * @param metadataArray BIG sub group metadata array
176      *     <p>qualityArray and metadataArray use the same subgroup index
177      */
178     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
createBroadcast( boolean isPublicBroadcast, String broadcastName, byte[] broadcastCode, byte[] publicMetadata, int[] qualityArray, byte[][] metadataArray)179     public void createBroadcast(
180             boolean isPublicBroadcast,
181             String broadcastName,
182             byte[] broadcastCode,
183             byte[] publicMetadata,
184             int[] qualityArray,
185             byte[][] metadataArray) {
186         createBroadcastNative(
187                 isPublicBroadcast,
188                 broadcastName,
189                 broadcastCode,
190                 publicMetadata,
191                 qualityArray,
192                 metadataArray);
193     }
194 
195     /**
196      * Update LeAudio Broadcast instance metadata.
197      *
198      * @param broadcastId broadcast instance identifier
199      * @param broadcastName BIG broadcast name
200      * @param publicMetadata BIG public broadcast meta data
201      * @param metadataArray BIG sub group metadata array
202      */
203     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
updateMetadata( int broadcastId, String broadcastName, byte[] publicMetadata, byte[][] metadataArray)204     public void updateMetadata(
205             int broadcastId, String broadcastName, byte[] publicMetadata, byte[][] metadataArray) {
206         updateMetadataNative(broadcastId, broadcastName, publicMetadata, metadataArray);
207     }
208 
209     /**
210      * Start LeAudio Broadcast instance.
211      *
212      * @param broadcastId broadcast instance identifier
213      */
214     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
startBroadcast(int broadcastId)215     public void startBroadcast(int broadcastId) {
216         startBroadcastNative(broadcastId);
217     }
218 
219     /**
220      * Stop LeAudio Broadcast instance.
221      *
222      * @param broadcastId broadcast instance identifier
223      */
224     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stopBroadcast(int broadcastId)225     public void stopBroadcast(int broadcastId) {
226         stopBroadcastNative(broadcastId);
227     }
228 
229     /**
230      * Pause LeAudio Broadcast instance.
231      *
232      * @param broadcastId broadcast instance identifier
233      */
234     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
pauseBroadcast(int broadcastId)235     public void pauseBroadcast(int broadcastId) {
236         pauseBroadcastNative(broadcastId);
237     }
238 
239     /**
240      * Destroy LeAudio Broadcast instance.
241      *
242      * @param broadcastId broadcast instance identifier
243      */
244     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
destroyBroadcast(int broadcastId)245     public void destroyBroadcast(int broadcastId) {
246         destroyBroadcastNative(broadcastId);
247     }
248 
249     /** Get all LeAudio Broadcast instance states. */
250     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
getBroadcastMetadata(int broadcastId)251     public void getBroadcastMetadata(int broadcastId) {
252         getBroadcastMetadataNative(broadcastId);
253     }
254 
255     // Native methods that call into the JNI interface
initNative()256     private native void initNative();
257 
stopNative()258     private native void stopNative();
259 
cleanupNative()260     private native void cleanupNative();
261 
createBroadcastNative( boolean isPublicBroadcast, String broadcastName, byte[] broadcastCode, byte[] publicMetadata, int[] qualityArray, byte[][] metadataArray)262     private native void createBroadcastNative(
263             boolean isPublicBroadcast,
264             String broadcastName,
265             byte[] broadcastCode,
266             byte[] publicMetadata,
267             int[] qualityArray,
268             byte[][] metadataArray);
269 
updateMetadataNative( int broadcastId, String broadcastName, byte[] publicMetadata, byte[][] metadataArray)270     private native void updateMetadataNative(
271             int broadcastId, String broadcastName, byte[] publicMetadata, byte[][] metadataArray);
272 
startBroadcastNative(int broadcastId)273     private native void startBroadcastNative(int broadcastId);
274 
stopBroadcastNative(int broadcastId)275     private native void stopBroadcastNative(int broadcastId);
276 
pauseBroadcastNative(int broadcastId)277     private native void pauseBroadcastNative(int broadcastId);
278 
destroyBroadcastNative(int broadcastId)279     private native void destroyBroadcastNative(int broadcastId);
280 
getBroadcastMetadataNative(int broadcastId)281     private native void getBroadcastMetadataNative(int broadcastId);
282 }
283