Loading packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +8 −5 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.documentsui.DocumentsActivity.State; import com.android.documentsui.ProviderExecutor.Preemptable; import com.android.documentsui.RecentsProvider.StateColumns; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.RootInfo; Loading Loading @@ -528,7 +529,7 @@ public class DirectoryFragment extends Fragment { if (iconThumb != null) { final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); if (oldTask != null) { oldTask.reallyCancel(); oldTask.preempt(); iconThumb.setTag(null); } } Loading Loading @@ -794,7 +795,7 @@ public class DirectoryFragment extends Fragment { final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); if (oldTask != null) { oldTask.reallyCancel(); oldTask.preempt(); iconThumb.setTag(null); } Loading @@ -818,7 +819,7 @@ public class DirectoryFragment extends Fragment { final ThumbnailAsyncTask task = new ThumbnailAsyncTask( uri, iconMime, iconThumb, mThumbSize); iconThumb.setTag(task); task.executeOnExecutor(ProviderExecutor.forAuthority(docAuthority)); ProviderExecutor.forAuthority(docAuthority).execute(task); } } Loading Loading @@ -988,7 +989,8 @@ public class DirectoryFragment extends Fragment { } } private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> { private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> implements Preemptable { private final Uri mUri; private final ImageView mIconMime; private final ImageView mIconThumb; Loading @@ -1004,7 +1006,8 @@ public class DirectoryFragment extends Fragment { mSignal = new CancellationSignal(); } public void reallyCancel() { @Override public void preempt() { cancel(false); mSignal.cancel(); } Loading packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ public class DocumentsApplication extends Application { packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); packageFilter.addDataScheme("package"); registerReceiver(mCacheReceiver, packageFilter); Loading packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,15 @@ package com.android.documentsui; import android.os.AsyncTask; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; Loading @@ -29,7 +34,7 @@ public class ProviderExecutor extends Thread implements Executor { @GuardedBy("sExecutors") private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap(); public static Executor forAuthority(String authority) { public static ProviderExecutor forAuthority(String authority) { synchronized (sExecutors) { ProviderExecutor executor = sExecutors.get(authority); if (executor == null) { Loading @@ -42,10 +47,54 @@ public class ProviderExecutor extends Thread implements Executor { } } public interface Preemptable { void preempt(); } private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>(); private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList(); private void preempt() { synchronized (mPreemptable) { int count = 0; for (WeakReference<Preemptable> ref : mPreemptable) { final Preemptable p = ref.get(); if (p != null) { count++; p.preempt(); } } mPreemptable.clear(); } } /** * Execute the given task. If given task is not {@link Preemptable}, it will * preempt all outstanding preemptable tasks. */ public <P> void execute(AsyncTask<P, ?, ?> task, P... params) { if (task instanceof Preemptable) { synchronized (mPreemptable) { mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task)); } task.executeOnExecutor(mNonPreemptingExecutor, params); } else { task.executeOnExecutor(this, params); } } private Executor mNonPreemptingExecutor = new Executor() { @Override public void execute(Runnable command) { Preconditions.checkNotNull(command); mQueue.add(command); } }; @Override public void execute(Runnable command) { preempt(); Preconditions.checkNotNull(command); mQueue.add(command); } Loading packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +3 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,8 @@ import java.util.concurrent.TimeUnit; public class RootsCache { private static final boolean LOGD = true; // TODO: cache roots in local provider to avoid spinning up backends // TODO: root updates should trigger UI refresh public static final Uri sNotificationUri = Uri.parse( "content://com.android.documentsui.roots/"); private final Context mContext; private final ContentObserver mObserver; Loading Loading @@ -201,6 +201,7 @@ public class RootsCache { mStoppedAuthorities = mTaskStoppedAuthorities; } mFirstLoad.countDown(); resolver.notifyChange(sNotificationUri, null, false); return null; } Loading packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java +7 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import com.android.documentsui.model.RootInfo; import java.util.Collection; public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); private final RootsCache mRoots; private final State mState; Loading @@ -34,6 +36,9 @@ public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { super(context); mRoots = roots; mState = state; getContext().getContentResolver() .registerContentObserver(RootsCache.sNotificationUri, false, mObserver); } @Override Loading Loading @@ -77,5 +82,7 @@ public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { onStopLoading(); mResult = null; getContext().getContentResolver().unregisterContentObserver(mObserver); } } Loading
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +8 −5 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.documentsui.DocumentsActivity.State; import com.android.documentsui.ProviderExecutor.Preemptable; import com.android.documentsui.RecentsProvider.StateColumns; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.RootInfo; Loading Loading @@ -528,7 +529,7 @@ public class DirectoryFragment extends Fragment { if (iconThumb != null) { final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); if (oldTask != null) { oldTask.reallyCancel(); oldTask.preempt(); iconThumb.setTag(null); } } Loading Loading @@ -794,7 +795,7 @@ public class DirectoryFragment extends Fragment { final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); if (oldTask != null) { oldTask.reallyCancel(); oldTask.preempt(); iconThumb.setTag(null); } Loading @@ -818,7 +819,7 @@ public class DirectoryFragment extends Fragment { final ThumbnailAsyncTask task = new ThumbnailAsyncTask( uri, iconMime, iconThumb, mThumbSize); iconThumb.setTag(task); task.executeOnExecutor(ProviderExecutor.forAuthority(docAuthority)); ProviderExecutor.forAuthority(docAuthority).execute(task); } } Loading Loading @@ -988,7 +989,8 @@ public class DirectoryFragment extends Fragment { } } private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> { private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> implements Preemptable { private final Uri mUri; private final ImageView mIconMime; private final ImageView mIconThumb; Loading @@ -1004,7 +1006,8 @@ public class DirectoryFragment extends Fragment { mSignal = new CancellationSignal(); } public void reallyCancel() { @Override public void preempt() { cancel(false); mSignal.cancel(); } Loading
packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ public class DocumentsApplication extends Application { packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); packageFilter.addDataScheme("package"); registerReceiver(mCacheReceiver, packageFilter); Loading
packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,15 @@ package com.android.documentsui; import android.os.AsyncTask; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; Loading @@ -29,7 +34,7 @@ public class ProviderExecutor extends Thread implements Executor { @GuardedBy("sExecutors") private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap(); public static Executor forAuthority(String authority) { public static ProviderExecutor forAuthority(String authority) { synchronized (sExecutors) { ProviderExecutor executor = sExecutors.get(authority); if (executor == null) { Loading @@ -42,10 +47,54 @@ public class ProviderExecutor extends Thread implements Executor { } } public interface Preemptable { void preempt(); } private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>(); private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList(); private void preempt() { synchronized (mPreemptable) { int count = 0; for (WeakReference<Preemptable> ref : mPreemptable) { final Preemptable p = ref.get(); if (p != null) { count++; p.preempt(); } } mPreemptable.clear(); } } /** * Execute the given task. If given task is not {@link Preemptable}, it will * preempt all outstanding preemptable tasks. */ public <P> void execute(AsyncTask<P, ?, ?> task, P... params) { if (task instanceof Preemptable) { synchronized (mPreemptable) { mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task)); } task.executeOnExecutor(mNonPreemptingExecutor, params); } else { task.executeOnExecutor(this, params); } } private Executor mNonPreemptingExecutor = new Executor() { @Override public void execute(Runnable command) { Preconditions.checkNotNull(command); mQueue.add(command); } }; @Override public void execute(Runnable command) { preempt(); Preconditions.checkNotNull(command); mQueue.add(command); } Loading
packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +3 −2 Original line number Diff line number Diff line Loading @@ -60,8 +60,8 @@ import java.util.concurrent.TimeUnit; public class RootsCache { private static final boolean LOGD = true; // TODO: cache roots in local provider to avoid spinning up backends // TODO: root updates should trigger UI refresh public static final Uri sNotificationUri = Uri.parse( "content://com.android.documentsui.roots/"); private final Context mContext; private final ContentObserver mObserver; Loading Loading @@ -201,6 +201,7 @@ public class RootsCache { mStoppedAuthorities = mTaskStoppedAuthorities; } mFirstLoad.countDown(); resolver.notifyChange(sNotificationUri, null, false); return null; } Loading
packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java +7 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import com.android.documentsui.model.RootInfo; import java.util.Collection; public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); private final RootsCache mRoots; private final State mState; Loading @@ -34,6 +36,9 @@ public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { super(context); mRoots = roots; mState = state; getContext().getContentResolver() .registerContentObserver(RootsCache.sNotificationUri, false, mObserver); } @Override Loading Loading @@ -77,5 +82,7 @@ public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> { onStopLoading(); mResult = null; getContext().getContentResolver().unregisterContentObserver(mObserver); } }