Home | History | Annotate | Download | only in documentsui
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.documentsui;
     18 
     19 import static junit.framework.Assert.assertEquals;
     20 import static junit.framework.Assert.assertFalse;
     21 import static junit.framework.Assert.assertNotNull;
     22 import static junit.framework.Assert.assertSame;
     23 import static junit.framework.Assert.assertTrue;
     24 
     25 import android.content.ClipData;
     26 import android.content.ClipDescription;
     27 import android.graphics.drawable.Drawable;
     28 import android.os.PersistableBundle;
     29 import android.support.test.filters.SmallTest;
     30 import android.support.test.runner.AndroidJUnit4;
     31 import android.util.Pair;
     32 import android.view.KeyEvent;
     33 import android.view.View;
     34 
     35 import com.android.documentsui.DragAndDropManager.State;
     36 import com.android.documentsui.DragAndDropManager.RuntimeDragAndDropManager;
     37 import com.android.documentsui.base.DocumentStack;
     38 import com.android.documentsui.base.RootInfo;
     39 import com.android.documentsui.services.FileOperationService;
     40 import com.android.documentsui.services.FileOperations;
     41 import com.android.documentsui.testing.ClipDatas;
     42 import com.android.documentsui.testing.KeyEvents;
     43 import com.android.documentsui.testing.TestActionHandler;
     44 import com.android.documentsui.testing.TestDocumentClipper;
     45 import com.android.documentsui.testing.TestDrawable;
     46 import com.android.documentsui.testing.TestEnv;
     47 import com.android.documentsui.testing.TestEventListener;
     48 import com.android.documentsui.testing.TestIconHelper;
     49 import com.android.documentsui.testing.TestProvidersAccess;
     50 import com.android.documentsui.testing.TestSelectionDetails;
     51 import com.android.documentsui.testing.Views;
     52 
     53 import org.junit.Before;
     54 import org.junit.Test;
     55 import org.junit.runner.RunWith;
     56 import org.mockito.Mockito;
     57 
     58 import java.util.Arrays;
     59 
     60 @RunWith(AndroidJUnit4.class)
     61 @SmallTest
     62 public class DragAndDropManagerTests {
     63 
     64     private static final String PLURAL_FORMAT = "%1$d items";
     65 
     66     private TestEnv mEnv;
     67     private TestActivity mActivity;
     68     private TestDragShadowBuilder mShadowBuilder;
     69     private View mStartDragView;
     70     private View mUpdateShadowView;
     71     private TestActionHandler mActions;
     72 
     73     private TestDocumentClipper mClipper;
     74     private TestSelectionDetails mDetails;
     75     private ClipData mClipData;
     76 
     77     private TestIconHelper mIconHelper;
     78     private Drawable mDefaultIcon;
     79 
     80     private TestEventListener<ClipData> mStartDragListener;
     81     private TestEventListener<Void> mShadowUpdateListener;
     82     private TestEventListener<Integer> mFlagListener;
     83 
     84     private TestEventListener<Integer> mCallbackListener;
     85     private FileOperations.Callback mCallback = new FileOperations.Callback() {
     86         @Override
     87         public void onOperationResult(@Status int status,
     88                 @FileOperationService.OpType int opType, int docCount) {
     89             mCallbackListener.accept(status);
     90         }
     91     };
     92 
     93     private DragAndDropManager mManager;
     94 
     95     @Before
     96     public void setUp() {
     97         mEnv = TestEnv.create();
     98         mActivity = TestActivity.create(mEnv);
     99         mActivity.resources.plurals.put(R.plurals.elements_dragged, PLURAL_FORMAT);
    100 
    101         mShadowBuilder = TestDragShadowBuilder.create();
    102 
    103         mStartDragView = Views.createTestView();
    104         mUpdateShadowView = Views.createTestView();
    105 
    106         mActions = new TestActionHandler(mEnv);
    107 
    108         mClipper = new TestDocumentClipper();
    109         mDetails = new TestSelectionDetails();
    110         mDetails.canDelete = true;
    111         ClipDescription description = new ClipDescription("", new String[]{});
    112         description.setExtras(new PersistableBundle());
    113         mClipData = ClipDatas.createTestClipData(description);
    114         mClipper.nextClip = mClipData;
    115 
    116         mDefaultIcon = new TestDrawable();
    117         mIconHelper = TestIconHelper.create();
    118         mIconHelper.nextDocumentIcon = new TestDrawable();
    119 
    120         mStartDragListener = new TestEventListener<>();
    121         mShadowUpdateListener = new TestEventListener<>();
    122         mCallbackListener = new TestEventListener<>();
    123         mFlagListener = new TestEventListener<>();
    124 
    125         mManager = new RuntimeDragAndDropManager(mActivity, mClipper, mShadowBuilder,
    126                 mDefaultIcon) {
    127             @Override
    128             void startDragAndDrop(View v, ClipData clipData, DragShadowBuilder builder,
    129                     Object localState, int flag) {
    130                 assertSame(mStartDragView, v);
    131                 assertSame(mShadowBuilder, builder);
    132                 assertNotNull(localState);
    133 
    134                 mFlagListener.accept(flag);
    135                 mStartDragListener.accept(clipData);
    136             }
    137 
    138             @Override
    139             void updateDragShadow(View v) {
    140                 assertSame(mUpdateShadowView, v);
    141 
    142                 mShadowUpdateListener.accept(null);
    143             }
    144         };
    145     }
    146 
    147     @Test
    148     public void testStartDrag_SetsCorrectClipData() {
    149         mManager.startDrag(
    150                 mStartDragView,
    151                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    152                 TestProvidersAccess.HOME,
    153                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    154                         TestEnv.FILE_JPG.derivedUri),
    155                 mDetails,
    156                 mIconHelper,
    157                 TestEnv.FOLDER_0);
    158 
    159         mStartDragListener.assertLastArgument(mClipper.nextClip);
    160     }
    161 
    162     @Test
    163     public void testStartDrag_SetsCorrectClipData_NullParent() {
    164         mManager.startDrag(
    165                 mStartDragView,
    166                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    167                 TestProvidersAccess.HOME,
    168                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    169                         TestEnv.FILE_JPG.derivedUri),
    170                 mDetails,
    171                 mIconHelper,
    172                 null);
    173 
    174         mStartDragListener.assertLastArgument(mClipper.nextClip);
    175     }
    176 
    177     @Test
    178     public void testStartDrag_BuildsCorrectShadow_SingleDoc() {
    179         mManager.startDrag(
    180                 mStartDragView,
    181                 Arrays.asList(TestEnv.FILE_APK),
    182                 TestProvidersAccess.HOME,
    183                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri),
    184                 mDetails,
    185                 mIconHelper,
    186                 TestEnv.FOLDER_0);
    187 
    188         mShadowBuilder.title.assertLastArgument(TestEnv.FILE_APK.displayName);
    189         mShadowBuilder.icon.assertLastArgument(mIconHelper.nextDocumentIcon);
    190     }
    191 
    192     @Test
    193     public void testStartDrag_BuildsCorrectShadow_MultipleDocs() {
    194         mManager.startDrag(
    195                 mStartDragView,
    196                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    197                 TestProvidersAccess.HOME,
    198                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    199                         TestEnv.FILE_JPG.derivedUri),
    200                 mDetails,
    201                 mIconHelper,
    202                 TestEnv.FOLDER_0);
    203 
    204         mShadowBuilder.title.assertLastArgument(mActivity.getResources().getQuantityString(
    205                 R.plurals.elements_dragged, 2, 2));
    206         mShadowBuilder.icon.assertLastArgument(mDefaultIcon);
    207     }
    208 
    209     @Test
    210     public void testCanSpringOpen_ReturnsFalse_RootNotSupportCreate() {
    211         mManager.startDrag(
    212                 mStartDragView,
    213                 Arrays.asList(TestEnv.FOLDER_1, TestEnv.FILE_JPG),
    214                 TestProvidersAccess.HOME,
    215                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FOLDER_1.derivedUri,
    216                         TestEnv.FILE_JPG.derivedUri),
    217                 mDetails,
    218                 mIconHelper,
    219                 TestEnv.FOLDER_0);
    220 
    221         assertFalse(mManager.canSpringOpen(TestProvidersAccess.HAMMY, TestEnv.FOLDER_2));
    222     }
    223 
    224     @Test
    225     public void testInArchiveUris_HasCorrectFlagPermission() {
    226         mDetails.containsFilesInArchive = true;
    227         mManager.startDrag(
    228                 mStartDragView,
    229                 Arrays.asList(TestEnv.FILE_IN_ARCHIVE),
    230                 TestProvidersAccess.HOME,
    231                 Arrays.asList(TestEnv.FILE_ARCHIVE.derivedUri, TestEnv.FILE_IN_ARCHIVE.derivedUri),
    232                 mDetails,
    233                 mIconHelper,
    234                 TestEnv.FILE_ARCHIVE);
    235 
    236         mFlagListener.assertLastArgument(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE);
    237     }
    238 
    239     @Test
    240     public void testCanSpringOpen_ReturnsFalse_DocIsInvalidDestination() {
    241         mManager.startDrag(
    242                 mStartDragView,
    243                 Arrays.asList(TestEnv.FOLDER_1, TestEnv.FILE_JPG),
    244                 TestProvidersAccess.HOME,
    245                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FOLDER_1.derivedUri,
    246                         TestEnv.FILE_JPG.derivedUri),
    247                 mDetails,
    248                 mIconHelper,
    249                 TestEnv.FOLDER_0);
    250 
    251         assertFalse(mManager.canSpringOpen(TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1));
    252     }
    253 
    254     @Test
    255     public void testCanSpringOpen() {
    256         mManager.startDrag(
    257                 mStartDragView,
    258                 Arrays.asList(TestEnv.FOLDER_1, TestEnv.FILE_JPG),
    259                 TestProvidersAccess.HOME,
    260                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FOLDER_1.derivedUri,
    261                         TestEnv.FILE_JPG.derivedUri),
    262                 mDetails,
    263                 mIconHelper,
    264                 TestEnv.FOLDER_0);
    265 
    266         assertTrue(mManager.canSpringOpen(TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_2));
    267     }
    268 
    269     @Test
    270     public void testDefaultToUnknownState() {
    271         mManager.startDrag(
    272                 mStartDragView,
    273                 Arrays.asList(TestEnv.FOLDER_1, TestEnv.FILE_JPG),
    274                 TestProvidersAccess.HOME,
    275                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FOLDER_1.derivedUri,
    276                         TestEnv.FILE_JPG.derivedUri),
    277                 mDetails,
    278                 mIconHelper,
    279                 TestEnv.FOLDER_0);
    280 
    281         mShadowBuilder.state.assertLastArgument(DragAndDropManager.STATE_UNKNOWN);
    282     }
    283 
    284     @Test
    285     public void testUpdateStateToNotAllowed() {
    286         mManager.startDrag(
    287                 mStartDragView,
    288                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    289                 TestProvidersAccess.HOME,
    290                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    291                         TestEnv.FILE_JPG.derivedUri),
    292                 mDetails,
    293                 mIconHelper,
    294                 TestEnv.FOLDER_0);
    295 
    296         mManager.updateStateToNotAllowed(mUpdateShadowView);
    297 
    298         assertStateUpdated(DragAndDropManager.STATE_NOT_ALLOWED);
    299     }
    300 
    301     @Test
    302     public void testUpdateState_UpdatesToNotAllowed_RootNotSupportCreate() {
    303         mManager.startDrag(
    304                 mStartDragView,
    305                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    306                 TestProvidersAccess.HOME,
    307                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    308                         TestEnv.FILE_JPG.derivedUri),
    309                 mDetails,
    310                 mIconHelper,
    311                 TestEnv.FOLDER_0);
    312 
    313         final @State int state = mManager.updateState(
    314                 mUpdateShadowView, TestProvidersAccess.HAMMY, TestEnv.FOLDER_2);
    315 
    316         assertEquals(DragAndDropManager.STATE_NOT_ALLOWED, state);
    317         assertStateUpdated(DragAndDropManager.STATE_NOT_ALLOWED);
    318     }
    319 
    320     @Test
    321     public void testUpdateState_UpdatesToUnknown_RootDocIsNull() {
    322         mManager.startDrag(
    323                 mStartDragView,
    324                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    325                 TestProvidersAccess.HOME,
    326                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    327                         TestEnv.FILE_JPG.derivedUri),
    328                 mDetails,
    329                 mIconHelper,
    330                 TestEnv.FOLDER_0);
    331 
    332         final @State int state = mManager.updateState(
    333                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, null);
    334 
    335         assertEquals(DragAndDropManager.STATE_UNKNOWN, state);
    336         assertStateUpdated(DragAndDropManager.STATE_UNKNOWN);
    337     }
    338 
    339     @Test
    340     public void testUpdateState_UpdatesToMove_SameRoot() {
    341         mManager.startDrag(
    342                 mStartDragView,
    343                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    344                 TestProvidersAccess.DOWNLOADS,
    345                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    346                         TestEnv.FILE_JPG.derivedUri),
    347                 mDetails,
    348                 mIconHelper,
    349                 TestEnv.FOLDER_0);
    350 
    351         final @State int state = mManager.updateState(
    352                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    353 
    354         assertEquals(DragAndDropManager.STATE_MOVE, state);
    355         assertStateUpdated(DragAndDropManager.STATE_MOVE);
    356     }
    357 
    358     @Test
    359     public void testUpdateState_UpdatesToCopy_DifferentRoot() {
    360         mManager.startDrag(
    361                 mStartDragView,
    362                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    363                 TestProvidersAccess.HOME,
    364                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    365                         TestEnv.FILE_JPG.derivedUri),
    366                 mDetails,
    367                 mIconHelper,
    368                 TestEnv.FOLDER_0);
    369 
    370         final @State int state = mManager.updateState(
    371                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    372 
    373         assertEquals(DragAndDropManager.STATE_COPY, state);
    374         assertStateUpdated(DragAndDropManager.STATE_COPY);
    375     }
    376 
    377     @Test
    378     public void testUpdateState_UpdatesToCopy_SameRoot_LeftCtrlPressed() {
    379         mManager.startDrag(
    380                 mStartDragView,
    381                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    382                 TestProvidersAccess.DOWNLOADS,
    383                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    384                         TestEnv.FILE_JPG.derivedUri),
    385                 mDetails,
    386                 mIconHelper,
    387                 TestEnv.FOLDER_0);
    388 
    389         KeyEvent event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_DOWN);
    390         mManager.onKeyEvent(event);
    391 
    392         final @State int state = mManager.updateState(
    393                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    394 
    395         assertEquals(DragAndDropManager.STATE_COPY, state);
    396         assertStateUpdated(DragAndDropManager.STATE_COPY);
    397     }
    398 
    399     @Test
    400     public void testUpdateState_UpdatesToCopy_SameRoot_RightCtrlPressed() {
    401         mManager.startDrag(
    402                 mStartDragView,
    403                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    404                 TestProvidersAccess.DOWNLOADS,
    405                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    406                         TestEnv.FILE_JPG.derivedUri),
    407                 mDetails,
    408                 mIconHelper,
    409                 TestEnv.FOLDER_0);
    410 
    411         KeyEvent event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_DOWN);
    412         mManager.onKeyEvent(event);
    413 
    414         final @State int state = mManager.updateState(
    415                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    416 
    417         assertEquals(DragAndDropManager.STATE_COPY, state);
    418         assertStateUpdated(DragAndDropManager.STATE_COPY);
    419     }
    420 
    421     @Test
    422     public void testUpdateState_UpdatesToMove_DifferentRoot_LeftCtrlPressed() {
    423         mManager.startDrag(
    424                 mStartDragView,
    425                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    426                 TestProvidersAccess.HOME,
    427                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    428                         TestEnv.FILE_JPG.derivedUri),
    429                 mDetails,
    430                 mIconHelper,
    431                 TestEnv.FOLDER_0);
    432 
    433         KeyEvent event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_DOWN);
    434         mManager.onKeyEvent(event);
    435 
    436         final @State int state = mManager.updateState(
    437                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    438 
    439         assertEquals(DragAndDropManager.STATE_MOVE, state);
    440         assertStateUpdated(DragAndDropManager.STATE_MOVE);
    441     }
    442 
    443     @Test
    444     public void testUpdateState_UpdatesToMove_DifferentRoot_RightCtrlPressed() {
    445         mManager.startDrag(
    446                 mStartDragView,
    447                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    448                 TestProvidersAccess.HOME,
    449                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    450                         TestEnv.FILE_JPG.derivedUri),
    451                 mDetails,
    452                 mIconHelper,
    453                 TestEnv.FOLDER_0);
    454 
    455         KeyEvent event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_DOWN);
    456         mManager.onKeyEvent(event);
    457 
    458         final @State int state = mManager.updateState(
    459                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    460 
    461         assertEquals(DragAndDropManager.STATE_MOVE, state);
    462         assertStateUpdated(DragAndDropManager.STATE_MOVE);
    463     }
    464 
    465     @Test
    466     public void testUpdateState_UpdatesToMove_SameRoot_LeftCtrlReleased() {
    467         mManager.startDrag(
    468                 mStartDragView,
    469                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    470                 TestProvidersAccess.DOWNLOADS,
    471                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    472                         TestEnv.FILE_JPG.derivedUri),
    473                 mDetails,
    474                 mIconHelper,
    475                 TestEnv.FOLDER_0);
    476 
    477         KeyEvent event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_DOWN);
    478         mManager.onKeyEvent(event);
    479 
    480         event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_UP);
    481         mManager.onKeyEvent(event);
    482 
    483         final @State int state = mManager.updateState(
    484                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    485 
    486         assertEquals(DragAndDropManager.STATE_MOVE, state);
    487         assertStateUpdated(DragAndDropManager.STATE_MOVE);
    488     }
    489 
    490     @Test
    491     public void testUpdateState_UpdatesToMove_SameRoot_RightCtrlReleased() {
    492         mManager.startDrag(
    493                 mStartDragView,
    494                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    495                 TestProvidersAccess.DOWNLOADS,
    496                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    497                         TestEnv.FILE_JPG.derivedUri),
    498                 mDetails,
    499                 mIconHelper,
    500                 TestEnv.FOLDER_0);
    501 
    502         KeyEvent event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_DOWN);
    503         mManager.onKeyEvent(event);
    504 
    505         event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_UP);
    506         mManager.onKeyEvent(event);
    507 
    508         final @State int state = mManager.updateState(
    509                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    510 
    511         assertEquals(DragAndDropManager.STATE_MOVE, state);
    512         assertStateUpdated(DragAndDropManager.STATE_MOVE);
    513     }
    514 
    515     @Test
    516     public void testUpdateState_UpdatesToCopy_DifferentRoot_LeftCtrlReleased() {
    517         mManager.startDrag(
    518                 mStartDragView,
    519                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    520                 TestProvidersAccess.HOME,
    521                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    522                         TestEnv.FILE_JPG.derivedUri),
    523                 mDetails,
    524                 mIconHelper,
    525                 TestEnv.FOLDER_0);
    526 
    527         KeyEvent event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_DOWN);
    528         mManager.onKeyEvent(event);
    529 
    530         event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_UP);
    531         mManager.onKeyEvent(event);
    532 
    533         final @State int state = mManager.updateState(
    534                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    535 
    536         assertEquals(DragAndDropManager.STATE_COPY, state);
    537         assertStateUpdated(DragAndDropManager.STATE_COPY);
    538     }
    539 
    540     @Test
    541     public void testUpdateState_UpdatesToCopy_DifferentRoot_RightCtrlReleased() {
    542         mManager.startDrag(
    543                 mStartDragView,
    544                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    545                 TestProvidersAccess.HOME,
    546                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    547                         TestEnv.FILE_JPG.derivedUri),
    548                 mDetails,
    549                 mIconHelper,
    550                 TestEnv.FOLDER_0);
    551 
    552         KeyEvent event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_DOWN);
    553         mManager.onKeyEvent(event);
    554 
    555         event = KeyEvents.createRightCtrlKey(KeyEvent.ACTION_UP);
    556         mManager.onKeyEvent(event);
    557 
    558         final @State int state = mManager.updateState(
    559                 mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    560 
    561         assertEquals(DragAndDropManager.STATE_COPY, state);
    562         assertStateUpdated(DragAndDropManager.STATE_COPY);
    563     }
    564 
    565     @Test
    566     public void testResetState_UpdatesToUnknown() {
    567         mManager.startDrag(
    568                 mStartDragView,
    569                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    570                 TestProvidersAccess.HOME,
    571                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    572                         TestEnv.FILE_JPG.derivedUri),
    573                 mDetails,
    574                 mIconHelper,
    575                 TestEnv.FOLDER_0);
    576 
    577         mManager.updateStateToNotAllowed(mUpdateShadowView);
    578 
    579         mManager.resetState(mUpdateShadowView);
    580 
    581         assertStateUpdated(DragAndDropManager.STATE_UNKNOWN);
    582     }
    583 
    584     @Test
    585     public void testDrop_Rejects_RootNotSupportCreate_DropOnRoot() {
    586         mManager.startDrag(
    587                 mStartDragView,
    588                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    589                 TestProvidersAccess.HOME,
    590                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    591                         TestEnv.FILE_JPG.derivedUri),
    592                 mDetails,
    593                 mIconHelper,
    594                 TestEnv.FOLDER_0);
    595 
    596         mManager.updateState(mUpdateShadowView, TestProvidersAccess.HAMMY, TestEnv.FOLDER_1);
    597 
    598         assertFalse(mManager.drop(
    599                 mClipData, mManager, TestProvidersAccess.HAMMY, mActions, mCallback));
    600     }
    601 
    602     @Test
    603     public void testDrop_Rejects_InvalidRoot() {
    604         RootInfo root = new RootInfo();
    605         root.authority = TestProvidersAccess.HOME.authority;
    606         root.documentId = TestEnv.FOLDER_0.documentId;
    607 
    608         mManager.startDrag(
    609                 mStartDragView,
    610                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    611                 root,
    612                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    613                         TestEnv.FILE_JPG.derivedUri),
    614                 mDetails,
    615                 mIconHelper,
    616                 TestEnv.FOLDER_0);
    617 
    618         mManager.updateState(mUpdateShadowView, TestProvidersAccess.HOME, TestEnv.FOLDER_0);
    619 
    620         assertFalse(mManager.drop(mClipData, mManager, root, mActions, mCallback));
    621     }
    622 
    623     @Test
    624     public void testDrop_Fails_NotGetRootDoc() throws Exception {
    625         mManager.startDrag(
    626                 mStartDragView,
    627                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    628                 TestProvidersAccess.HOME,
    629                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    630                         TestEnv.FILE_JPG.derivedUri),
    631                 mDetails,
    632                 mIconHelper,
    633                 TestEnv.FOLDER_0);
    634 
    635         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    636 
    637         mManager.drop(
    638                 mClipData, mManager, TestProvidersAccess.DOWNLOADS, mActions, mCallback);
    639 
    640         mEnv.beforeAsserts();
    641         mCallbackListener.assertLastArgument(FileOperations.Callback.STATUS_FAILED);
    642     }
    643 
    644     @Test
    645     public void testDrop_Copies_DifferentRoot_DropOnRoot() throws Exception {
    646         mActions.nextRootDocument = TestEnv.FOLDER_1;
    647 
    648         mManager.startDrag(
    649                 mStartDragView,
    650                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    651                 TestProvidersAccess.HOME,
    652                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    653                         TestEnv.FILE_JPG.derivedUri),
    654                 mDetails,
    655                 mIconHelper,
    656                 TestEnv.FOLDER_0);
    657 
    658         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    659 
    660         mManager.drop(
    661                 mClipData, mManager, TestProvidersAccess.DOWNLOADS, mActions, mCallback);
    662 
    663         mEnv.beforeAsserts();
    664         final DocumentStack expect =
    665                 new DocumentStack(TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    666         mClipper.copyFromClip.assertLastArgument(Pair.create(expect, mClipData));
    667         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_COPY);
    668     }
    669 
    670     @Test
    671     public void testDrop_Moves_SameRoot_DropOnRoot() throws Exception {
    672         mActions.nextRootDocument = TestEnv.FOLDER_1;
    673 
    674         mManager.startDrag(
    675                 mStartDragView,
    676                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    677                 TestProvidersAccess.DOWNLOADS,
    678                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    679                         TestEnv.FILE_JPG.derivedUri),
    680                 mDetails,
    681                 mIconHelper,
    682                 TestEnv.FOLDER_0);
    683 
    684         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    685 
    686         mManager.drop(
    687                 mClipData, mManager, TestProvidersAccess.DOWNLOADS, mActions, mCallback);
    688 
    689         mEnv.beforeAsserts();
    690         final DocumentStack expect =
    691                 new DocumentStack(TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    692         mClipper.copyFromClip.assertLastArgument(Pair.create(expect, mClipData));
    693         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_MOVE);
    694     }
    695 
    696     @Test
    697     public void testDrop_Copies_SameRoot_DropOnRoot_ReleasesCtrlBeforeGettingRootDocument()
    698             throws Exception{
    699         mActions.nextRootDocument = TestEnv.FOLDER_1;
    700 
    701         mManager.startDrag(
    702                 mStartDragView,
    703                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    704                 TestProvidersAccess.DOWNLOADS,
    705                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    706                         TestEnv.FILE_JPG.derivedUri),
    707                 mDetails,
    708                 mIconHelper,
    709                 TestEnv.FOLDER_0);
    710 
    711         KeyEvent event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_DOWN);
    712         mManager.onKeyEvent(event);
    713 
    714         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    715 
    716         mManager.drop(
    717                 mClipData, mManager, TestProvidersAccess.DOWNLOADS, mActions, mCallback);
    718 
    719         event = KeyEvents.createLeftCtrlKey(KeyEvent.ACTION_UP);
    720         mManager.onKeyEvent(event);
    721 
    722         mEnv.beforeAsserts();
    723         final DocumentStack expect =
    724                 new DocumentStack(TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1);
    725         mClipper.copyFromClip.assertLastArgument(Pair.create(expect, mClipData));
    726         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_COPY);
    727     }
    728 
    729     @Test
    730     public void testDrop_Rejects_RootNotSupportCreate_DropOnDocument() {
    731         mManager.startDrag(
    732                 mStartDragView,
    733                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    734                 TestProvidersAccess.HOME,
    735                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    736                         TestEnv.FILE_JPG.derivedUri),
    737                 mDetails,
    738                 mIconHelper,
    739                 TestEnv.FOLDER_0);
    740 
    741         mManager.updateState(mUpdateShadowView, TestProvidersAccess.HAMMY, TestEnv.FOLDER_2);
    742 
    743         final DocumentStack stack = new DocumentStack(
    744                 TestProvidersAccess.HAMMY, TestEnv.FOLDER_1, TestEnv.FOLDER_2);
    745         assertFalse(mManager.drop(mClipData, mManager, stack, mCallback));
    746     }
    747 
    748     @Test
    749     public void testDrop_Copies_DifferentRoot_DropOnDocument() {
    750         mManager.startDrag(
    751                 mStartDragView,
    752                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    753                 TestProvidersAccess.HOME,
    754                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    755                         TestEnv.FILE_JPG.derivedUri),
    756                 mDetails,
    757                 mIconHelper,
    758                 TestEnv.FOLDER_0);
    759 
    760         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_2);
    761 
    762         final DocumentStack stack = new DocumentStack(
    763                 TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1, TestEnv.FOLDER_2);
    764         assertTrue(mManager.drop(mClipData, mManager, stack, mCallback));
    765 
    766         mClipper.copyFromClip.assertLastArgument(Pair.create(stack, mClipData));
    767         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_COPY);
    768     }
    769 
    770     @Test
    771     public void testDrop_Moves_SameRoot_DropOnDocument() {
    772         mManager.startDrag(
    773                 mStartDragView,
    774                 Arrays.asList(TestEnv.FILE_APK, TestEnv.FILE_JPG),
    775                 TestProvidersAccess.DOWNLOADS,
    776                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_APK.derivedUri,
    777                         TestEnv.FILE_JPG.derivedUri),
    778                 mDetails,
    779                 mIconHelper,
    780                 TestEnv.FOLDER_0);
    781 
    782         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_2);
    783 
    784         final DocumentStack stack = new DocumentStack(
    785                 TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1, TestEnv.FOLDER_2);
    786         assertTrue(mManager.drop(mClipData, mManager, stack, mCallback));
    787 
    788         mClipper.copyFromClip.assertLastArgument(Pair.create(stack, mClipData));
    789         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_MOVE);
    790     }
    791 
    792     @Test
    793     public void testDrop_Copies_SameRoot_ReadOnlyFile_DropOnDocument() {
    794         mDetails.canDelete = false;
    795         mManager.startDrag(
    796                 mStartDragView,
    797                 Arrays.asList(TestEnv.FILE_READ_ONLY),
    798                 TestProvidersAccess.DOWNLOADS,
    799                 Arrays.asList(TestEnv.FOLDER_0.derivedUri, TestEnv.FILE_READ_ONLY.derivedUri),
    800                 mDetails,
    801                 mIconHelper,
    802                 TestEnv.FOLDER_0);
    803 
    804         mManager.updateState(mUpdateShadowView, TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_2);
    805 
    806         final DocumentStack stack = new DocumentStack(
    807                 TestProvidersAccess.DOWNLOADS, TestEnv.FOLDER_1, TestEnv.FOLDER_2);
    808         assertTrue(mManager.drop(mClipData, mManager, stack, mCallback));
    809 
    810         mClipper.copyFromClip.assertLastArgument(Pair.create(stack, mClipData));
    811         mClipper.opType.assertLastArgument(FileOperationService.OPERATION_COPY);
    812     }
    813 
    814     private void assertStateUpdated(@State int expected) {
    815         mShadowBuilder.state.assertLastArgument(expected);
    816         mShadowUpdateListener.assertCalled();
    817     }
    818 
    819     public static class TestDragShadowBuilder extends DragShadowBuilder {
    820 
    821         public TestEventListener<String> title;
    822         public TestEventListener<Drawable> icon;
    823         public TestEventListener<Integer> state;
    824 
    825         private TestDragShadowBuilder() {
    826             super(null);
    827         }
    828 
    829         @Override
    830         void updateTitle(String title) {
    831             this.title.accept(title);
    832         }
    833 
    834         @Override
    835         void updateIcon(Drawable icon) {
    836             this.icon.accept(icon);
    837         }
    838 
    839         @Override
    840         void onStateUpdated(@State int state) {
    841             this.state.accept(state);
    842         }
    843 
    844         public static TestDragShadowBuilder create() {
    845             TestDragShadowBuilder builder =
    846                     Mockito.mock(TestDragShadowBuilder.class, Mockito.CALLS_REAL_METHODS);
    847 
    848             builder.title = new TestEventListener<>();
    849             builder.icon = new TestEventListener<>();
    850             builder.state = new TestEventListener<>();
    851 
    852             return builder;
    853         }
    854     }
    855 }
    856