OSDN Git Service

Implement createBondOutOfBand
authorJakub Pawlowski <jpawlowski@google.com>
Tue, 29 Dec 2015 21:21:30 +0000 (13:21 -0800)
committerJakub Pawlowski <jpawlowski@google.com>
Thu, 4 Feb 2016 00:15:20 +0000 (16:15 -0800)
This patch implements out of band pairing that uses optional data.
Currently it works only for LE transport, using Temporary Key value.
In future fields might be added to OOBData to support other options for
optional data.

Change-Id: I1b4942e656be7b5d1ae5a4bf9d867ffd74753798

jni/com_android_bluetooth_btservice_AdapterService.cpp
src/com/android/bluetooth/btservice/AdapterService.java
src/com/android/bluetooth/btservice/BondStateMachine.java

index 80cb6f1..197adbb 100755 (executable)
@@ -31,6 +31,8 @@
 
 namespace android {
 
+#define OOB_TK_SIZE 16
+
 #define ADDITIONAL_NREFS 50
 static jmethodID method_stateChangeCallback;
 static jmethodID method_adapterPropertyChangedCallback;
@@ -772,6 +774,54 @@ static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, j
     return result;
 }
 
+static jbyteArray callByteArrayGetter(JNIEnv* env, jobject object, char* className, char* methodName) {
+    jclass myClass = env->FindClass(className);
+    jmethodID myMethod = env->GetMethodID(myClass, methodName, "()[B");
+    return (jbyteArray) env->CallObjectMethod(object, myMethod);
+}
+
+static jboolean createBondOutOfBandNative(JNIEnv* env, jobject obj, jbyteArray address,
+                jint transport, jobject oobData) {
+    jbyte *addr;
+    jboolean result = JNI_FALSE;
+    bt_out_of_band_data_t oob_data;
+
+    memset(&oob_data, 0, sizeof(oob_data));
+
+    if (!sBluetoothInterface) return result;
+
+    addr = env->GetByteArrayElements(address, NULL);
+    if (addr == NULL) {
+        jniThrowIOException(env, EINVAL);
+        return result;
+    }
+
+    jbyte* smTKBytes = NULL;
+    jbyteArray smTK = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getSecurityManagerTk");
+    if (smTK != NULL) {
+        smTKBytes = env->GetByteArrayElements(smTK, NULL);
+        int len = env->GetArrayLength(smTK);
+        if (len != OOB_TK_SIZE) {
+            ALOGI("%s: wrong length of smTK, should be empty or %d bytes.", __FUNCTION__, OOB_TK_SIZE);
+            jniThrowIOException(env, EINVAL);
+            goto done;
+        }
+        memcpy(oob_data.sm_tk, smTKBytes, len);
+    }
+
+    if (sBluetoothInterface->create_bond_out_of_band((bt_bdaddr_t *)addr, transport, &oob_data)
+        == BT_STATUS_SUCCESS)
+        result = JNI_TRUE;
+
+done:
+    env->ReleaseByteArrayElements(address, addr, 0);
+
+    if (smTK != NULL)
+        env->ReleaseByteArrayElements(smTK, smTKBytes, 0);
+
+    return result;
+}
+
 static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
     ALOGV("%s:",__FUNCTION__);
 
