19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "UEventObserver" 189cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown//#define LOG_NDEBUG 0 199cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/Log.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "hardware_legacy/uevent.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h" 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown#include <utils/Mutex.h> 289cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown#include <utils/Vector.h> 299cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown#include <utils/String8.h> 309cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown#include <ScopedUtfChars.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownnamespace android { 339cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 349cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic Mutex gMatchesMutex; 359cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic Vector<String8> gMatches; 369cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 379cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic void nativeSetup(JNIEnv *env, jclass clazz) { 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!uevent_init()) { 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/RuntimeException", 409cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown "Unable to open socket for UEventObserver"); 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic bool isMatch(const char* buffer, size_t length) { 459cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown AutoMutex _l(gMatchesMutex); 469cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 479cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown for (size_t i = 0; i < gMatches.size(); i++) { 489cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown const String8& match = gMatches.itemAt(i); 499cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 509cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown // Consider all zero-delimited fields of the buffer. 519cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown const char* field = buffer; 52c51cb89dd64cf366c162cf0fed4ba893f5c3e985Jeff Brown const char* end = buffer + length + 1; 539cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown do { 549cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown if (strstr(field, match.string())) { 559cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown ALOGV("Matched uevent message with pattern: %s", match.string()); 569cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown return true; 579cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 589cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown field += strlen(field) + 1; 599cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } while (field != end); 609cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 619cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown return false; 629cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown} 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) { 659cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown char buffer[1024]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown for (;;) { 689cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown int length = uevent_next_event(buffer, sizeof(buffer) - 1); 699cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown if (length <= 0) { 709cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown return NULL; 719cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 729cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown buffer[length] = '\0'; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown ALOGV("Received uevent message: %s", buffer); 759cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 769cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown if (isMatch(buffer, length)) { 779cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown // Assume the message is ASCII. 789cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown jchar message[length]; 799cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown for (int i = 0; i < length; i++) { 809cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown message[i] = buffer[i]; 819cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 829cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown return env->NewString(message, length); 839cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 849cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 859cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown} 869cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 879cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic void nativeAddMatch(JNIEnv* env, jclass clazz, jstring matchStr) { 889cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown ScopedUtfChars match(env, matchStr); 899cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 909cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown AutoMutex _l(gMatchesMutex); 919cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown gMatches.add(String8(match.c_str())); 929cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown} 939cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 949cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brownstatic void nativeRemoveMatch(JNIEnv* env, jclass clazz, jstring matchStr) { 959cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown ScopedUtfChars match(env, matchStr); 969cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown 979cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown AutoMutex _l(gMatchesMutex); 989cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown for (size_t i = 0; i < gMatches.size(); i++) { 999cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown if (gMatches.itemAt(i) == match.c_str()) { 1009cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown gMatches.removeAt(i); 1019cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown break; // only remove first occurrence 1029cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 1039cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 1079cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown { "nativeSetup", "()V", 1089cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown (void *)nativeSetup }, 1099cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown { "nativeWaitForNextEvent", "()Ljava/lang/String;", 1109cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown (void *)nativeWaitForNextEvent }, 1119cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown { "nativeAddMatch", "(Ljava/lang/String;)V", 1129cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown (void *)nativeAddMatch }, 1139cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown { "nativeRemoveMatch", "(Ljava/lang/String;)V", 1149cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown (void *)nativeRemoveMatch }, 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_UEventObserver(JNIEnv *env) 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/os/UEventObserver"); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 1243762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find android/os/UEventObserver"); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, 1299cf36b7a77bb8e821f9e593fdbb200f8a1742ff0Jeff Brown "android/os/UEventObserver", gMethods, NELEM(gMethods)); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 133