在前面的Linux文件系统Inotify机制中介绍了Linux对文件变更监控过程。Android系统在此基础上封装了一个FileObserver类来方便使用Inotify机制。FileObserver是一个抽象类,需要定义子类实现该类的onEvent抽象方法,当被监控的文件或者目录发生变更事件时,将回调FileObserver的onEvent()函数来处理文件或目录的变更事件。

事件监控过程

在FileObserver类中定义了一个静态内部类ObserverThread,该线程类才是真正实现文件或目录监控过程。各种类型的FileObserver都拥有一个ObserverThread实例:

frameworks\base\core\java\android\os\FileObserver.java

public abstract class FileObserver {

//可监控的事件类型

public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE

| CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE | DELETE_SELF | MOVE_SELF;

//静态创建并启动一个文件监控线程

private static ObserverThread s_observerThread;

static {

s_observerThread = new ObserverThread();

s_observerThread.start();

}

// instance

private String m_path;

private Integer m_descriptor;

private int m_mask;

}

FileObserver类通过静态方式构造了一个ObserverThread对象:

public ObserverThread() {

super("FileObserver");

m_fd = init();//初始化一个inotify实例,Observer线程就是对该inotify实例进行监控

}

frameworks\base\core\jni\android_util_FileObserver.cpp

static jint android_os_fileobserver_init(JNIEnv* env, jobject object)

{

#ifdef HAVE_INOTIFY

return (jint)inotify_init();//初始化一个inotify实例

#else // HAVE_INOTIFY

return -1;

#endif // HAVE_INOTIFY

}

inotify_init()函数实现在Linux文件系统Inotify机制有详细介绍,然后启动ObserverThread线程,ObserverThread线程运行体:

frameworks\base\core\java\android\os\FileObserve$ObserverThread

public void run() {

observe(m_fd);//监控inotify实例句柄

}

frameworks\base\core\jni\android_util_FileObserver.cpp

static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd)

{

#ifdef HAVE_INOTIFY

char event_buf[512];//定义事件数组

struct inotify_event* event;

while (1)

{

int event_pos = 0;

//从inotify实例句柄中读取事件

int num_bytes = read(fd, event_buf, sizeof(event_buf));

if (num_bytes < (int)sizeof(*event))

{

if (errno == EINTR)

continue;

ALOGE("***** ERROR! android_os_fileobserver_observe() got a short event!");

return;

}

//循环处理读取到的事件

while (num_bytes >= (int)sizeof(*event))

{

int event_size;

event = (struct inotify_event *)(event_buf + event_pos);

jstring path = NULL;

if (event->len > 0)

{

path = env->NewStringUTF(event->name);

}

//调用ObserverThread的onEvent函数通知上层响应

env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);

if (env->ExceptionCheck()) {

env->ExceptionDescribe();

env->ExceptionClear();

}

if (path != NULL)

{

env->DeleteLocalRef(path);

}

event_size = sizeof(*event) + event->len;

num_bytes -= event_size;

event_pos += event_size;

}

}

#endif // HAVE_INOTIFY

}

ObserverThread线程循环从inotify实例句柄中读取事件,然后回调ObserverThread的onEvent函数来处理事件。

frameworks\base\core\java\android\os\FileObserve$ObserverThread

public void onEvent(int wfd, int mask, String path) {

// look up our observer, fixing up the map if necessary...

FileObserver observer = null;

synchronized (m_observers) {

//根据wfd句柄从m_observers表中查找出注册的FileObserver对象

WeakReference weak = m_observers.get(wfd);

if (weak != null) { // can happen with lots of events from a dead wfd

observer = (FileObserver) weak.get();

if (observer == null) {

m_observers.remove(wfd);

}

}

}

// ...then call out to the observer without the sync lock held

if (observer != null) {

try {

//调用对应的FileObserver对象的onEvent函数来处理事件

observer.onEvent(mask, path);

} catch (Throwable throwable) {

Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);

}

}

}

注册监控watch

FileObserver类提供了startWatching()函数来启动文件监控

frameworks\base\core\java\android\os\FileObserver.java

public void startWatching() {

if (m_descriptor < 0) {

m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);

}

}

由ObserverThread线程对象启动监控

frameworks\base\core\java\android\os\FileObserver$ObserverThread

public int startWatching(String path, int mask, FileObserver observer) {

//在Inotify实例中添加一个watch对象,并得到一个watch对象句柄

int wfd = startWatching(m_fd, path, mask);

Integer i = new Integer(wfd);

if (wfd >= 0) {

//将watch对象句柄和响应该watch事件的FileObserver以键值对的形式保存在m_observers成员变量中

synchronized (m_observers) {

m_observers.put(i, new WeakReference(observer));

}

}

return i;

}

ObserverThread又调用native方法android_os_fileobserver_startWatching()来添加一个watch

frameworks\base\core\jni\android_util_FileObserver.cpp

static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask)

{

int res = -1;

#ifdef HAVE_INOTIFY

if (fd >= 0)

{

const char* path = env->GetStringUTFChars(pathString, NULL);

//在Inotify实例上添加一个watch对象

res = inotify_add_watch(fd, path, mask);

env->ReleaseStringUTFChars(pathString, path);

}

#endif // HAVE_INOTIFY

return res;

}

注销监控watch

FileObserver类提供了使用stopWatching()函数来停止文件监控。

frameworks\base\core\java\android\os\FileObserver$ObserverThread

public void stopWatching() {

if (m_descriptor >= 0) {

s_observerThread.stopWatching(m_descriptor);

m_descriptor = -1;

}

}

frameworks\base\core\java\android\os\FileObserve$ObserverThread

public void stopWatching(int descriptor) {

stopWatching(m_fd, descriptor);

}

frameworks\base\core\jni\android_util_FileObserver.cpp

static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd)

{

#ifdef HAVE_INOTIFY

inotify_rm_watch((int)fd, (uint32_t)wfd);

#endif // HAVE_INOTIFY

}

528a8bfe83dbc1bd27abe73e56e338c0.png

原文:http://blog.csdn.net/yangwen123/article/details/36379763

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