blob: 578788c0f8d27a69a67324c7f27a7b0358258214 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //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
Steven Moreland2279b252017-07-19 09:50:45 -070018#include <nativehelper/JNIHelp.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#include "jni.h"
20#include "utils/Log.h"
21#include "utils/misc.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080022#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
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
Yabin Cui20a9cf42014-11-10 15:43:18 -080032#if defined(__linux__)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033#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{
Yabin Cui20a9cf42014-11-10 15:43:18 -080042#if defined(__linux__)
Nick Kralevich4b3a08c2019-01-28 10:39:10 -080043 return (jint)inotify_init1(IN_CLOEXEC);
Yabin Cui20a9cf42014-11-10 15:43:18 -080044#else
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 return -1;
Yabin Cui20a9cf42014-11-10 15:43:18 -080046#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047}
48
49static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd)
50{
Yabin Cui20a9cf42014-11-10 15:43:18 -080051#if defined(__linux__)
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 char event_buf[512];
54 struct inotify_event* event;
Yabin Cui20a9cf42014-11-10 15:43:18 -080055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 while (1)
57 {
58 int event_pos = 0;
59 int num_bytes = read(fd, event_buf, sizeof(event_buf));
Yabin Cui20a9cf42014-11-10 15:43:18 -080060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 if (num_bytes < (int)sizeof(*event))
62 {
63 if (errno == EINTR)
64 continue;
65
Steve Block3762c312012-01-06 19:20:56 +000066 ALOGE("***** ERROR! android_os_fileobserver_observe() got a short event!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 return;
68 }
Yabin Cui20a9cf42014-11-10 15:43:18 -080069
Mike Lockwood59d25d02010-02-18 07:01:28 -050070 while (num_bytes >= (int)sizeof(*event))
71 {
72 int event_size;
73 event = (struct inotify_event *)(event_buf + event_pos);
74
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 jstring path = NULL;
Yabin Cui20a9cf42014-11-10 15:43:18 -080076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 if (event->len > 0)
78 {
79 path = env->NewStringUTF(event->name);
80 }
Mike Lockwood59d25d02010-02-18 07:01:28 -050081
82 env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);
83 if (env->ExceptionCheck()) {
84 env->ExceptionDescribe();
85 env->ExceptionClear();
86 }
The Android Open Source Projectb22d55b2009-03-05 15:45:10 -080087 if (path != NULL)
88 {
89 env->DeleteLocalRef(path);
90 }
Mike Lockwood59d25d02010-02-18 07:01:28 -050091
92 event_size = sizeof(*event) + event->len;
93 num_bytes -= event_size;
94 event_pos += event_size;
95 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 }
Yabin Cui20a9cf42014-11-10 15:43:18 -080097
98#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099}
100
101static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask)
102{
103 int res = -1;
Yabin Cui20a9cf42014-11-10 15:43:18 -0800104
105#if defined(__linux__)
106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 if (fd >= 0)
108 {
109 const char* path = env->GetStringUTFChars(pathString, NULL);
Yabin Cui20a9cf42014-11-10 15:43:18 -0800110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 res = inotify_add_watch(fd, path, mask);
Yabin Cui20a9cf42014-11-10 15:43:18 -0800112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 env->ReleaseStringUTFChars(pathString, path);
114 }
115
Yabin Cui20a9cf42014-11-10 15:43:18 -0800116#endif
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 return res;
119}
120
121static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd)
122{
Yabin Cui20a9cf42014-11-10 15:43:18 -0800123#if defined(__linux__)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
125 inotify_rm_watch((int)fd, (uint32_t)wfd);
126
Yabin Cui20a9cf42014-11-10 15:43:18 -0800127#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128}
129
Daniel Micay76f6a862015-09-19 17:31:01 -0400130static const JNINativeMethod sMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 /* name, signature, funcPtr */
132 { "init", "()I", (void*)android_os_fileobserver_init },
133 { "observe", "(I)V", (void*)android_os_fileobserver_observe },
134 { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching },
135 { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching }
Yabin Cui20a9cf42014-11-10 15:43:18 -0800136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137};
138
139int register_android_os_FileObserver(JNIEnv* env)
140{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800141 jclass clazz = FindClassOrDie(env, "android/os/FileObserver$ObserverThread");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800143 method_onEvent = GetMethodIDOrDie(env, clazz, "onEvent", "(IILjava/lang/String;)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800145 return RegisterMethodsOrDie(env, "android/os/FileObserver$ObserverThread", sMethods,
146 NELEM(sMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147}
148
149} /* namespace android */