Loading src/com/android/documentsui/BaseActivity.java +30 −13 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import com.android.documentsui.dirlist.Model; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.DocumentStack; import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperationService; import com.android.documentsui.services.FileOperations; import java.io.FileNotFoundException; import java.util.ArrayList; Loading @@ -71,6 +73,32 @@ import java.util.concurrent.Executor; public abstract class BaseActivity extends Activity implements SearchManagerListener, NavigationViewManager.Environment { public final FileOperations.Callback fileOpCallback = (status, opType, docCount) -> { if (status == FileOperations.Callback.STATUS_REJECTED) { Snackbars.showPasteFailed(this); return; } if (docCount == 0) { // Nothing has been pasted, so there is no need to show a snackbar. return; } switch (opType) { case FileOperationService.OPERATION_MOVE: Snackbars.showMove(this, docCount); break; case FileOperationService.OPERATION_COPY: Snackbars.showCopy(this, docCount); break; case FileOperationService.OPERATION_DELETE: // We don't show anything for deletion. break; default: throw new UnsupportedOperationException("Unsupported Operation: " + opType); } }; private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests"; State mState; Loading Loading @@ -706,17 +734,6 @@ public abstract class BaseActivity extends Activity mNavDrawerHasFocus = !mNavDrawerHasFocus; } DocumentInfo getRootDocumentBlocking(RootInfo root) { try { final Uri uri = DocumentsContract.buildDocumentUri( root.authority, root.documentId); return DocumentInfo.fromUri(getContentResolver(), uri); } catch (FileNotFoundException e) { Log.w(mTag, "Failed to find root", e); return null; } } /** * Pops the top entry off the directory stack, and returns the user to the previous directory. * If the directory stack only contains one item, this method does nothing. Loading Loading @@ -780,7 +797,7 @@ public abstract class BaseActivity extends Activity @Override protected DocumentInfo run(Void... params) { return mOwner.getRootDocumentBlocking(mRoot); return mRoot.getRootDocumentBlocking(mOwner); } @Override Loading Loading @@ -816,7 +833,7 @@ public abstract class BaseActivity extends Activity final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = mOwner.getRootDocumentBlocking(defaultRoot); mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } Loading src/com/android/documentsui/CheckedTask.java +1 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ abstract class CheckedTask<Input, Output> finish(result); } @FunctionalInterface interface Check { boolean stop(); } Loading src/com/android/documentsui/FilesActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -519,7 +519,7 @@ public class FilesActivity extends BaseActivity { } catch (FileNotFoundException e) { Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri); } mState.stack.add(mOwner.getRootDocumentBlocking(root)); mState.stack.add(root.getRootDocumentBlocking(mOwner)); return null; } Loading src/com/android/documentsui/ItemDragListener.java +2 −3 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.util.Log; import android.view.DragEvent; import android.view.View; import android.view.View.OnDragListener; import android.view.ViewConfiguration; import com.android.documentsui.ItemDragListener.DragHost; import com.android.internal.annotations.VisibleForTesting; Loading @@ -39,7 +38,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener { private static final String TAG = "ItemDragListener"; @VisibleForTesting static final int SPRING_TIMEOUT = ViewConfiguration.getLongPressTimeout(); static final int SPRING_TIMEOUT = 1000; protected final H mDragHost; private final Timer mHoverTimer; Loading Loading @@ -82,7 +81,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener { TimerTask task = createOpenTask(v); assert (task != null); v.setTag(R.id.drag_hovering_tag, task); mHoverTimer.schedule(task, ViewConfiguration.getLongPressTimeout()); mHoverTimer.schedule(task, SPRING_TIMEOUT); } private void handleLocationEvent(View v, float x, float y) { Loading src/com/android/documentsui/RootsFragment.java +70 −8 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.content.Loader; Loading @@ -33,16 +34,14 @@ import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.Settings; import android.support.annotation.Nullable; import android.text.TextUtils; import android.text.format.Formatter; import android.util.Log; import android.view.ContextMenu; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; Loading @@ -60,7 +59,11 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.android.documentsui.CheckedTask.Check; import com.android.documentsui.clipping.DocumentClipper; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperations; import java.util.ArrayList; import java.util.Collection; Loading @@ -81,6 +84,20 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost private static final String TAG = "RootsFragment"; private static final String EXTRA_INCLUDE_APPS = "includeApps"; private final OnDragListener mDragListener = new ItemDragListener<RootsFragment>(this) { @Override public boolean handleDropEventChecked(View v, DragEvent event) { final int position = (Integer) v.getTag(R.id.item_position_tag); final Item item = mAdapter.getItem(position); assert(item.isDropTarget()); BaseActivity activity = getBaseActivity(); return item.dropOn(event.getClipData(), activity, RootsFragment.this::isDetached, activity.fileOpCallback); } }; private ListView mList; private RootsAdapter mAdapter; private LoaderCallbacks<Collection<RootInfo>> mCallbacks; Loading Loading @@ -165,8 +182,8 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS); mAdapter = new RootsAdapter(context, result, handlerAppIntent, state, new ItemDragListener<>(RootsFragment.this)); mAdapter = new RootsAdapter(context, result, handlerAppIntent, state, mDragListener); mList.setAdapter(mAdapter); onCurrentRootChanged(); Loading Loading @@ -247,12 +264,12 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost * In RootsFragment we open the hovered root. */ @Override public void onViewHovered(View view) { public void onViewHovered(View v) { // SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView. RootItemView itemView = (RootItemView) view; RootItemView itemView = (RootItemView) v; itemView.drawRipple(); final int position = (Integer) view.getTag(R.id.item_position_tag); final int position = (Integer) v.getTag(R.id.item_position_tag); final Item item = mAdapter.getItem(position); item.open(this); } Loading Loading @@ -374,6 +391,11 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost abstract boolean isDropTarget(); abstract void open(RootsFragment fragment); boolean dropOn(ClipData data, Context context, Check check, FileOperations.Callback callback) { return false; } } private static class RootItem extends Item { Loading Loading @@ -440,6 +462,14 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost Metrics.logRootVisited(fragment.getActivity(), root); activity.onRootPicked(root); } @Override boolean dropOn( ClipData data, Context context, Check check, FileOperations.Callback callback) { ProviderExecutor executor = ProviderExecutor.forAuthority(root.authority); new DropOnRootTask(data, root, context, check, callback).executeOnExecutor(executor); return true; } } private static class SpacerItem extends Item { Loading Loading @@ -518,6 +548,38 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost } } private static class DropOnRootTask extends CheckedTask<Void, DocumentInfo> { private ClipData mData; private RootInfo mDstRoot; private Context mContext; private FileOperations.Callback mCallback; private DropOnRootTask(ClipData data, RootInfo dstRoot, Context context, Check check, FileOperations.Callback callback) { super(check); mData = data; mDstRoot = dstRoot; mContext = context; mCallback = callback; } @Override public DocumentInfo run(Void... args) { return mDstRoot.getRootDocumentBlocking(mContext); } @Override public void finish(DocumentInfo doc) { if (doc != null) { DocumentClipper clipper = DocumentsApplication.getDocumentClipper(mContext); clipper.copyFromClipData(mDstRoot, doc, mData, mCallback); } else { Log.e(TAG, "Failed to get doc."); } } } private static class RootsAdapter extends ArrayAdapter<Item> { private static final Map<String, Long> sIdMap = new HashMap<String, Long>(); // the next available id to associate with a new string id Loading Loading
src/com/android/documentsui/BaseActivity.java +30 −13 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ import com.android.documentsui.dirlist.Model; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.DocumentStack; import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperationService; import com.android.documentsui.services.FileOperations; import java.io.FileNotFoundException; import java.util.ArrayList; Loading @@ -71,6 +73,32 @@ import java.util.concurrent.Executor; public abstract class BaseActivity extends Activity implements SearchManagerListener, NavigationViewManager.Environment { public final FileOperations.Callback fileOpCallback = (status, opType, docCount) -> { if (status == FileOperations.Callback.STATUS_REJECTED) { Snackbars.showPasteFailed(this); return; } if (docCount == 0) { // Nothing has been pasted, so there is no need to show a snackbar. return; } switch (opType) { case FileOperationService.OPERATION_MOVE: Snackbars.showMove(this, docCount); break; case FileOperationService.OPERATION_COPY: Snackbars.showCopy(this, docCount); break; case FileOperationService.OPERATION_DELETE: // We don't show anything for deletion. break; default: throw new UnsupportedOperationException("Unsupported Operation: " + opType); } }; private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests"; State mState; Loading Loading @@ -706,17 +734,6 @@ public abstract class BaseActivity extends Activity mNavDrawerHasFocus = !mNavDrawerHasFocus; } DocumentInfo getRootDocumentBlocking(RootInfo root) { try { final Uri uri = DocumentsContract.buildDocumentUri( root.authority, root.documentId); return DocumentInfo.fromUri(getContentResolver(), uri); } catch (FileNotFoundException e) { Log.w(mTag, "Failed to find root", e); return null; } } /** * Pops the top entry off the directory stack, and returns the user to the previous directory. * If the directory stack only contains one item, this method does nothing. Loading Loading @@ -780,7 +797,7 @@ public abstract class BaseActivity extends Activity @Override protected DocumentInfo run(Void... params) { return mOwner.getRootDocumentBlocking(mRoot); return mRoot.getRootDocumentBlocking(mOwner); } @Override Loading Loading @@ -816,7 +833,7 @@ public abstract class BaseActivity extends Activity final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = mOwner.getRootDocumentBlocking(defaultRoot); mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } Loading
src/com/android/documentsui/CheckedTask.java +1 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ abstract class CheckedTask<Input, Output> finish(result); } @FunctionalInterface interface Check { boolean stop(); } Loading
src/com/android/documentsui/FilesActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -519,7 +519,7 @@ public class FilesActivity extends BaseActivity { } catch (FileNotFoundException e) { Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri); } mState.stack.add(mOwner.getRootDocumentBlocking(root)); mState.stack.add(root.getRootDocumentBlocking(mOwner)); return null; } Loading
src/com/android/documentsui/ItemDragListener.java +2 −3 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.util.Log; import android.view.DragEvent; import android.view.View; import android.view.View.OnDragListener; import android.view.ViewConfiguration; import com.android.documentsui.ItemDragListener.DragHost; import com.android.internal.annotations.VisibleForTesting; Loading @@ -39,7 +38,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener { private static final String TAG = "ItemDragListener"; @VisibleForTesting static final int SPRING_TIMEOUT = ViewConfiguration.getLongPressTimeout(); static final int SPRING_TIMEOUT = 1000; protected final H mDragHost; private final Timer mHoverTimer; Loading Loading @@ -82,7 +81,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener { TimerTask task = createOpenTask(v); assert (task != null); v.setTag(R.id.drag_hovering_tag, task); mHoverTimer.schedule(task, ViewConfiguration.getLongPressTimeout()); mHoverTimer.schedule(task, SPRING_TIMEOUT); } private void handleLocationEvent(View v, float x, float y) { Loading
src/com/android/documentsui/RootsFragment.java +70 −8 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.content.Loader; Loading @@ -33,16 +34,14 @@ import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.Settings; import android.support.annotation.Nullable; import android.text.TextUtils; import android.text.format.Formatter; import android.util.Log; import android.view.ContextMenu; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; Loading @@ -60,7 +59,11 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.android.documentsui.CheckedTask.Check; import com.android.documentsui.clipping.DocumentClipper; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperations; import java.util.ArrayList; import java.util.Collection; Loading @@ -81,6 +84,20 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost private static final String TAG = "RootsFragment"; private static final String EXTRA_INCLUDE_APPS = "includeApps"; private final OnDragListener mDragListener = new ItemDragListener<RootsFragment>(this) { @Override public boolean handleDropEventChecked(View v, DragEvent event) { final int position = (Integer) v.getTag(R.id.item_position_tag); final Item item = mAdapter.getItem(position); assert(item.isDropTarget()); BaseActivity activity = getBaseActivity(); return item.dropOn(event.getClipData(), activity, RootsFragment.this::isDetached, activity.fileOpCallback); } }; private ListView mList; private RootsAdapter mAdapter; private LoaderCallbacks<Collection<RootInfo>> mCallbacks; Loading Loading @@ -165,8 +182,8 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS); mAdapter = new RootsAdapter(context, result, handlerAppIntent, state, new ItemDragListener<>(RootsFragment.this)); mAdapter = new RootsAdapter(context, result, handlerAppIntent, state, mDragListener); mList.setAdapter(mAdapter); onCurrentRootChanged(); Loading Loading @@ -247,12 +264,12 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost * In RootsFragment we open the hovered root. */ @Override public void onViewHovered(View view) { public void onViewHovered(View v) { // SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView. RootItemView itemView = (RootItemView) view; RootItemView itemView = (RootItemView) v; itemView.drawRipple(); final int position = (Integer) view.getTag(R.id.item_position_tag); final int position = (Integer) v.getTag(R.id.item_position_tag); final Item item = mAdapter.getItem(position); item.open(this); } Loading Loading @@ -374,6 +391,11 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost abstract boolean isDropTarget(); abstract void open(RootsFragment fragment); boolean dropOn(ClipData data, Context context, Check check, FileOperations.Callback callback) { return false; } } private static class RootItem extends Item { Loading Loading @@ -440,6 +462,14 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost Metrics.logRootVisited(fragment.getActivity(), root); activity.onRootPicked(root); } @Override boolean dropOn( ClipData data, Context context, Check check, FileOperations.Callback callback) { ProviderExecutor executor = ProviderExecutor.forAuthority(root.authority); new DropOnRootTask(data, root, context, check, callback).executeOnExecutor(executor); return true; } } private static class SpacerItem extends Item { Loading Loading @@ -518,6 +548,38 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost } } private static class DropOnRootTask extends CheckedTask<Void, DocumentInfo> { private ClipData mData; private RootInfo mDstRoot; private Context mContext; private FileOperations.Callback mCallback; private DropOnRootTask(ClipData data, RootInfo dstRoot, Context context, Check check, FileOperations.Callback callback) { super(check); mData = data; mDstRoot = dstRoot; mContext = context; mCallback = callback; } @Override public DocumentInfo run(Void... args) { return mDstRoot.getRootDocumentBlocking(mContext); } @Override public void finish(DocumentInfo doc) { if (doc != null) { DocumentClipper clipper = DocumentsApplication.getDocumentClipper(mContext); clipper.copyFromClipData(mDstRoot, doc, mData, mCallback); } else { Log.e(TAG, "Failed to get doc."); } } } private static class RootsAdapter extends ArrayAdapter<Item> { private static final Map<String, Long> sIdMap = new HashMap<String, Long>(); // the next available id to associate with a new string id Loading