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