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
19c041f5a3b835242fee920c16b5ba6b48e72de007Jeff Sharkeyimport android.annotation.Nullable;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
253dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor/**
263dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>)
273dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * to fire an event after files are accessed or changed by by any process on
283dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * the device (including this one).  FileObserver is an abstract class;
293dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * subclasses must implement the event handler {@link #onEvent(int, String)}.
303dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
313dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>Each FileObserver instance monitors a single file or directory.
323dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * If a directory is monitored, events will be triggered for all files and
336aad995042599dd0f5def79fea85cee90439c9a8Scott Main * subdirectories inside the monitored directory.</p>
343dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
353dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p>An event mask is used to specify which changes or actions to report.
363dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * Event type constants are used to describe the possible changes in the
373dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * event mask as well as what actually happened in event callbacks.</p>
383dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor *
393dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * <p class="caution"><b>Warning</b>: If a FileObserver is garbage collected, it
403dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * will stop sending events.  To ensure you keep receiving events, you must
413dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor * keep a reference to the FileObserver instance from some other live object.</p>
423dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class FileObserver {
443dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was read from a file */
459bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ACCESS = 0x00000001;
463dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Data was written to a file */
479bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MODIFY = 0x00000002;
483dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Metadata (permissions, owner, timestamp) was changed explicitly */
499bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int ATTRIB = 0x00000004;
503dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open for writing, and closed it */
519bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_WRITE = 0x00000008;
523dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: Someone had a file or directory open read-only, and closed it */
539bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CLOSE_NOWRITE = 0x00000010;
543dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or directory was opened */
559bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int OPEN = 0x00000020;
563dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved from the monitored directory */
579bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_FROM = 0x00000040;
583dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file or subdirectory was moved to the monitored directory */
599bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVED_TO = 0x00000080;
603dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A new file or subdirectory was created under the monitored directory */
619bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int CREATE = 0x00000100;
623dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: A file was deleted from the monitored directory */
639bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE = 0x00000200;
643dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was deleted; monitoring effectively stops */
659bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int DELETE_SELF = 0x00000400;
663dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event type: The monitored file or directory was moved; monitoring continues */
679bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public static final int MOVE_SELF = 0x00000800;
689bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
693dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /** Event mask: All valid event types, combined */
703dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
72d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            | DELETE_SELF | MOVE_SELF;
739bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOG_TAG = "FileObserver";
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class ObserverThread extends Thread {
77d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();
78d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private int m_fd;
79d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
80d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public ObserverThread() {
81d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            super("FileObserver");
82d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_fd = init();
83d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
84d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
85d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void run() {
86d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            observe(m_fd);
87d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
88d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
89d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public int startWatching(String path, int mask, FileObserver observer) {
90d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            int wfd = startWatching(m_fd, path, mask);
91d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
92d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            Integer i = new Integer(wfd);
93d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (wfd >= 0) {
94d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                synchronized (m_observers) {
95d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    m_observers.put(i, new WeakReference(observer));
96d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
98d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
99d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            return i;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void stopWatching(int descriptor) {
103d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            stopWatching(m_fd, descriptor);
104d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
105d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
106d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        public void onEvent(int wfd, int mask, String path) {
107d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // look up our observer, fixing up the map if necessary...
108d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            FileObserver observer = null;
109d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
110d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            synchronized (m_observers) {
111d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                WeakReference weak = m_observers.get(wfd);
112d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                if (weak != null) {  // can happen with lots of events from a dead wfd
113d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer = (FileObserver) weak.get();
114d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    if (observer == null) {
115d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                        m_observers.remove(wfd);
116d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    }
117d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
118d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            }
119d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor
120d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            // ...then call out to the observer without the sync lock held
121d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            if (observer != null) {
122d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                try {
123d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    observer.onEvent(mask, path);
124d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                } catch (Throwable throwable) {
125d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                    Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);
126d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor                }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
130d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int init();
131d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void observe(int fd);
132d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native int startWatching(int fd, String path, int mask);
133d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        private native void stopWatching(int fd, int wfd);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ObserverThread s_observerThread;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
139d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread = new ObserverThread();
140d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        s_observerThread.start();
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // instance
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String m_path;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Integer m_descriptor;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int m_mask;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1483dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1493dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Equivalent to FileObserver(path, FileObserver.ALL_EVENTS).
1503dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path) {
152d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        this(path, ALL_EVENTS);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1553dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1563dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Create a new file observer for a certain file or directory.
1573dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Monitoring does not start on creation!  You must call
1583dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * {@link #startWatching()} before you will receive events.
1593dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
1603dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The file or directory to monitor
1613dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param mask The event or events (added together) to watch for
1623dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileObserver(String path, int mask) {
164d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_path = path;
165d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_mask = mask;
166d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        m_descriptor = -1;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
170d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        stopWatching();
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1733dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1743dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Start watching for events.  The monitored file or directory must exist at
1753dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * this time, or else no events will be reported (even if it appears later).
1763dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * If monitoring is already started, this call has no effect.
1773dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startWatching() {
179d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor < 0) {
180d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);
181d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1843dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1853dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * Stop watching for events.  Some events may be in process, so events
1863dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * may continue to be reported even after this method completes.  If
1873dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * monitoring is already stopped, this call has no effect.
1883dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopWatching() {
190d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        if (m_descriptor >= 0) {
191d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            s_observerThread.stopWatching(m_descriptor);
192d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor            m_descriptor = -1;
193d95244faef7b54fe46223aec1ed5754cd9b74a3eDan Egnor        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1963dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor    /**
1973dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * The event handler, which must be implemented by subclasses.
1983dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
1993dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p class="note">This method is invoked on a special FileObserver thread.
2003dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * It runs independently of any threads, so take care to use appropriate
2013dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * synchronization!  Consider using {@link Handler#post(Runnable)} to shift
2023dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * event handling work to the main thread to avoid concurrency problems.</p>
2033dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2043dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * <p>Event handlers must not throw exceptions.</p>
2053dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     *
2063dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param event The type of event which happened
2073dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     * @param path The path, relative to the main monitored file or directory,
208c041f5a3b835242fee920c16b5ba6b48e72de007Jeff Sharkey     *     of the file or directory which triggered the event.  This value can
209c041f5a3b835242fee920c16b5ba6b48e72de007Jeff Sharkey     *     be {@code null} for certain events, such as {@link #MOVE_SELF}.
2103dc1c7f5e84a888bc0a3aee764e9c6fa01395d8aDan Egnor     */
211c041f5a3b835242fee920c16b5ba6b48e72de007Jeff Sharkey    public abstract void onEvent(int event, @Nullable String path);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
213