Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2013 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 package com.android.cts.verifier.bluetooth;
     18 
     19 import android.app.Service;
     20 import android.bluetooth.BluetoothDevice;
     21 import android.bluetooth.BluetoothGatt;
     22 import android.bluetooth.BluetoothGattCharacteristic;
     23 import android.bluetooth.BluetoothGattDescriptor;
     24 import android.bluetooth.BluetoothGattServer;
     25 import android.bluetooth.BluetoothGattServerCallback;
     26 import android.bluetooth.BluetoothGattService;
     27 import android.bluetooth.BluetoothManager;
     28 import android.bluetooth.BluetoothProfile;
     29 import android.bluetooth.le.AdvertiseCallback;
     30 import android.bluetooth.le.AdvertiseData;
     31 import android.bluetooth.le.AdvertiseSettings;
     32 import android.bluetooth.le.BluetoothLeAdvertiser;
     33 import android.content.Context;
     34 import android.content.Intent;
     35 import android.os.Build;
     36 import android.os.Handler;
     37 import android.os.IBinder;
     38 import android.os.ParcelUuid;
     39 import android.util.Log;
     40 import android.widget.Toast;
     41 
     42 import com.android.cts.verifier.R;
     43 
     44 import java.util.ArrayList;
     45 import java.util.Arrays;
     46 import java.util.HashMap;
     47 import java.util.LinkedHashMap;
     48 import java.util.List;
     49 import java.util.Set;
     50 import java.util.Timer;
     51 import java.util.UUID;
     52 
     53 public class BleServerService extends Service {
     54 
     55     public static final boolean DEBUG = true;
     56     public static final String TAG = "BleServerService";
     57 
     58     public static final int COMMAND_ADD_SERVICE = 0;
     59     public static final int COMMAND_WRITE_CHARACTERISTIC = 1;
     60     public static final int COMMAND_WRITE_DESCRIPTOR = 2;
     61 
     62     public static final String BLE_BLUETOOTH_MISMATCH_SECURE =
     63             "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_SECURE";
     64     public static final String BLE_BLUETOOTH_MISMATCH_INSECURE =
     65             "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_INSECURE";
     66     public static final String BLE_BLUETOOTH_DISABLED =
     67             "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISABLED";
     68     public static final String BLE_ACTION_SERVER_SECURE =
     69             "com.android.cts.verifier.bluetooth.BLE_ACTION_SERVER_SECURE";
     70     public static final String BLE_ACTION_SERVER_NON_SECURE =
     71             "com.android.cts.verifier.bluetooth.BLE_ACTION_SERVER_NON_SECURE";
     72 
     73 
     74     public static final String BLE_SERVER_CONNECTED =
     75             "com.android.cts.verifier.bluetooth.BLE_SERVER_CONNECTED";
     76     public static final String BLE_SERVER_DISCONNECTED =
     77             "com.android.cts.verifier.bluetooth.BLE_SERVER_DISCONNECTED";
     78     public static final String BLE_SERVICE_ADDED =
     79             "com.android.cts.verifier.bluetooth.BLE_SERVICE_ADDED";
     80     public static final String BLE_MTU_REQUEST_23BYTES =
     81             "com.android.cts.verifier.bluetooth.BLE_MTU_REQUEST_23BYTES";
     82     public static final String BLE_MTU_REQUEST_512BYTES =
     83             "com.android.cts.verifier.bluetooth.BLE_MTU_REQUEST_512BYTES";
     84     public static final String BLE_CHARACTERISTIC_READ_REQUEST =
     85             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST";
     86     public static final String BLE_CHARACTERISTIC_WRITE_REQUEST =
     87             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST";
     88     public static final String BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION =
     89             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION";
     90     public static final String BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION =
     91             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION";
     92     public static final String BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED =
     93             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED";
     94     public static final String BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED =
     95             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED";
     96     public static final String BLE_CHARACTERISTIC_NOTIFICATION_REQUEST =
     97             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_NOTIFICATION_REQUEST";
     98     public static final String BLE_CHARACTERISTIC_INDICATE_REQUEST =
     99             "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_INDICATE_REQUEST";
    100     public static final String BLE_DESCRIPTOR_READ_REQUEST =
    101             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST";
    102     public static final String BLE_DESCRIPTOR_WRITE_REQUEST =
    103             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST";
    104     public static final String BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION =
    105             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION";
    106     public static final String BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION =
    107             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION";
    108     public static final String BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED =
    109             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED";
    110     public static final String BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED =
    111             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED";
    112     public static final String BLE_EXECUTE_WRITE =
    113             "com.android.cts.verifier.bluetooth.BLE_EXECUTE_WRITE";
    114     public static final String BLE_OPEN_FAIL =
    115             "com.android.cts.verifier.bluetooth.BLE_OPEN_FAIL";
    116     public static final String BLE_RELIABLE_WRITE_BAD_RESP =
    117             "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_BAD_RESP";
    118     public static final String BLE_ADVERTISE_UNSUPPORTED =
    119             "com.android.cts.verifier.bluetooth.BLE_ADVERTISE_UNSUPPORTED";
    120     public static final String BLE_ADD_SERVICE_FAIL =
    121             "com.android.cts.verifier.bluetooth.BLE_ADD_SERVICE_FAIL";
    122 
    123     private static final UUID SERVICE_UUID =
    124             UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");
    125     private static final UUID CHARACTERISTIC_UUID =
    126             UUID.fromString("00009998-0000-1000-8000-00805f9b34fb");
    127     private static final UUID CHARACTERISTIC_RESULT_UUID =
    128             UUID.fromString("00009974-0000-1000-8000-00805f9b34fb");
    129     private static final UUID UPDATE_CHARACTERISTIC_UUID =
    130             UUID.fromString("00009997-0000-1000-8000-00805f9b34fb");
    131     private static final UUID DESCRIPTOR_UUID =
    132             UUID.fromString("00009996-0000-1000-8000-00805f9b34fb");
    133     public static final UUID ADV_SERVICE_UUID=
    134             UUID.fromString("00003333-0000-1000-8000-00805f9b34fb");
    135 
    136     private static final UUID SERVICE_UUID_ADDITIONAL =
    137             UUID.fromString("00009995-0000-1000-8000-00805f9b34fb");
    138     private static final UUID SERVICE_UUID_INCLUDED =
    139             UUID.fromString("00009994-0000-1000-8000-00805f9b34fb");
    140 
    141     // Variable for registration permission of Characteristic
    142     private static final UUID CHARACTERISTIC_NO_READ_UUID =
    143             UUID.fromString("00009984-0000-1000-8000-00805f9b34fb");
    144     private static final UUID CHARACTERISTIC_NO_WRITE_UUID =
    145             UUID.fromString("00009983-0000-1000-8000-00805f9b34fb");
    146     private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID =
    147             UUID.fromString("00009982-0000-1000-8000-00805f9b34fb");
    148     private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID =
    149             UUID.fromString("00009981-0000-1000-8000-00805f9b34fb");
    150 
    151     // Variable for registration permission of Descriptor
    152     private static final UUID DESCRIPTOR_NO_READ_UUID =
    153             UUID.fromString("00009973-0000-1000-8000-00805f9b34fb");
    154     private static final UUID DESCRIPTOR_NO_WRITE_UUID =
    155             UUID.fromString("00009972-0000-1000-8000-00805f9b34fb");
    156     private static final UUID DESCRIPTOR_NEED_ENCRYPTED_READ_UUID =
    157             UUID.fromString("00009969-0000-1000-8000-00805f9b34fb");
    158     private static final UUID DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID =
    159             UUID.fromString("00009968-0000-1000-8000-00805f9b34fb");
    160 
    161     //  Variable for registration upper limit confirmation of Characteristic
    162     private static final UUID UPDATE_CHARACTERISTIC_UUID_1 =
    163             UUID.fromString("00009989-0000-1000-8000-00805f9b34fb");
    164     private static final UUID UPDATE_CHARACTERISTIC_UUID_2 =
    165             UUID.fromString("00009988-0000-1000-8000-00805f9b34fb");
    166     private static final UUID UPDATE_CHARACTERISTIC_UUID_3 =
    167             UUID.fromString("00009987-0000-1000-8000-00805f9b34fb");
    168     private static final UUID UPDATE_CHARACTERISTIC_UUID_4 =
    169             UUID.fromString("00009986-0000-1000-8000-00805f9b34fb");
    170     private static final UUID UPDATE_CHARACTERISTIC_UUID_5 =
    171             UUID.fromString("00009985-0000-1000-8000-00805f9b34fb");
    172     private static final UUID UPDATE_CHARACTERISTIC_UUID_6 =
    173             UUID.fromString("00009979-0000-1000-8000-00805f9b34fb");
    174     private static final UUID UPDATE_CHARACTERISTIC_UUID_7 =
    175             UUID.fromString("00009978-0000-1000-8000-00805f9b34fb");
    176     private static final UUID UPDATE_CHARACTERISTIC_UUID_8 =
    177             UUID.fromString("00009977-0000-1000-8000-00805f9b34fb");
    178     private static final UUID UPDATE_CHARACTERISTIC_UUID_9 =
    179             UUID.fromString("00009976-0000-1000-8000-00805f9b34fb");
    180     private static final UUID UPDATE_CHARACTERISTIC_UUID_10 =
    181             UUID.fromString("00009975-0000-1000-8000-00805f9b34fb");
    182     private static final UUID UPDATE_CHARACTERISTIC_UUID_11 =
    183             UUID.fromString("00009959-0000-1000-8000-00805f9b34fb");
    184     private static final UUID UPDATE_CHARACTERISTIC_UUID_12 =
    185             UUID.fromString("00009958-0000-1000-8000-00805f9b34fb");
    186     private static final UUID UPDATE_CHARACTERISTIC_UUID_13 =
    187             UUID.fromString("00009957-0000-1000-8000-00805f9b34fb");
    188     private static final UUID UPDATE_CHARACTERISTIC_UUID_14 =
    189             UUID.fromString("00009956-0000-1000-8000-00805f9b34fb");
    190     private static final UUID UPDATE_CHARACTERISTIC_UUID_15 =
    191             UUID.fromString("00009955-0000-1000-8000-00805f9b34fb");
    192 
    193     private static final UUID UPDATE_DESCRIPTOR_UUID =
    194             UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    195 
    196     private static final UUID INDICATE_CHARACTERISTIC_UUID =
    197             UUID.fromString("00009971-0000-1000-8000-00805f9b34fb");
    198 
    199     private static final int CONN_INTERVAL = 150;   // connection interval 150ms
    200 
    201     // Delay of notification when secure test failed to start.
    202     private static final long NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE = 5 * 1000;
    203 
    204     public static final String WRITE_VALUE = "SERVER_TEST";
    205     private static final String NOTIFY_VALUE = "NOTIFY_TEST";
    206     private static final String INDICATE_VALUE = "INDICATE_TEST";
    207     public static final String READ_NO_PERMISSION = "READ_NO_CHAR";
    208     public static final String WRITE_NO_PERMISSION = "WRITE_NO_CHAR";
    209     public static final String DESCRIPTOR_READ_NO_PERMISSION = "READ_NO_DESC";
    210     public static final String DESCRIPTOR_WRITE_NO_PERMISSION = "WRITE_NO_DESC";
    211 
    212     private BluetoothManager mBluetoothManager;
    213     private BluetoothGattServer mGattServer;
    214     private BluetoothGattService mService;
    215     private BluetoothDevice mDevice;
    216     private Timer mNotificationTimer;
    217     private Handler mHandler;
    218     private String mReliableWriteValue;
    219     private BluetoothLeAdvertiser mAdvertiser;
    220     private boolean mIndicated;
    221     private int mNotifyCount;
    222     private boolean mSecure;
    223     private int mCountMtuChange;
    224     private int mMtuSize = -1;
    225     private String mMtuTestReceivedData;
    226     private Runnable mResetValuesTask;
    227     private BluetoothGattService mAdditionalNotificationService;
    228 
    229     // Task to notify failure of starting secure test.
    230     //   Secure test calls BluetoothDevice#createBond() when devices were not paired.
    231     //   createBond() causes onConnectionStateChange() twice, and it works as strange sequence.
    232     //   At the first onConnectionStateChange(), target device is not paired(bond state is
    233     //   BluetoothDevice.BOND_NONE).
    234     //   At the second onConnectionStateChange(), target devices is paired(bond state is
    235     //   BluetoothDevice.BOND_BONDED).
    236     //   CTS Verifier will perform lazy check of bond state.Verifier checks bond state
    237     //   after NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE from the first onConnectionStateChange().
    238     private Runnable mNotificationTaskOfSecureTestStartFailure;
    239 
    240     @Override
    241     public void onCreate() {
    242         super.onCreate();
    243 
    244         mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    245         mAdvertiser = mBluetoothManager.getAdapter().getBluetoothLeAdvertiser();
    246         mGattServer = mBluetoothManager.openGattServer(this, mCallbacks);
    247 
    248         mService = createService();
    249         mAdditionalNotificationService = createAdditionalNotificationService();
    250 
    251         mDevice = null;
    252         mReliableWriteValue = "";
    253 
    254         mHandler = new Handler();
    255         if (!mBluetoothManager.getAdapter().isEnabled()) {
    256             notifyBluetoothDisabled();
    257         } else if (mGattServer == null) {
    258             notifyOpenFail();
    259         } else if (mAdvertiser == null) {
    260             notifyAdvertiseUnsupported();
    261         } else {
    262             // start adding services
    263             mNotifyCount = 11;
    264             mSecure = false;
    265             mCountMtuChange = 0;
    266             if (!mGattServer.addService(mService)) {
    267                 notifyAddServiceFail();
    268             }
    269         }
    270     }
    271 
    272     private void notifyBluetoothDisabled() {
    273         Intent intent = new Intent(BLE_BLUETOOTH_DISABLED);
    274         sendBroadcast(intent);
    275     }
    276 
    277     private void notifyMismatchSecure() {
    278         Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_SECURE);
    279         sendBroadcast(intent);
    280     }
    281 
    282     private void notifyMismatchInsecure() {
    283         /*
    284         Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_INSECURE);
    285         sendBroadcast(intent);
    286         */
    287     }
    288 
    289     @Override
    290     public int onStartCommand(Intent intent, int flags, int startId) {
    291         String action = intent.getAction();
    292         if (action != null) {
    293             switch (action) {
    294             case BLE_ACTION_SERVER_SECURE:
    295                 mSecure = true;
    296                 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
    297                     showMessage("Skip MTU test.");
    298                     mCountMtuChange = 1;
    299                     notifyMtuRequest();
    300                     mCountMtuChange = 2;
    301                     notifyMtuRequest();
    302                     mCountMtuChange = 0;
    303                 }
    304                 break;
    305             case BLE_ACTION_SERVER_NON_SECURE:
    306                 mSecure = false;
    307                 break;
    308             }
    309         }
    310 
    311         if (mBluetoothManager.getAdapter().isEnabled() && (mAdvertiser != null)) {
    312             startAdvertise();
    313         }
    314         return START_NOT_STICKY;
    315     }
    316 
    317     @Override
    318     public IBinder onBind(Intent intent) {
    319         return null;
    320     }
    321 
    322     @Override
    323     public void onDestroy() {
    324         super.onDestroy();
    325         cancelNotificationTaskOfSecureTestStartFailure();
    326         stopAdvertise();
    327         if (mGattServer == null) {
    328            return;
    329         }
    330         if (mDevice != null) {
    331             mGattServer.cancelConnection(mDevice);
    332         }
    333         mGattServer.clearServices();
    334         mGattServer.close();
    335     }
    336 
    337     /**
    338      * Sets default value to characteristic and descriptor.
    339      *
    340      * Set operation will be done after connection interval.
    341      * (If set values immediately, multiple read/write operations may fail.)
    342      */
    343     private synchronized void resetValues() {
    344         // cancel pending task
    345         if (mResetValuesTask != null) {
    346             mHandler.removeCallbacks(mResetValuesTask);
    347             mResetValuesTask = null;
    348         }
    349 
    350         // reserve task
    351         mResetValuesTask = new Runnable() {
    352             @Override
    353             public void run() {
    354                 getCharacteristic(CHARACTERISTIC_UUID).setValue(WRITE_VALUE.getBytes());
    355                 getDescriptor().setValue(WRITE_VALUE.getBytes());
    356             }
    357         };
    358         mHandler.postDelayed(mResetValuesTask, CONN_INTERVAL);
    359     }
    360 
    361     private void notifyOpenFail() {
    362         if (DEBUG) {
    363             Log.d(TAG, "notifyOpenFail");
    364         }
    365         Intent intent = new Intent(BLE_OPEN_FAIL);
    366         sendBroadcast(intent);
    367     }
    368 
    369     private void notifyAddServiceFail() {
    370         if (DEBUG) {
    371             Log.d(TAG, "notifyAddServiceFail");
    372         }
    373         Intent intent = new Intent(BLE_ADD_SERVICE_FAIL);
    374         sendBroadcast(intent);
    375     }
    376 
    377     private void notifyAdvertiseUnsupported() {
    378         if (DEBUG) {
    379             Log.d(TAG, "notifyAdvertiseUnsupported");
    380         }
    381         Intent intent = new Intent(BLE_ADVERTISE_UNSUPPORTED);
    382         sendBroadcast(intent);
    383     }
    384 
    385     private void notifyConnected() {
    386         if (DEBUG) {
    387             Log.d(TAG, "notifyConnected");
    388         }
    389         Intent intent = new Intent(BLE_SERVER_CONNECTED);
    390         sendBroadcast(intent);
    391 
    392         resetValues();
    393     }
    394 
    395     private void notifyDisconnected() {
    396         if (DEBUG) {
    397             Log.d(TAG, "notifyDisconnected");
    398         }
    399         Intent intent = new Intent(BLE_SERVER_DISCONNECTED);
    400         sendBroadcast(intent);
    401     }
    402 
    403     private void notifyServiceAdded() {
    404         if (DEBUG) {
    405             Log.d(TAG, "notifyServiceAdded");
    406         }
    407         Intent intent = new Intent(BLE_SERVICE_ADDED);
    408         sendBroadcast(intent);
    409     }
    410 
    411     private void notifyMtuRequest() {
    412         if (DEBUG) {
    413             Log.d(TAG, "notifyMtuRequest");
    414         }
    415         Intent intent;
    416         if (mCountMtuChange == 1) {
    417             intent = new Intent(BLE_MTU_REQUEST_23BYTES);
    418         } else if (mCountMtuChange == 2) {
    419             intent = new Intent(BLE_MTU_REQUEST_512BYTES);
    420         } else {
    421             return; // never occurs
    422         }
    423         sendBroadcast(intent);
    424     }
    425 
    426     private void notifyCharacteristicReadRequest(boolean resetValues) {
    427         if (DEBUG) {
    428             Log.d(TAG, "notifyCharacteristicReadRequest");
    429         }
    430         Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST);
    431         sendBroadcast(intent);
    432 
    433         if (resetValues) {
    434             resetValues();
    435         }
    436     }
    437 
    438     private void notifyCharacteristicWriteRequest() {
    439         if (DEBUG) {
    440             Log.d(TAG, "notifyCharacteristicWriteRequest");
    441         }
    442         Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST);
    443         sendBroadcast(intent);
    444 
    445         resetValues();
    446     }
    447 
    448     private void notifyCharacteristicReadRequestWithoutPermission() {
    449         if (DEBUG) {
    450             Log.d(TAG, "notifyCharacteristicReadRequestWithoutPermission");
    451         }
    452         Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION);
    453         sendBroadcast(intent);
    454 
    455         resetValues();
    456     }
    457 
    458     private void notifyCharacteristicWriteRequestWithoutPermission() {
    459         if (DEBUG) {
    460             Log.d(TAG, "notifyCharacteristicWriteRequestWithoutPermission");
    461         }
    462         Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION);
    463         sendBroadcast(intent);
    464 
    465         resetValues();
    466     }
    467 
    468     private void notifyCharacteristicReadRequestNeedEncrypted() {
    469         if (DEBUG) {
    470             Log.d(TAG, "notifyCharacteristicReadRequestNeedEncrypted");
    471         }
    472         Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED);
    473         sendBroadcast(intent);
    474 
    475         resetValues();
    476     }
    477 
    478     private void notifyCharacteristicWriteRequestNeedEncrypted() {
    479         if (DEBUG) {
    480             Log.d(TAG, "notifyCharacteristicWriteRequestNeedEncrypted");
    481         }
    482         Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED);
    483         sendBroadcast(intent);
    484 
    485         resetValues();
    486     }
    487 
    488     private void notifyCharacteristicNotificationRequest() {
    489         if (DEBUG) {
    490             Log.d(TAG, "notifyCharacteristicNotificationRequest");
    491         }
    492         mNotifyCount = 11;
    493         Intent intent = new Intent(BLE_CHARACTERISTIC_NOTIFICATION_REQUEST);
    494         sendBroadcast(intent);
    495 
    496         resetValues();
    497     }
    498 
    499     private void notifyCharacteristicIndicationRequest() {
    500         if (DEBUG) {
    501             Log.d(TAG, "notifyCharacteristicIndicationRequest");
    502         }
    503         Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATE_REQUEST);
    504         sendBroadcast(intent);
    505 
    506         resetValues();
    507     }
    508 
    509     private void notifyDescriptorReadRequest() {
    510         if (DEBUG) {
    511             Log.d(TAG, "notifyDescriptorReadRequest");
    512         }
    513         Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST);
    514         sendBroadcast(intent);
    515 
    516         resetValues();
    517     }
    518 
    519     private void notifyDescriptorWriteRequest() {
    520         if (DEBUG) {
    521             Log.d(TAG, "notifyDescriptorWriteRequest");
    522         }
    523         Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST);
    524         sendBroadcast(intent);
    525 
    526         resetValues();
    527     }
    528 
    529     private void notifyDescriptorReadRequestWithoutPermission() {
    530         if (DEBUG) {
    531             Log.d(TAG, "notifyDescriptorReadRequestWithoutPermission");
    532         }
    533         Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION);
    534         sendBroadcast(intent);
    535 
    536         resetValues();
    537     }
    538 
    539     private void notifyDescriptorWriteRequestWithoutPermission() {
    540         if (DEBUG) {
    541             Log.d(TAG, "notifyDescriptorWriteRequestWithoutPermission");
    542         }
    543         Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION);
    544         sendBroadcast(intent);
    545 
    546         resetValues();
    547     }
    548 
    549     private void notifyDescriptorReadRequestNeedEncrypted() {
    550         if (DEBUG) {
    551             Log.d(TAG, "notifyDescriptorReadRequestNeedEncrypted");
    552         }
    553         Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED);
    554         sendBroadcast(intent);
    555 
    556         resetValues();
    557     }
    558 
    559     private void notifyDescriptorWriteRequestNeedEncrypted() {
    560         if (DEBUG) {
    561             Log.d(TAG, "notifyDescriptorWriteRequestNeedEncrypted");
    562         }
    563         Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED);
    564         sendBroadcast(intent);
    565 
    566         resetValues();
    567     }
    568 
    569     private void notifyExecuteWrite() {
    570         if (DEBUG) {
    571             Log.d(TAG, "notifyExecuteWrite");
    572         }
    573         Intent intent = new Intent(BLE_EXECUTE_WRITE);
    574         sendBroadcast(intent);
    575 
    576         resetValues();
    577     }
    578 
    579     private void notifyReliableWriteBadResp() {
    580         if (DEBUG) {
    581             Log.d(TAG, "notifyReliableWriteBadResp");
    582         }
    583         Intent intent = new Intent(BLE_RELIABLE_WRITE_BAD_RESP);
    584         sendBroadcast(intent);
    585 
    586         resetValues();
    587     }
    588 
    589     private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
    590         BluetoothGattCharacteristic characteristic = mService.getCharacteristic(uuid);
    591         if (characteristic == null) {
    592             showMessage("Characteristic not found");
    593         }
    594         return characteristic;
    595     }
    596 
    597     private BluetoothGattDescriptor getDescriptor() {
    598         BluetoothGattDescriptor descriptor = null;
    599 
    600         BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID);
    601         if (characteristic != null) {
    602             descriptor = characteristic.getDescriptor(DESCRIPTOR_UUID);
    603             if (descriptor == null) {
    604                 showMessage("Descriptor not found");
    605             }
    606         }
    607         return descriptor;
    608     }
    609 
    610     /**
    611      * Create service for notification test
    612      * @return
    613      */
    614     private BluetoothGattService createAdditionalNotificationService() {
    615         BluetoothGattService service =
    616                 new BluetoothGattService(SERVICE_UUID_ADDITIONAL, BluetoothGattService.SERVICE_TYPE_PRIMARY);
    617 
    618         BluetoothGattCharacteristic notiCharacteristic =
    619                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_1, 0x12, 0x1);
    620         BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    621         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    622         notiCharacteristic.addDescriptor(descriptor);
    623         notiCharacteristic.setValue(NOTIFY_VALUE);
    624         service.addCharacteristic(notiCharacteristic);
    625 
    626         notiCharacteristic =
    627                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_2, 0x14, 0x11);
    628         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    629         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    630         notiCharacteristic.addDescriptor(descriptor);
    631         notiCharacteristic.setValue(NOTIFY_VALUE);
    632         service.addCharacteristic(notiCharacteristic);
    633 
    634         notiCharacteristic =
    635                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_3, 0x16, 0x11);
    636         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    637         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    638         notiCharacteristic.addDescriptor(descriptor);
    639         notiCharacteristic.setValue(NOTIFY_VALUE);
    640         service.addCharacteristic(notiCharacteristic);
    641 
    642         notiCharacteristic =
    643                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_4, 0x18, 0x10);
    644         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    645         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    646         notiCharacteristic.addDescriptor(descriptor);
    647         notiCharacteristic.setValue(NOTIFY_VALUE);
    648         service.addCharacteristic(notiCharacteristic);
    649 
    650         notiCharacteristic =
    651                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_5, 0x1C, 0x11);
    652         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    653         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    654         notiCharacteristic.addDescriptor(descriptor);
    655         notiCharacteristic.setValue(NOTIFY_VALUE);
    656         service.addCharacteristic(notiCharacteristic);
    657 
    658         notiCharacteristic =
    659                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_11, 0x3A, 0x11);
    660         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    661         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    662         notiCharacteristic.addDescriptor(descriptor);
    663         notiCharacteristic.setValue(NOTIFY_VALUE);
    664         service.addCharacteristic(notiCharacteristic);
    665 
    666         notiCharacteristic =
    667                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_12, 0x3C, 0x11);
    668         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    669         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    670         notiCharacteristic.addDescriptor(descriptor);
    671         notiCharacteristic.setValue(NOTIFY_VALUE);
    672         service.addCharacteristic(notiCharacteristic);
    673 
    674         notiCharacteristic =
    675                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_13, 0x3E, 0x11);
    676         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    677         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    678         notiCharacteristic.addDescriptor(descriptor);
    679         notiCharacteristic.setValue(NOTIFY_VALUE);
    680         service.addCharacteristic(notiCharacteristic);
    681 
    682         notiCharacteristic =
    683                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_14, 0x10, 0x0);
    684         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    685         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    686         notiCharacteristic.addDescriptor(descriptor);
    687         notiCharacteristic.setValue(NOTIFY_VALUE);
    688         service.addCharacteristic(notiCharacteristic);
    689 
    690         notiCharacteristic =
    691                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_15, 0x30, 0x0);
    692         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    693         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    694         notiCharacteristic.addDescriptor(descriptor);
    695         notiCharacteristic.setValue(NOTIFY_VALUE);
    696         service.addCharacteristic(notiCharacteristic);
    697 
    698         return service;
    699     }
    700 
    701     private BluetoothGattService createService() {
    702         BluetoothGattService service =
    703                 new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
    704         BluetoothGattCharacteristic characteristic =
    705                 new BluetoothGattCharacteristic(CHARACTERISTIC_UUID, 0x0A, 0x11);
    706         characteristic.setValue(WRITE_VALUE.getBytes());
    707 
    708         BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(DESCRIPTOR_UUID, 0x11);
    709         descriptor.setValue(WRITE_VALUE.getBytes());
    710         characteristic.addDescriptor(descriptor);
    711 
    712         BluetoothGattDescriptor descriptor_permission = new BluetoothGattDescriptor(DESCRIPTOR_NO_READ_UUID, 0x10);
    713         characteristic.addDescriptor(descriptor_permission);
    714 
    715         descriptor_permission = new BluetoothGattDescriptor(DESCRIPTOR_NO_WRITE_UUID, 0x01);
    716         characteristic.addDescriptor(descriptor_permission);
    717 
    718         service.addCharacteristic(characteristic);
    719 
    720         characteristic =
    721                 new BluetoothGattCharacteristic(CHARACTERISTIC_RESULT_UUID, 0x0A, 0x11);
    722 
    723         BluetoothGattDescriptor descriptor_encrypted = new BluetoothGattDescriptor(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID, 0x02);
    724         characteristic.addDescriptor(descriptor_encrypted);
    725 
    726         descriptor_encrypted = new BluetoothGattDescriptor(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID, 0x20);
    727         characteristic.addDescriptor(descriptor_encrypted);
    728 
    729         service.addCharacteristic(characteristic);
    730 
    731         // Add new Characteristics
    732         // Registered the characteristic of read permission for operation confirmation.
    733         characteristic =
    734                 new BluetoothGattCharacteristic(CHARACTERISTIC_NO_READ_UUID, 0x0A, 0x10);
    735         service.addCharacteristic(characteristic);
    736 
    737         // Registered the characteristic of write permission for operation confirmation.
    738         characteristic =
    739                 new BluetoothGattCharacteristic(CHARACTERISTIC_NO_WRITE_UUID, 0x0A, 0x01);
    740         service.addCharacteristic(characteristic);
    741 
    742         // Registered the characteristic of authenticate (Encrypted) for operation confirmation.
    743         characteristic =
    744                 new BluetoothGattCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID, 0x0A, 0x02);
    745         service.addCharacteristic(characteristic);
    746 
    747         characteristic =
    748                 new BluetoothGattCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID, 0x0A, 0x20);
    749         service.addCharacteristic(characteristic);
    750 
    751         // Add new Characteristics(Indicate)
    752         BluetoothGattCharacteristic indicateCharacteristic =
    753                 new BluetoothGattCharacteristic(INDICATE_CHARACTERISTIC_UUID, 0x2A, 0x11);
    754         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    755         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    756         indicateCharacteristic.addDescriptor(descriptor);
    757         indicateCharacteristic.setValue(INDICATE_VALUE);
    758         service.addCharacteristic(indicateCharacteristic);
    759 
    760         // Add new Characteristics(Notify)
    761         BluetoothGattCharacteristic notiCharacteristic =
    762                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID, 0x1A, 0x11);
    763         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    764         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    765         notiCharacteristic.addDescriptor(descriptor);
    766         notiCharacteristic.setValue(NOTIFY_VALUE);
    767         service.addCharacteristic(notiCharacteristic);
    768 
    769         notiCharacteristic =
    770                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_6, 0x1E, 0x11);
    771         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    772         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    773         notiCharacteristic.addDescriptor(descriptor);
    774         notiCharacteristic.setValue(NOTIFY_VALUE);
    775         service.addCharacteristic(notiCharacteristic);
    776 
    777         notiCharacteristic =
    778                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_7, 0x32, 0x1);
    779         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    780         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    781         notiCharacteristic.addDescriptor(descriptor);
    782         notiCharacteristic.setValue(NOTIFY_VALUE);
    783         service.addCharacteristic(notiCharacteristic);
    784 
    785         notiCharacteristic =
    786                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_8, 0x34, 0x11);
    787         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    788         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    789         notiCharacteristic.addDescriptor(descriptor);
    790         notiCharacteristic.setValue(NOTIFY_VALUE);
    791         service.addCharacteristic(notiCharacteristic);
    792 
    793         notiCharacteristic =
    794                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_9, 0x36, 0x11);
    795         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    796         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    797         notiCharacteristic.addDescriptor(descriptor);
    798         notiCharacteristic.setValue(NOTIFY_VALUE);
    799         service.addCharacteristic(notiCharacteristic);
    800 
    801         notiCharacteristic =
    802                 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_10, 0x38, 0x10);
    803         descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11);
    804         descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
    805         notiCharacteristic.addDescriptor(descriptor);
    806         notiCharacteristic.setValue(NOTIFY_VALUE);
    807         service.addCharacteristic(notiCharacteristic);
    808 
    809         return service;
    810     }
    811 
    812     private void showMessage(final String msg) {
    813         mHandler.post(new Runnable() {
    814             public void run() {
    815                 Toast.makeText(BleServerService.this, msg, Toast.LENGTH_SHORT).show();
    816             }
    817         });
    818     }
    819 
    820     private void onMtuTestDataReceive() {
    821 
    822         Log.d(TAG, "onMtuTestDataReceive(" + mCountMtuChange + "):" + mMtuTestReceivedData);
    823 
    824         // verify
    825         if (mMtuTestReceivedData.equals(BleClientService.WRITE_VALUE_512BYTES_FOR_MTU)) {
    826 
    827             // write back data
    828             // MTU test verifies whether the write/read operations go well.
    829             BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID);
    830             characteristic.setValue(mMtuTestReceivedData.getBytes());
    831 
    832             notifyMtuRequest();
    833         } else {
    834             showMessage(getString(R.string.ble_mtu_fail_message));
    835         }
    836         mMtuTestReceivedData = "";
    837         if (mCountMtuChange >= 2) {
    838             // All MTU change tests completed
    839             mCountMtuChange = 0;
    840         }
    841     }
    842 
    843     private synchronized void cancelNotificationTaskOfSecureTestStartFailure() {
    844         if (mNotificationTaskOfSecureTestStartFailure != null) {
    845             mHandler.removeCallbacks(mNotificationTaskOfSecureTestStartFailure);
    846             mNotificationTaskOfSecureTestStartFailure = null;
    847         }
    848     }
    849 
    850     private final BluetoothGattServerCallback mCallbacks = new BluetoothGattServerCallback() {
    851         @Override
    852         public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
    853             if (DEBUG) {
    854                 Log.d(TAG, "onConnectionStateChange: newState=" + newState);
    855             }
    856 
    857             if (status == BluetoothGatt.GATT_SUCCESS) {
    858                 if (newState == BluetoothProfile.STATE_CONNECTED) {
    859                     mDevice = device;
    860                     boolean bonded = false;
    861                     Set<BluetoothDevice> pairedDevices = mBluetoothManager.getAdapter().getBondedDevices();
    862                     if (pairedDevices.size() > 0) {
    863                         for (BluetoothDevice target : pairedDevices) {
    864                             if (target.getAddress().equals(device.getAddress())) {
    865                                 bonded = true;
    866                                 break;
    867                             }
    868                         }
    869                     }
    870 
    871                     if (mSecure && ((device.getBondState() == BluetoothDevice.BOND_NONE) || !bonded)) {
    872                         // not pairing and execute Secure Test
    873                         cancelNotificationTaskOfSecureTestStartFailure();
    874                         /*
    875                         mNotificationTaskOfSecureTestStartFailure = new Runnable() {
    876                             @Override
    877                             public void run() {
    878                                 mNotificationTaskOfSecureTestStartFailure = null;
    879                                 if (mSecure && (mDevice.getBondState() != BluetoothDevice.BOND_BONDED)) {
    880                                     notifyMismatchSecure();
    881                                 }
    882                             }
    883                         };
    884                         mHandler.postDelayed(mNotificationTaskOfSecureTestStartFailure,
    885                                 NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE);
    886                         */
    887                     } else if (!mSecure && ((device.getBondState() != BluetoothDevice.BOND_NONE) || bonded)) {
    888                         // already pairing nad execute Insecure Test
    889                         /*
    890                         notifyMismatchInsecure();
    891                         */
    892                     } else {
    893                         cancelNotificationTaskOfSecureTestStartFailure();
    894                         notifyConnected();
    895                     }
    896                 } else if (status == BluetoothProfile.STATE_DISCONNECTED) {
    897                     notifyDisconnected();
    898                     mDevice = null;
    899                 }
    900             }
    901         }
    902 
    903         @Override
    904         public void onServiceAdded(int status, BluetoothGattService service) {
    905             if (DEBUG) {
    906                 Log.d(TAG, "onServiceAdded(): " + service.getUuid());
    907                 dumpService(service, 0);
    908             }
    909             if (status == BluetoothGatt.GATT_SUCCESS) {
    910                 UUID uuid = service.getUuid();
    911 
    912                 if (uuid.equals(mService.getUuid())) {
    913                     // create and add nested service
    914                     BluetoothGattService includedService =
    915                             new BluetoothGattService(SERVICE_UUID_INCLUDED, BluetoothGattService.SERVICE_TYPE_SECONDARY);
    916                     BluetoothGattCharacteristic characteristic =
    917                         new BluetoothGattCharacteristic(CHARACTERISTIC_UUID, 0x0A, 0x11);
    918                     characteristic.setValue(WRITE_VALUE.getBytes());
    919                     BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(DESCRIPTOR_UUID, 0x11);
    920                     descriptor.setValue(WRITE_VALUE.getBytes());
    921                     characteristic.addDescriptor(descriptor);
    922                     includedService.addCharacteristic(characteristic);
    923                     mGattServer.addService(includedService);
    924                 } else if (uuid.equals(SERVICE_UUID_INCLUDED)) {
    925                     mService.addService(service);
    926                     mGattServer.addService(mAdditionalNotificationService);
    927                 } else if (uuid.equals(mAdditionalNotificationService.getUuid())) {
    928                     // all services added
    929                     notifyServiceAdded();
    930                 } else {
    931                     notifyAddServiceFail();
    932                 }
    933             } else {
    934                 notifyAddServiceFail();
    935             }
    936         }
    937 
    938         @Override
    939         public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
    940             if (mGattServer == null) {
    941                 if (DEBUG) {
    942                     Log.d(TAG, "GattServer is null, return");
    943                 }
    944                 return;
    945             }
    946             if (DEBUG) {
    947                 Log.d(TAG, "onCharacteristicReadRequest()");
    948             }
    949 
    950             boolean finished = false;
    951             byte[] value = null;
    952             if (mMtuSize > 0) {
    953                 byte[] buf = characteristic.getValue();
    954                 if (buf != null) {
    955                     int len = Math.min((buf.length - offset), mMtuSize);
    956                     if (len > 0) {
    957                         value = Arrays.copyOfRange(buf, offset, (offset + len));
    958                     }
    959                     finished = ((offset + len) >= buf.length);
    960                     if (finished) {
    961                         Log.d(TAG, "sent whole data: " + (new String(characteristic.getValue())));
    962                     }
    963                 }
    964             } else {
    965                 value = characteristic.getValue();
    966                 finished = true;
    967             }
    968 
    969             mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
    970 
    971             UUID uid = characteristic.getUuid();
    972             if (uid.equals(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID)) {
    973                 notifyCharacteristicReadRequestNeedEncrypted();
    974             } else {
    975                 notifyCharacteristicReadRequest(finished);
    976             }
    977         }
    978 
    979         @Override
    980         public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
    981                 BluetoothGattCharacteristic characteristic,
    982                 boolean preparedWrite, boolean responseNeeded,
    983                 int offset, byte[] value) {
    984             if (mGattServer == null) {
    985                 if (DEBUG) {
    986                     Log.d(TAG, "GattServer is null, return");
    987                 }
    988                 return;
    989             }
    990             if (DEBUG) {
    991                 Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite + ", responseNeeded= " + responseNeeded);
    992             }
    993 
    994             if (characteristic.getUuid().equals(CHARACTERISTIC_RESULT_UUID)) {
    995                 String resValue = new String(value);
    996                 Log.d(TAG, "CHARACTERISTIC_RESULT_UUID: resValue=" + resValue);
    997                 switch (resValue) {
    998                     case WRITE_NO_PERMISSION:
    999                         notifyCharacteristicWriteRequestWithoutPermission();
   1000                         break;
   1001                     case READ_NO_PERMISSION:
   1002                         notifyCharacteristicReadRequestWithoutPermission();
   1003                         break;
   1004                     case DESCRIPTOR_WRITE_NO_PERMISSION:
   1005                         notifyDescriptorWriteRequestWithoutPermission();
   1006                         break;
   1007                     case DESCRIPTOR_READ_NO_PERMISSION:
   1008                         notifyDescriptorReadRequestWithoutPermission();
   1009                         break;
   1010                 }
   1011                 if (responseNeeded) {
   1012                     mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   1013                 }
   1014                 return;
   1015             }
   1016 
   1017             // MTU test flow
   1018             if (mCountMtuChange > 0) {
   1019                 if (preparedWrite) {
   1020                     mMtuTestReceivedData += new String(value);
   1021                 } else {
   1022                     String strValue = new String(value);
   1023                     if (mCountMtuChange > 0) {
   1024                         mMtuTestReceivedData = strValue;
   1025                         onMtuTestDataReceive();
   1026                     }
   1027                 }
   1028                 if (responseNeeded) {
   1029                     mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   1030                 }
   1031 
   1032                 return;
   1033             }
   1034 
   1035             // Reliable write with bad response test flow
   1036             String valueStr = new String(value);
   1037             if (BleClientService.WRITE_VALUE_BAD_RESP.equals(valueStr)) {
   1038                 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
   1039                 notifyReliableWriteBadResp();
   1040                 return;
   1041             }
   1042 
   1043             if (preparedWrite) {
   1044                 mReliableWriteValue += (new String(value));
   1045             } else {
   1046                 characteristic.setValue(value);
   1047                 // verify
   1048                 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), characteristic.getValue())) {
   1049                     UUID uid = characteristic.getUuid();
   1050                     if (uid.equals(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID)) {
   1051                         notifyCharacteristicWriteRequestNeedEncrypted();
   1052                     } else {
   1053                         notifyCharacteristicWriteRequest();
   1054                     }
   1055                 } else {
   1056                     showMessage("Written data is not correct");
   1057                 }
   1058             }
   1059 
   1060             if (responseNeeded) {
   1061                 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   1062             }
   1063         }
   1064 
   1065         @Override
   1066         public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
   1067                 int offset, BluetoothGattDescriptor descriptor) {
   1068             if (mGattServer == null) {
   1069                 if (DEBUG) {
   1070                     Log.d(TAG, "GattServer is null, return");
   1071                 }
   1072                 return;
   1073             }
   1074                 if (DEBUG) {
   1075                 Log.d(TAG, "onDescriptorReadRequest(): (descriptor == getDescriptor())="
   1076                         + (descriptor == getDescriptor()));
   1077             }
   1078 
   1079             UUID uid = descriptor.getUuid();
   1080             if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID)){
   1081                 notifyDescriptorReadRequestNeedEncrypted();
   1082             } else {
   1083                 notifyDescriptorReadRequest();
   1084             }
   1085 
   1086             byte[] value = descriptor.getValue();
   1087             if (value == null) {
   1088                 throw new RuntimeException("descriptor data read is null");
   1089             }
   1090 
   1091             mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   1092         }
   1093 
   1094         @Override
   1095         public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
   1096                 BluetoothGattDescriptor descriptor,
   1097                 boolean preparedWrite, boolean responseNeeded,
   1098                 int offset,  byte[] value) {
   1099             if (mGattServer == null) {
   1100                 if (DEBUG) {
   1101                     Log.d(TAG, "GattServer is null, return");
   1102                 }
   1103                 return;
   1104             }
   1105             BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
   1106             UUID uid = characteristic.getUuid();
   1107             if (DEBUG) {
   1108                 Log.d(TAG, "onDescriptorWriteRequest: preparedWrite=" + preparedWrite + ", responseNeeded= " + responseNeeded);
   1109                 Log.d(TAG, "   characteristic uuid = " + uid);
   1110             }
   1111 
   1112             descriptor.setValue(value);
   1113             UUID duid = descriptor.getUuid();
   1114             // If there is a written request to the CCCD for Notify.
   1115             if (duid.equals(UPDATE_DESCRIPTOR_UUID)) {
   1116                 if (Arrays.equals(value, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) {
   1117                     mGattServer.notifyCharacteristicChanged(mDevice, descriptor.getCharacteristic(), false);
   1118                     mIndicated = false;
   1119                 } else if (Arrays.equals(value, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) {
   1120                     mGattServer.notifyCharacteristicChanged(mDevice, descriptor.getCharacteristic(), true);
   1121                     mIndicated = true;
   1122                 }
   1123             } else if (duid.equals(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID)) {
   1124                 // verify
   1125                 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), descriptor.getValue())) {
   1126                     notifyDescriptorWriteRequestNeedEncrypted();
   1127                 } else {
   1128                     showMessage("Written data is not correct");
   1129                 }
   1130             } else {
   1131                 // verify
   1132                 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), descriptor.getValue())) {
   1133                     notifyDescriptorWriteRequest();
   1134                 } else {
   1135                     showMessage("Written data is not correct");
   1136                 }
   1137             }
   1138             if (responseNeeded) {
   1139                 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   1140             }
   1141         }
   1142 
   1143         @Override
   1144         public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
   1145             if (mGattServer == null) {
   1146                 if (DEBUG) {
   1147                     Log.d(TAG, "GattServer is null, return");
   1148                 }
   1149                 return;
   1150             }
   1151             if (DEBUG) {
   1152                 Log.d(TAG, "onExecuteWrite");
   1153             }
   1154 
   1155             if (execute) {
   1156                 if (mCountMtuChange > 0) {
   1157                     onMtuTestDataReceive();
   1158                 } else {
   1159                     // verify
   1160                     String str = BleClientService.WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE
   1161                             + BleClientService.WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE;
   1162                     if (str.equals(mReliableWriteValue)) {
   1163                         notifyExecuteWrite();
   1164                     } else {
   1165                         showMessage("Failed to receive data");
   1166                         Log.d(TAG, "Failed to receive data:" + mReliableWriteValue);
   1167                     }
   1168                 }
   1169                 mReliableWriteValue = "";
   1170             }
   1171             mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
   1172         }
   1173 
   1174         @Override
   1175         public void onNotificationSent(BluetoothDevice device, int status) {
   1176             if (mGattServer == null) {
   1177                 if (DEBUG) {
   1178                     Log.d(TAG, "GattServer is null, return");
   1179                 }
   1180                 return;
   1181             }
   1182             if (DEBUG) {
   1183                 Log.d(TAG, "onNotificationSent");
   1184             }
   1185 
   1186             if (status == BluetoothGatt.GATT_SUCCESS) {
   1187                 if (mIndicated) {
   1188                     notifyCharacteristicIndicationRequest();
   1189                 } else {
   1190                     mNotifyCount--;
   1191                     if (mNotifyCount == 0) {
   1192                         notifyCharacteristicNotificationRequest();
   1193                     }
   1194                 }
   1195             }
   1196         }
   1197 
   1198         @Override
   1199         public void onMtuChanged(BluetoothDevice device, int mtu) {
   1200             if (mGattServer == null) {
   1201                 if (DEBUG) {
   1202                     Log.d(TAG, "GattServer is null, return");
   1203                 }
   1204                 return;
   1205             }
   1206             if (DEBUG) {
   1207                 Log.d(TAG, "onMtuChanged");
   1208             }
   1209 
   1210             mMtuSize = mtu;
   1211             if (mCountMtuChange == 0) {
   1212                 if (mtu != 23) {
   1213                     String msg = String.format(getString(R.string.ble_mtu_mismatch_message),
   1214                             23, mtu);
   1215                     showMessage(msg);
   1216                 }
   1217             } else if (mCountMtuChange == 1) {
   1218                 if (mtu != 512) {
   1219                     String msg = String.format(getString(R.string.ble_mtu_mismatch_message),
   1220                             512, mtu);
   1221                     showMessage(msg);
   1222                 }
   1223             }
   1224             mMtuTestReceivedData = "";
   1225             ++mCountMtuChange;
   1226         }
   1227     };
   1228 
   1229     private void startAdvertise() {
   1230         if (DEBUG) {
   1231             Log.d(TAG, "startAdvertise");
   1232         }
   1233         AdvertiseData data = new AdvertiseData.Builder()
   1234             .addServiceData(new ParcelUuid(ADV_SERVICE_UUID), new byte[]{1,2,3})
   1235             .addServiceUuid(new ParcelUuid(ADV_SERVICE_UUID))
   1236             .build();
   1237         AdvertiseSettings setting = new AdvertiseSettings.Builder()
   1238             .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
   1239             .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
   1240             .setConnectable(true)
   1241             .build();
   1242         mAdvertiser.startAdvertising(setting, data, mAdvertiseCallback);
   1243     }
   1244 
   1245     private void stopAdvertise() {
   1246         if (DEBUG) {
   1247             Log.d(TAG, "stopAdvertise");
   1248         }
   1249         if (mAdvertiser != null) {
   1250             mAdvertiser.stopAdvertising(mAdvertiseCallback);
   1251         }
   1252     }
   1253 
   1254     private final AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback(){
   1255         @Override
   1256         public void onStartFailure(int errorCode) {
   1257             // Implementation for API Test.
   1258             super.onStartFailure(errorCode);
   1259             if (DEBUG) {
   1260                 Log.d(TAG, "onStartFailure");
   1261             }
   1262 
   1263             if (errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED) {
   1264                 notifyAdvertiseUnsupported();
   1265             } else {
   1266                 notifyOpenFail();
   1267             }
   1268         }
   1269 
   1270         @Override
   1271         public void onStartSuccess(AdvertiseSettings settingsInEffect) {
   1272             // Implementation for API Test.
   1273             super.onStartSuccess(settingsInEffect);
   1274             if (DEBUG) {
   1275                 Log.d(TAG, "onStartSuccess");
   1276             }
   1277         }
   1278     };
   1279 
   1280     /*protected*/ static void dumpService(BluetoothGattService service, int level) {
   1281         String indent = "";
   1282         for (int i = 0; i < level; ++i) {
   1283             indent += "  ";
   1284         }
   1285 
   1286         Log.d(TAG, indent + "[service]");
   1287         Log.d(TAG, indent + "UUID: " + service.getUuid());
   1288         Log.d(TAG, indent + "  [characteristics]");
   1289         for (BluetoothGattCharacteristic ch : service.getCharacteristics()) {
   1290             Log.d(TAG, indent + "    UUID: " + ch.getUuid());
   1291             Log.d(TAG, indent + "      properties: " + String.format("0x%02X", ch.getProperties()));
   1292             Log.d(TAG, indent + "      permissions: " + String.format("0x%02X", ch.getPermissions()));
   1293             Log.d(TAG, indent + "      [descriptors]");
   1294             for (BluetoothGattDescriptor d : ch.getDescriptors()) {
   1295                 Log.d(TAG, indent + "        UUID: " + d.getUuid());
   1296                 Log.d(TAG, indent + "          permissions: " + String.format("0x%02X", d.getPermissions()));
   1297             }
   1298         }
   1299 
   1300         if (service.getIncludedServices() != null) {
   1301             Log.d(TAG, indent + "  [included services]");
   1302             for (BluetoothGattService s : service.getIncludedServices()) {
   1303                 dumpService(s, level+1);
   1304             }
   1305         }
   1306     }
   1307 
   1308 }
   1309 
   1310