/* * Copyright (C) 2010 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. */ #define LOG_TAG "UsbDeviceManagerJNI" #include "utils/Log.h" #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include #include #include #include #include #include #include #define DRIVER_NAME "/dev/usb_accessory" namespace android { static struct parcel_file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; } gParcelFileDescriptorOffsets; static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { ALOGE("An exception was thrown by callback '%s'.", methodName); LOGE_EX(env); env->ExceptionClear(); } } static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) { char buffer[256]; buffer[0] = 0; int length = ioctl(fd, cmd, buffer); if (buffer[0]) { jstring obj = env->NewStringUTF(buffer); env->SetObjectArrayElement(strArray, index, obj); env->DeleteLocalRef(obj); } } static jobjectArray android_server_UsbDeviceManager_getAccessoryStrings(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { ALOGE("could not open %s", DRIVER_NAME); return NULL; } jclass stringClass = env->FindClass("java/lang/String"); jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL); if (!strArray) goto out; set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5); out: close(fd); return strArray; } static jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { ALOGE("could not open %s", DRIVER_NAME); return NULL; } jobject fileDescriptor = jniCreateFileDescriptor(env, fd); if (fileDescriptor == NULL) { return NULL; } return env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); } static jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { ALOGE("could not open %s", DRIVER_NAME); return false; } int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED); close(fd); return (result == 1); } static jint android_server_UsbDeviceManager_getAudioMode(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { ALOGE("could not open %s", DRIVER_NAME); return false; } int result = ioctl(fd, ACCESSORY_GET_AUDIO_MODE); close(fd); return result; } static JNINativeMethod method_table[] = { { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void*)android_server_UsbDeviceManager_getAccessoryStrings }, { "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;", (void*)android_server_UsbDeviceManager_openAccessory }, { "nativeIsStartRequested", "()Z", (void*)android_server_UsbDeviceManager_isStartRequested }, { "nativeGetAudioMode", "()I", (void*)android_server_UsbDeviceManager_getAudioMode }, }; int register_android_server_UsbDeviceManager(JNIEnv *env) { jclass clazz = env->FindClass("com/android/server/usb/UsbDeviceManager"); if (clazz == NULL) { ALOGE("Can't find com/android/server/usb/UsbDeviceManager"); return -1; } clazz = env->FindClass("android/os/ParcelFileDescriptor"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "", "(Ljava/io/FileDescriptor;)V"); LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, "Unable to find constructor for android.os.ParcelFileDescriptor"); return jniRegisterNativeMethods(env, "com/android/server/usb/UsbDeviceManager", method_table, NELEM(method_table)); } };