Loading api/current.txt +6 −2 Original line number Diff line number Diff line Loading @@ -34408,8 +34408,12 @@ package android.os { } public abstract class FileObserver { ctor public FileObserver(String); ctor public FileObserver(String, int); ctor @Deprecated public FileObserver(String); ctor public FileObserver(@NonNull java.io.File); ctor public FileObserver(@NonNull java.util.List<java.io.File>); ctor @Deprecated public FileObserver(String, int); ctor public FileObserver(@NonNull java.io.File, int); ctor public FileObserver(@NonNull java.util.List<java.io.File>, int); method protected void finalize(); method public abstract void onEvent(int, @Nullable String); method public void startWatching(); core/java/android/os/FileObserver.java +83 −24 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import java.io.File; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; /** * Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>) Loading @@ -28,7 +32,7 @@ import java.util.HashMap; * the device (including this one). FileObserver is an abstract class; * subclasses must implement the event handler {@link #onEvent(int, String)}. * * <p>Each FileObserver instance monitors a single file or directory. * <p>Each FileObserver instance can monitor multiple files or directories. * If a directory is monitored, events will be triggered for all files and * subdirectories inside the monitored directory.</p> * Loading Loading @@ -86,21 +90,32 @@ public abstract class FileObserver { observe(m_fd); } public int startWatching(String path, int mask, FileObserver observer) { int wfd = startWatching(m_fd, path, mask); public int[] startWatching(List<File> files, int mask, FileObserver observer) { final int count = files.size(); final String[] paths = new String[count]; for (int i = 0; i < count; ++i) { paths[i] = files.get(i).getAbsolutePath(); } final int[] wfds = new int[count]; Arrays.fill(wfds, -1); Integer i = new Integer(wfd); if (wfd >= 0) { startWatching(m_fd, paths, mask, wfds); final WeakReference<FileObserver> fileObserverWeakReference = new WeakReference<>(observer); synchronized (m_observers) { m_observers.put(i, new WeakReference(observer)); for (int wfd : wfds) { if (wfd >= 0) { m_observers.put(wfd, fileObserverWeakReference); } } } return i; return wfds; } public void stopWatching(int descriptor) { stopWatching(m_fd, descriptor); public void stopWatching(int[] descriptors) { stopWatching(m_fd, descriptors); } public void onEvent(int wfd, int mask, String path) { Loading Loading @@ -129,8 +144,8 @@ public abstract class FileObserver { private native int init(); private native void observe(int fd); private native int startWatching(int fd, String path, int mask); private native void stopWatching(int fd, int wfd); private native void startWatching(int fd, String[] paths, int mask, int[] wfds); private native void stopWatching(int fd, int[] wfds); } private static ObserverThread s_observerThread; Loading @@ -141,15 +156,34 @@ public abstract class FileObserver { } // instance private String m_path; private Integer m_descriptor; private int m_mask; private final List<File> mFiles; private int[] mDescriptors; private final int mMask; /** * Equivalent to FileObserver(path, FileObserver.ALL_EVENTS). * * @deprecated use {@link #FileObserver(File)} instead. */ @Deprecated public FileObserver(String path) { this(path, ALL_EVENTS); this(new File(path)); } /** * Equivalent to FileObserver(file, FileObserver.ALL_EVENTS). */ public FileObserver(@NonNull File file) { this(Arrays.asList(file)); } /** * Equivalent to FileObserver(paths, FileObserver.ALL_EVENTS). * * @param files The files or directories to monitor */ public FileObserver(@NonNull List<File> files) { this(files, ALL_EVENTS); } /** Loading @@ -159,11 +193,36 @@ public abstract class FileObserver { * * @param path The file or directory to monitor * @param mask The event or events (added together) to watch for * * @deprecated use {@link #FileObserver(File, int)} instead. */ @Deprecated public FileObserver(String path, int mask) { m_path = path; m_mask = mask; m_descriptor = -1; this(new File(path), mask); } /** * Create a new file observer for a certain file or directory. * Monitoring does not start on creation! You must call * {@link #startWatching()} before you will receive events. * * @param file The file or directory to monitor * @param mask The event or events (added together) to watch for */ public FileObserver(@NonNull File file, int mask) { this(Arrays.asList(file), mask); } /** * Version of {@link #FileObserver(File, int)} that allows callers to monitor * multiple files or directories. * * @param files The files or directories to monitor * @param mask The event or events (added together) to watch for */ public FileObserver(@NonNull List<File> files, int mask) { mFiles = files; mMask = mask; } protected void finalize() { Loading @@ -176,8 +235,8 @@ public abstract class FileObserver { * If monitoring is already started, this call has no effect. */ public void startWatching() { if (m_descriptor < 0) { m_descriptor = s_observerThread.startWatching(m_path, m_mask, this); if (mDescriptors == null) { mDescriptors = s_observerThread.startWatching(mFiles, mMask, this); } } Loading @@ -187,9 +246,9 @@ public abstract class FileObserver { * monitoring is already stopped, this call has no effect. */ public void stopWatching() { if (m_descriptor >= 0) { s_observerThread.stopWatching(m_descriptor); m_descriptor = -1; if (mDescriptors != null) { s_observerThread.stopWatching(mDescriptors); mDescriptors = null; } } Loading core/jni/android_util_FileObserver.cpp +27 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ */ #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> #include "jni.h" #include "utils/Log.h" #include "utils/misc.h" Loading Loading @@ -98,31 +100,45 @@ static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd #endif } static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask) static void android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jobjectArray pathStrings, jint mask, jintArray wfdArray) { int res = -1; ScopedIntArrayRW wfds(env, wfdArray); if (wfds.get() == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", "Failed to get ScopedIntArrayRW"); } #if defined(__linux__) if (fd >= 0) { const char* path = env->GetStringUTFChars(pathString, NULL); size_t count = wfds.size(); for (jsize i = 0; i < count; ++i) { jstring pathString = (jstring) env->GetObjectArrayElement(pathStrings, i); res = inotify_add_watch(fd, path, mask); ScopedUtfChars path(env, pathString); env->ReleaseStringUTFChars(pathString, path); wfds[i] = inotify_add_watch(fd, path.c_str(), mask); } } #endif return res; } static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd) static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jintArray wfdArray) { #if defined(__linux__) inotify_rm_watch((int)fd, (uint32_t)wfd); ScopedIntArrayRO wfds(env, wfdArray); if (wfds.get() == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", "Failed to get ScopedIntArrayRO"); } size_t count = wfds.size(); for (size_t i = 0; i < count; ++i) { inotify_rm_watch((int)fd, (uint32_t)wfds[i]); } #endif } Loading @@ -131,8 +147,8 @@ static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ { "init", "()I", (void*)android_os_fileobserver_init }, { "observe", "(I)V", (void*)android_os_fileobserver_observe }, { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching }, { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching } { "startWatching", "(I[Ljava/lang/String;I[I)V", (void*)android_os_fileobserver_startWatching }, { "stopWatching", "(I[I)V", (void*)android_os_fileobserver_stopWatching } }; Loading Loading
api/current.txt +6 −2 Original line number Diff line number Diff line Loading @@ -34408,8 +34408,12 @@ package android.os { } public abstract class FileObserver { ctor public FileObserver(String); ctor public FileObserver(String, int); ctor @Deprecated public FileObserver(String); ctor public FileObserver(@NonNull java.io.File); ctor public FileObserver(@NonNull java.util.List<java.io.File>); ctor @Deprecated public FileObserver(String, int); ctor public FileObserver(@NonNull java.io.File, int); ctor public FileObserver(@NonNull java.util.List<java.io.File>, int); method protected void finalize(); method public abstract void onEvent(int, @Nullable String); method public void startWatching();
core/java/android/os/FileObserver.java +83 −24 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import java.io.File; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; /** * Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>) Loading @@ -28,7 +32,7 @@ import java.util.HashMap; * the device (including this one). FileObserver is an abstract class; * subclasses must implement the event handler {@link #onEvent(int, String)}. * * <p>Each FileObserver instance monitors a single file or directory. * <p>Each FileObserver instance can monitor multiple files or directories. * If a directory is monitored, events will be triggered for all files and * subdirectories inside the monitored directory.</p> * Loading Loading @@ -86,21 +90,32 @@ public abstract class FileObserver { observe(m_fd); } public int startWatching(String path, int mask, FileObserver observer) { int wfd = startWatching(m_fd, path, mask); public int[] startWatching(List<File> files, int mask, FileObserver observer) { final int count = files.size(); final String[] paths = new String[count]; for (int i = 0; i < count; ++i) { paths[i] = files.get(i).getAbsolutePath(); } final int[] wfds = new int[count]; Arrays.fill(wfds, -1); Integer i = new Integer(wfd); if (wfd >= 0) { startWatching(m_fd, paths, mask, wfds); final WeakReference<FileObserver> fileObserverWeakReference = new WeakReference<>(observer); synchronized (m_observers) { m_observers.put(i, new WeakReference(observer)); for (int wfd : wfds) { if (wfd >= 0) { m_observers.put(wfd, fileObserverWeakReference); } } } return i; return wfds; } public void stopWatching(int descriptor) { stopWatching(m_fd, descriptor); public void stopWatching(int[] descriptors) { stopWatching(m_fd, descriptors); } public void onEvent(int wfd, int mask, String path) { Loading Loading @@ -129,8 +144,8 @@ public abstract class FileObserver { private native int init(); private native void observe(int fd); private native int startWatching(int fd, String path, int mask); private native void stopWatching(int fd, int wfd); private native void startWatching(int fd, String[] paths, int mask, int[] wfds); private native void stopWatching(int fd, int[] wfds); } private static ObserverThread s_observerThread; Loading @@ -141,15 +156,34 @@ public abstract class FileObserver { } // instance private String m_path; private Integer m_descriptor; private int m_mask; private final List<File> mFiles; private int[] mDescriptors; private final int mMask; /** * Equivalent to FileObserver(path, FileObserver.ALL_EVENTS). * * @deprecated use {@link #FileObserver(File)} instead. */ @Deprecated public FileObserver(String path) { this(path, ALL_EVENTS); this(new File(path)); } /** * Equivalent to FileObserver(file, FileObserver.ALL_EVENTS). */ public FileObserver(@NonNull File file) { this(Arrays.asList(file)); } /** * Equivalent to FileObserver(paths, FileObserver.ALL_EVENTS). * * @param files The files or directories to monitor */ public FileObserver(@NonNull List<File> files) { this(files, ALL_EVENTS); } /** Loading @@ -159,11 +193,36 @@ public abstract class FileObserver { * * @param path The file or directory to monitor * @param mask The event or events (added together) to watch for * * @deprecated use {@link #FileObserver(File, int)} instead. */ @Deprecated public FileObserver(String path, int mask) { m_path = path; m_mask = mask; m_descriptor = -1; this(new File(path), mask); } /** * Create a new file observer for a certain file or directory. * Monitoring does not start on creation! You must call * {@link #startWatching()} before you will receive events. * * @param file The file or directory to monitor * @param mask The event or events (added together) to watch for */ public FileObserver(@NonNull File file, int mask) { this(Arrays.asList(file), mask); } /** * Version of {@link #FileObserver(File, int)} that allows callers to monitor * multiple files or directories. * * @param files The files or directories to monitor * @param mask The event or events (added together) to watch for */ public FileObserver(@NonNull List<File> files, int mask) { mFiles = files; mMask = mask; } protected void finalize() { Loading @@ -176,8 +235,8 @@ public abstract class FileObserver { * If monitoring is already started, this call has no effect. */ public void startWatching() { if (m_descriptor < 0) { m_descriptor = s_observerThread.startWatching(m_path, m_mask, this); if (mDescriptors == null) { mDescriptors = s_observerThread.startWatching(mFiles, mMask, this); } } Loading @@ -187,9 +246,9 @@ public abstract class FileObserver { * monitoring is already stopped, this call has no effect. */ public void stopWatching() { if (m_descriptor >= 0) { s_observerThread.stopWatching(m_descriptor); m_descriptor = -1; if (mDescriptors != null) { s_observerThread.stopWatching(mDescriptors); mDescriptors = null; } } Loading
core/jni/android_util_FileObserver.cpp +27 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ */ #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> #include "jni.h" #include "utils/Log.h" #include "utils/misc.h" Loading Loading @@ -98,31 +100,45 @@ static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd #endif } static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask) static void android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jobjectArray pathStrings, jint mask, jintArray wfdArray) { int res = -1; ScopedIntArrayRW wfds(env, wfdArray); if (wfds.get() == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", "Failed to get ScopedIntArrayRW"); } #if defined(__linux__) if (fd >= 0) { const char* path = env->GetStringUTFChars(pathString, NULL); size_t count = wfds.size(); for (jsize i = 0; i < count; ++i) { jstring pathString = (jstring) env->GetObjectArrayElement(pathStrings, i); res = inotify_add_watch(fd, path, mask); ScopedUtfChars path(env, pathString); env->ReleaseStringUTFChars(pathString, path); wfds[i] = inotify_add_watch(fd, path.c_str(), mask); } } #endif return res; } static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd) static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jintArray wfdArray) { #if defined(__linux__) inotify_rm_watch((int)fd, (uint32_t)wfd); ScopedIntArrayRO wfds(env, wfdArray); if (wfds.get() == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", "Failed to get ScopedIntArrayRO"); } size_t count = wfds.size(); for (size_t i = 0; i < count; ++i) { inotify_rm_watch((int)fd, (uint32_t)wfds[i]); } #endif } Loading @@ -131,8 +147,8 @@ static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ { "init", "()I", (void*)android_os_fileobserver_init }, { "observe", "(I)V", (void*)android_os_fileobserver_observe }, { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching }, { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching } { "startWatching", "(I[Ljava/lang/String;I[I)V", (void*)android_os_fileobserver_startWatching }, { "stopWatching", "(I[I)V", (void*)android_os_fileobserver_stopWatching } }; Loading