Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae937584 authored by Garfield Tan's avatar Garfield Tan
Browse files

Some refactor around default init location for picker.

* Isolate DocumentStack initialization to a static method. Address
  Steve's comment in ag/1971473.
* Move the special init location logic in PickActivity for create and
  copy destination action into ActionHandler

Change-Id: I0f5b6d0cf6b83c282ed9e14ae46a05269ac971e7
parent 15ed8b2c
Loading
Loading
Loading
Loading
+45 −20
Original line number Diff line number Diff line
@@ -19,11 +19,15 @@ package com.android.documentsui.base;
import static com.android.documentsui.base.Shared.DEBUG;

import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.DocumentsProvider;
import android.util.Log;

import com.android.documentsui.picker.LastAccessedProvider;
import com.android.documentsui.roots.RootsAccess;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
@@ -171,26 +175,6 @@ public class DocumentStack implements Durable, Parcelable {
        return mRoot != null && mRoot.isRecents();
    }

    public void updateRoot(Collection<RootInfo> matchingRoots) throws FileNotFoundException {
        for (RootInfo root : matchingRoots) {
            if (root.equals(this.mRoot)) {
                this.mRoot = root;
                return;
            }
        }
        throw new FileNotFoundException("Failed to find matching mRoot for " + mRoot);
    }

    /**
     * Update a possibly stale restored stack against a live
     * {@link DocumentsProvider}.
     */
    public void updateDocuments(ContentResolver resolver) throws FileNotFoundException {
        for (DocumentInfo info : mList) {
            info.updateSelf(resolver);
        }
    }

    /**
     * Resets this stack to the given stack. It takes the reference of {@link #mList} and
     * {@link #mRoot} instead of making a copy.
@@ -218,6 +202,47 @@ public class DocumentStack implements Durable, Parcelable {
        mRoot = null;
    }

    private void updateRoot(Collection<RootInfo> matchingRoots) throws FileNotFoundException {
        for (RootInfo root : matchingRoots) {
            // RootInfo's equals() only checks authority and rootId, so this will update RootInfo if
            // its flag has changed.
            if (root.equals(this.mRoot)) {
                this.mRoot = root;
                return;
            }
        }
        throw new FileNotFoundException("Failed to find matching mRoot for " + mRoot);
    }

    /**
     * Update a possibly stale restored stack against a live
     * {@link DocumentsProvider}.
     */
    private void updateDocuments(ContentResolver resolver) throws FileNotFoundException {
        for (DocumentInfo info : mList) {
            info.updateSelf(resolver);
        }
    }

    public static @Nullable DocumentStack fromLastAccessedCursor(
            Cursor cursor, Collection<RootInfo> matchingRoots, ContentResolver resolver)
            throws IOException {

        if (cursor.moveToFirst()) {
            DocumentStack stack = new DocumentStack();
            final byte[] rawStack = cursor.getBlob(
                    cursor.getColumnIndex(LastAccessedProvider.Columns.STACK));
            DurableUtils.readFromArray(rawStack, stack);

            stack.updateRoot(matchingRoots);
            stack.updateDocuments(resolver);

            return stack;
        }

        return null;
    }

    @Override
    public void read(DataInputStream in) throws IOException {
        final int version = in.readInt();
+20 −4
Original line number Diff line number Diff line
@@ -136,19 +136,35 @@ class ActionHandler<T extends Activity & Addons> extends AbstractActionHandler<T

    private void loadLastAccessedStack() {
        if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
        new LoadLastAccessedStackTask<>(mActivity, mState, mRoots, this::onLoadedLastAccessedStack)
        new LoadLastAccessedStackTask<>(mActivity, mState, mRoots, this::onLastAccessedStackLoaded)
                .execute();
    }

    @VisibleForTesting
    void onLoadedLastAccessedStack(@Nullable DocumentStack stack) {
    void onLastAccessedStackLoaded(@Nullable DocumentStack stack) {
        if (stack == null) {
            mState.stack.changeRoot(mRoots.getRecentsRoot());
            loadDefaultLocation();
        } else {
            mState.stack.reset(stack);
            mActivity.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
        }
    }

    private void loadDefaultLocation() {
        switch (mState.action) {
            case State.ACTION_PICK_COPY_DESTINATION:
            case State.ACTION_CREATE:
                loadHomeDir();
                break;
            case State.ACTION_GET_CONTENT:
            case State.ACTION_OPEN:
            case State.ACTION_OPEN_TREE:
                mState.stack.changeRoot(mRoots.getRecentsRoot());
                mActivity.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
                break;
            default:
                throw new UnsupportedOperationException("Unexpected action type: " + mState.action);
        }
    }

    @Override
+2 −22
Original line number Diff line number Diff line
@@ -67,39 +67,19 @@ final class LoadLastAccessedStackTask<T extends Activity & CommonAddons>

    @Override
    protected DocumentStack run(Void... params) {
        DocumentStack stack = null;

        String callingPackage = Shared.getCallingPackageName(mOwner);
        Uri resumeUri = LastAccessedProvider.buildLastAccessed(
                callingPackage);
        Cursor cursor = mOwner.getContentResolver().query(resumeUri, null, null, null, null);
        try {
            if (cursor.moveToFirst()) {
                stack = new DocumentStack();
                final byte[] rawStack = cursor.getBlob(
                        cursor.getColumnIndex(Columns.STACK));
                DurableUtils.readFromArray(rawStack, stack);
            }
            return DocumentStack.fromLastAccessedCursor(
                    cursor, mRoots.getMatchingRootsBlocking(mState), mOwner.getContentResolver());
        } catch (IOException e) {
            Log.w(TAG, "Failed to resume: ", e);
        } finally {
            IoUtils.closeQuietly(cursor);
        }

        if (stack != null) {
            // Update the restored stack to ensure we have freshest data
            final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
            try {

                stack.updateRoot(matchingRoots);
                stack.updateDocuments(mOwner.getContentResolver());
                return stack;

            } catch (FileNotFoundException e) {
                Log.w(TAG, "Failed to restore stack for package: " + callingPackage, e);
            }
        }

        return null;
    }

+9 −14
Original line number Diff line number Diff line
@@ -282,10 +282,6 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons {
        final DocumentInfo cwd = getCurrentDirectory();

        if (mState.stack.isRecents()) {
            if (mState.action == ACTION_CREATE ||
                mState.action == ACTION_PICK_COPY_DESTINATION) {
                mInjector.actions.loadRoot(Shared.getDefaultRootUri(this));
            } else {
            DirectoryFragment.showRecentsOpen(fm, anim);

            // In recents we pick layout mode based on the mimetype,
@@ -295,7 +291,6 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons {
            boolean visualMimes = MimeTypes.mimeMatches(
                    MimeTypes.VISUAL_MIMES, mState.acceptMimes);
            mState.derivedMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
            }
        } else {
                // Normal boring directory
                DirectoryFragment.showDirectory(fm, root, cwd, anim);
+44 −12
Original line number Diff line number Diff line
@@ -16,9 +16,6 @@

package com.android.documentsui.picker;

import static com.android.documentsui.base.State.ACTION_GET_CONTENT;
import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@@ -28,13 +25,12 @@ import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Path;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentProvider;

import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
import com.android.documentsui.base.State.ActionType;
import com.android.documentsui.testing.DocumentStackAsserts;
import com.android.documentsui.testing.TestEnv;
import com.android.documentsui.testing.TestRootsAccess;
@@ -45,7 +41,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Arrays;
import java.util.List;

@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -124,13 +119,30 @@ public class ActionHandlerTest {
    }

    @Test
    public void testOnLoadedLastAccessStackCallback_defaultToRecents() throws Exception {
        mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
    public void testOnLastAccessedStackLoaded_defaultToRecents_getContent() throws Exception {
        testOnLastAccessedStackLoaded_defaultToRecentsOnAction(State.ACTION_GET_CONTENT);
    }

        mHandler.onLoadedLastAccessedStack(null);
    @Test
    public void testOnLastAccessedStackLoaded_defaultToRecents_open() throws Exception {
        testOnLastAccessedStackLoaded_defaultToRecentsOnAction(State.ACTION_OPEN);
    }

        assertEquals(TestRootsAccess.RECENTS, mEnv.state.stack.getRoot());
        mActivity.refreshCurrentRootAndDirectory.assertCalled();
    @Test
    public void testOnLastAccessedStackLoaded_defaultToRecents_openTree() throws Exception {
        testOnLastAccessedStackLoaded_defaultToRecentsOnAction(State.ACTION_OPEN_TREE);
    }

    @Test
    public void testOnLastAccessedStackLoaded_DefaultsToDownloads_create() throws Exception {
        testOnLastAccessedStackLoaded_defaultToDownloadsOnAction(State.ACTION_CREATE);
    }

    @Test
    public void testOnLastAccessedStackLoaded_DefaultsToDownloads_pickCopyDestination()
            throws Exception {
        testOnLastAccessedStackLoaded_defaultToDownloadsOnAction(
                State.ACTION_PICK_COPY_DESTINATION);
    }

    @Test
@@ -142,6 +154,26 @@ public class ActionHandlerTest {
        mActivity.refreshCurrentRootAndDirectory.assertCalled();
    }

    private void testOnLastAccessedStackLoaded_defaultToRecentsOnAction(@ActionType int action) {
        mEnv.state.action = action;
        mActivity.refreshCurrentRootAndDirectory.assertNotCalled();

        mHandler.onLastAccessedStackLoaded(null);

        assertEquals(TestRootsAccess.RECENTS, mEnv.state.stack.getRoot());
        mActivity.refreshCurrentRootAndDirectory.assertCalled();
    }

    private void testOnLastAccessedStackLoaded_defaultToDownloadsOnAction(@ActionType int action)
            throws Exception {
        mEnv.state.action = action;
        mActivity.refreshCurrentRootAndDirectory.assertNotCalled();

        mHandler.onLastAccessedStackLoaded(null);

        assertRootPicked(TestRootsAccess.DOWNLOADS.getUri());
    }

    private void assertRootPicked(Uri expectedUri) throws Exception {
        mEnv.beforeAsserts();