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

Commit 4f9a610a authored by Andre Eisenbach's avatar Andre Eisenbach Committed by Gerrit Code Review
Browse files

Merge "HID: Add support for Set Idle and Get Idle commands (4/4)"

parents bad40a0a 0c390505
Loading
Loading
Loading
Loading
+59 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ static jmethodID method_onGetProtocolMode;
static jmethodID method_onGetReport;
static jmethodID method_onHandshake;
static jmethodID method_onVirtualUnplug;
static jmethodID method_onGetIdleTime;

static const bthh_interface_t* sBluetoothHidInterface = NULL;
static jobject mCallbacksObj = NULL;
@@ -157,12 +158,26 @@ static void handshake_callback(bt_bdaddr_t* bd_addr, bthh_status_t hh_status) {
                               (jint)hh_status);
}

static void get_idle_time_callback(bt_bdaddr_t* bd_addr,
                                   bthh_status_t hh_status, int idle_time) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

  ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
  if (!addr.get()) {
    ALOGE("%s: Fail to new jbyteArray bd addr", __func__);
    return;
  }
  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetIdleTime, addr.get(),
                               (jint)idle_time);
}

static bthh_callbacks_t sBluetoothHidCallbacks = {
    sizeof(sBluetoothHidCallbacks),
    connection_state_callback,
    NULL,
    get_protocol_mode_callback,
    NULL,
    get_idle_time_callback,
    get_report_callback,
    virtual_unplug_callback,
    handshake_callback};
@@ -177,6 +192,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
  method_onGetReport = env->GetMethodID(clazz, "onGetReport", "([B[BI)V");
  method_onHandshake = env->GetMethodID(clazz, "onHandshake", "([BI)V");
  method_onVirtualUnplug = env->GetMethodID(clazz, "onVirtualUnplug", "([BI)V");
  method_onGetIdleTime = env->GetMethodID(clazz, "onGetIdleTime", "([BI)V");

  ALOGI("%s: succeeds", __func__);
}
@@ -434,7 +450,7 @@ static jboolean sendDataNative(JNIEnv* env, jobject object, jbyteArray address,
  bt_status_t status =
      sBluetoothHidInterface->send_data((bt_bdaddr_t*)addr, (char*)c_report);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed set report, status: %d", status);
    ALOGE("Failed set data, status: %d", status);
    ret = JNI_FALSE;
  }
  env->ReleaseStringUTFChars(report, c_report);
@@ -443,6 +459,45 @@ static jboolean sendDataNative(JNIEnv* env, jobject object, jbyteArray address,
  return ret;
}

static jboolean getIdleTimeNative(JNIEnv* env, jobject object,
                                  jbyteArray address) {
  if (!sBluetoothHidInterface) return JNI_FALSE;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    ALOGE("%s: Bluetooth device address null", __func__);
    return JNI_FALSE;
  }

  bt_status_t status = sBluetoothHidInterface->get_idle_time((bt_bdaddr_t*)addr);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("%s: Failed get idle time, status: %d", __func__, status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);

  return status == BT_STATUS_SUCCESS ? JNI_TRUE : JNI_FALSE;
}

static jboolean setIdleTimeNative(JNIEnv* env, jobject object,
                                  jbyteArray address, jbyte idle_time) {
  if (!sBluetoothHidInterface) return JNI_FALSE;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    ALOGE("%s: Bluetooth device address null", __func__);
    return JNI_FALSE;
  }

  bt_status_t status = sBluetoothHidInterface->set_idle_time(
           (bt_bdaddr_t*)addr, idle_time);
  if (status != BT_STATUS_SUCCESS) {
    ALOGE("%s: Failed set idle time, status: %d", __func__, status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);

  return status == BT_STATUS_SUCCESS ? JNI_TRUE : JNI_FALSE;
}