@@ -1166,6 +1216,7 @@ static JNINativeMethod sMethods[] = {
     {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
     {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
     {"createBondNative", "([BI)Z", (void*) createBondNative},
+    {"createBondOutOfBandNative", "([BILandroid/bluetooth/OobData;)Z", (void*) createBondOutOfBandNative},
     {"removeBondNative", "([B)Z", (void*) removeBondNative},
     {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
     {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
index 2cef503..afc11d3 100644 (file)
@@ -33,6 +33,7 @@ import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothManager;
 import android.bluetooth.IBluetoothManagerCallback;
 import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.OobData;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -963,7 +964,18 @@ public class AdapterService extends Service {
 
             AdapterService service = getService();
             if (service == null) return false;
-            return service.createBond(device, transport);
+            return service.createBond(device, transport, null);
+        }
+
+        public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) {
+            if (!Utils.checkCaller()) {
+                Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user");
+                return false;
+            }
+
+            AdapterService service = getService();
+            if (service == null) return false;
+            return service.createBond(device, transport, oobData);
         }
 
         public boolean cancelBondProcess(BluetoothDevice device) {
@@ -1460,8 +1472,7 @@ public class AdapterService extends Service {
          }
      }
 
-
-     boolean createBond(BluetoothDevice device, int transport) {
+     boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
             "Need BLUETOOTH ADMIN permission");
         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
@@ -1476,6 +1487,12 @@ public class AdapterService extends Service {
         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
         msg.obj = device;
         msg.arg1 = transport;
+
+        if (oobData != null) {
+            Bundle oobDataBundle = new Bundle();
+            oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
+            msg.setData(oobDataBundle);
+        }
         mBondStateMachine.sendMessage(msg);
         return true;
     }
@@ -2136,6 +2153,7 @@ public class AdapterService extends Service {
     /*package*/ native boolean getDevicePropertyNative(byte[] address, int type);
 
     /*package*/ native boolean createBondNative(byte[] address, int transport);
+    /*package*/ native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData);
     /*package*/ native boolean removeBondNative(byte[] address);
     /*package*/ native boolean cancelBondNative(byte[] address);
     /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid);
index 7bed94a..7a34ba9 100644 (file)
@@ -23,6 +23,8 @@ import android.bluetooth.BluetoothDevice;
 import com.android.bluetooth.a2dp.A2dpService;
 import com.android.bluetooth.hid.HidService;
 import com.android.bluetooth.hfp.HeadsetService;
+
+import android.bluetooth.OobData;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Message;
@@ -66,6 +68,8 @@ final class BondStateMachine extends StateMachine {
     private PendingCommandState mPendingCommandState = new PendingCommandState();
     private StableState mStableState = new StableState();
 
+    public static final String OOBDATA = "oobdata";
+
     private BondStateMachine(AdapterService service,
             AdapterProperties prop, RemoteDevices remoteDevices) {
         super("BondStateMachine:");
@@ -110,7 +114,11 @@ final class BondStateMachine extends StateMachine {
             switch(msg.what) {
 
               case CREATE_BOND:
-                  createBond(dev, msg.arg1, true);
+                  OobData oobData = null;
+                  if (msg.getData() != null)
+                      oobData = msg.getData().getParcelable(OOBDATA);
+
+                  createBond(dev, msg.arg1, oobData, true);
                   break;
               case REMOVE_BOND:
                   removeBond(dev, true);
@@ -171,7 +179,11 @@ final class BondStateMachine extends StateMachine {
 
             switch (msg.what) {
                 case CREATE_BOND:
-                    result = createBond(dev, msg.arg1, false);
+                    OobData oobData = null;
+                    if (msg.getData() != null)
+                        oobData = msg.getData().getParcelable(OOBDATA);
+
+                    result = createBond(dev, msg.arg1, oobData, false);
                     break;
                 case REMOVE_BOND:
                     result = removeBond(dev, false);
@@ -288,11 +300,19 @@ final class BondStateMachine extends StateMachine {
         return false;
     }
 
-    private boolean createBond(BluetoothDevice dev, int transport, boolean transition) {
+    private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
+                               boolean transition) {
         if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
             infoLog("Bond address is:" + dev);
             byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
-            if (!mAdapterService.createBondNative(addr, transport)) {
+            boolean result;
+            if (oobData != null) {
+                result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
+            } else {
+                result = mAdapterService.createBondNative(addr, transport);
+            }
+
+            if (!result) {
                 sendIntent(dev, BluetoothDevice.BOND_NONE,
                            BluetoothDevice.UNBOND_REASON_REMOVED);
                 return false;