NativeInterface.java revision 93d129a2679021c3275ba940405ba2609853b9ee
1/*
2 * Copyright (c) 2017 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 inteface that is used by state machine/service to either or receive messages
19 * from the native stack. This file is registered for the native methods in corresponding CPP file.
20 */
21package com.android.bluetooth.hfpclient;
22
23import com.android.bluetooth.Utils;
24
25import android.bluetooth.BluetoothAdapter;
26import android.bluetooth.BluetoothDevice;
27import android.util.Log;
28
29class NativeInterface {
30    private static String TAG = "NativeInterface";
31    private static boolean DBG = false;
32
33    NativeInterface() {}
34
35    // Native methods that call into the JNI interface
36    static native void classInitNative();
37    static native void initializeNative();
38    static native void cleanupNative();
39    static native boolean connectNative(byte[] address);
40    static native boolean disconnectNative(byte[] address);
41    static native boolean connectAudioNative(byte[] address);
42    static native boolean disconnectAudioNative(byte[] address);
43    static native boolean startVoiceRecognitionNative(byte[] address);
44    static native boolean stopVoiceRecognitionNative(byte[] address);
45    static native boolean setVolumeNative(byte[] address, int volumeType, int volume);
46    static native boolean dialNative(byte[] address, String number);
47    static native boolean dialMemoryNative(byte[] address, int location);
48    static native boolean handleCallActionNative(byte[] address, int action, int index);
49    static native boolean queryCurrentCallsNative(byte[] address);
50    static native boolean queryCurrentOperatorNameNative(byte[] address);
51    static native boolean retrieveSubscriberInfoNative(byte[] address);
52    static native boolean sendDtmfNative(byte[] address, byte code);
53    static native boolean requestLastVoiceTagNumberNative(byte[] address);
54    static native boolean sendATCmdNative(byte[] address, int atCmd, int val1,
55            int val2, String arg);
56
57    private BluetoothDevice getDevice(byte[] address) {
58        return BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
59    }
60
61    // Callbacks from the native back into the java framework. All callbacks are routed via the
62    // Service which will disambiguate which state machine the message should be routed through.
63    private void onConnectionStateChanged(int state, int peer_feat, int chld_feat, byte[] address) {
64        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
65        event.valueInt = state;
66        event.valueInt2 = peer_feat;
67        event.valueInt3 = chld_feat;
68        event.device = getDevice(address);
69        // BluetoothAdapter.getDefaultAdapter().getRemoteDevice(Utils.getAddressStringFromByte(address));
70        if (DBG) {
71            Log.d(TAG, "Device addr "  + event.device.getAddress() + " State " + state);
72        }
73        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
74        if (service != null) {
75            service.messageFromNative(event);
76        } else {
77            Log.w(TAG, "Ignoring message because service not available: " + event);
78        }
79    }
80
81    private void onAudioStateChanged(int state, byte[] address) {
82        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED);
83        event.valueInt = state;
84        event.device = getDevice(address);
85        if (DBG) {
86            Log.d(TAG, "onAudioStateChanged: address " + address + " event "  + event);
87        }
88        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
89        if (service != null) {
90            service.messageFromNative(event);
91        } else {
92            Log.w(TAG, "onAudioStateChanged: Ignoring message because service not available: " + event);
93        }
94    }
95
96    private void onVrStateChanged(int state) {
97        Log.w(TAG, "onVrStateChanged not supported");
98    }
99
100    private void onNetworkState(int state, byte[] address) {
101        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_STATE);
102        event.valueInt = state;
103        event.device = getDevice(address);
104        if (DBG) {
105            Log.d(TAG, "onVrStateChanged: address " + address + " event "  + event);
106        }
107
108        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
109        if (service != null) {
110            service.messageFromNative(event);
111        } else {
112            Log.w(TAG, "onVrStateChanged: Ignoring message because service not available: " + event);
113        }
114    }
115
116    private void onNetworkRoaming(int state, byte[] address) {
117        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_ROAMING_STATE);
118        event.valueInt = state;
119        event.device = getDevice(address);
120        if (DBG) {
121            Log.d(TAG, "onNetworkRoaming: incoming: " + event);
122        }
123        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
124        if (service != null) {
125            service.messageFromNative(event);
126        } else {
127            Log.w(TAG, "onNetworkRoaming: Ignoring message because service not available: " + event);
128        }
129    }
130
131    private void onNetworkSignal(int signal, byte[] address) {
132        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_SIGNAL);
133        event.valueInt = signal;
134        event.device = getDevice(address);
135        if (DBG) {
136            Log.d(TAG, "onNetworkSignal: address " + address + " event "  + event);
137        }
138        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
139        if (service != null) {
140            service.messageFromNative(event);
141        } else {
142            Log.w(TAG, "onNetworkSignal: Ignoring message because service not available: " + event);
143        }
144    }
145
146    private void onBatteryLevel(int level, byte[] address) {
147        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_BATTERY_LEVEL);
148        event.valueInt = level;
149        event.device = getDevice(address);
150        if (DBG) {
151            Log.d(TAG, "onBatteryLevel: address " + address + " event "  + event);
152        }
153        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
154        if (service != null) {
155            service.messageFromNative(event);
156        } else {
157            Log.w(TAG, "onBatteryLevel: Ignoring message because service not available: " + event);
158        }
159    }
160
161    private void onCurrentOperator(String name, byte[] address) {
162        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_OPERATOR_NAME);
163        event.valueString = name;
164        event.device = getDevice(address);
165        if (DBG) {
166            Log.d(TAG, "onCurrentOperator: address " + address + " event "  + event);
167        }
168        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
169        if (service != null) {
170            service.messageFromNative(event);
171        } else {
172            Log.w(TAG, "onCurrentOperator: Ignoring message because service not available: " + event);
173        }
174    }
175
176    private void onCall(int call, byte[] address) {
177        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL);
178        event.valueInt = call;
179        event.device = getDevice(address);
180        if (DBG) {
181            Log.d(TAG, "onCall: address " + address + " event "  + event);
182        }
183        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
184        if (service != null) {
185            service.messageFromNative(event);
186        } else {
187            Log.w(TAG, "onCall: Ignoring message because service not available: " + event);
188        }
189    }
190
191    /**
192     * CIEV (Call indicators) notifying if call(s) are getting set up.
193     *
194     * Values include:
195     * 0 - No current call is in setup
196     * 1 - Incoming call process ongoing
197     * 2 - Outgoing call process ongoing
198     * 3 - Remote party being alerted for outgoing call
199     */
200    private void onCallSetup(int callsetup, byte[] address) {
201        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLSETUP);
202        event.valueInt = callsetup;
203        event.device = getDevice(address);
204        if (DBG) {
205            Log.d(TAG, "onCallSetup: addr " + address + " device" + event.device);
206            Log.d(TAG, "onCallSetup: address " + address + " event "  + event);
207        }
208        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
209        if (service != null) {
210            service.messageFromNative(event);
211        } else {
212            Log.w(TAG, "onCallSetup: Ignoring message because service not available: " + event);
213        }
214    }
215
216    /**
217     * CIEV (Call indicators) notifying call held states.
218     *
219     * Values include:
220     * 0 - No calls held
221     * 1 - Call is placed on hold or active/held calls wapped (The AG has both an ACTIVE and HELD
222     * call)
223     * 2 - Call on hold, no active call
224     */
225    private void onCallHeld(int callheld, byte[] address) {
226        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLHELD);
227        event.valueInt = callheld;
228        event.device = getDevice(address);
229        if (DBG) {
230            Log.d(TAG, "onCallHeld: address " + address + " event "  + event);
231        }
232        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
233        if (service != null) {
234            service.messageFromNative(event);
235        } else {
236            Log.w(TAG, "onCallHeld: Ignoring message because service not available: " + event);
237        }
238    }
239
240    private void onRespAndHold(int resp_and_hold, byte[] address) {
241        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RESP_AND_HOLD);
242        event.valueInt = resp_and_hold;
243        event.device = getDevice(address);
244        if (DBG) {
245            Log.d(TAG, "onRespAndHold: address " + address + " event "  + event);
246        }
247        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
248        if (service != null) {
249            service.messageFromNative(event);
250        } else {
251            Log.w(TAG, "onRespAndHold: Ignoring message because service not available: " + event);
252        }
253    }
254
255    private void onClip(String number, byte[] address) {
256        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CLIP);
257        event.valueString = number;
258        event.device = getDevice(address);
259        if (DBG) {
260            Log.d(TAG, "onClip: address " + address + " event "  + event);
261        }
262        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
263        if (service != null) {
264            service.messageFromNative(event);
265        } else {
266            Log.w(TAG, "onClip: Ignoring message because service not available: " + event);
267        }
268    }
269
270    private void onCallWaiting(String number, byte[] address) {
271        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL_WAITING);
272        event.valueString = number;
273        event.device = getDevice(address);
274        if (DBG) {
275            Log.d(TAG, "onCallWaiting: address " + address + " event "  + event);
276        }
277        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
278        if (service != null) {
279            service.messageFromNative(event);
280        } else {
281            Log.w(TAG, "onCallWaiting: Ignoring message because service not available: " + event);
282        }
283    }
284
285    private void onCurrentCalls(
286            int index, int dir, int state, int mparty, String number, byte[] address) {
287        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CURRENT_CALLS);
288        event.valueInt = index;
289        event.valueInt2 = dir;
290        event.valueInt3 = state;
291        event.valueInt4 = mparty;
292        event.valueString = number;
293        event.device = getDevice(address);
294        if (DBG) {
295            Log.d(TAG, "onCurrentCalls: address " + address + " event "  + event);
296        }
297        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
298        if (service != null) {
299            service.messageFromNative(event);
300        } else {
301            Log.w(TAG, "onCurrentCalls: Ignoring message because service not available: " + event);
302        }
303    }
304
305    private void onVolumeChange(int type, int volume, byte[] address) {
306        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VOLUME_CHANGED);
307        event.valueInt = type;
308        event.valueInt2 = volume;
309        event.device = getDevice(address);
310        if (DBG) {
311            Log.d(TAG, "onVolumeChange: address " + address + " event "  + event);
312        }
313        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
314        // Ignore volume changes from the Phone. This is to avoid the scenario where we may have two
315        // phones connected each tries to set different volumes.
316        Log.w(TAG, "onVolumeChange: Ignoring message: " + event);
317    }
318
319    private void onCmdResult(int type, int cme, byte[] address) {
320        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT);
321        event.valueInt = type;
322        event.valueInt2 = cme;
323        event.device = getDevice(address);
324        if (DBG) {
325            Log.d(TAG, "onCmdResult: address " + address + " event "  + event);
326        }
327        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
328        if (service != null) {
329            service.messageFromNative(event);
330        } else {
331            Log.w(TAG, "onCmdResult: Ignoring message because service not available: " + event);
332        }
333    }
334
335    private void onSubscriberInfo(String number, int type, byte[] address) {
336        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_SUBSCRIBER_INFO);
337        event.valueInt = type;
338        event.valueString = number;
339        event.device = getDevice(address);
340        if (DBG) {
341            Log.d(TAG, "onSubscriberInfo: address " + address + " event "  + event);
342        }
343        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
344        if (service != null) {
345            service.messageFromNative(event);
346        } else {
347            Log.w(TAG, "onSubscriberInfo: Ignoring message because service not available: " + event);
348        }
349    }
350
351    private void onInBandRing(int in_band, byte[] address) {
352        Log.w(TAG, "onInBandRing not supported");
353    }
354
355    private void onLastVoiceTagNumber(String number, byte[] address) {
356        Log.w(TAG, "onLastVoiceTagNumber not supported");
357    }
358
359    private void onRingIndication(byte[] address) {
360        StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RING_INDICATION);
361        event.device = getDevice(address);
362        if (DBG) {
363            Log.d(TAG, "onRingIndication: address " + address + " event "  + event);
364        }
365        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
366        if (service != null) {
367            service.messageFromNative(event);
368        } else {
369            Log.w(TAG, "onRingIndication: Ignoring message because service not available: " + event);
370        }
371    }
372}
373