Loading src/com/android/documentsui/AbstractActionHandler.java +10 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.documentsui.sidebar.EjectRootTask; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Provides support for specializing the actions (viewDocument etc.) to the host activity. Loading @@ -58,6 +59,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> implements ActionHandler { private static final String TAG = "AbstractActionHandler"; private static final int REFRESH_SPINNER_TIMEOUT = 500; protected final T mActivity; protected final State mState; Loading Loading @@ -106,6 +108,14 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> listener).executeOnExecutor(ProviderExecutor.forAuthority(root.authority)); } @Override public void refreshDocument(DocumentInfo doc, BooleanConsumer callback) { RefreshTask task = new RefreshTask(mState, doc, REFRESH_SPINNER_TIMEOUT, mActivity.getApplicationContext(), mActivity::isDestroyed, callback); task.executeOnExecutor(mExecutors.lookup(doc == null ? null : doc.authority)); } @Override public void openSelectedInNewWindow() { throw new UnsupportedOperationException("Can't open in new window."); Loading src/com/android/documentsui/ActionHandler.java +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,12 @@ public interface ActionHandler { */ void ejectRoot(RootInfo root, BooleanConsumer listener); /** * Attempts to refresh the given DocumentInfo, which should be at the top of the state stack. * Returns a boolean answer to the callback, given by {@link ContentProvider#refresh}. */ void refreshDocument(DocumentInfo doc, BooleanConsumer callback); void showAppDetails(ResolveInfo info); void openRoot(RootInfo root); Loading src/com/android/documentsui/RefreshTask.java +19 −14 Original line number Diff line number Diff line Loading @@ -29,12 +29,12 @@ import android.os.CancellationSignal; import android.util.Log; import com.android.documentsui.base.ApplicationScope; import com.android.documentsui.base.BooleanConsumer; import com.android.documentsui.base.CheckedTask; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; import java.util.function.Consumer; /** * A {@link CheckedTask} that calls * {@link ContentResolver#refresh(Uri, android.os.Bundle, android.os.CancellationSignal)} on the Loading @@ -46,14 +46,14 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { private final @ApplicationScope Context mContext; private final State mState; private final Uri mUri; private final Consumer<Boolean> mCallback; private final DocumentInfo mDoc; private final BooleanConsumer mCallback; private final CancellationSignal mSignal; public RefreshTask(State state, Uri uri, long timeout, @ApplicationScope Context context, Check check, Consumer<Boolean> callback) { public RefreshTask(State state, DocumentInfo doc, long timeout, @ApplicationScope Context context, Check check, BooleanConsumer callback) { super(check); mUri = uri; mDoc = doc; mContext = context; mState = state; mCallback = callback; Loading @@ -63,13 +63,18 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { @Override public @Nullable Boolean run(Void... params) { if (mUri == null) { Log.w(TAG, "Attempted to refresh on a null uri. Aborting."); if (mDoc == null) { Log.w(TAG, "Ignoring attempt to refresh due to null DocumentInfo."); return false; } if (mState.stack.isEmpty()) { Log.w(TAG, "Ignoring attempt to refresh due to empty stack."); return false; } if (mUri != mState.stack.peek().derivedUri) { Log.w(TAG, "Attempted to refresh on a non-top-level uri. Aborting."); if (!mDoc.derivedUri.equals(mState.stack.peek().derivedUri)) { Log.w(TAG, "Ignoring attempt to refresh on a non-top-level uri."); return false; } Loading @@ -78,17 +83,17 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { // and we will update accordingly. Else, we just tell the callback that Refresh is not // supported. if (!Shared.ENABLE_OMC_API_FEATURES) { Log.w(TAG, "Attempted to call Refresh on an older Android platform. Aborting."); Log.w(TAG, "Ignoring attempt to call Refresh on an older Android platform."); return false; } final ContentResolver resolver = mContext.getContentResolver(); final String authority = mUri.getAuthority(); final String authority = mDoc.authority; boolean refreshSupported = false; ContentProviderClient client = null; try { client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority); refreshSupported = client.refresh(mUri, null, mSignal); refreshSupported = client.refresh(mDoc.derivedUri, null, mSignal); } catch (Exception e) { Log.w(TAG, "Failed to refresh", e); } finally { Loading src/com/android/documentsui/TimeoutTask.java +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.documentsui; import android.annotation.CallSuper; import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; import com.android.documentsui.base.CheckedTask; import com.android.documentsui.base.DocumentInfo; Loading Loading @@ -48,7 +49,9 @@ public abstract class TimeoutTask<Input, Output> extends CheckedTask<Input, Outp return; } Handler handler = new Handler(); // Need to initialize handler to main Looper so it can initialize correctly in test cases // Instrumentation threads don't have looper initialized Handler handler = new Handler(Looper.getMainLooper()); handler.postDelayed(() -> { if (getStatus() == AsyncTask.Status.RUNNING) { onTimeout(); Loading src/com/android/documentsui/dirlist/DirectoryFragment.java +9 −12 Original line number Diff line number Diff line Loading @@ -1145,10 +1145,8 @@ public class DirectoryFragment extends Fragment cache.removeUri(mModel.getItemUri(ids[i])); } final Uri uri = mState.stack.peek().derivedUri; RefreshTask task = new RefreshTask(mState, uri, REFRESH_SPINNER_TIMEOUT, getContext().getApplicationContext(), this::isDetached, (Boolean refreshSupported) -> { final DocumentInfo doc = mState.stack.peek(); mActions.refreshDocument(doc, (boolean refreshSupported) -> { if (refreshSupported) { mRefreshLayout.setRefreshing(false); } else { Loading @@ -1156,7 +1154,6 @@ public class DirectoryFragment extends Fragment getLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallbacks); } }); task.executeOnExecutor(mActivity.getExecutorForCurrentDirectory()); } private final class ModelUpdateListener implements EventListener<Model.Update> { Loading Loading
src/com/android/documentsui/AbstractActionHandler.java +10 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.documentsui.sidebar.EjectRootTask; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Provides support for specializing the actions (viewDocument etc.) to the host activity. Loading @@ -58,6 +59,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> implements ActionHandler { private static final String TAG = "AbstractActionHandler"; private static final int REFRESH_SPINNER_TIMEOUT = 500; protected final T mActivity; protected final State mState; Loading Loading @@ -106,6 +108,14 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> listener).executeOnExecutor(ProviderExecutor.forAuthority(root.authority)); } @Override public void refreshDocument(DocumentInfo doc, BooleanConsumer callback) { RefreshTask task = new RefreshTask(mState, doc, REFRESH_SPINNER_TIMEOUT, mActivity.getApplicationContext(), mActivity::isDestroyed, callback); task.executeOnExecutor(mExecutors.lookup(doc == null ? null : doc.authority)); } @Override public void openSelectedInNewWindow() { throw new UnsupportedOperationException("Can't open in new window."); Loading
src/com/android/documentsui/ActionHandler.java +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,12 @@ public interface ActionHandler { */ void ejectRoot(RootInfo root, BooleanConsumer listener); /** * Attempts to refresh the given DocumentInfo, which should be at the top of the state stack. * Returns a boolean answer to the callback, given by {@link ContentProvider#refresh}. */ void refreshDocument(DocumentInfo doc, BooleanConsumer callback); void showAppDetails(ResolveInfo info); void openRoot(RootInfo root); Loading
src/com/android/documentsui/RefreshTask.java +19 −14 Original line number Diff line number Diff line Loading @@ -29,12 +29,12 @@ import android.os.CancellationSignal; import android.util.Log; import com.android.documentsui.base.ApplicationScope; import com.android.documentsui.base.BooleanConsumer; import com.android.documentsui.base.CheckedTask; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; import java.util.function.Consumer; /** * A {@link CheckedTask} that calls * {@link ContentResolver#refresh(Uri, android.os.Bundle, android.os.CancellationSignal)} on the Loading @@ -46,14 +46,14 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { private final @ApplicationScope Context mContext; private final State mState; private final Uri mUri; private final Consumer<Boolean> mCallback; private final DocumentInfo mDoc; private final BooleanConsumer mCallback; private final CancellationSignal mSignal; public RefreshTask(State state, Uri uri, long timeout, @ApplicationScope Context context, Check check, Consumer<Boolean> callback) { public RefreshTask(State state, DocumentInfo doc, long timeout, @ApplicationScope Context context, Check check, BooleanConsumer callback) { super(check); mUri = uri; mDoc = doc; mContext = context; mState = state; mCallback = callback; Loading @@ -63,13 +63,18 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { @Override public @Nullable Boolean run(Void... params) { if (mUri == null) { Log.w(TAG, "Attempted to refresh on a null uri. Aborting."); if (mDoc == null) { Log.w(TAG, "Ignoring attempt to refresh due to null DocumentInfo."); return false; } if (mState.stack.isEmpty()) { Log.w(TAG, "Ignoring attempt to refresh due to empty stack."); return false; } if (mUri != mState.stack.peek().derivedUri) { Log.w(TAG, "Attempted to refresh on a non-top-level uri. Aborting."); if (!mDoc.derivedUri.equals(mState.stack.peek().derivedUri)) { Log.w(TAG, "Ignoring attempt to refresh on a non-top-level uri."); return false; } Loading @@ -78,17 +83,17 @@ public class RefreshTask extends TimeoutTask<Void, Boolean> { // and we will update accordingly. Else, we just tell the callback that Refresh is not // supported. if (!Shared.ENABLE_OMC_API_FEATURES) { Log.w(TAG, "Attempted to call Refresh on an older Android platform. Aborting."); Log.w(TAG, "Ignoring attempt to call Refresh on an older Android platform."); return false; } final ContentResolver resolver = mContext.getContentResolver(); final String authority = mUri.getAuthority(); final String authority = mDoc.authority; boolean refreshSupported = false; ContentProviderClient client = null; try { client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority); refreshSupported = client.refresh(mUri, null, mSignal); refreshSupported = client.refresh(mDoc.derivedUri, null, mSignal); } catch (Exception e) { Log.w(TAG, "Failed to refresh", e); } finally { Loading
src/com/android/documentsui/TimeoutTask.java +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.documentsui; import android.annotation.CallSuper; import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; import com.android.documentsui.base.CheckedTask; import com.android.documentsui.base.DocumentInfo; Loading Loading @@ -48,7 +49,9 @@ public abstract class TimeoutTask<Input, Output> extends CheckedTask<Input, Outp return; } Handler handler = new Handler(); // Need to initialize handler to main Looper so it can initialize correctly in test cases // Instrumentation threads don't have looper initialized Handler handler = new Handler(Looper.getMainLooper()); handler.postDelayed(() -> { if (getStatus() == AsyncTask.Status.RUNNING) { onTimeout(); Loading
src/com/android/documentsui/dirlist/DirectoryFragment.java +9 −12 Original line number Diff line number Diff line Loading @@ -1145,10 +1145,8 @@ public class DirectoryFragment extends Fragment cache.removeUri(mModel.getItemUri(ids[i])); } final Uri uri = mState.stack.peek().derivedUri; RefreshTask task = new RefreshTask(mState, uri, REFRESH_SPINNER_TIMEOUT, getContext().getApplicationContext(), this::isDetached, (Boolean refreshSupported) -> { final DocumentInfo doc = mState.stack.peek(); mActions.refreshDocument(doc, (boolean refreshSupported) -> { if (refreshSupported) { mRefreshLayout.setRefreshing(false); } else { Loading @@ -1156,7 +1154,6 @@ public class DirectoryFragment extends Fragment getLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallbacks); } }); task.executeOnExecutor(mActivity.getExecutorForCurrentDirectory()); } private final class ModelUpdateListener implements EventListener<Model.Update> { Loading