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