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" 22ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.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 3220a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#if defined(__linux__) 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{ 4220a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#if defined(__linux__) 4320a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui return (jint)inotify_init(); 4420a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#else 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4620a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#endif 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5120a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#if defined(__linux__) 5220a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char event_buf[512]; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct inotify_event* event; 5520a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (1) 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event_pos = 0; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int num_bytes = read(fd, event_buf, sizeof(event_buf)); 6020a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (num_bytes < (int)sizeof(*event)) 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errno == EINTR) 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 663762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("***** ERROR! android_os_fileobserver_observe() got a short event!"); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6920a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 7059d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood while (num_bytes >= (int)sizeof(*event)) 7159d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood { 7259d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood int event_size; 7359d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood event = (struct inotify_event *)(event_buf + event_pos); 7459d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jstring path = NULL; 7620a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event->len > 0) 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path = env->NewStringUTF(event->name); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8159d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood 8259d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path); 8359d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood if (env->ExceptionCheck()) { 8459d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood env->ExceptionDescribe(); 8559d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood env->ExceptionClear(); 8659d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood } 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 } 9159d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood 9259d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood event_size = sizeof(*event) + event->len; 9359d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood num_bytes -= event_size; 9459d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood event_pos += event_size; 9559d25d00a17cc41d3b4416f9c90b29fe8e349645Mike Lockwood } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9720a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 9820a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#endif 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; 10420a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 10520a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#if defined(__linux__) 10620a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 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); 11020a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = inotify_add_watch(fd, path, mask); 11220a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(pathString, path); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11620a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#endif 11720a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 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{ 12320a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#if defined(__linux__) 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inotify_rm_watch((int)fd, (uint32_t)wfd); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12720a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui#endif 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const 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 } 13620a9cf4fe40a7bf605681e28a5e7fca329f8624bYabin Cui 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{ 141ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe jclass clazz = FindClassOrDie(env, "android/os/FileObserver$ObserverThread"); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 143ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe method_onEvent = GetMethodIDOrDie(env, clazz, "onEvent", "(IILjava/lang/String;)V"); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 145ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, "android/os/FileObserver$ObserverThread", sMethods, 146ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe NELEM(sMethods)); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} /* namespace android */ 150