• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Defines the native interface that is used by state machine/service to
19  * send or receive messages from the native stack. This file is registered
20  * for the native methods in the corresponding JNI C++ file.
21  */
22 package com.android.bluetooth.hearingaid;
23 
24 import android.bluetooth.BluetoothAdapter;
25 import android.bluetooth.BluetoothDevice;
26 import android.support.annotation.VisibleForTesting;
27 import android.util.Log;
28 
29 import com.android.bluetooth.Utils;
30 import com.android.internal.annotations.GuardedBy;
31 
32 /**
33  * HearingAid Native Interface to/from JNI.
34  */
35 public class HearingAidNativeInterface {
36     private static final String TAG = "HearingAidNativeInterface";
37     private static final boolean DBG = true;
38     private BluetoothAdapter mAdapter;
39 
40     @GuardedBy("INSTANCE_LOCK")
41     private static HearingAidNativeInterface sInstance;
42     private static final Object INSTANCE_LOCK = new Object();
43 
44     static {
classInitNative()45         classInitNative();
46     }
47 
HearingAidNativeInterface()48     private HearingAidNativeInterface() {
49         mAdapter = BluetoothAdapter.getDefaultAdapter();
50         if (mAdapter == null) {
51             Log.wtfStack(TAG, "No Bluetooth Adapter Available");
52         }
53     }
54 
55     /**
56      * Get singleton instance.
57      */
getInstance()58     public static HearingAidNativeInterface getInstance() {
59         synchronized (INSTANCE_LOCK) {
60             if (sInstance == null) {
61                 sInstance = new HearingAidNativeInterface();
62             }
63             return sInstance;
64         }
65     }
66 
67     /**
68      * Initializes the native interface.
69      *
70      * priorities to configure.
71      */
72     @VisibleForTesting (otherwise = VisibleForTesting.PACKAGE_PRIVATE)
init()73     public void init() {
74         initNative();
75     }
76 
77     /**
78      * Cleanup the native interface.
79      */
80     @VisibleForTesting (otherwise = VisibleForTesting.PACKAGE_PRIVATE)
cleanup()81     public void cleanup() {
82         cleanupNative();
83     }
84 
85     /**
86      * Initiates HearingAid connection to a remote device.
87      *
88      * @param device the remote device
89      * @return true on success, otherwise false.
90      */
91     @VisibleForTesting (otherwise = VisibleForTesting.PACKAGE_PRIVATE)
connectHearingAid(BluetoothDevice device)92     public boolean connectHearingAid(BluetoothDevice device) {
93         return connectHearingAidNative(getByteAddress(device));
94     }
95 
96     /**
97      * Disconnects HearingAid from a remote device.
98      *
99      * @param device the remote device
100      * @return true on success, otherwise false.
101      */
102     @VisibleForTesting (otherwise = VisibleForTesting.PACKAGE_PRIVATE)
disconnectHearingAid(BluetoothDevice device)103     public boolean disconnectHearingAid(BluetoothDevice device) {
104         return disconnectHearingAidNative(getByteAddress(device));
105     }
106 
107     /**
108      * Sets the HearingAid volume
109      * @param volume
110      */
111     @VisibleForTesting (otherwise = VisibleForTesting.PACKAGE_PRIVATE)
setVolume(int volume)112     public void setVolume(int volume) {
113         setVolumeNative(volume);
114     }
115 
getDevice(byte[] address)116     private BluetoothDevice getDevice(byte[] address) {
117         return mAdapter.getRemoteDevice(address);
118     }
119 
getByteAddress(BluetoothDevice device)120     private byte[] getByteAddress(BluetoothDevice device) {
121         if (device == null) {
122             return Utils.getBytesFromAddress("00:00:00:00:00:00");
123         }
124         return Utils.getBytesFromAddress(device.getAddress());
125     }
126 
sendMessageToService(HearingAidStackEvent event)127     private void sendMessageToService(HearingAidStackEvent event) {
128         HearingAidService service = HearingAidService.getHearingAidService();
129         if (service != null) {
130             service.messageFromNative(event);
131         } else {
132             Log.e(TAG, "Event ignored, service not available: " + event);
133         }
134     }
135 
136     // Callbacks from the native stack back into the Java framework.
137     // All callbacks are routed via the Service which will disambiguate which
138     // state machine the message should be routed to.
139 
onConnectionStateChanged(int state, byte[] address)140     private void onConnectionStateChanged(int state, byte[] address) {
141         HearingAidStackEvent event =
142                 new HearingAidStackEvent(HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
143         event.device = getDevice(address);
144         event.valueInt1 = state;
145 
146         if (DBG) {
147             Log.d(TAG, "onConnectionStateChanged: " + event);
148         }
149         sendMessageToService(event);
150     }
151 
onDeviceAvailable(byte capabilities, long hiSyncId, byte[] address)152     private void onDeviceAvailable(byte capabilities, long hiSyncId, byte[] address) {
153         HearingAidStackEvent event = new HearingAidStackEvent(
154                 HearingAidStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
155         event.device = getDevice(address);
156         event.valueInt1 = capabilities;
157         event.valueLong2 = hiSyncId;
158 
159         if (DBG) {
160             Log.d(TAG, "onDeviceAvailable: " + event);
161         }
162         sendMessageToService(event);
163     }
164 
165     // Native methods that call into the JNI interface
classInitNative()166     private static native void classInitNative();
initNative()167     private native void initNative();
cleanupNative()168     private native void cleanupNative();
connectHearingAidNative(byte[] address)169     private native boolean connectHearingAidNative(byte[] address);
disconnectHearingAidNative(byte[] address)170     private native boolean disconnectHearingAidNative(byte[] address);
setVolumeNative(int volume)171     private native void setVolumeNative(int volume);
172 }
173