Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bd92c45 authored by Zach Johnson's avatar Zach Johnson Committed by android-build-merger
Browse files

Merge "Move BluetoothSocketManager to java"

am: 5c345f99

Change-Id: Ice81b1972dfa10687c9ef6567b0d15596e6951bf
parents f79c1941 5c345f99
Loading
Loading
Loading
Loading
+88 −23
Original line number Diff line number Diff line
@@ -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 @@ namespace android {
#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 sJniAdapterServiceObj;
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 @@ static bool cleanupNative(JNIEnv* env, jobject obj) {
    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 @@ static jboolean getRemoteServicesNative(JNIEnv* env, jobject obj,
  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 @@ static jbyteArray obfuscateAddressNative(JNIEnv* env, jobject obj,
  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 @@ static JNINativeMethod sMethods[] = {
    {"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 @@ static JNINativeMethod sMethods[] = {
    {"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(
+18 −8
Original line number Diff line number Diff line
@@ -198,6 +198,8 @@ public class AdapterService extends Service {
    private SilenceDeviceManager mSilenceDeviceManager;
    private AppOpsManager mAppOps;

    private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;

    /**
     * Register a {@link ProfileService} with AdapterService.
     *
@@ -432,6 +434,8 @@ public class AdapterService extends Service {
                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 @@ public class AdapterService extends Service {
            mProfileServicesState.clear();
        }

        if (mBluetoothSocketManagerBinder != null) {
            mBluetoothSocketManagerBinder.cleanUp();
            mBluetoothSocketManagerBinder = null;
        }

        if (mBinder != null) {
            mBinder.cleanup();
            mBinder = null;  //Do not remove. Otherwise Binder leak!
@@ -2390,12 +2399,7 @@ public class AdapterService extends Service {
    }

    IBluetoothSocketManager getSocketManager() {
        android.os.IBinder obj = getSocketManagerNative();
        if (obj == null) {
            return null;
        }

        return IBluetoothSocketManager.Stub.asInterface(obj);
        return IBluetoothSocketManager.Stub.asInterface(mBluetoothSocketManagerBinder);
    }

    boolean factoryReset() {
@@ -2951,8 +2955,6 @@ public class AdapterService extends Service {

    private native int readEnergyInfo();

    private native IBinder getSocketManagerNative();

    private native void setSystemUiUidNative(int systemUiUid);

    private static native void setForegroundUserIdNative(int foregroundUserId);
@@ -2972,6 +2974,14 @@ public class AdapterService extends Service {

    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.
+93 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}