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

Commit 988d8a35 authored by Steve McKay's avatar Steve McKay
Browse files

Move launch logic into ActionHandlers.

Add test.
Add RootsAccess interface to RootsCache (to faciliate testing).
Create a new TestEnv class that:
    * bootstaps basic data and dependencies
    * installs test executor so async tasks can be executed predictably.
    * instruments main thread to ensure AsyncTasks return results
      before we continue to make asserts.
Add new Lookup interface to provide improved semantics over j.u.f.Function.
Inject access to Provider specific Executors by way of Lookup.

Change-Id: I0fc71897a4cc40d26c5fa3ae3bb88bad7dbdcf5c
parent 14627f5f
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Parcelable;

import com.android.documentsui.AbstractActionHandler.CommonAddons;
@@ -27,15 +28,21 @@ import com.android.documentsui.base.BooleanConsumer;
import com.android.documentsui.base.ConfirmationCallback;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView.AnimationType;
import com.android.documentsui.dirlist.DocumentDetails;
import com.android.documentsui.dirlist.Model;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.manager.LauncherActivity;
import com.android.documentsui.roots.LoadRootTask;
import com.android.documentsui.roots.RootsAccess;
import com.android.documentsui.sidebar.EjectRootTask;

import java.util.List;
import java.util.concurrent.Executor;

/**
 * Provides support for specializing the actions (viewDocument etc.) to the host activity.
@@ -44,10 +51,24 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons>
        implements ActionHandler {

    protected final T mActivity;
    protected final State mState;
    protected final RootsAccess mRoots;
    protected final Lookup<String, Executor> mExecutors;

    public AbstractActionHandler(
            T activity,
            State state,
            RootsAccess roots,
            Lookup<String, Executor> executors) {

    public AbstractActionHandler(T activity) {
        assert(activity != null);
        assert(state != null);
        assert(roots != null);

        mActivity = activity;
        mState = state;
        mRoots = roots;
        mExecutors = executors;
    }

    @Override
@@ -116,14 +137,25 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons>
        throw new UnsupportedOperationException("Delete not supported!");
    }

    @Override
    public final void loadRoot(Uri uri) {
        new LoadRootTask<>(mActivity, mRoots, mState, uri).executeOnExecutor(
                mExecutors.lookup(uri.getAuthority()));
    }

    protected final void loadHomeDir() {
        loadRoot(Shared.getDefaultRootUri(mActivity));
    }

    /**
     * A class primarily for the support of isolating our tests
     * from our concrete activity implementations.
     */
    public interface CommonAddons {
       void onRootPicked(RootInfo root);
       void onDocumentPicked(DocumentInfo doc, Model model);
       // TODO: Move this to PickAddons.
       void onDocumentsPicked(List<DocumentInfo> docs);
       void onDocumentPicked(DocumentInfo doc, Model model);
       void refreshCurrentRootAndDirectory(@AnimationType int anim);
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.documentsui;

import android.content.ClipData;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;

import com.android.documentsui.base.BooleanConsumer;
import com.android.documentsui.base.ConfirmationCallback;
@@ -48,6 +50,8 @@ public interface ActionHandler {

    void openRoot(ResolveInfo app);

    void loadRoot(Uri uri);

    void openInNewWindow(DocumentStack path);

    void pasteIntoFolder(RootInfo root);
@@ -59,4 +63,11 @@ public interface ActionHandler {
    boolean openDocument(DocumentDetails doc);

    void deleteDocuments(Model model, Selection selection, ConfirmationCallback callback);

    /**
     * Called when initial activity setup is complete. Implementations
     * should override this method to set the initial location of the
     * app.
     */
    void initLocation(Intent intent);
}
+1 −36
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
@@ -69,7 +68,6 @@ import com.android.documentsui.dirlist.FragmentTuner;
import com.android.documentsui.dirlist.Model;
import com.android.documentsui.dirlist.MultiSelectManager;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.roots.LoadRootTask;
import com.android.documentsui.roots.RootsCache;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.sorting.SortController;
@@ -182,7 +180,6 @@ public abstract class BaseActivity
        getContentResolver().registerContentObserver(
                RootsCache.sNotificationUri, false, mRootsCacheObserver);


        DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
        setActionBar(toolbar);

@@ -418,11 +415,6 @@ public abstract class BaseActivity
        invalidateOptionsMenu();
    }

    protected final void loadRoot(final Uri uri) {
        new LoadRootTask(this, mRoots, mState, uri).executeOnExecutor(
                ProviderExecutor.forAuthority(uri.getAuthority()));
    }

    /**
     * This is called when user hovers over a doc for enough time during a drag n' drop, to open a
     * folder that accepts drop. We should only open a container that's not an archive.
@@ -442,7 +434,7 @@ public abstract class BaseActivity
        List<String> authorities = new ArrayList<>();
        if (getIntent().getBooleanExtra(DocumentsContract.EXTRA_EXCLUDE_SELF, false)) {
            // Exclude roots provided by the calling package.
            String packageName = getCallingPackageMaybeExtra();
            String packageName = Shared.getCallingPackageName(this);
            try {
                PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName,
                        PackageManager.GET_PROVIDERS);
@@ -461,22 +453,6 @@ public abstract class BaseActivity
        return (root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
    }

    public final String getCallingPackageMaybeExtra() {
        String callingPackage = getCallingPackage();
        // System apps can set the calling package name using an extra.
        try {
            ApplicationInfo info = getPackageManager().getApplicationInfo(callingPackage, 0);
            if (info.isSystemApp() || info.isUpdatedSystemApp()) {
                final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME);
                if (extra != null) {
                    callingPackage = extra;
                }
            }
        } finally {
            return callingPackage;
        }
    }

    public static BaseActivity get(Fragment fragment) {
        return (BaseActivity) fragment.getActivity();
    }
@@ -485,17 +461,6 @@ public abstract class BaseActivity
        return mState;
    }

    /*
     * Get the default directory to be presented after starting the activity.
     * Method can be overridden if the change of the behavior of the the child activity is needed.
     */
    public Uri getDefaultRoot() {
        return Shared.shouldShowDocumentsRoot(this, getIntent())
                ? DocumentsContract.buildHomeUri()
                : DocumentsContract.buildRootUri(
                        "com.android.providers.downloads.documents", "downloads");
    }

    /**
     * Set internal storage visible based on explicit user action.
     */
+1 −1
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ import android.net.Uri;
import android.os.RemoteException;
import android.text.format.DateUtils;

import com.android.documentsui.clipping.ClipStorage;
import com.android.documentsui.clipping.ClipStore;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.clipping.ClipStorage;
import com.android.documentsui.roots.RootsCache;

public class DocumentsApplication extends Application {
+1 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ public class NavigationViewManager {
    interface Environment {
        RootInfo getCurrentRoot();
        String getDrawerTitle();
        @Deprecated  // Use CommonAddones#refreshCurrentRootAndDirectory
        void refreshCurrentRootAndDirectory(int animation);
        boolean isSearchExpanded();
    }
Loading