diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-10-28 09:57:20 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-10-28 09:57:20 -0700 |
commit | e643e33736e14a59f1f9a8acb4d630b2ea671a31 (patch) | |
tree | c49128d55abe5befd51309eaea5e7d4aa725fb7d /packages/ExternalStorageProvider/src/com/android | |
parent | f65dd213900603116c7b064bfdfb57662f7682c3 (diff) | |
parent | 99dcb2eb3578c3d14658b3850cb3e32608e173b1 (diff) | |
download | frameworks_base-e643e33736e14a59f1f9a8acb4d630b2ea671a31.zip frameworks_base-e643e33736e14a59f1f9a8acb4d630b2ea671a31.tar.gz frameworks_base-e643e33736e14a59f1f9a8acb4d630b2ea671a31.tar.bz2 |
am 99dcb2eb: am 10e509dc: Merge "Use inotify to update DocumentsUI." into klp-dev
* commit '99dcb2eb3578c3d14658b3850cb3e32608e173b1':
Use inotify to update DocumentsUI.
Diffstat (limited to 'packages/ExternalStorageProvider/src/com/android')
-rw-r--r-- | packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 65e3eee..559e052 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -16,14 +16,17 @@ package com.android.externalstorage; +import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.MatrixCursor; import android.database.MatrixCursor.RowBuilder; import android.graphics.Point; +import android.net.Uri; import android.os.CancellationSignal; import android.os.Environment; +import android.os.FileObserver; import android.os.ParcelFileDescriptor; import android.os.storage.StorageManager; import android.os.storage.StorageVolume; @@ -49,6 +52,8 @@ import java.util.Map; public class ExternalStorageProvider extends DocumentsProvider { private static final String TAG = "ExternalStorage"; + private static final boolean LOG_INOTIFY = false; + public static final String AUTHORITY = "com.android.externalstorage.documents"; // docId format: root:path/to/file @@ -83,6 +88,9 @@ public class ExternalStorageProvider extends DocumentsProvider { @GuardedBy("mRootsLock") private HashMap<String, File> mIdToPath; + @GuardedBy("mObservers") + private Map<File, DirectoryObserver> mObservers = Maps.newHashMap(); + @Override public boolean onCreate() { mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE); @@ -327,8 +335,9 @@ public class ExternalStorageProvider extends DocumentsProvider { public Cursor queryChildDocuments( String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection)); final File parent = getFileForDocId(parentDocumentId); + final MatrixCursor result = new DirectoryCursor( + resolveDocumentProjection(projection), parentDocumentId, parent); for (File file : parent.listFiles()) { includeFile(result, null, file); } @@ -431,4 +440,86 @@ public class ExternalStorageProvider extends DocumentsProvider { } return name; } + + private void startObserving(File file, Uri notifyUri) { + synchronized (mObservers) { + DirectoryObserver observer = mObservers.get(file); + if (observer == null) { + observer = new DirectoryObserver( + file, getContext().getContentResolver(), notifyUri); + observer.startWatching(); + mObservers.put(file, observer); + } + observer.mRefCount++; + + if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer); + } + } + + private void stopObserving(File file) { + synchronized (mObservers) { + DirectoryObserver observer = mObservers.get(file); + if (observer == null) return; + + observer.mRefCount--; + if (observer.mRefCount == 0) { + mObservers.remove(file); + observer.stopWatching(); + } + + if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer); + } + } + + private static class DirectoryObserver extends FileObserver { + private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO + | CREATE | DELETE | DELETE_SELF | MOVE_SELF; + + private final File mFile; + private final ContentResolver mResolver; + private final Uri mNotifyUri; + + private int mRefCount = 0; + + public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) { + super(file.getAbsolutePath(), NOTIFY_EVENTS); + mFile = file; + mResolver = resolver; + mNotifyUri = notifyUri; + } + + @Override + public void onEvent(int event, String path) { + if ((event & NOTIFY_EVENTS) != 0) { + if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path); + mResolver.notifyChange(mNotifyUri, null, false); + } + } + + @Override + public String toString() { + return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}"; + } + } + + private class DirectoryCursor extends MatrixCursor { + private final File mFile; + + public DirectoryCursor(String[] columnNames, String docId, File file) { + super(columnNames); + + final Uri notifyUri = DocumentsContract.buildChildDocumentsUri( + AUTHORITY, docId); + setNotificationUri(getContext().getContentResolver(), notifyUri); + + mFile = file; + startObserving(mFile, notifyUri); + } + + @Override + public void close() { + super.close(); + stopObserving(mFile); + } + } } |