Merge branch 'master' into easysetup
[platform/upstream/iotivity.git] / android / android_api / base / 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 = "713d0000-503e-4c75-ba94-3148f18d941e";
44
45     private CaLeClientInterface(Context context) {
46
47         caLeRegisterLeScanCallback(mLeScanCallback);
48         caLeRegisterGattCallback(mGattCallback);
49
50         registerIntentFilter(context);
51     }
52
53     public static void getLeScanCallback() {
54         caLeRegisterLeScanCallback(mLeScanCallback);
55     }
56
57     public static void getLeGattCallback() {
58         caLeRegisterGattCallback(mGattCallback);
59     }
60
61     private static IntentFilter registerIntentFilter(Context context) {
62         IntentFilter filter = new IntentFilter();
63         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
64         filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
65         context.registerReceiver(mReceiver, filter);
66         return filter;
67     }
68
69     private native static void caLeRegisterLeScanCallback(BluetoothAdapter.LeScanCallback callback);
70
71     private native static void caLeRegisterGattCallback(BluetoothGattCallback callback);
72
73     // BluetoothAdapter.LeScanCallback
74     private native static void caLeScanCallback(BluetoothDevice device,
75                                                 int rssi, byte[] scanRecord);
76
77     // BluetoothGattCallback
78     private native static void caLeGattConnectionStateChangeCallback(
79             BluetoothGatt gatt, int status, int newState);
80
81     private native static void caLeGattServicesDiscoveredCallback(BluetoothGatt gatt, int status);
82
83     private native static void caLeGattCharacteristicReadCallback(
84             BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
85             byte[] data, int status);
86
87     private native static void caLeGattCharacteristicWriteCallback(
88             BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
89             byte[] data, int status);
90
91     private native static void caLeGattCharacteristicChangedCallback(
92             BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] data);
93
94     private native static void caLeGattDescriptorReadCallback(BluetoothGatt gatt,
95                                                              BluetoothGattDescriptor descriptor,
96                                                              int status);
97
98     private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt,
99                                                               BluetoothGattDescriptor descriptor,
100                                                               int status);
101
102     private native static void caLeGattReliableWriteCompletedCallback(BluetoothGatt gatt,
103                                                                      int status);
104
105     private native static void caLeGattReadRemoteRssiCallback(BluetoothGatt gatt, int rssi,
106                                                              int status);
107
108     // Network Monitor
109     private native static void caLeStateChangedCallback(int state);
110
111     // bond state
112     private native static void caLeBondStateChangedCallback(String address);
113
114     // Callback
115     private static BluetoothAdapter.LeScanCallback mLeScanCallback =
116                    new BluetoothAdapter.LeScanCallback() {
117
118         @Override
119         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
120
121             try {
122                 List<UUID> uuids = getUuids(scanRecord);
123                 for (UUID uuid : uuids) {
124                     Log.d("CA", "UUID : " + uuid.toString());
125                     if(uuid.toString().contains(SERVICE_UUID)) {
126                         Log.d("CA", "we found that has the Device");
127                         caLeScanCallback(device, rssi, scanRecord);
128                     }
129                 }
130             } catch(UnsatisfiedLinkError e) {
131
132             }
133         }
134     };
135
136     private static List<UUID> getUuids(final byte[] scanRecord) {
137         List<UUID> uuids = new ArrayList<UUID>();
138
139         int offset = 0;
140         while (offset < (scanRecord.length - 2)) {
141             int len = scanRecord[offset++];
142             if (len == 0)
143                 break;
144
145             int type = scanRecord[offset++];
146
147             switch (type) {
148             case 0x02:
149             case 0x03:
150                 while (len > 1) {
151                     int uuid16 = scanRecord[offset++];
152                     uuid16 += (scanRecord[offset++] << 8);
153                     len -= 2;
154                     uuids.add(UUID.fromString(String.format(
155                             "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
156                 }
157                 break;
158             case 0x06:
159             case 0x07:
160                 while (len >= 16) {
161                     try {
162                         ByteBuffer buffer = ByteBuffer.wrap(scanRecord, offset++, 16).
163                                                             order(ByteOrder.LITTLE_ENDIAN);
164                         long mostSigBits = buffer.getLong();
165                         long leastSigBits = buffer.getLong();
166                         uuids.add(new UUID(leastSigBits, mostSigBits));
167                     } catch (IndexOutOfBoundsException e) {
168                         Log.e("CA", e.toString());
169                         continue;
170                     } finally {
171                         offset += 15;
172                         len -= 16;
173                     }
174                 }
175                 break;
176             default:
177                 offset += (len - 1);
178                 break;
179             }
180         }
181         return uuids;
182     }
183
184     private static final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
185
186         @Override
187         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
188             super.onConnectionStateChange(gatt, status, newState);
189
190             caLeGattConnectionStateChangeCallback(gatt, status, newState);
191         }
192
193         @Override
194         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
195             super.onServicesDiscovered(gatt, status);
196
197             caLeGattServicesDiscoveredCallback(gatt, status);
198         }
199
200         @Override
201         public void onCharacteristicRead(BluetoothGatt gatt,
202                 BluetoothGattCharacteristic characteristic, int status) {
203             super.onCharacteristicRead(gatt, characteristic, status);
204
205             caLeGattCharacteristicReadCallback(gatt, characteristic,
206                                                characteristic.getValue(), status);
207         }
208
209         @Override
210         public void onCharacteristicWrite(BluetoothGatt gatt,
211                 BluetoothGattCharacteristic characteristic, int status) {
212             super.onCharacteristicWrite(gatt, characteristic, status);
213
214             caLeGattCharacteristicWriteCallback(gatt, characteristic,
215                                                 characteristic.getValue(), status);
216         }
217
218         @Override
219         public void onCharacteristicChanged(BluetoothGatt gatt,
220                 BluetoothGattCharacteristic characteristic) {
221             super.onCharacteristicChanged(gatt, characteristic);
222
223             caLeGattCharacteristicChangedCallback(gatt, characteristic,
224                                                   characteristic.getValue());
225         }
226
227         @Override
228         public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
229                 int status) {
230             super.onDescriptorRead(gatt, descriptor, status);
231
232             caLeGattDescriptorReadCallback(gatt, descriptor, status);
233         }
234
235         @Override
236         public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
237                 int status) {
238             super.onDescriptorWrite(gatt, descriptor, status);
239
240             caLeGattDescriptorWriteCallback(gatt, descriptor, status);
241         }
242
243         @Override
244         public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
245             super.onReliableWriteCompleted(gatt, status);
246
247             caLeGattReliableWriteCompletedCallback(gatt, status);
248         }
249
250         @Override
251         public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
252             super.onReadRemoteRssi(gatt, rssi, status);
253
254             caLeGattReadRemoteRssiCallback(gatt, rssi, status);
255         }
256     };
257
258     private static final BroadcastReceiver mReceiver = new BroadcastReceiver() {
259
260         @Override
261         public void onReceive(Context context, Intent intent) {
262
263             String action = intent.getAction();
264
265             if (action != null && action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
266
267                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
268                                                BluetoothAdapter.ERROR);
269
270                 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_OFF)
271                 {
272                     caLeStateChangedCallback(state);
273                 }
274             }
275
276             if (action != null && action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
277
278                 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
279                                                    BluetoothDevice.ERROR);
280
281                 if (bondState == BluetoothDevice.BOND_NONE) {
282                     if ((intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
283                             BluetoothDevice.ERROR) == BluetoothDevice.BOND_BONDED)) {
284                             BluetoothDevice device = intent
285                                 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
286
287                         caLeBondStateChangedCallback(device.getAddress());
288                     }
289                 }
290             }
291         }
292     };
293 }
294