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

Commit b24ecf63 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adding blocking to DirectoryLoader when Band Selection is active." into nyc-andromeda-dev

parents d79cc4ab 9fea3122
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@ import android.content.AsyncTaskLoader;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.OperationCanceledException;
import android.os.RemoteException;
import android.provider.DocumentsContract.Document;
@@ -42,8 +44,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {

    private static final String[] SEARCH_REJECT_MIMES = new String[] { Document.MIME_TYPE_DIR };

    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    private final LockingContentObserver mObserver;
    private final RootInfo mRoot;
    private final Uri mUri;
    private final SortModel mModel;
@@ -59,6 +60,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
            DocumentInfo doc,
            Uri uri,
            SortModel model,
            DirectoryReloadLock lock,
            boolean inSearchMode) {

        super(context, ProviderExecutor.forAuthority(root.authority));
@@ -67,6 +69,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
        mModel = model;
        mDoc = doc;
        mSearchMode = inSearchMode;
        mObserver = new LockingContentObserver(lock, this::onContentChanged);
    }

    @Override
@@ -181,4 +184,25 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {

        getContext().getContentResolver().unregisterContentObserver(mObserver);
    }

    private static final class LockingContentObserver extends ContentObserver {
        private final DirectoryReloadLock mLock;
        private final Runnable mContentChangedCallback;

        public LockingContentObserver(DirectoryReloadLock lock, Runnable contentChangedCallback) {
            super(new Handler());
            mLock = lock;
            mContentChangedCallback = contentChangedCallback;
        }

        @Override
        public boolean deliverSelfNotifications() {
            return true;
        }

        @Override
        public void onChange(boolean selfChange) {
            mLock.tryUpdate(mContentChangedCallback);
        }
    }
}
+67 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui;

import android.annotation.MainThread;
import android.annotation.Nullable;

import com.android.documentsui.base.Shared;
import com.android.documentsui.selection.BandController;

/**
 * A lock used by {@link DirectoryLoader} and {@link BandController} to ensure refresh is blocked
 * while Band Selection is active.
 */
public final class DirectoryReloadLock {
    private int mPauseCount = 0;
    private @Nullable Runnable mCallback;

    /**
     * Increment the block count by 1
     */
    @MainThread
    public void block() {
        Shared.checkMainLoop();
        mPauseCount++;
    }

    /**
     * Decrement the block count by 1; If no other object is trying to block and there exists some
     * callback, that callback will be run
     */
    @MainThread
    public void unblock() {
        Shared.checkMainLoop();
        mPauseCount--;
        if (mPauseCount == 0 && mCallback != null) {
            mCallback.run();
            mCallback = null;
        }
    }

    /**
     * Attempts to run the given Runnable if not-blocked, or else the Runnable is set to be ran next
     * (replacing any previous set Runnables).
     */
    public void tryUpdate(Runnable update) {
        if (mPauseCount == 0) {
            update.run();
        } else {
            mCallback = update;
        }
    }
}
 No newline at end of file
+5 −1
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import com.android.documentsui.BaseActivity;
import com.android.documentsui.BaseActivity.RetainedState;
import com.android.documentsui.DirectoryLoader;
import com.android.documentsui.DirectoryResult;
import com.android.documentsui.DirectoryReloadLock;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.FocusManager;
import com.android.documentsui.ItemDragListener;
@@ -186,6 +187,7 @@ public class DirectoryFragment extends Fragment
    private View mProgressBar;

    private DirectoryState mLocalState;
    private DirectoryReloadLock mReloadLock = new DirectoryReloadLock();

    // Note, we use !null to indicate that selection was restored (from rotation).
    // So don't fiddle with this field unless you've got the bigger picture in mind.
