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

Commit 039d579a authored by Sarvesh Kalwit's avatar Sarvesh Kalwit
Browse files

Add MSFT extension support to JNI layer

Bug: 360384904
Bug: 365787977
Test: m -j
Flag: le_scan_msft_support
Change-Id: I4f010d82d2187cd993d621ce14af49c09a281bcd
parent cc7d9dd0
Loading
Loading
Loading
Loading
+152 −0
Original line number Diff line number Diff line
@@ -180,6 +180,9 @@ static jmethodID method_onBatchScanThresholdCrossed;
static jmethodID method_createOnTrackAdvFoundLostObject;
static jmethodID method_onTrackAdvFoundLost;
static jmethodID method_onScanParamSetupCompleted;
static jmethodID method_onMsftAdvMonitorAdd;
static jmethodID method_onMsftAdvMonitorRemove;
static jmethodID method_onMsftAdvMonitorEnable;

/**
 * Periodic scanner callback methods
@@ -1875,6 +1878,142 @@ static void gattClientScanFilterEnableNative(JNIEnv* /* env */, jobject /* objec
  sScanner->ScanFilterEnable(enable, base::Bind(&scan_enable_cb, client_if));
}

void msft_monitor_add_cb(int filter_index, uint8_t monitor_handle, uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid() || !mScanCallbacksObj) {
    return;
  }
  sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorAdd, filter_index,
                               monitor_handle, status);
}

void msft_monitor_remove_cb(int filter_index, uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid() || !mScanCallbacksObj) {
    return;
  }
  sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorRemove, filter_index,
                               status);
}

void msft_monitor_enable_cb(uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid() || !mScanCallbacksObj) {
    return;
  }
  sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onMsftAdvMonitorEnable, status);
}

static bool gattClientIsMsftSupportedNative(JNIEnv* /* env */, jobject /* object */) {
  return sScanner && sScanner->IsMsftSupported();
}

