Merge "Move BluetoothSocketManager to java"
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 775fb37..c6bbc0c 100644
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -22,7 +22,6 @@
#include "utils/Log.h"
#include "utils/misc.h"
-#include <android_util_Binder.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <cutils/properties.h>
@@ -40,7 +39,7 @@
#include <pthread.h>
-using android::bluetooth::BluetoothSocketManagerBinderServer;
+using bluetooth::Uuid;
namespace android {
// OOB_LE_BD_ADDR_SIZE is 6 bytes addres + 1 byte address type
@@ -49,6 +48,8 @@
#define OOB_LE_SC_C_SIZE 16
#define OOB_LE_SC_R_SIZE 16
+const jint INVALID_FD = -1;
+
static jmethodID method_stateChangeCallback;
static jmethodID method_adapterPropertyChangedCallback;
static jmethodID method_devicePropertyChangedCallback;
@@ -79,11 +80,6 @@
static jobject sJniCallbacksObj;
static jfieldID sJniCallbacksField;
-namespace {
-android::sp<BluetoothSocketManagerBinderServer> sSocketManager = NULL;
-std::mutex sSocketManagerMutex;
-}
-
const bt_interface_t* getBluetoothInterface() { return sBluetoothInterface; }
JNIEnv* getCallbackEnv() { return callbackEnv; }
@@ -758,10 +754,6 @@
env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
android_bluetooth_UidTraffic.clazz = NULL;
}
- {
- std::lock_guard<std::mutex> lock(sSocketManagerMutex);
- sSocketManager = nullptr;
- }
return JNI_TRUE;
}
@@ -1135,15 +1127,6 @@
return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
-static jobject getSocketManagerNative(JNIEnv* env) {
- std::lock_guard<std::mutex> lock(sSocketManagerMutex);
- if (!sSocketManager.get()) {
- sSocketManager =
- new BluetoothSocketManagerBinderServer(sBluetoothSocketInterface);
- }
- return javaObjectForIBinder(env, IInterface::asBinder(sSocketManager));
-}
-
static void setSystemUiUidNative(JNIEnv* env, jobject obj, jint uid) {
android::bluetooth::systemUiUid = uid;
}
@@ -1249,6 +1232,85 @@
return output_bytes;
}
+static jint connectSocketNative(JNIEnv* env, jobject obj, jbyteArray address,
+ jint type, jbyteArray uuid, jint port,
+ jint flag, jint callingUid) {
+ int socket_fd = INVALID_FD;
+ jbyte* addr = nullptr;
+ jbyte* uuidBytes = nullptr;
+ Uuid btUuid;
+
+ if (!sBluetoothSocketInterface) {
+ goto done;
+ }
+ addr = env->GetByteArrayElements(address, nullptr);
+ uuidBytes = env->GetByteArrayElements(uuid, nullptr);
+ if (addr == nullptr || uuidBytes == nullptr) {
+ jniThrowIOException(env, EINVAL);
+ goto done;
+ }
+
+ btUuid = Uuid::From128BitBE((uint8_t*)uuidBytes);
+ if (sBluetoothSocketInterface->connect((RawAddress*)addr, (btsock_type_t)type,
+ &btUuid, port, &socket_fd, flag,
+ callingUid) != BT_STATUS_SUCCESS) {
+ socket_fd = INVALID_FD;
+ }
+
+done:
+ if (addr) env->ReleaseByteArrayElements(address, addr, 0);
+ if (uuidBytes) env->ReleaseByteArrayElements(uuid, uuidBytes, 0);
+ return socket_fd;
+}
+
+static jint createSocketChannelNative(JNIEnv* env, jobject obj, jint type,
+ jstring serviceName, jbyteArray uuid,
+ jint port, jint flag, jint callingUid) {
+ int socket_fd = INVALID_FD;
+ jbyte* uuidBytes = nullptr;
+ Uuid btUuid;
+ const char* nativeServiceName = nullptr;
+
+ if (!sBluetoothSocketInterface) {
+ goto done;
+ }
+ uuidBytes = env->GetByteArrayElements(uuid, nullptr);
+ nativeServiceName = env->GetStringUTFChars(serviceName, nullptr);
+ if (uuidBytes == nullptr) {
+ jniThrowIOException(env, EINVAL);
+ goto done;
+ }
+ btUuid = Uuid::From128BitBE((uint8_t*)uuidBytes);
+
+ if (sBluetoothSocketInterface->listen((btsock_type_t)type, nativeServiceName,
+ &btUuid, port, &socket_fd, flag,
+ callingUid) != BT_STATUS_SUCCESS) {
+ socket_fd = INVALID_FD;
+ }
+
+done:
+ if (uuidBytes) env->ReleaseByteArrayElements(uuid, uuidBytes, 0);
+ if (nativeServiceName)
+ env->ReleaseStringUTFChars(serviceName, nativeServiceName);
+ return socket_fd;
+}
+
+static void requestMaximumTxDataLengthNative(JNIEnv* env, jobject obj,
+ jbyteArray address) {
+ if (!sBluetoothSocketInterface) {
+ return;
+ }
+ jbyte* addr = env->GetByteArrayElements(address, nullptr);
+ if (addr == nullptr) {
+ jniThrowIOException(env, EINVAL);
+ return;
+ }
+
+ RawAddress addressVar = *(RawAddress*)addr;
+ sBluetoothSocketInterface->request_max_tx_data_length(addressVar);
+ env->ReleaseByteArrayElements(address, addr, 1);
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void*)classInitNative},
@@ -1272,8 +1334,6 @@
{"pinReplyNative", "([BZI[B)Z", (void*)pinReplyNative},
{"sspReplyNative", "([BIZI)Z", (void*)sspReplyNative},
{"getRemoteServicesNative", "([B)Z", (void*)getRemoteServicesNative},
- {"getSocketManagerNative", "()Landroid/os/IBinder;",
- (void*)getSocketManagerNative},
{"setSystemUiUidNative", "(I)V", (void*)setSystemUiUidNative},
{"setForegroundUserIdNative", "(I)V", (void*)setForegroundUserIdNative},
{"alarmFiredNative", "()V", (void*)alarmFiredNative},
@@ -1284,7 +1344,12 @@
{"factoryResetNative", "()Z", (void*)factoryResetNative},
{"interopDatabaseClearNative", "()V", (void*)interopDatabaseClearNative},
{"interopDatabaseAddNative", "(I[BI)V", (void*)interopDatabaseAddNative},
- {"obfuscateAddressNative", "([B)[B", (void*)obfuscateAddressNative}};
+ {"obfuscateAddressNative", "([B)[B", (void*)obfuscateAddressNative},
+ {"connectSocketNative", "([BI[BIII)I", (void*)connectSocketNative},
+ {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
+ (void*)createSocketChannelNative},
+ {"requestMaximumTxDataLengthNative", "([B)V",
+ (void*)requestMaximumTxDataLengthNative}};
int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {
return jniRegisterNativeMethods(
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 508eacf..d68b5f1 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -198,6 +198,8 @@
private SilenceDeviceManager mSilenceDeviceManager;
private AppOpsManager mAppOps;
+ private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;
+
/**
* Register a {@link ProfileService} with AdapterService.
*
@@ -432,6 +434,8 @@
Looper.getMainLooper());
mSilenceDeviceManager.start();
+ mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this);
+
setAdapterService(this);
// First call to getSharedPreferences will result in a file read into
@@ -737,6 +741,11 @@
mProfileServicesState.clear();
}
+ if (mBluetoothSocketManagerBinder != null) {
+ mBluetoothSocketManagerBinder.cleanUp();
+ mBluetoothSocketManagerBinder = null;
+ }
+
if (mBinder != null) {
mBinder.cleanup();
mBinder = null; //Do not remove. Otherwise Binder leak!
@@ -2378,12 +2387,7 @@
}
IBluetoothSocketManager getSocketManager() {
- android.os.IBinder obj = getSocketManagerNative();
- if (obj == null) {
- return null;
- }
-
- return IBluetoothSocketManager.Stub.asInterface(obj);
+ return IBluetoothSocketManager.Stub.asInterface(mBluetoothSocketManagerBinder);
}
boolean factoryReset() {
@@ -2939,8 +2943,6 @@
private native int readEnergyInfo();
- private native IBinder getSocketManagerNative();
-
private native void setSystemUiUidNative(int systemUiUid);
private static native void setForegroundUserIdNative(int foregroundUserId);
@@ -2960,6 +2962,14 @@
private native byte[] obfuscateAddressNative(byte[] address);
+ /*package*/ native int connectSocketNative(
+ byte[] address, int type, byte[] uuid, int port, int flag, int callingUid);
+
+ /*package*/ native int createSocketChannelNative(
+ int type, String serviceName, byte[] uuid, int port, int flag, int callingUid);
+
+ /*package*/ native void requestMaximumTxDataLengthNative(byte[] address);
+
// Returns if this is a mock object. This is currently used in testing so that we may not call
// System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
// calling finalize() which in turn calls System.exit() and the process crashes.
diff --git a/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java b/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
new file mode 100644
index 0000000..42595ab
--- /dev/null
+++ b/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bluetooth.btservice;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothSocketManager;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelUuid;
+import com.android.bluetooth.Utils;
+
+class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
+ private static final String TAG = "BluetoothSocketManagerBinder";
+
+ private static final int INVALID_FD = -1;
+ private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+
+ private AdapterService mService;
+
+ BluetoothSocketManagerBinder(AdapterService service) {
+ mService = service;
+ }
+
+ void cleanUp() {
+ mService = null;
+ }
+
+ @Override
+ public ParcelFileDescriptor connectSocket(
+ BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag) {
+
+ enforceBluetoothAndActiveUser();
+
+ return marshalFd(mService.connectSocketNative(
+ Utils.getBytesFromAddress(device.getAddress()),
+ type,
+ Utils.uuidToByteArray(uuid),
+ port,
+ flag,
+ Binder.getCallingUid()));
+ }
+
+ @Override
+ public ParcelFileDescriptor createSocketChannel(
+ int type, String serviceName, ParcelUuid uuid, int port, int flag) {
+
+ enforceBluetoothAndActiveUser();
+
+ return marshalFd(mService.createSocketChannelNative(
+ type,
+ serviceName,
+ Utils.uuidToByteArray(uuid),
+ port,
+ flag,
+ Binder.getCallingUid()));
+
+ }
+
+ @Override
+ public void requestMaximumTxDataLength(BluetoothDevice device) {
+ enforceBluetoothAndActiveUser();
+
+ mService.requestMaximumTxDataLengthNative(Utils.getBytesFromAddress(device.getAddress()));
+ }
+
+ private void enforceBluetoothAndActiveUser() {
+ if (!Utils.checkCallerAllowManagedProfiles(mService)) {
+ throw new SecurityException("Not allowed for non-active user");
+ }
+ mService.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ }
+
+ private static ParcelFileDescriptor marshalFd(int fd) {
+ if (fd == INVALID_FD) {
+ return null;
+ }
+ return ParcelFileDescriptor.adoptFd(fd);
+ }
+}