android_util_FileObserver.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* //device/libs/android_runtime/android_util_FileObserver.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "JNIHelp.h" 19#include "jni.h" 20#include "utils/Log.h" 21#include "utils/misc.h" 22#include "android_runtime/AndroidRuntime.h" 23 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27#include <stdint.h> 28#include <fcntl.h> 29#include <sys/ioctl.h> 30#include <errno.h> 31 32#ifdef HAVE_INOTIFY 33#include <sys/inotify.h> 34#endif 35 36namespace android { 37 38static jmethodID method_onEvent; 39 40static jint android_os_fileobserver_init(JNIEnv* env, jobject object) 41{ 42#ifdef HAVE_INOTIFY 43 44 return (jint)inotify_init(); 45 46#else // HAVE_INOTIFY 47 48 return -1; 49 50#endif // HAVE_INOTIFY 51} 52 53static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd) 54{ 55#ifdef HAVE_INOTIFY 56 57 char event_buf[512]; 58 struct inotify_event* event; 59 60 while (1) 61 { 62 int event_pos = 0; 63 int num_bytes = read(fd, event_buf, sizeof(event_buf)); 64 65 if (num_bytes < (int)sizeof(*event)) 66 { 67 if (errno == EINTR) 68 continue; 69 70 LOGE("***** ERROR! android_os_fileobserver_observe() got a short event!"); 71 return; 72 } 73 74 while (num_bytes >= (int)sizeof(*event)) 75 { 76 int event_size; 77 event = (struct inotify_event *)(event_buf + event_pos); 78 79 jstring path = NULL; 80 81 if (event->len > 0) 82 { 83 path = env->NewStringUTF(event->name); 84 } 85 86 env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path); 87 88 event_size = sizeof(*event) + event->len; 89 num_bytes -= event_size; 90 event_pos += event_size; 91 } 92 } 93 94#endif // HAVE_INOTIFY 95} 96 97static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask) 98{ 99 int res = -1; 100 101#ifdef HAVE_INOTIFY 102 103 if (fd >= 0) 104 { 105 const char* path = env->GetStringUTFChars(pathString, NULL); 106 107 res = inotify_add_watch(fd, path, mask); 108 109 env->ReleaseStringUTFChars(pathString, path); 110 } 111 112#endif // HAVE_INOTIFY 113 114 return res; 115} 116 117static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd) 118{ 119#ifdef HAVE_INOTIFY 120 121 inotify_rm_watch((int)fd, (uint32_t)wfd); 122 123#endif // HAVE_INOTIFY 124} 125 126static JNINativeMethod sMethods[] = { 127 /* name, signature, funcPtr */ 128 { "init", "()I", (void*)android_os_fileobserver_init }, 129 { "observe", "(I)V", (void*)android_os_fileobserver_observe }, 130 { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching }, 131 { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching } 132 133}; 134 135int register_android_os_FileObserver(JNIEnv* env) 136{ 137 jclass clazz; 138 139 clazz = env->FindClass("android/os/FileObserver$ObserverThread"); 140 141 if (clazz == NULL) 142 { 143 LOGE("Can't find android/os/FileObserver$ObserverThread"); 144 return -1; 145 } 146 147 method_onEvent = env->GetMethodID(clazz, "onEvent", "(IILjava/lang/String;)V"); 148 if (method_onEvent == NULL) 149 { 150 LOGE("Can't find FileObserver.onEvent(int, int, String)"); 151 return -1; 152 } 153 154 return AndroidRuntime::registerNativeMethods(env, "android/os/FileObserver$ObserverThread", sMethods, NELEM(sMethods)); 155} 156 157} /* namespace android */ 158