static void gattClientMsftAdvMonitorAddNative(JNIEnv* env, jobject /* object*/,
                                              jobject msft_adv_monitor,
                                              jobjectArray msft_adv_monitor_patterns,
                                              jobject msft_adv_monitor_address, jint filter_index) {
  if (!sScanner) {
    return;
  }

  jclass msftAdvMonitorClazz = env->GetObjectClass(msft_adv_monitor);
  jfieldID rssiThresholdHighFid = env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_high", "B");
  jfieldID rssiThresholdLowFid = env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_low", "B");
  jfieldID rssiThresholdLowTimeIntervalFid =
          env->GetFieldID(msftAdvMonitorClazz, "rssi_threshold_low_time_interval", "B");
  jfieldID rssiSamplingPeriodFid =
          env->GetFieldID(msftAdvMonitorClazz, "rssi_sampling_period", "B");
  jfieldID conditionTypeFid = env->GetFieldID(msftAdvMonitorClazz, "condition_type", "B");

  jclass msftAdvMonitorAddressClazz = env->GetObjectClass(msft_adv_monitor_address);
  jfieldID addrTypeFid = env->GetFieldID(msftAdvMonitorAddressClazz, "addr_type", "B");
  jfieldID bdAddrFid = env->GetFieldID(msftAdvMonitorAddressClazz, "bd_addr", "Ljava/lang/String;");

  MsftAdvMonitor native_msft_adv_monitor{};
  ScopedLocalRef<jobject> msft_adv_monitor_object(env, msft_adv_monitor);
  native_msft_adv_monitor.rssi_threshold_high =
          env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdHighFid);
  native_msft_adv_monitor.rssi_threshold_low =
          env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdLowFid);
  native_msft_adv_monitor.rssi_threshold_low_time_interval =
          env->GetByteField(msft_adv_monitor_object.get(), rssiThresholdLowTimeIntervalFid);
  native_msft_adv_monitor.rssi_sampling_period =
          env->GetByteField(msft_adv_monitor_object.get(), rssiSamplingPeriodFid);
  native_msft_adv_monitor.condition_type =
          env->GetByteField(msft_adv_monitor_object.get(), conditionTypeFid);

  MsftAdvMonitorAddress native_msft_adv_monitor_address{};
  ScopedLocalRef<jobject> msft_adv_monitor_address_object(env, msftAdvMonitorAddressClazz);
  native_msft_adv_monitor_address.addr_type =
          env->GetByteField(msft_adv_monitor_address_object.get(), addrTypeFid);
  native_msft_adv_monitor_address.bd_addr = str2addr(
          env, (jstring)env->GetObjectField(msft_adv_monitor_address_object.get(), bdAddrFid));
  native_msft_adv_monitor.addr_info = native_msft_adv_monitor_address;

  int numPatterns = env->GetArrayLength(msft_adv_monitor_patterns);
  if (numPatterns == 0) {
    sScanner->MsftAdvMonitorAdd(std::move(native_msft_adv_monitor),
                                base::Bind(&msft_monitor_add_cb, filter_index));
    return;
  }

  jclass msftAdvMonitorPatternClazz =
          env->GetObjectClass(env->GetObjectArrayElement(msft_adv_monitor_patterns, 0));
  jfieldID adTypeFid = env->GetFieldID(msftAdvMonitorPatternClazz, "ad_type", "B");
  jfieldID startByteFid = env->GetFieldID(msftAdvMonitorPatternClazz, "start_byte", "B");
  jfieldID patternFid = env->GetFieldID(msftAdvMonitorPatternClazz, "pattern", "[B");

  std::vector<MsftAdvMonitorPattern> patterns;
  for (int i = 0; i < numPatterns; i++) {
    MsftAdvMonitorPattern native_msft_adv_monitor_pattern{};
    ScopedLocalRef<jobject> msft_adv_monitor_pattern_object(
            env, env->GetObjectArrayElement(msft_adv_monitor_patterns, i));
    native_msft_adv_monitor_pattern.ad_type =
            env->GetByteField(msft_adv_monitor_pattern_object.get(), adTypeFid);
    native_msft_adv_monitor_pattern.start_byte =
            env->GetByteField(msft_adv_monitor_pattern_object.get(), startByteFid);

    ScopedLocalRef<jbyteArray> patternByteArray(
            env,
            (jbyteArray)env->GetObjectField(msft_adv_monitor_pattern_object.get(), patternFid));
    if (patternByteArray.get() != nullptr) {
      jbyte* patternBytes = env->GetByteArrayElements(patternByteArray.get(), NULL);
      if (patternBytes == NULL) {
        jniThrowIOException(env, EINVAL);
        return;
      }
      for (int j = 0; j < env->GetArrayLength(patternByteArray.get()); j++) {
        native_msft_adv_monitor_pattern.pattern.push_back(patternBytes[j]);
      }
    }

    patterns.push_back(native_msft_adv_monitor_pattern);
  }
  native_msft_adv_monitor.patterns = patterns;

  sScanner->MsftAdvMonitorAdd(std::move(native_msft_adv_monitor),
                              base::Bind(&msft_monitor_add_cb, filter_index));
}

static void gattClientMsftAdvMonitorRemoveNative(JNIEnv* /* env */, jobject /* object */,
                                                 int filter_index, int monitor_handle) {
  if (!sScanner) {
    return;
  }
  sScanner->MsftAdvMonitorRemove(monitor_handle, base::Bind(&msft_monitor_remove_cb, filter_index));
}

static void gattClientMsftAdvMonitorEnableNative(JNIEnv* /* env */, jobject /* object */,
                                                 jboolean enable) {
  if (!sScanner) {
    return;
  }
  sScanner->MsftAdvMonitorEnable(enable, base::Bind(&msft_monitor_enable_cb));
}