@@ -308,13 +310,14 @@ public class DirectoryFragment extends Fragment
        mSelectionMetadata = new SelectionMetadata(mModel::getItem);
        mSelectionMgr.addItemCallback(mSelectionMetadata);

        GestureSelector gestureSel = GestureSelector.create(mSelectionMgr, mRecView);
        GestureSelector gestureSel = GestureSelector.create(mSelectionMgr, mRecView, mReloadLock);

        if (mState.allowMultiple) {
            mBandController = new BandController(
                    mRecView,
                    mAdapter,
                    mSelectionMgr,
                    mReloadLock,
                    (int pos) -> {
                        // The band selection model only operates on documents and directories.
                        // Exclude other types of adapter items like whitespace and dividers.
@@ -1232,6 +1235,7 @@ public class DirectoryFragment extends Fragment
                            mLocalState.mDocument,
                            contentsUri,
                            mState.sortModel,
                            mReloadLock,
                            mLocalState.mSearchMode);

                case TYPE_RECENT_OPEN:
+8 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.View;

import com.android.documentsui.DirectoryReloadLock;
import com.android.documentsui.R;
import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.dirlist.DocumentsAdapter;
@@ -61,6 +62,7 @@ public class BandController extends OnScrollListener {
    private final SelectionEnvironment mEnvironment;
    private final DocumentsAdapter mAdapter;
    private final SelectionManager mSelectionManager;
    private final DirectoryReloadLock mLock;
    private final Runnable mViewScroller;
    private final GridModel.OnSelectionChangedListener mGridListener;

@@ -75,16 +77,19 @@ public class BandController extends OnScrollListener {
            final RecyclerView view,
            DocumentsAdapter adapter,
            SelectionManager selectionManager,
            DirectoryReloadLock lock,
            IntPredicate gridItemTester) {
        this(new RuntimeSelectionEnvironment(view), adapter, selectionManager, gridItemTester);
        this(new RuntimeSelectionEnvironment(view), adapter, selectionManager, lock, gridItemTester);
    }

    private BandController(
            SelectionEnvironment env,
            DocumentsAdapter adapter,
            SelectionManager selectionManager,
            DirectoryReloadLock lock,
            IntPredicate gridItemTester) {

        mLock = lock;
        selectionManager.bindContoller(this);

        mEnvironment = env;
@@ -265,6 +270,7 @@ public class BandController extends OnScrollListener {
    private void startBandSelect(Point origin) {
        if (DEBUG) Log.d(TAG, "Starting band select @ " + origin);

        mLock.block();
        mOrigin = origin;
        mModelBuilder.run();  // Creates a new selection model.
        mModel.startSelection(mOrigin);
@@ -314,6 +320,7 @@ public class BandController extends OnScrollListener {

        mModel = null;
        mOrigin = null;
        mLock.unblock();
    }

    private void onSelectionChanged(Set<String> updatedSelection) {
+12 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.android.documentsui.DirectoryReloadLock;
import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.ui.ViewAutoScroller;
import com.android.documentsui.ui.ViewAutoScroller.ScrollActionDelegate;
@@ -40,6 +41,7 @@ public final class GestureSelector {
    private final Runnable mDragScroller;
    private final IntSupplier mHeight;
    private final ViewFinder mViewFinder;
    private final DirectoryReloadLock mLock;
    private int mLastStartedItemPos = -1;
    private boolean mStarted = false;
    private Point mLastInterceptedPoint;
@@ -48,10 +50,12 @@ public final class GestureSelector {
            SelectionManager selectionMgr,
            IntSupplier heightSupplier,
            ViewFinder viewFinder,
            ScrollActionDelegate actionDelegate) {
            ScrollActionDelegate actionDelegate,
            DirectoryReloadLock lock) {
        mSelectionMgr = selectionMgr;
        mHeight = heightSupplier;
        mViewFinder = viewFinder;
        mLock = lock;

        ScrollDistanceDelegate distanceDelegate = new ScrollDistanceDelegate() {
            @Override
@@ -75,7 +79,8 @@ public final class GestureSelector {

    public static GestureSelector create(
            SelectionManager selectionMgr,
            RecyclerView scrollView) {
            RecyclerView scrollView,
            DirectoryReloadLock lock) {
        ScrollActionDelegate actionDelegate = new ScrollActionDelegate() {
            @Override
            public void scrollBy(int dy) {
@@ -97,7 +102,8 @@ public final class GestureSelector {
                        selectionMgr,
                        scrollView::getHeight,
                        scrollView::findChildViewUnder,
                        actionDelegate);
                        actionDelegate,
                        lock);

        return helper;
    }
@@ -162,6 +168,8 @@ public final class GestureSelector {
        mLastInterceptedPoint = e.getOrigin();
        if (mStarted) {
            mSelectionMgr.startRangeSelection(mLastStartedItemPos);
            // Gesture Selection about to start
            mLock.block();
            return true;
        }
        return false;
@@ -173,6 +181,7 @@ public final class GestureSelector {
        mLastStartedItemPos = -1;
        mStarted = false;
        mSelectionMgr.getSelection().applyProvisionalSelection();
        mLock.unblock();
        return false;
    }

Loading