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