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 com.android.internal.os.RuntimeInit;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
273dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor/**
283dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>)
293dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * to fire an event after files are accessed or changed by by any process on
303dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * the device (including this one).  FileObserver is an abstract class;
313dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * subclasses must implement the event handler {@link #onEvent(int, String)}.
323dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
333dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>Each FileObserver instance monitors a single file or directory.
343dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * If a directory is monitored, events will be triggered for all files and
356aad995042599dd0f5def79fea85cee90439c9a8Scott Main * subdirectories inside the monitored directory.</p>
363dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
373dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>An event mask is used to specify which changes or actions to report.
383dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Event type constants are used to describe the possible changes in the
393dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * event mask as well as what actually happened in event callbacks.</p>
403dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
413dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p class="caution"><b>Warning</b>: If a FileObserver is garbage collected, it
423dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * will stop sending events.  To ensure you keep receiving events, you must
433dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * keep a reference to the FileObserver instance from some other live object.</p>
443dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor */
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class FileObserver {
463dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was read from a file */
479bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ACCESS = 0x00000001;
483dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was written to a file */
499bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MODIFY = 0x00000002;
503dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Metadata (permissions, owner, timestamp) was changed explicitly */
519bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ATTRIB = 0x00000004;
523dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open for writing, and closed it */
539bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_WRITE = 0x00000008;
543dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open read-only, and closed it */
559bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_NOWRITE = 0x00000010;
563dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or directory was opened */
579bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int OPEN = 0x00000020;
583dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved from the monitored directory */
599bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_FROM = 0x00000040;
603dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved to the monitored directory */
619bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_TO = 0x00000080;
623dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A new file or subdirectory was created under the monitored directory */
639bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CREATE = 0x00000100;
643dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file was deleted from the monitored directory */
659bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE = 0x00000200;
663dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was deleted; monitoring effectively stops */
679bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE_SELF = 0x00000400;
683dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was moved; monitoring continues */
699bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVE_SELF = 0x00000800;
709bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
713dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event mask: All valid event types, combined */
723dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
74d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            | DELETE_SELF | MOVE_SELF;
759bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOG_TAG = "FileObserver";
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class ObserverThread extends Thread {
79d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();
80d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private int m_fd;
81d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
82d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public ObserverThread() {
83d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            super("FileObserver");
84d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_fd = init();
85d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
86d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
87d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void run() {
88d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            observe(m_fd);
89d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
90d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
91d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public int startWatching(String path, int mask, FileObserver observer) {
92d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            int wfd = startWatching(m_fd, path, mask);
93d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
94d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            Integer i = new Integer(wfd);
95d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (wfd >= 0) {
96d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                synchronized (m_observers) {
97d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    m_observers.put(i, new WeakReference(observer));
98d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
100d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
101d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            return i;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void stopWatching(int descriptor) {
105d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            stopWatching(m_fd, descriptor);
106d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
107d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
108d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void onEvent(int wfd, int mask, String path) {
109d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // look up our observer, fixing up the map if necessary...
110d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            FileObserver observer = null;
111d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
112d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            synchronized (m_observers) {
113d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                WeakReference weak = m_observers.get(wfd);
114d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                if (weak != null) {  // can happen with lots of events from a dead wfd
115d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer = (FileObserver) weak.get();
116d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    if (observer == null) {
117d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                        m_observers.remove(wfd);
118d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    }
119d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
120d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            }
121d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
122d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // ...then call out to the observer without the sync lock held
123d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (observer != null) {
124d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                try {
125d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer.onEvent(mask, path);
126d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                } catch (Throwable throwable) {
127d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);
128d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
132d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int init();
133d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void observe(int fd);
134d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int startWatching(int fd, String path, int mask);
135d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void stopWatching(int fd, int wfd);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ObserverThread s_observerThread;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
141d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread = new ObserverThread();
142d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread.start();
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // instance
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String m_path;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Integer m_descriptor;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int m_mask;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1503dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1513dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Equivalent to FileObserver(path, FileObserver.ALL_EVENTS).
1523dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path) {
154d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        this(path, ALL_EVENTS);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1573dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1583dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Create a new file observer for a certain file or directory.
1593dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Monitoring does not start on creation!  You must call
1603dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * {@link #startWatching()} before you will receive events.
1613dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
1623dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The file or directory to monitor
1633dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param mask The event or events (added together) to watch for
1643dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path, int mask) {
166d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_path = path;
167d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_mask = mask;
168d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_descriptor = -1;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
172d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        stopWatching();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1753dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1763dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Start watching for events.  The monitored file or directory must exist at
1773dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * this time, or else no events will be reported (even if it appears later).
1783dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * If monitoring is already started, this call has no effect.
1793dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startWatching() {
181d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor < 0) {
182d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);
183d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1863dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1873dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Stop watching for events.  Some events may be in process, so events
1883dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * may continue to be reported even after this method completes.  If
1893dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * monitoring is already stopped, this call has no effect.
1903dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopWatching() {
192d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor >= 0) {
193d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            s_observerThread.stopWatching(m_descriptor);
194d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = -1;
195d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1983dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1993dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * The event handler, which must be implemented by subclasses.
2003dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2013dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p class="note">This method is invoked on a special FileObserver thread.
2023dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * It runs independently of any threads, so take care to use appropriate
2033dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * synchronization!  Consider using {@link Handler#post(Runnable)} to shift
2043dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * event handling work to the main thread to avoid concurrency problems.</p>
2053dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2063dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p>Event handlers must not throw exceptions.</p>
2073dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2083dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param event The type of event which happened
2093dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The path, relative to the main monitored file or directory,
2103dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *     of the file or directory which triggered the event
2113dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public abstract void onEvent(int event, String path);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
214