Loading core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -36,3 +36,10 @@ flag { description: "Enable identifying midi device using USB sysfs" bug: "333778731" } flag { name: "enable_udc_sysfs_usb_state_update" namespace: "system_sw_usb" description: "Enable usb state update based on udc sysfs" bug: "339241080" } core/res/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -7090,4 +7090,7 @@ <!-- Whether to show GAIA education screen during account login of private space setup. OEM/Partner can explicitly opt to disable the screen. --> <bool name="config_enableGaiaEducationInPrivateSpace">true</bool> <!-- Whether to enable usb state update via udc sysfs. --> <bool name="config_enableUdcSysfsUsbStateUpdate">false</bool> </resources> core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -523,6 +523,7 @@ <java-symbol type="integer" name="config_defaultAnalogClockSecondsHandFps"/> <java-symbol type="bool" name="config_notificationCloseButtonSupported"/> <java-symbol type="bool" name="config_enableGaiaEducationInPrivateSpace"/> <java-symbol type="bool" name="config_enableUdcSysfsUsbStateUpdate"/> <java-symbol type="color" name="tab_indicator_text_v4" /> Loading services/core/jni/com_android_server_UsbDeviceManager.cpp +193 −14 Original line number Diff line number Diff line Loading @@ -15,33 +15,168 @@ */ #define LOG_TAG "UsbDeviceManagerJNI" #include "utils/Log.h" #include "jni.h" #include <android-base/properties.h> #include <android-base/unique_fd.h> #include <core_jni_helpers.h> #include <fcntl.h> #include <linux/usb/f_accessory.h> #include <nativehelper/JNIPlatformHelp.h> #include <nativehelper/ScopedUtfChars.h> #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "MtpDescriptors.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/epoll.h> #include <sys/ioctl.h> #include <linux/usb/f_accessory.h> #include <sys/stat.h> #include <sys/types.h> #include <thread> #include "MtpDescriptors.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "jni.h" #include "utils/Log.h" #define DRIVER_NAME "/dev/usb_accessory" #define EPOLL_MAX_EVENTS 4 #define USB_STATE_MAX_LEN 20 namespace android { static JavaVM *gvm = nullptr; static jmethodID gUpdateGadgetStateMethod; static struct parcel_file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; } gParcelFileDescriptorOffsets; /* * NativeGadgetMonitorThread starts a new thread to monitor udc state by epoll, * convert and update the state to UsbDeviceManager. */ class NativeGadgetMonitorThread { android::base::unique_fd mMonitorFd; int mPipefd[2]; std::thread mThread; jobject mCallbackObj; std::string mGadgetState; void handleStateUpdate(const char *state) { JNIEnv *env = AndroidRuntime::getJNIEnv(); std::string gadgetState; if (!std::strcmp(state, "not attached\n")) { gadgetState = "DISCONNECTED"; } else if (!std::strcmp(state, "attached\n") || !std::strcmp(state, "powered\n") || !std::strcmp(state, "default\n") || !std::strcmp(state, "addressed\n")) { gadgetState = "CONNECTED"; } else if (!std::strcmp(state, "configured\n")) { gadgetState = "CONFIGURED"; } else if (!std::strcmp(state, "suspended\n")) { return; } else { ALOGE("Unknown gadget state %s", state); return; } if (mGadgetState.compare(gadgetState)) { mGadgetState = gadgetState; jstring obj = env->NewStringUTF(gadgetState.c_str()); env->CallVoidMethod(mCallbackObj, gUpdateGadgetStateMethod, obj); } } int setupEpoll(android::base::unique_fd &epollFd) { struct epoll_event ev; ev.data.fd = mMonitorFd.get(); ev.events = EPOLLPRI; if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, mMonitorFd.get(), &ev) != 0) { ALOGE("epoll_ctl failed for monitor fd; errno=%d", errno); return errno; } ev.data.fd = mPipefd[0]; ev.events = EPOLLIN; if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, mPipefd[0], &ev) != 0) { ALOGE("epoll_ctl failed for pipe fd; errno=%d", errno); return errno; } return 0; } void monitorLoop() { android::base::unique_fd epollFd(epoll_create(EPOLL_MAX_EVENTS)); if (epollFd.get() == -1) { ALOGE("epoll_create failed; errno=%d", errno); return; } if (setupEpoll(epollFd) != 0) return; JNIEnv *env = nullptr; JavaVMAttachArgs aargs = {JNI_VERSION_1_4, "NativeGadgetMonitorThread", nullptr}; if (gvm->AttachCurrentThread(&env, &aargs) != JNI_OK || env == nullptr) { ALOGE("Couldn't attach thread"); return; } struct epoll_event events[EPOLL_MAX_EVENTS]; int nevents = 0; while (true) { nevents = epoll_wait(epollFd.get(), events, EPOLL_MAX_EVENTS, -1); if (nevents < 0) { ALOGE("usb epoll_wait failed; errno=%d", errno); continue; } for (int i = 0; i < nevents; ++i) { int fd = events[i].data.fd; if (fd == mPipefd[0]) { goto exit; } else if (fd == mMonitorFd.get()) { char state[USB_STATE_MAX_LEN] = {0}; lseek(fd, 0, SEEK_SET); read(fd, &state, USB_STATE_MAX_LEN); handleStateUpdate(state); } } } exit: auto res = gvm->DetachCurrentThread(); ALOGE_IF(res != JNI_OK, "Couldn't detach thread"); return; } void stop() { if (mThread.joinable()) { int c = 'q'; write(mPipefd[1], &c, 1); mThread.join(); } } DISALLOW_COPY_AND_ASSIGN(NativeGadgetMonitorThread); public: explicit NativeGadgetMonitorThread(jobject obj, android::base::unique_fd monitorFd) : mMonitorFd(std::move(monitorFd)), mGadgetState("") { mCallbackObj = AndroidRuntime::getJNIEnv()->NewGlobalRef(obj); pipe(mPipefd); mThread = std::thread(&NativeGadgetMonitorThread::monitorLoop, this); } ~NativeGadgetMonitorThread() { stop(); close(mPipefd[0]); close(mPipefd[1]); AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mCallbackObj); } }; static std::unique_ptr<NativeGadgetMonitorThread> sGadgetMonitorThread; static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) { char buffer[256]; Loading Loading @@ -135,6 +270,41 @@ static jobject android_server_UsbDeviceManager_openControl(JNIEnv *env, jobject return jifd; } static jboolean android_server_UsbDeviceManager_startGadgetMonitor(JNIEnv *env, jobject thiz, jstring jUdcName) { std::string filePath; ScopedUtfChars udcName(env, jUdcName); filePath = "/sys/class/udc/" + std::string(udcName.c_str()) + "/state"; android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY)); if (fd.get() == -1) { ALOGE("Cannot open %s", filePath.c_str()); return JNI_FALSE; } ALOGI("Start monitoring %s", filePath.c_str()); sGadgetMonitorThread.reset(new NativeGadgetMonitorThread(thiz, std::move(fd))); return JNI_TRUE; } static void android_server_UsbDeviceManager_stopGadgetMonitor(JNIEnv *env, jobject /* thiz */) { sGadgetMonitorThread.reset(); return; } static jstring android_server_UsbDeviceManager_waitAndGetProperty(JNIEnv *env, jobject thiz, jstring jPropName) { ScopedUtfChars propName(env, jPropName); std::string propValue; while (!android::base::WaitForPropertyCreation(propName.c_str())); propValue = android::base::GetProperty(propName.c_str(), "" /* default */); return env->NewStringUTF(propValue.c_str()); } static const JNINativeMethod method_table[] = { {"nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void *)android_server_UsbDeviceManager_getAccessoryStrings}, Loading @@ -143,16 +313,26 @@ static const JNINativeMethod method_table[] = { {"nativeIsStartRequested", "()Z", (void *)android_server_UsbDeviceManager_isStartRequested}, {"nativeOpenControl", "(Ljava/lang/String;)Ljava/io/FileDescriptor;", (void *)android_server_UsbDeviceManager_openControl}, {"nativeStartGadgetMonitor", "(Ljava/lang/String;)Z", (void *)android_server_UsbDeviceManager_startGadgetMonitor}, {"nativeStopGadgetMonitor", "()V", (void *)android_server_UsbDeviceManager_stopGadgetMonitor}, {"nativeWaitAndGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_server_UsbDeviceManager_waitAndGetProperty}, }; int register_android_server_UsbDeviceManager(JNIEnv *env) { int register_android_server_UsbDeviceManager(JavaVM *vm, JNIEnv *env) { gvm = vm; jclass clazz = env->FindClass("com/android/server/usb/UsbDeviceManager"); if (clazz == NULL) { ALOGE("Can't find com/android/server/usb/UsbDeviceManager"); return -1; } gUpdateGadgetStateMethod = GetMethodIDOrDie(env, clazz, "updateGadgetState", "(Ljava/lang/String;)V"); clazz = env->FindClass("android/os/ParcelFileDescriptor"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); Loading @@ -163,5 +343,4 @@ int register_android_server_UsbDeviceManager(JNIEnv *env) return jniRegisterNativeMethods(env, "com/android/server/usb/UsbDeviceManager", method_table, NELEM(method_table)); } }; services/core/jni/onload.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ int register_android_server_SerialService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); int register_android_server_UsbAlsaJackDetector(JNIEnv* env); int register_android_server_UsbAlsaMidiDevice(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbDeviceManager(JavaVM* vm, JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_vr_VrManagerService(JNIEnv* env); int register_android_server_vibrator_VibratorController(JavaVM* vm, JNIEnv* env); Loading Loading @@ -96,7 +96,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_SerialService(env); register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_UsbDeviceManager(env); register_android_server_UsbDeviceManager(vm, env); register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbAlsaMidiDevice(env); register_android_server_UsbHostManager(env); Loading Loading
core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -36,3 +36,10 @@ flag { description: "Enable identifying midi device using USB sysfs" bug: "333778731" } flag { name: "enable_udc_sysfs_usb_state_update" namespace: "system_sw_usb" description: "Enable usb state update based on udc sysfs" bug: "339241080" }
core/res/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -7090,4 +7090,7 @@ <!-- Whether to show GAIA education screen during account login of private space setup. OEM/Partner can explicitly opt to disable the screen. --> <bool name="config_enableGaiaEducationInPrivateSpace">true</bool> <!-- Whether to enable usb state update via udc sysfs. --> <bool name="config_enableUdcSysfsUsbStateUpdate">false</bool> </resources>
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -523,6 +523,7 @@ <java-symbol type="integer" name="config_defaultAnalogClockSecondsHandFps"/> <java-symbol type="bool" name="config_notificationCloseButtonSupported"/> <java-symbol type="bool" name="config_enableGaiaEducationInPrivateSpace"/> <java-symbol type="bool" name="config_enableUdcSysfsUsbStateUpdate"/> <java-symbol type="color" name="tab_indicator_text_v4" /> Loading
services/core/jni/com_android_server_UsbDeviceManager.cpp +193 −14 Original line number Diff line number Diff line Loading @@ -15,33 +15,168 @@ */ #define LOG_TAG "UsbDeviceManagerJNI" #include "utils/Log.h" #include "jni.h" #include <android-base/properties.h> #include <android-base/unique_fd.h> #include <core_jni_helpers.h> #include <fcntl.h> #include <linux/usb/f_accessory.h> #include <nativehelper/JNIPlatformHelp.h> #include <nativehelper/ScopedUtfChars.h> #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "MtpDescriptors.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/epoll.h> #include <sys/ioctl.h> #include <linux/usb/f_accessory.h> #include <sys/stat.h> #include <sys/types.h> #include <thread> #include "MtpDescriptors.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/Log.h" #include "jni.h" #include "utils/Log.h" #define DRIVER_NAME "/dev/usb_accessory" #define EPOLL_MAX_EVENTS 4 #define USB_STATE_MAX_LEN 20 namespace android { static JavaVM *gvm = nullptr; static jmethodID gUpdateGadgetStateMethod; static struct parcel_file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; } gParcelFileDescriptorOffsets; /* * NativeGadgetMonitorThread starts a new thread to monitor udc state by epoll, * convert and update the state to UsbDeviceManager. */ class NativeGadgetMonitorThread { android::base::unique_fd mMonitorFd; int mPipefd[2]; std::thread mThread; jobject mCallbackObj; std::string mGadgetState; void handleStateUpdate(const char *state) { JNIEnv *env = AndroidRuntime::getJNIEnv(); std::string gadgetState; if (!std::strcmp(state, "not attached\n")) { gadgetState = "DISCONNECTED"; } else if (!std::strcmp(state, "attached\n") || !std::strcmp(state, "powered\n") || !std::strcmp(state, "default\n") || !std::strcmp(state, "addressed\n")) { gadgetState = "CONNECTED"; } else if (!std::strcmp(state, "configured\n")) { gadgetState = "CONFIGURED"; } else if (!std::strcmp(state, "suspended\n")) { return; } else { ALOGE("Unknown gadget state %s", state); return; } if (mGadgetState.compare(gadgetState)) { mGadgetState = gadgetState; jstring obj = env->NewStringUTF(gadgetState.c_str()); env->CallVoidMethod(mCallbackObj, gUpdateGadgetStateMethod, obj); } } int setupEpoll(android::base::unique_fd &epollFd) { struct epoll_event ev; ev.data.fd = mMonitorFd.get(); ev.events = EPOLLPRI; if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, mMonitorFd.get(), &ev) != 0) { ALOGE("epoll_ctl failed for monitor fd; errno=%d", errno); return errno; } ev.data.fd = mPipefd[0]; ev.events = EPOLLIN; if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, mPipefd[0], &ev) != 0) { ALOGE("epoll_ctl failed for pipe fd; errno=%d", errno); return errno; } return 0; } void monitorLoop() { android::base::unique_fd epollFd(epoll_create(EPOLL_MAX_EVENTS)); if (epollFd.get() == -1) { ALOGE("epoll_create failed; errno=%d", errno); return; } if (setupEpoll(epollFd) != 0) return; JNIEnv *env = nullptr; JavaVMAttachArgs aargs = {JNI_VERSION_1_4, "NativeGadgetMonitorThread", nullptr}; if (gvm->AttachCurrentThread(&env, &aargs) != JNI_OK || env == nullptr) { ALOGE("Couldn't attach thread"); return; } struct epoll_event events[EPOLL_MAX_EVENTS]; int nevents = 0; while (true) { nevents = epoll_wait(epollFd.get(), events, EPOLL_MAX_EVENTS, -1); if (nevents < 0) { ALOGE("usb epoll_wait failed; errno=%d", errno); continue; } for (int i = 0; i < nevents; ++i) { int fd = events[i].data.fd; if (fd == mPipefd[0]) { goto exit; } else if (fd == mMonitorFd.get()) { char state[USB_STATE_MAX_LEN] = {0}; lseek(fd, 0, SEEK_SET); read(fd, &state, USB_STATE_MAX_LEN); handleStateUpdate(state); } } } exit: auto res = gvm->DetachCurrentThread(); ALOGE_IF(res != JNI_OK, "Couldn't detach thread"); return; } void stop() { if (mThread.joinable()) { int c = 'q'; write(mPipefd[1], &c, 1); mThread.join(); } } DISALLOW_COPY_AND_ASSIGN(NativeGadgetMonitorThread); public: explicit NativeGadgetMonitorThread(jobject obj, android::base::unique_fd monitorFd) : mMonitorFd(std::move(monitorFd)), mGadgetState("") { mCallbackObj = AndroidRuntime::getJNIEnv()->NewGlobalRef(obj); pipe(mPipefd); mThread = std::thread(&NativeGadgetMonitorThread::monitorLoop, this); } ~NativeGadgetMonitorThread() { stop(); close(mPipefd[0]); close(mPipefd[1]); AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mCallbackObj); } }; static std::unique_ptr<NativeGadgetMonitorThread> sGadgetMonitorThread; static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) { char buffer[256]; Loading Loading @@ -135,6 +270,41 @@ static jobject android_server_UsbDeviceManager_openControl(JNIEnv *env, jobject return jifd; } static jboolean android_server_UsbDeviceManager_startGadgetMonitor(JNIEnv *env, jobject thiz, jstring jUdcName) { std::string filePath; ScopedUtfChars udcName(env, jUdcName); filePath = "/sys/class/udc/" + std::string(udcName.c_str()) + "/state"; android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY)); if (fd.get() == -1) { ALOGE("Cannot open %s", filePath.c_str()); return JNI_FALSE; } ALOGI("Start monitoring %s", filePath.c_str()); sGadgetMonitorThread.reset(new NativeGadgetMonitorThread(thiz, std::move(fd))); return JNI_TRUE; } static void android_server_UsbDeviceManager_stopGadgetMonitor(JNIEnv *env, jobject /* thiz */) { sGadgetMonitorThread.reset(); return; } static jstring android_server_UsbDeviceManager_waitAndGetProperty(JNIEnv *env, jobject thiz, jstring jPropName) { ScopedUtfChars propName(env, jPropName); std::string propValue; while (!android::base::WaitForPropertyCreation(propName.c_str())); propValue = android::base::GetProperty(propName.c_str(), "" /* default */); return env->NewStringUTF(propValue.c_str()); } static const JNINativeMethod method_table[] = { {"nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void *)android_server_UsbDeviceManager_getAccessoryStrings}, Loading @@ -143,16 +313,26 @@ static const JNINativeMethod method_table[] = { {"nativeIsStartRequested", "()Z", (void *)android_server_UsbDeviceManager_isStartRequested}, {"nativeOpenControl", "(Ljava/lang/String;)Ljava/io/FileDescriptor;", (void *)android_server_UsbDeviceManager_openControl}, {"nativeStartGadgetMonitor", "(Ljava/lang/String;)Z", (void *)android_server_UsbDeviceManager_startGadgetMonitor}, {"nativeStopGadgetMonitor", "()V", (void *)android_server_UsbDeviceManager_stopGadgetMonitor}, {"nativeWaitAndGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_server_UsbDeviceManager_waitAndGetProperty}, }; int register_android_server_UsbDeviceManager(JNIEnv *env) { int register_android_server_UsbDeviceManager(JavaVM *vm, JNIEnv *env) { gvm = vm; jclass clazz = env->FindClass("com/android/server/usb/UsbDeviceManager"); if (clazz == NULL) { ALOGE("Can't find com/android/server/usb/UsbDeviceManager"); return -1; } gUpdateGadgetStateMethod = GetMethodIDOrDie(env, clazz, "updateGadgetState", "(Ljava/lang/String;)V"); clazz = env->FindClass("android/os/ParcelFileDescriptor"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); Loading @@ -163,5 +343,4 @@ int register_android_server_UsbDeviceManager(JNIEnv *env) return jniRegisterNativeMethods(env, "com/android/server/usb/UsbDeviceManager", method_table, NELEM(method_table)); } };
services/core/jni/onload.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ int register_android_server_SerialService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); int register_android_server_UsbAlsaJackDetector(JNIEnv* env); int register_android_server_UsbAlsaMidiDevice(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbDeviceManager(JavaVM* vm, JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_vr_VrManagerService(JNIEnv* env); int register_android_server_vibrator_VibratorController(JavaVM* vm, JNIEnv* env); Loading Loading @@ -96,7 +96,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_SerialService(env); register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_UsbDeviceManager(env); register_android_server_UsbDeviceManager(vm, env); register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbAlsaMidiDevice(env); register_android_server_UsbHostManager(env); Loading