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