added to call unregisterReceiver for Android BT/BLE.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / samples / android / casample / cAInterface / src / main / java / org / iotivity / ca / CaLeClientInterface.java
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 package org.iotivity.ca;
22
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.UUID;
28
29 import android.bluetooth.BluetoothAdapter;
30 import android.bluetooth.BluetoothDevice;
31 import android.bluetooth.BluetoothGatt;
32 import android.bluetooth.BluetoothGattCallback;
33 import android.bluetooth.BluetoothGattCharacteristic;
34 import android.bluetooth.BluetoothGattDescriptor;
35 import android.content.BroadcastReceiver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.util.Log;
40
41 public class CaLeClientInterface {
42
43     private static String SERVICE_UUID = "ADE3D529-C784-4F63-A987-EB69F70EE816";
44     private static String TAG          = "Sample_Service : CaLeClientInterface";
45     private static Context mContext;
46
47     private CaLeClientInterface(Context context) {
48         caLeRegisterLeScanCallback(mLeScanCallback);
49         caLeRegisterGattCallback(mGattCallback);
50         mContext = context;
51         registerIntentFilter();
52     }
53
54     public static void getLeScanCallback() {
55         caLeRegisterLeScanCallback(mLeScanCallback);
56     }
57
58     public static void getLeGattCallback() {
59         caLeRegisterGattCallback(mGattCallback);
60     }
61
62     private static IntentFilter registerIntentFilter() {
63         IntentFilter filter = new IntentFilter();
64         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
65         filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
66         mContext.registerReceiver(mReceiver, filter);
67         return filter;
68     }
69
70     public static void destroyLeInterface() {
71         mContext.unregisterReceiver(mReceiver);
72     }
73
74     private native static void caLeRegisterLeScanCallback(BluetoothAdapter.LeScanCallback callback);
75
76     private native static void caLeRegisterGattCallback(BluetoothGattCallback callback);
77
78     // BluetoothAdapter.LeScanCallback
79     private native static void caLeScanCallback(BluetoothDevice device);
80
81     // BluetoothGattCallback
82     private native static void caLeGattConnectionStateChangeCallback(
83             BluetoothGatt gatt, int status, int newState);
84
85     private native static void caLeGattServicesDiscoveredCallback(BluetoothGatt gatt, int status);
86
87     private native static void caLeGattCharacteristicWriteCallback(
88             BluetoothGatt gatt, byte[] data, int status);
89
90     private native static void caLeGattCharacteristicChangedCallback(
91             BluetoothGatt gatt, byte[] data);
92
93     private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt, int status);
94
95     private native static void caLeGattReliableWriteCompletedCallback(BluetoothGatt gatt,
96                                                                      int status);
97
98     private native static void caLeGattReadRemoteRssiCallback(BluetoothGatt gatt, int rssi,
99                                                              int status);
100
101     // Network Monitor
102     private native static void caLeStateChangedCallback(int state);
103
104     // bond state
105     private native static void caLeBondStateChangedCallback(String address);
106
107     // Callback
108     private static BluetoothAdapter.LeScanCallback mLeScanCallback =
109                    new BluetoothAdapter.LeScanCallback() {
110
111         @Override
112         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
113
114             try {
115                 List<UUID> uuids = getUuids(scanRecord);
116                 for (UUID uuid : uuids) {
117                     Log.d(TAG, "UUID : " + uuid.toString());
118                     if(uuid.toString().contains(SERVICE_UUID.toLowerCase())) {
119                         Log.d(TAG, "we found that has the Device");
120                         caLeScanCallback(device);
121                     }
122                 }
123             } catch(UnsatisfiedLinkError e) {
124
125             }
126         }
127     };
128
129     private static List<UUID> getUuids(final byte[] scanRecord) {
130         List<UUID> uuids = new ArrayList<UUID>();
131
132         int offset = 0;
133         while (offset < (scanRecord.length - 2)) {
134             int len = scanRecord[offset++];
135             if (len == 0)
136                 break;
137
138             int type = scanRecord[offset++];
139
140             switch (type) {
141             case 0x02:
142             case 0x03:
143                 while (len > 1) {
144                     int uuid16 = scanRecord[offset++];
145                     uuid16 += (scanRecord[offset++] << 8);
146                     len -= 2;
147                     uuids.add(UUID.fromString(String.format(
148                             "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
149                 }
150                 break;
151             case 0x06:
152             case 0x07:
153                 while (len >= 16) {
154                     try {
155                         ByteBuffer buffer = ByteBuffer.wrap(scanRecord, offset++, 16).
156                                                             order(ByteOrder.LITTLE_ENDIAN);
157                         long mostSigBits = buffer.getLong();
158                         long leastSigBits = buffer.getLong();
159                         uuids.add(new UUID(leastSigBits, mostSigBits));
160                     } catch (IndexOutOfBoundsException e) {
161                         Log.e(TAG, e.toString());
162                         continue;
163                     } finally {
164                         offset += 15;
165                         len -= 16;
166                     }
167                 }
168                 break;
169             default:
170                 offset += (len - 1);
171                 break;
172             }
173         }
174         return uuids;
175     }
176
177     private static final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
178
179         @Override
180         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
181             super.onConnectionStateChange(gatt, status, newState);
182
183             caLeGattConnectionStateChangeCallback(gatt, status, newState);
184         }
185
186         @Override
187         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
188             super.onServicesDiscovered(gatt, status);
189
190             caLeGattServicesDiscoveredCallback(gatt, status);
191         }
192
193         @Override
194         public void onCharacteristicRead(BluetoothGatt gatt,
195                 BluetoothGattCharacteristic characteristic, int status) {
196             super.onCharacteristicRead(gatt, characteristic, status);
197         }
198
199         @Override
200         public void onCharacteristicWrite(BluetoothGatt gatt,
201                 BluetoothGattCharacteristic characteristic, int status) {
202             super.onCharacteristicWrite(gatt, characteristic, status);
203
204             caLeGattCharacteristicWriteCallback(gatt, characteristic.getValue(), status);
205         }
206
207         @Override
208         public void onCharacteristicChanged(BluetoothGatt gatt,
209                 BluetoothGattCharacteristic characteristic) {
210             super.onCharacteristicChanged(gatt, characteristic);
211
212             caLeGattCharacteristicChangedCallback(gatt, characteristic.getValue());
213         }
214
215         @Override
216         public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
217                 int status) {
218             super.onDescriptorRead(gatt, descriptor, status);
219         }
220
221         @Override
222         public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
223                 int status) {
224             super.onDescriptorWrite(gatt, descriptor, status);
225
226             caLeGattDescriptorWriteCallback(gatt, status);
227         }
228
229         @Override
230         public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
231             super.onReliableWriteCompleted(gatt, status);
232         }
233
234         @Override
235         public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
236             super.onReadRemoteRssi(gatt, rssi, status);
237         }
238     };
239
240     private static final BroadcastReceiver mReceiver = new BroadcastReceiver() {
241
242         @Override
243         public void onReceive(Context context, Intent intent) {
244
245             String action = intent.getAction();
246
247             if (action != null && action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
248
249                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
250                                                BluetoothAdapter.ERROR);
251
252                 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_OFF)
253                 {
254                     caLeStateChangedCallback(state);
255                 }
256             }
257
258             if (action != null && action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
259
260                 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
261                                                    BluetoothDevice.ERROR);
262
263                 if (bondState == BluetoothDevice.BOND_NONE) {
264                     if ((intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
265                             BluetoothDevice.ERROR) == BluetoothDevice.BOND_BONDED)) {
266                             BluetoothDevice device = intent
267                                 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
268
269                         caLeBondStateChangedCallback(device.getAddress());
270                     }
271                 }
272             }
273         }
274     };
275 }
276