Home | History | Annotate | Download | only in hfpclient
      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  */
     21 package com.android.bluetooth.hfpclient;
     22 
     23 import android.bluetooth.BluetoothAdapter;
     24 import android.bluetooth.BluetoothDevice;
     25 import android.util.Log;
     26 
     27 class 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, byte[] address) {
    115         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VR_STATE_CHANGED);
    116         event.valueInt = state;
    117         event.device = getDevice(address);
    118         if (DBG) {
    119             Log.d(TAG, "onVrStateChanged: address " + address + " event " + event);
    120         }
    121 
    122         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    123         if (service != null) {
    124             service.messageFromNative(event);
    125         } else {
    126             Log.w(TAG,
    127                     "onVrStateChanged: Ignoring message because service not available: " + event);
    128         }
    129     }
    130 
    131     private void onNetworkState(int state, byte[] address) {
    132         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_STATE);
    133         event.valueInt = state;
    134         event.device = getDevice(address);
    135         if (DBG) {
    136             Log.d(TAG, "onNetworkStateChanged: address " + address + " event " + event);
    137         }
    138 
    139         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    140         if (service != null) {
    141             service.messageFromNative(event);
    142         } else {
    143             Log.w(TAG,
    144                     "onNetworkStateChanged: Ignoring message because service not available: "
    145                             + event);
    146         }
    147     }
    148 
    149     private void onNetworkRoaming(int state, byte[] address) {
    150         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_ROAMING_STATE);
    151         event.valueInt = state;
    152         event.device = getDevice(address);
    153         if (DBG) {
    154             Log.d(TAG, "onNetworkRoaming: incoming: " + event);
    155         }
    156         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    157         if (service != null) {
    158             service.messageFromNative(event);
    159         } else {
    160             Log.w(TAG,
    161                     "onNetworkRoaming: Ignoring message because service not available: " + event);
    162         }
    163     }
    164 
    165     private void onNetworkSignal(int signal, byte[] address) {
    166         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_SIGNAL);
    167         event.valueInt = signal;
    168         event.device = getDevice(address);
    169         if (DBG) {
    170             Log.d(TAG, "onNetworkSignal: address " + address + " event " + event);
    171         }
    172         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    173         if (service != null) {
    174             service.messageFromNative(event);
    175         } else {
    176             Log.w(TAG, "onNetworkSignal: Ignoring message because service not available: " + event);
    177         }
    178     }
    179 
    180     private void onBatteryLevel(int level, byte[] address) {
    181         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_BATTERY_LEVEL);
    182         event.valueInt = level;
    183         event.device = getDevice(address);
    184         if (DBG) {
    185             Log.d(TAG, "onBatteryLevel: address " + address + " event " + event);
    186         }
    187         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    188         if (service != null) {
    189             service.messageFromNative(event);
    190         } else {
    191             Log.w(TAG, "onBatteryLevel: Ignoring message because service not available: " + event);
    192         }
    193     }
    194 
    195     private void onCurrentOperator(String name, byte[] address) {
    196         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_OPERATOR_NAME);
    197         event.valueString = name;
    198         event.device = getDevice(address);
    199         if (DBG) {
    200             Log.d(TAG, "onCurrentOperator: address " + address + " event " + event);
    201         }
    202         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    203         if (service != null) {
    204             service.messageFromNative(event);
    205         } else {
    206             Log.w(TAG,
    207                     "onCurrentOperator: Ignoring message because service not available: " + event);
    208         }
    209     }
    210 
    211     private void onCall(int call, byte[] address) {
    212         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL);
    213         event.valueInt = call;
    214         event.device = getDevice(address);
    215         if (DBG) {
    216             Log.d(TAG, "onCall: address " + address + " event " + event);
    217         }
    218         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    219         if (service != null) {
    220             service.messageFromNative(event);
    221         } else {
    222             Log.w(TAG, "onCall: Ignoring message because service not available: " + event);
    223         }
    224     }
    225 
    226     /**
    227      * CIEV (Call indicators) notifying if call(s) are getting set up.
    228      *
    229      * Values include:
    230      * 0 - No current call is in setup
    231      * 1 - Incoming call process ongoing
    232      * 2 - Outgoing call process ongoing
    233      * 3 - Remote party being alerted for outgoing call
    234      */
    235     private void onCallSetup(int callsetup, byte[] address) {
    236         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLSETUP);
    237         event.valueInt = callsetup;
    238         event.device = getDevice(address);
    239         if (DBG) {
    240             Log.d(TAG, "onCallSetup: addr " + address + " device" + event.device);
    241             Log.d(TAG, "onCallSetup: address " + address + " event " + event);
    242         }
    243         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    244         if (service != null) {
    245             service.messageFromNative(event);
    246         } else {
    247             Log.w(TAG, "onCallSetup: Ignoring message because service not available: " + event);
    248         }
    249     }
    250 
    251     /**
    252      * CIEV (Call indicators) notifying call held states.
    253      *
    254      * Values include:
    255      * 0 - No calls held
    256      * 1 - Call is placed on hold or active/held calls wapped (The AG has both an ACTIVE and HELD
    257      * call)
    258      * 2 - Call on hold, no active call
    259      */
    260     private void onCallHeld(int callheld, byte[] address) {
    261         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLHELD);
    262         event.valueInt = callheld;
    263         event.device = getDevice(address);
    264         if (DBG) {
    265             Log.d(TAG, "onCallHeld: address " + address + " event " + event);
    266         }
    267         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    268         if (service != null) {
    269             service.messageFromNative(event);
    270         } else {
    271             Log.w(TAG, "onCallHeld: Ignoring message because service not available: " + event);
    272         }
    273     }
    274 
    275     private void onRespAndHold(int respAndHold, byte[] address) {
    276         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RESP_AND_HOLD);
    277         event.valueInt = respAndHold;
    278         event.device = getDevice(address);
    279         if (DBG) {
    280             Log.d(TAG, "onRespAndHold: address " + address + " event " + event);
    281         }
    282         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    283         if (service != null) {
    284             service.messageFromNative(event);
    285         } else {
    286             Log.w(TAG, "onRespAndHold: Ignoring message because service not available: " + event);
    287         }
    288     }
    289 
    290     private void onClip(String number, byte[] address) {
    291         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CLIP);
    292         event.valueString = number;
    293         event.device = getDevice(address);
    294         if (DBG) {
    295             Log.d(TAG, "onClip: address " + address + " event " + event);
    296         }
    297         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    298         if (service != null) {
    299             service.messageFromNative(event);
    300         } else {
    301             Log.w(TAG, "onClip: Ignoring message because service not available: " + event);
    302         }
    303     }
    304 
    305     private void onCallWaiting(String number, byte[] address) {
    306         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL_WAITING);
    307         event.valueString = number;
    308         event.device = getDevice(address);
    309         if (DBG) {
    310             Log.d(TAG, "onCallWaiting: address " + address + " event " + event);
    311         }
    312         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    313         if (service != null) {
    314             service.messageFromNative(event);
    315         } else {
    316             Log.w(TAG, "onCallWaiting: Ignoring message because service not available: " + event);
    317         }
    318     }
    319 
    320     private void onCurrentCalls(int index, int dir, int state, int mparty, String number,
    321             byte[] address) {
    322         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CURRENT_CALLS);
    323         event.valueInt = index;
    324         event.valueInt2 = dir;
    325         event.valueInt3 = state;
    326         event.valueInt4 = mparty;
    327         event.valueString = number;
    328         event.device = getDevice(address);
    329         if (DBG) {
    330             Log.d(TAG, "onCurrentCalls: address " + address + " event " + event);
    331         }
    332         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    333         if (service != null) {
    334             service.messageFromNative(event);
    335         } else {
    336             Log.w(TAG, "onCurrentCalls: Ignoring message because service not available: " + event);
    337         }
    338     }
    339 
    340     private void onVolumeChange(int type, int volume, byte[] address) {
    341         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VOLUME_CHANGED);
    342         event.valueInt = type;
    343         event.valueInt2 = volume;
    344         event.device = getDevice(address);
    345         if (DBG) {
    346             Log.d(TAG, "onVolumeChange: address " + address + " event " + event);
    347         }
    348         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    349         if (service != null) {
    350             service.messageFromNative(event);
    351         } else {
    352             Log.w(TAG, "onVolumeChange: Ignoring message because service not available: " + event);
    353         }
    354     }
    355 
    356     private void onCmdResult(int type, int cme, byte[] address) {
    357         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT);
    358         event.valueInt = type;
    359         event.valueInt2 = cme;
    360         event.device = getDevice(address);
    361         if (DBG) {
    362             Log.d(TAG, "onCmdResult: address " + address + " event " + event);
    363         }
    364         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    365         if (service != null) {
    366             service.messageFromNative(event);
    367         } else {
    368             Log.w(TAG, "onCmdResult: Ignoring message because service not available: " + event);
    369         }
    370     }
    371 
    372     private void onSubscriberInfo(String number, int type, byte[] address) {
    373         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_SUBSCRIBER_INFO);
    374         event.valueInt = type;
    375         event.valueString = number;
    376         event.device = getDevice(address);
    377         if (DBG) {
    378             Log.d(TAG, "onSubscriberInfo: address " + address + " event " + event);
    379         }
    380         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    381         if (service != null) {
    382             service.messageFromNative(event);
    383         } else {
    384             Log.w(TAG,
    385                     "onSubscriberInfo: Ignoring message because service not available: " + event);
    386         }
    387     }
    388 
    389     private void onInBandRing(int inBand, byte[] address) {
    390         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_IN_BAND_RINGTONE);
    391         event.valueInt = inBand;
    392         event.device = getDevice(address);
    393         if (DBG) {
    394             Log.d(TAG, "onInBandRing: address " + address + " event " + event);
    395         }
    396         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    397         if (service != null) {
    398             service.messageFromNative(event);
    399         } else {
    400             Log.w(TAG,
    401                     "onInBandRing: Ignoring message because service not available: " + event);
    402         }
    403     }
    404 
    405     private void onLastVoiceTagNumber(String number, byte[] address) {
    406         Log.w(TAG, "onLastVoiceTagNumber not supported");
    407     }
    408 
    409     private void onRingIndication(byte[] address) {
    410         StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RING_INDICATION);
    411         event.device = getDevice(address);
    412         if (DBG) {
    413             Log.d(TAG, "onRingIndication: address " + address + " event " + event);
    414         }
    415         HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
    416         if (service != null) {
    417             service.messageFromNative(event);
    418         } else {
    419             Log.w(TAG,
    420                     "onRingIndication: Ignoring message because service not available: " + event);
    421         }
    422     }
    423 }
    424