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

Commit c225a3d7 authored by William Escande's avatar William Escande
Browse files

AdapterService: Split native interface for test

Bug: 295237486
Test: atest AdapterServiceTest
Test: atest AdapterServiceRestartTest
Test: atest AdapterServiceFactoryResetTest
Test: atest AdapterPropertiesTest
Change-Id: I78ddb76dabb2ccc5ee518ae40139de055e8c8ebd
parent 10839dcf
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -817,7 +817,7 @@ static void energy_info_recv_callback(bt_activity_energy_info* p_energy_info,
  }

  sCallbackEnv->CallVoidMethod(
      sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
      sJniCallbacksObj, method_energyInfo, p_energy_info->status,
      p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
      p_energy_info->idle_time, p_energy_info->energy_used, array.get());
}
@@ -910,7 +910,7 @@ static int acquire_wake_lock_callout(const char* lock_name) {
    ScopedLocalRef<jstring> lock_name_jni(env, env->NewStringUTF(lock_name));
    if (lock_name_jni.get()) {
      bool acquired = env->CallBooleanMethod(
          sJniAdapterServiceObj, method_acquireWakeLock, lock_name_jni.get());
          sJniCallbacksObj, method_acquireWakeLock, lock_name_jni.get());
      if (!acquired) ret = BT_STATUS_WAKELOCK_ERROR;
    } else {
      ALOGE("%s unable to allocate string: %s", __func__, lock_name);
@@ -941,7 +941,7 @@ static int release_wake_lock_callout(const char* lock_name) {
    ScopedLocalRef<jstring> lock_name_jni(env, env->NewStringUTF(lock_name));
    if (lock_name_jni.get()) {
      bool released = env->CallBooleanMethod(
          sJniAdapterServiceObj, method_releaseWakeLock, lock_name_jni.get());
          sJniCallbacksObj, method_releaseWakeLock, lock_name_jni.get());
      if (!released) ret = BT_STATUS_WAKELOCK_ERROR;
    } else {
      ALOGE("%s unable to allocate string: %s", __func__, lock_name);
@@ -1014,15 +1014,19 @@ static void classInitNative(JNIEnv* env, jclass clazz) {

  method_adapterPropertyChangedCallback = env->GetMethodID(
      jniCallbackClass, "adapterPropertyChangedCallback", "([I[[B)V");

  method_discoveryStateChangeCallback = env->GetMethodID(
      jniCallbackClass, "discoveryStateChangeCallback", "(I)V");

  method_devicePropertyChangedCallback = env->GetMethodID(
      jniCallbackClass, "devicePropertyChangedCallback", "([B[I[[B)V");

  method_deviceFoundCallback =
      env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");

  method_pinRequestCallback =
      env->GetMethodID(jniCallbackClass, "pinRequestCallback", "([B[BIZ)V");

  method_sspRequestCallback =
      env->GetMethodID(jniCallbackClass, "sspRequestCallback", "([B[BIII)V");

@@ -1047,12 +1051,15 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
  method_switchCodecCallback =
      env->GetMethodID(jniCallbackClass, "switchCodecCallback", "(Z)V");

  method_acquireWakeLock =
      env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
  method_releaseWakeLock =
      env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
  method_energyInfo = env->GetMethodID(
      clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
  method_acquireWakeLock = env->GetMethodID(jniCallbackClass, "acquireWakeLock",
                                            "(Ljava/lang/String;)Z");

  method_releaseWakeLock = env->GetMethodID(jniCallbackClass, "releaseWakeLock",
                                            "(Ljava/lang/String;)Z");

  method_energyInfo =
      env->GetMethodID(jniCallbackClass, "energyInfoCallback",
                       "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");

  if (env->GetJavaVM(&vm) != JNI_OK) {
    ALOGE("Could not get JavaVM");
@@ -1705,7 +1712,7 @@ static jboolean getRemoteServicesNative(JNIEnv* env, jobject obj,
  return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

static int readEnergyInfo() {
static int readEnergyInfoNative() {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) return JNI_FALSE;
@@ -1934,7 +1941,7 @@ static void metadataChangedNative(JNIEnv* env, jobject obj, jbyteArray address,
  return;
}

static jboolean isLogRedactionEnabled(JNIEnv* env, jobject obj) {
static jboolean isLogRedactionEnabledNative(JNIEnv* env, jobject obj) {
  ALOGV("%s", __func__);
  return bluetooth::os::should_log_be_redacted();
}
@@ -2181,7 +2188,7 @@ static JNINativeMethod sMethods[] = {
    {"pinReplyNative", "([BZI[B)Z", (void*)pinReplyNative},
    {"sspReplyNative", "([BIZI)Z", (void*)sspReplyNative},
    {"getRemoteServicesNative", "([BI)Z", (void*)getRemoteServicesNative},
    {"readEnergyInfo", "()I", (void*)readEnergyInfo},
    {"readEnergyInfoNative", "()I", (void*)readEnergyInfoNative},
    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V",
     (void*)dumpNative},
    {"dumpMetricsNative", "()[B", (void*)dumpMetricsNative},
@@ -2197,7 +2204,7 @@ static JNINativeMethod sMethods[] = {
     (void*)requestMaximumTxDataLengthNative},
    {"allowLowLatencyAudioNative", "(Z[B)Z", (void*)allowLowLatencyAudioNative},
    {"metadataChangedNative", "([BI[B)V", (void*)metadataChangedNative},
    {"isLogRedactionEnabled", "()Z", (void*)isLogRedactionEnabled},
    {"isLogRedactionEnabledNative", "()Z", (void*)isLogRedactionEnabledNative},
    {"interopMatchAddrNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
     (void*)interopMatchAddrNative},
    {"interopMatchNameNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
@@ -2218,7 +2225,7 @@ static JNINativeMethod sMethods[] = {

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env, "com/android/bluetooth/btservice/AdapterService", sMethods,
      env, "com/android/bluetooth/btservice/AdapterNativeInterface", sMethods,
      NELEM(sMethods));
}

+367 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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.OobData;
import android.util.Log;

import com.android.bluetooth.Utils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;

/** Native interface to be used by AdapterService */
public class AdapterNativeInterface {
    private static final String TAG = AdapterNativeInterface.class.getSimpleName();

    private JniCallbacks mJniCallbacks;

    @GuardedBy("INSTANCE_LOCK")
    private static AdapterNativeInterface sInstance;

    private static final Object INSTANCE_LOCK = new Object();

    static {
        if (Utils.isInstrumentationTestMode()) {
            Log.w(TAG, "App is instrumented. Skip loading the native");
        } else {
            classInitNative();
        }
    }

    private AdapterNativeInterface() {}

    static AdapterNativeInterface getInstance() {
        synchronized (INSTANCE_LOCK) {
            if (sInstance == null) {
                sInstance = new AdapterNativeInterface();
            }
            return sInstance;
        }
    }

    /** Set singleton instance. */
    @VisibleForTesting
    public static void setInstance(AdapterNativeInterface instance) {
        synchronized (INSTANCE_LOCK) {
            sInstance = instance;
        }
    }

    JniCallbacks getCallbacks() {
        return mJniCallbacks;
    }

    boolean init(
            AdapterService service,
            AdapterProperties adapterProperties,
            boolean startRestricted,
            boolean isCommonCriteriaMode,
            int configCompareResult,
            String[] initFlags,
            boolean isAtvDevice,
            String userDataDirectory) {
        mJniCallbacks = new JniCallbacks(service, adapterProperties);
        return initNative(
                startRestricted,
                isCommonCriteriaMode,
                configCompareResult,
                initFlags,
                isAtvDevice,
                userDataDirectory);
    }

    void cleanup() {
        cleanupNative();
    }

    boolean enable() {
        return enableNative();
    }

    boolean disable() {
        return disableNative();
    }

    boolean setAdapterProperty(int type, byte[] val) {
        return setAdapterPropertyNative(type, val);
    }

    boolean getAdapterProperties() {
        return getAdapterPropertiesNative();
    }

    boolean getAdapterProperty(int type) {
        return getAdapterPropertyNative(type);
    }

    boolean setAdapterProperty(int type) {
        return setAdapterPropertyNative(type);
    }

    boolean setDeviceProperty(byte[] address, int type, byte[] val) {
        return setDevicePropertyNative(address, type, val);
    }

    boolean getDeviceProperty(byte[] address, int type) {
        return getDevicePropertyNative(address, type);
    }

    boolean createBond(byte[] address, int addressType, int transport) {
        return createBondNative(address, addressType, transport);
    }

    boolean createBondOutOfBand(byte[] address, int transport, OobData p192Data, OobData p256Data) {
        return createBondOutOfBandNative(address, transport, p192Data, p256Data);
    }

    boolean removeBond(byte[] address) {
        return removeBondNative(address);
    }

    boolean cancelBond(byte[] address) {
        return cancelBondNative(address);
    }

    void generateLocalOobData(int transport) {
        generateLocalOobDataNative(transport);
    }

    boolean sdpSearch(byte[] address, byte[] uuid) {
        return sdpSearchNative(address, uuid);
    }

    int getConnectionState(byte[] address) {
        return getConnectionStateNative(address);
    }

    boolean startDiscovery() {
        return startDiscoveryNative();
    }

    boolean cancelDiscovery() {
        return cancelDiscoveryNative();
    }

    boolean pinReply(byte[] address, boolean accept, int len, byte[] pin) {
        return pinReplyNative(address, accept, len, pin);
    }

    boolean sspReply(byte[] address, int type, boolean accept, int passkey) {
        return sspReplyNative(address, type, accept, passkey);
    }

    boolean getRemoteServices(byte[] address, int transport) {
        return getRemoteServicesNative(address, transport);
    }

    boolean getRemoteMasInstances(byte[] address) {
        return getRemoteMasInstancesNative(address);
    }

    int readEnergyInfo() {
        return readEnergyInfoNative();
    }

    boolean factoryReset() {
        return factoryResetNative();
    }

    void dump(FileDescriptor fd, String[] arguments) {
        dumpNative(fd, arguments);
    }

    byte[] dumpMetrics() {
        return dumpMetricsNative();
    }

    byte[] obfuscateAddress(byte[] address) {
        return obfuscateAddressNative(address);
    }

    boolean setBufferLengthMillis(int codec, int value) {
        return setBufferLengthMillisNative(codec, value);
    }

    int getMetricId(byte[] address) {
        return getMetricIdNative(address);
    }

    int connectSocket(byte[] address, int type, byte[] uuid, int port, int flag, int callingUid) {
        return connectSocketNative(address, type, uuid, port, flag, callingUid);
    }

    int createSocketChannel(
            int type, String serviceName, byte[] uuid, int port, int flag, int callingUid) {
        return createSocketChannelNative(type, serviceName, uuid, port, flag, callingUid);
    }

    void requestMaximumTxDataLength(byte[] address) {
        requestMaximumTxDataLengthNative(address);
    }

    boolean allowLowLatencyAudio(boolean allowed, byte[] address) {
        return allowLowLatencyAudioNative(allowed, address);
    }

    void metadataChanged(byte[] address, int key, byte[] value) {
        metadataChangedNative(address, key, value);
    }

    boolean interopMatchAddr(String featureName, String address) {
        return interopMatchAddrNative(featureName, address);
    }

    boolean interopMatchName(String featureName, String name) {
        return interopMatchNameNative(featureName, name);
    }

    boolean interopMatchAddrOrName(String featureName, String address) {
        return interopMatchAddrOrNameNative(featureName, address);
    }

    void interopDatabaseAddRemoveAddr(
            boolean doAdd, String featureName, String address, int length) {
        interopDatabaseAddRemoveAddrNative(doAdd, featureName, address, length);
    }

    void interopDatabaseAddRemoveName(boolean doAdd, String featureName, String name) {
        interopDatabaseAddRemoveNameNative(doAdd, featureName, name);
    }

    int getRemotePbapPceVersion(String address) {
        return getRemotePbapPceVersionNative(address);
    }

    boolean pbapPseDynamicVersionUpgradeIsEnabled() {
        return pbapPseDynamicVersionUpgradeIsEnabledNative();
    }

    boolean isLogRedactionEnabled() {
        return isLogRedactionEnabledNative();
    }

    /**********************************************************************************************/
    /*********************************** callbacks from native ************************************/
    /**********************************************************************************************/

    // See JniCallbacks.java

    /**********************************************************************************************/
    /******************************************* native *******************************************/
    /**********************************************************************************************/

    private static native void classInitNative();

    private native boolean initNative(
            boolean startRestricted,
            boolean isCommonCriteriaMode,
            int configCompareResult,
            String[] initFlags,
            boolean isAtvDevice,
            String userDataDirectory);

    private native void cleanupNative();

    private native boolean enableNative();

    private native boolean disableNative();

    private native boolean setAdapterPropertyNative(int type, byte[] val);

    private native boolean getAdapterPropertiesNative();

    private native boolean getAdapterPropertyNative(int type);

    private native boolean setAdapterPropertyNative(int type);

    private native boolean setDevicePropertyNative(byte[] address, int type, byte[] val);

    private native boolean getDevicePropertyNative(byte[] address, int type);

    private native boolean createBondNative(byte[] address, int addressType, int transport);

    private native boolean createBondOutOfBandNative(
            byte[] address, int transport, OobData p192Data, OobData p256Data);

    private native boolean removeBondNative(byte[] address);

    private native boolean cancelBondNative(byte[] address);

    private native void generateLocalOobDataNative(int transport);

    private native boolean sdpSearchNative(byte[] address, byte[] uuid);

    private native int getConnectionStateNative(byte[] address);

    private native boolean startDiscoveryNative();

    private native boolean cancelDiscoveryNative();

    private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin);

    private native boolean sspReplyNative(byte[] address, int type, boolean accept, int passkey);

    private native boolean getRemoteServicesNative(byte[] address, int transport);

    private native boolean getRemoteMasInstancesNative(byte[] address);

    private native int readEnergyInfoNative();

    private native boolean factoryResetNative();

    private native void dumpNative(FileDescriptor fd, String[] arguments);

    private native byte[] dumpMetricsNative();

    private native byte[] obfuscateAddressNative(byte[] address);

    private native boolean setBufferLengthMillisNative(int codec, int value);

    private native int getMetricIdNative(byte[] address);

    private native int connectSocketNative(
            byte[] address, int type, byte[] uuid, int port, int flag, int callingUid);

    private native int createSocketChannelNative(
            int type, String serviceName, byte[] uuid, int port, int flag, int callingUid);

    private native void requestMaximumTxDataLengthNative(byte[] address);

    private native boolean allowLowLatencyAudioNative(boolean allowed, byte[] address);

    private native void metadataChangedNative(byte[] address, int key, byte[] value);

    private native boolean interopMatchAddrNative(String featureName, String address);

    private native boolean interopMatchNameNative(String featureName, String name);

    private native boolean interopMatchAddrOrNameNative(String featureName, String address);

    private native void interopDatabaseAddRemoveAddrNative(
            boolean doAdd, String featureName, String address, int length);

    private native void interopDatabaseAddRemoveNameNative(
            boolean doAdd, String featureName, String name);

    private native int getRemotePbapPceVersionNative(String address);

    private native boolean pbapPseDynamicVersionUpgradeIsEnabledNative();

    private native boolean isLogRedactionEnabledNative();
}
+18 −11
Original line number Diff line number Diff line
@@ -317,15 +317,18 @@ class AdapterProperties {
     */
    boolean setName(String name) {
        synchronized (mObject) {
            return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME,
                    name.getBytes());
            return mService.getNative()
                    .setAdapterProperty(AbstractionLayer.BT_PROPERTY_BDNAME, name.getBytes());
        }
    }

    boolean setIoCapability(int capability) {
        synchronized (mObject) {
            boolean result = mService.setAdapterPropertyNative(
                    AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS, Utils.intToByteArray(capability));
            boolean result =
                    mService.getNative()
                            .setAdapterProperty(
                                    AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS,
                                    Utils.intToByteArray(capability));

            if (result) {
                mLocalIOCapability = capability;
@@ -360,7 +363,9 @@ class AdapterProperties {
    boolean setScanMode(int scanMode) {
        addScanChangeLog(scanMode);
        synchronized (mObject) {
            return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE,
            return mService.getNative()
                    .setAdapterProperty(
                            AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE,
                            Utils.intToByteArray(AdapterService.convertScanModeToHal(scanMode)));
        }
    }
@@ -586,7 +591,7 @@ class AdapterProperties {
     * @param size the size to set
     */
    boolean setBufferLengthMillis(int codec, int size) {
        return mService.setBufferLengthMillisNative(codec, size);
        return mService.getNative().setBufferLengthMillis(codec, size);
    }

    /**
@@ -653,7 +658,8 @@ class AdapterProperties {
            String address = device.getAddress();
            String identityAddress = mService.getIdentityAddress(address);
            if (currentIdentityAddress.equals(identityAddress) && !currentAddress.equals(address)) {
                if (mService.removeBondNative(Utils.getBytesFromAddress(device.getAddress()))) {
                if (mService.getNative()
                        .removeBond(Utils.getBytesFromAddress(device.getAddress()))) {
                    mBondedDevices.remove(device);
                    infoLog("Removing old bond record: "
                                    + device
@@ -676,7 +682,8 @@ class AdapterProperties {

    boolean setDiscoverableTimeout(int timeout) {
        synchronized (mObject) {
            return mService.setAdapterPropertyNative(
            return mService.getNative()
                    .setAdapterProperty(
                            AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT,
                            Utils.intToByteArray(timeout));
        }
+54 −169

File changed.

Preview size limit exceeded, changes collapsed.

+22 −19
Original line number Diff line number Diff line
@@ -51,7 +51,8 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
        }

        return marshalFd(
                mService.connectSocketNative(
                mService.getNative()
                        .connectSocket(
                                Utils.getBytesFromAddress(
                                        type == BluetoothSocket.TYPE_L2CAP_LE
                                                ? device.getAddress()
@@ -73,14 +74,15 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
            return null;
        }

        return marshalFd(mService.createSocketChannelNative(
        return marshalFd(
                mService.getNative()
                        .createSocketChannel(
                                type,
                                serviceName,
                                Utils.uuidToByteArray(uuid),
                                port,
                                flag,
                                Binder.getCallingUid()));

    }

    @Override
@@ -91,7 +93,8 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
            return;
        }

        mService.requestMaximumTxDataLengthNative(Utils.getBytesFromAddress(device.getAddress()));
        mService.getNative()
                .requestMaximumTxDataLength(Utils.getBytesFromAddress(device.getAddress()));
    }

    private void enforceActiveUser() {
Loading