Merge "Use inotify to update DocumentsUI." into klp-dev
This commit is contained in:
@ -84,7 +84,6 @@ import com.google.android.collect.Lists;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Display the documents inside a single directory.
|
||||
@ -127,9 +126,7 @@ public class DirectoryFragment extends Fragment {
|
||||
private static final String EXTRA_QUERY = "query";
|
||||
private static final String EXTRA_IGNORE_STATE = "ignoreState";
|
||||
|
||||
private static AtomicInteger sLoaderId = new AtomicInteger(4000);
|
||||
|
||||
private final int mLoaderId = sLoaderId.incrementAndGet();
|
||||
private final int mLoaderId = 42;
|
||||
|
||||
public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
|
||||
show(fm, TYPE_NORMAL, root, doc, null, anim);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user