19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* //device/libs/android_runtime/android_util_FileObserver.cpp 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/Log.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/ioctl.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_INOTIFY 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/inotify.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID method_onEvent; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_fileobserver_init(JNIEnv* env, jobject object) 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_INOTIFY 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)inotify_init(); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else // HAVE_INOTIFY 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif // HAVE_INOTIFY 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd) 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_INOTIFY 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char event_buf[512]; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct inotify_event* event; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (1) 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event_pos = 0; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int num_bytes = read(fd, event_buf, sizeof(event_buf)); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (num_bytes < (int)sizeof(*event)) 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errno == EINTR) 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("***** ERROR! android_os_fileobserver_observe() got a short event!"); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (num_bytes >= (int)sizeof(*event)) 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event_size; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = (struct inotify_event *)(event_buf + event_pos); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jstring path = NULL; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event->len > 0) 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path = env->NewStringUTF(event->name); 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path); 87b22d55b9f8048b2a1ed99b90894c19388bebd7aeThe Android Open Source Project if (path != NULL) 88b22d55b9f8048b2a1ed99b90894c19388bebd7aeThe Android Open Source Project { 89b22d55b9f8048b2a1ed99b90894c19388bebd7aeThe Android Open Source Project env->DeleteLocalRef(path); 90b22d55b9f8048b2a1ed99b90894c19388bebd7aeThe Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event_size = sizeof(*event) + event->len; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project num_bytes -= event_size; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event_pos += event_size; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif // HAVE_INOTIFY 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask) 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res = -1; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_INOTIFY 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd >= 0) 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* path = env->GetStringUTFChars(pathString, NULL); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = inotify_add_watch(fd, path, mask); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(pathString, path); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif // HAVE_INOTIFY 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd) 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_INOTIFY 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inotify_rm_watch((int)fd, (uint32_t)wfd); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif // HAVE_INOTIFY 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "init", "()I", (void*)android_os_fileobserver_init }, 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "observe", "(I)V", (void*)android_os_fileobserver_observe }, 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching }, 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_FileObserver(JNIEnv* env) 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/os/FileObserver$ObserverThread"); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find android/os/FileObserver$ObserverThread"); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method_onEvent = env->GetMethodID(clazz, "onEvent", "(IILjava/lang/String;)V"); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method_onEvent == NULL) 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find FileObserver.onEvent(int, int, String)"); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/os/FileObserver$ObserverThread", sMethods, NELEM(sMethods)); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} /* namespace android */ 162