static void gattClientConfigureMTUNative(JNIEnv* /* env */, jobject /* object */, jint conn_id,
                                         jint mtu) {
  if (!sGattIf) {
@@ -2697,6 +2836,16 @@ static int register_com_android_bluetooth_gatt_scan(JNIEnv* env) {
          {"gattClientScanFilterClearNative", "(II)V", (void*)gattClientScanFilterClearNative},
          {"gattClientScanFilterEnableNative", "(IZ)V", (void*)gattClientScanFilterEnableNative},
          {"gattSetScanParametersNative", "(IIII)V", (void*)gattSetScanParametersNative},
          // MSFT HCI Extension functions.
          {"gattClientIsMsftSupportedNative", "()Z", (void*)gattClientIsMsftSupportedNative},
          {"gattClientMsftAdvMonitorAddNative",
           "(Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Monitor;[Lcom/android/bluetooth/le_scan/"
           "MsftAdvMonitor$Pattern;Lcom/android/bluetooth/le_scan/MsftAdvMonitor$Address;I)V",
           (void*)gattClientMsftAdvMonitorAddNative},
          {"gattClientMsftAdvMonitorRemoveNative", "(II)V",
           (void*)gattClientMsftAdvMonitorRemoveNative},
          {"gattClientMsftAdvMonitorEnableNative", "(Z)V",
           (void*)gattClientMsftAdvMonitorEnableNative},
  };
  const int result = REGISTER_NATIVE_METHODS(
          env, "com/android/bluetooth/le_scan/ScanNativeInterface", methods);
@@ -2723,6 +2872,9 @@ static int register_com_android_bluetooth_gatt_scan(JNIEnv* env) {
          {"onTrackAdvFoundLost", "(Lcom/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo;)V",
           &method_onTrackAdvFoundLost},
          {"onScanParamSetupCompleted", "(II)V", &method_onScanParamSetupCompleted},
          {"onMsftAdvMonitorAdd", "(III)V", &method_onMsftAdvMonitorAdd},
          {"onMsftAdvMonitorRemove", "(II)V", &method_onMsftAdvMonitorRemove},
          {"onMsftAdvMonitorEnable", "(I)V", &method_onMsftAdvMonitorEnable},
  };
  GET_JAVA_METHODS(env, "com/android/bluetooth/le_scan/ScanNativeInterface", javaMethods);
  return 0;
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.le_scan;

class MsftAdvMonitor {
    static class Monitor {
        public byte rssi_threshold_high;
        public byte rssi_threshold_low;
        public byte rssi_threshold_low_time_interval;
        public byte rssi_sampling_period;
        public byte condition_type;
    }

    static class Pattern {
        public byte ad_type;
        public byte start_byte;
        public byte[] pattern;
    }

    static class Address {
        byte addr_type;
        String bd_addr;
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -98,6 +98,19 @@ public class ScanNativeInterface {

    private native void gattClientScanFilterEnableNative(int clientIf, boolean enable);

    /************************** MSFT scan related native methods *****************************/
    private native boolean gattClientIsMsftSupportedNative();

    private native void gattClientMsftAdvMonitorAddNative(
            MsftAdvMonitor.Monitor msft_adv_monitor,
            MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns,
            MsftAdvMonitor.Address msft_adv_monitor_address,
            int filter_index);

    private native void gattClientMsftAdvMonitorRemoveNative(int filter_index, int monitor_handle);

    private native void gattClientMsftAdvMonitorEnableNative(boolean enable);

    /************************** Batch related native methods *********************************/
    private native void gattClientConfigBatchScanStorageNative(
            int clientIf,
@@ -371,4 +384,10 @@ public class ScanNativeInterface {
        }
        mScanHelper.onScanParamSetupCompleted(status, scannerId);
    }

    void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) {}

    void onMsftAdvMonitorRemove(int filter_index, int status) {}

    void onMsftAdvMonitorEnable(int status) {}
}
+3 −3
Original line number Diff line number Diff line
@@ -287,13 +287,13 @@ void BleScannerInterfaceImpl::MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEn
void BleScannerInterfaceImpl::OnMsftAdvMonitorAdd(uint8_t monitor_handle,
                                                  bluetooth::hci::ErrorCode status) {
  log::info("in shim layer");
  msft_callbacks_.Add.Run(monitor_handle, (uint8_t)status);
  do_in_jni_thread(base::BindOnce(msft_callbacks_.Add, monitor_handle, (uint8_t)status));
}

/** Callback of removing MSFT filter */
void BleScannerInterfaceImpl::OnMsftAdvMonitorRemove(bluetooth::hci::ErrorCode status) {
  log::info("in shim layer");
  msft_callbacks_.Remove.Run((uint8_t)status);
  do_in_jni_thread(base::BindOnce(msft_callbacks_.Remove, (uint8_t)status));
}

/** Callback of enabling / disabling MSFT scan filter */
@@ -307,7 +307,7 @@ void BleScannerInterfaceImpl::OnMsftAdvMonitorEnable(bool enable,
                   : bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL);
  }

  msft_callbacks_.Enable.Run((uint8_t)status);
  do_in_jni_thread(base::BindOnce(msft_callbacks_.Enable, (uint8_t)status));
}

/** Sets the LE scan interval and window in units of N*0.625 msec */