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

Commit abf9557e authored by Daniel Norman's avatar Daniel Norman
Browse files

Adds JNI for accessibility in system_server to perform HIDRAW ioctls.

These are used by the Braille Display HID APIs in the following
change in this topic. That API is hidden behind a flag.

Since these ioctls cannot be tested in automation (without requiring a
real Braille display to be physically connected) this JNI should remain
as very thin wrappers around ioctls that can be replaced by mock
implementations in tests.

The child of this change tests the *usage* of these ioctls (not the
ioctls directly) in BrailleDisplayConnectionTest.

Bug: 303522222
Bug: 316035785
Test: manual (use API in the topic, which invokes these ioctls)
Change-Id: I93f8c117f14f8b15d8bb3396e185e65c5fdebee8
parent 8f5970f5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ cc_library_static {
        "tvinput/BufferProducerThread.cpp",
        "tvinput/JTvInputHal.cpp",
        "tvinput/TvInputHal_hidl.cpp",
        "com_android_server_accessibility_BrailleDisplayConnection.cpp",
        "com_android_server_adb_AdbDebuggingManager.cpp",
        "com_android_server_am_BatteryStatsService.cpp",
        "com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp",
+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ per-file Android.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION
per-file com_android_server_SystemClock* = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file com_android_server_Usb* = file:/services/usb/OWNERS
per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
per-file com_android_server_accessibility_* = file:/services/accessibility/OWNERS
per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
per-file com_android_server_location_* = file:/location/java/android/location/OWNERS
+103 −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.
 */

#include <core_jni_helpers.h>
#include <jni.h>
#include <linux/hidraw.h>
#include <linux/input.h>
#include <nativehelper/JNIHelp.h>
#include <sys/ioctl.h>

/*
 * This file defines simple wrappers around the kernel UAPI HIDRAW driver's ioctl() commands.
 * See kernel example samples/hidraw/hid-example.c
 *
 * All methods expect an open file descriptor int from Java.
 */

namespace android {

namespace {

// Max size we allow for the result from HIDIOCGRAWUNIQ (Bluetooth address or USB serial number).
// Copied from linux/hid.h struct hid_device->uniq char array size; the ioctl implementation
// writes at most this many bytes to the provided buffer.
constexpr int UNIQ_SIZE_MAX = 64;

} // anonymous namespace

static jint com_android_server_accessibility_BrailleDisplayConnection_getHidrawDescSize(
        JNIEnv* env, jobject thiz, int fd) {
    int size = 0;
    if (ioctl(fd, HIDIOCGRDESCSIZE, &size) < 0) {
        return -1;
    }
    return size;
}

static jbyteArray com_android_server_accessibility_BrailleDisplayConnection_getHidrawDesc(
        JNIEnv* env, jobject thiz, int fd, int descSize) {
    struct hidraw_report_descriptor desc;
    desc.size = descSize;
    if (ioctl(fd, HIDIOCGRDESC, &desc) < 0) {
        return nullptr;
    }
    jbyteArray result = env->NewByteArray(descSize);
    if (result != nullptr) {
        env->SetByteArrayRegion(result, 0, descSize, (jbyte*)desc.value);
    }
    // Local ref is not deleted because it is returned to Java
    return result;
}

static jstring com_android_server_accessibility_BrailleDisplayConnection_getHidrawUniq(JNIEnv* env,
                                                                                       jobject thiz,
                                                                                       int fd) {
    char buf[UNIQ_SIZE_MAX];
    if (ioctl(fd, HIDIOCGRAWUNIQ(UNIQ_SIZE_MAX), buf) < 0) {
        return nullptr;
    }
    // Local ref is not deleted because it is returned to Java
    return env->NewStringUTF(buf);
}

static jint com_android_server_accessibility_BrailleDisplayConnection_getHidrawBusType(JNIEnv* env,
                                                                                       jobject thiz,
                                                                                       int fd) {
    struct hidraw_devinfo info;
    if (ioctl(fd, HIDIOCGRAWINFO, &info) < 0) {
        return -1;
    }
    return info.bustype;
}

static const JNINativeMethod gMethods[] = {
        {"nativeGetHidrawDescSize", "(I)I",
         (void*)com_android_server_accessibility_BrailleDisplayConnection_getHidrawDescSize},
        {"nativeGetHidrawDesc", "(II)[B",
         (void*)com_android_server_accessibility_BrailleDisplayConnection_getHidrawDesc},
        {"nativeGetHidrawUniq", "(I)Ljava/lang/String;",
         (void*)com_android_server_accessibility_BrailleDisplayConnection_getHidrawUniq},
        {"nativeGetHidrawBusType", "(I)I",
         (void*)com_android_server_accessibility_BrailleDisplayConnection_getHidrawBusType},
};

int register_com_android_server_accessibility_BrailleDisplayConnection(JNIEnv* env) {
    return RegisterMethodsOrDie(env, "com/android/server/accessibility/BrailleDisplayConnection",
                                gMethods, NELEM(gMethods));
}

}; // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
int register_com_android_server_SystemClockTime(JNIEnv* env);
int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
int register_com_android_server_accessibility_BrailleDisplayConnection(JNIEnv* env);
};

using namespace android;
@@ -132,5 +133,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
    register_com_android_server_display_DisplayControl(env);
    register_com_android_server_SystemClockTime(env);
    register_android_server_display_smallAreaDetectionController(env);
    register_com_android_server_accessibility_BrailleDisplayConnection(env);
    return JNI_VERSION_1_4;
}