static JNINativeMethod sMethods[] = {
    {"classInitNative", "()V", (void*)classInitNative},
    {"initializeNative", "()V", (void*)initializeNative},
@@ -455,6 +510,8 @@ static JNINativeMethod sMethods[] = {
    {"getReportNative", "([BBBI)Z", (void*)getReportNative},
    {"setReportNative", "([BBLjava/lang/String;)Z", (void*)setReportNative},
    {"sendDataNative", "([BLjava/lang/String;)Z", (void*)sendDataNative},
    {"getIdleTimeNative", "([B)Z", (void*)getIdleTimeNative},
    {"setIdleTimeNative", "([BB)Z", (void*)setIdleTimeNative},
};

int register_com_android_bluetooth_hid(JNIEnv* env) {
+78 −0
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@ public class HidService extends ProfileService {
    private static final int MESSAGE_SEND_DATA = 11;
    private static final int MESSAGE_ON_VIRTUAL_UNPLUG = 12;
    private static final int MESSAGE_ON_HANDSHAKE = 13;
    private static final int MESSAGE_GET_IDLE_TIME = 14;
    private static final int MESSAGE_ON_GET_IDLE_TIME = 15;
    private static final int MESSAGE_SET_IDLE_TIME = 16;

    static {
        classInitNative();
@@ -287,6 +290,25 @@ public class HidService extends ProfileService {
                    broadcastVirtualUnplugStatus(device, status);
                }
                break;
                case MESSAGE_GET_IDLE_TIME: {
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    if (!getIdleTimeNative(Utils.getByteAddress(device))) {
                        Log.e(TAG, "Error: get idle time native returns false");
                    }
                } break;
                case MESSAGE_ON_GET_IDLE_TIME: {
                    BluetoothDevice device = getDevice((byte[]) msg.obj);
                    int idleTime = msg.arg1;
                    broadcastIdleTime(device, idleTime);
                } break;
                case MESSAGE_SET_IDLE_TIME: {
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    Bundle data = msg.getData();
                    byte idleTime = data.getByte(BluetoothInputDevice.EXTRA_IDLE_TIME);
                    if (!setIdleTimeNative(Utils.getByteAddress(device), idleTime)) {
                        Log.e(TAG, "Error: get idle time native returns false");
                    }
                } break;
            }
        }
    };
@@ -394,6 +416,18 @@ public class HidService extends ProfileService {
            if (service == null) return false;
            return service.sendData(device, report);
        }

        public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
            HidService service = getService();
            if (service == null) return false;
            return service.setIdleTime(device, idleTime);
        }

        public boolean getIdleTime(BluetoothDevice device) {
            HidService service = getService();
            if (service == null) return false;
            return service.getIdleTime(device);
        }
    };

    //APIs
@@ -550,6 +584,32 @@ public class HidService extends ProfileService {
        return sendDataNative(Utils.getByteAddress(device), report);
    }

    boolean getIdleTime(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        int state = this.getConnectionState(device);
        if (state != BluetoothInputDevice.STATE_CONNECTED) {
            return false;
        }
        Message msg = mHandler.obtainMessage(MESSAGE_GET_IDLE_TIME, device);
        mHandler.sendMessage(msg);
        return true;
    }

    boolean setIdleTime(BluetoothDevice device, byte idleTime) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        int state = this.getConnectionState(device);
        if (state != BluetoothInputDevice.STATE_CONNECTED) {
            return false;
        }
        Message msg = mHandler.obtainMessage(MESSAGE_SET_IDLE_TIME);
        msg.obj = device;
        Bundle data = new Bundle();
        data.putByte(BluetoothInputDevice.EXTRA_IDLE_TIME, idleTime);
        msg.setData(data);
        mHandler.sendMessage(msg);
        return true;
    }

    private void onGetProtocolMode(byte[] address, int mode) {
        Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE);
        msg.obj = address;
@@ -557,6 +617,13 @@ public class HidService extends ProfileService {
        mHandler.sendMessage(msg);
    }

    private void onGetIdleTime(byte[] address, int idleTime) {
        Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_IDLE_TIME);
        msg.obj = address;
        msg.arg1 = idleTime;
        mHandler.sendMessage(msg);
    }

    private void onGetReport(byte[] address, byte[] report, int rpt_size) {
        Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_REPORT);
        msg.obj = address;
@@ -645,6 +712,15 @@ public class HidService extends ProfileService {
        sendBroadcast(intent, BLUETOOTH_PERM);
    }

    private void broadcastIdleTime(BluetoothDevice device, int idleTime) {
        Intent intent = new Intent(BluetoothInputDevice.ACTION_IDLE_TIME_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothInputDevice.EXTRA_IDLE_TIME, idleTime);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        sendBroadcast(intent, BLUETOOTH_PERM);
        if (DBG) log("Idle time (" + device + "): " + idleTime);
    }

    private boolean okToConnect(BluetoothDevice device) {
        AdapterService adapterService = AdapterService.getAdapterService();
        //check if it is inbound connection in Quiet mode, priority and Bond status
@@ -701,4 +777,6 @@ public class HidService extends ProfileService {
    private native boolean getReportNative(byte[]btAddress, byte reportType, byte reportId, int bufferSize);
    private native boolean setReportNative(byte[] btAddress, byte reportType, String report);
    private native boolean sendDataNative(byte[] btAddress, String report);
    private native boolean setIdleTimeNative(byte[] btAddress, byte idleTime);
    private native boolean getIdleTimeNative(byte[] btAddress);
}