19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
243dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor/**
253dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>)
263dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * to fire an event after files are accessed or changed by by any process on
273dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * the device (including this one).  FileObserver is an abstract class;
283dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * subclasses must implement the event handler {@link #onEvent(int, String)}.
293dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
303dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>Each FileObserver instance monitors a single file or directory.
313dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * If a directory is monitored, events will be triggered for all files and
326aad995042599dd0f5def79fea85cee90439c9a8Scott Main * subdirectories inside the monitored directory.</p>
333dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
343dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>An event mask is used to specify which changes or actions to report.
353dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Event type constants are used to describe the possible changes in the
363dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * event mask as well as what actually happened in event callbacks.</p>
373dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
383dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p class="caution"><b>Warning</b>: If a FileObserver is garbage collected, it
393dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * will stop sending events.  To ensure you keep receiving events, you must
403dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * keep a reference to the FileObserver instance from some other live object.</p>
413dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor */
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class FileObserver {
433dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was read from a file */
449bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ACCESS = 0x00000001;
453dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was written to a file */
469bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MODIFY = 0x00000002;
473dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Metadata (permissions, owner, timestamp) was changed explicitly */
489bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ATTRIB = 0x00000004;
493dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open for writing, and closed it */
509bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_WRITE = 0x00000008;
513dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open read-only, and closed it */
529bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_NOWRITE = 0x00000010;
533dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or directory was opened */
549bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int OPEN = 0x00000020;
553dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved from the monitored directory */
569bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_FROM = 0x00000040;
573dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved to the monitored directory */
589bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_TO = 0x00000080;
593dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A new file or subdirectory was created under the monitored directory */
609bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CREATE = 0x00000100;
613dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file was deleted from the monitored directory */
629bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE = 0x00000200;
633dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was deleted; monitoring effectively stops */
649bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE_SELF = 0x00000400;
653dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was moved; monitoring continues */
669bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVE_SELF = 0x00000800;
679bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
683dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event mask: All valid event types, combined */
693dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
71d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            | DELETE_SELF | MOVE_SELF;
729bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOG_TAG = "FileObserver";
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class ObserverThread extends Thread {
76d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();
77d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private int m_fd;
78d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
79d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public ObserverThread() {
80d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            super("FileObserver");
81d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_fd = init();
82d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
83d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
84d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void run() {
85d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            observe(m_fd);
86d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
87d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
88d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public int startWatching(String path, int mask, FileObserver observer) {
89d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            int wfd = startWatching(m_fd, path, mask);
90d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
91d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            Integer i = new Integer(wfd);
92d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (wfd >= 0) {
93d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                synchronized (m_observers) {
94d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    m_observers.put(i, new WeakReference(observer));
95d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
97d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
98d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            return i;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
101d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void stopWatching(int descriptor) {
102d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            stopWatching(m_fd, descriptor);
103d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
104d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
105d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void onEvent(int wfd, int mask, String path) {
106d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // look up our observer, fixing up the map if necessary...
107d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            FileObserver observer = null;
108d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
109d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            synchronized (m_observers) {
110d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                WeakReference weak = m_observers.get(wfd);
111d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                if (weak != null) {  // can happen with lots of events from a dead wfd
112d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer = (FileObserver) weak.get();
113d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    if (observer == null) {
114d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                        m_observers.remove(wfd);
115d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    }
116d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
117d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            }
118d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
119d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // ...then call out to the observer without the sync lock held
120d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (observer != null) {
121d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                try {
122d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer.onEvent(mask, path);
123d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                } catch (Throwable throwable) {
124d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);
125d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int init();
130d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void observe(int fd);
131d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int startWatching(int fd, String path, int mask);
132d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void stopWatching(int fd, int wfd);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ObserverThread s_observerThread;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
138d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread = new ObserverThread();
139d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread.start();
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // instance
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String m_path;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Integer m_descriptor;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int m_mask;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1473dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1483dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Equivalent to FileObserver(path, FileObserver.ALL_EVENTS).
1493dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path) {
151d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        this(path, ALL_EVENTS);
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1543dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1553dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Create a new file observer for a certain file or directory.
1563dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Monitoring does not start on creation!  You must call
1573dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * {@link #startWatching()} before you will receive events.
1583dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
1593dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The file or directory to monitor
1603dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param mask The event or events (added together) to watch for
1613dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path, int mask) {
163d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_path = path;
164d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_mask = mask;
165d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_descriptor = -1;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
169d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        stopWatching();
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1723dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1733dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Start watching for events.  The monitored file or directory must exist at
1743dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * this time, or else no events will be reported (even if it appears later).
1753dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * If monitoring is already started, this call has no effect.
1763dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startWatching() {
178d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor < 0) {
179d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);
180d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1833dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1843dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Stop watching for events.  Some events may be in process, so events
1853dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * may continue to be reported even after this method completes.  If
1863dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * monitoring is already stopped, this call has no effect.
1873dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopWatching() {
189d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor >= 0) {
190d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            s_observerThread.stopWatching(m_descriptor);
191d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = -1;
192d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1953dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1963dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * The event handler, which must be implemented by subclasses.
1973dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
1983dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p class="note">This method is invoked on a special FileObserver thread.
1993dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * It runs independently of any threads, so take care to use appropriate
2003dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * synchronization!  Consider using {@link Handler#post(Runnable)} to shift
2013dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * event handling work to the main thread to avoid concurrency problems.</p>
2023dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2033dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p>Event handlers must not throw exceptions.</p>
2043dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2053dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param event The type of event which happened
2063dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The path, relative to the main monitored file or directory,
2073dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *     of the file or directory which triggered the event
2083dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract void onEvent(int event, String path);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
211