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