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

Commit bc59e41a authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6412615 from d2db36ca to rvc-release

Change-Id: Ide57938c6907822bfe8fd3cd424b489486bf98aa
parents c510832c d2db36ca
Loading
Loading
Loading
Loading
+90 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.documentsui.base.State.MODE_LIST;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -31,6 +32,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.DocumentsContract;
@@ -136,6 +138,8 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On

    private static final int CACHE_EVICT_LIMIT = 100;
    private static final int REFRESH_SPINNER_TIMEOUT = 500;
    private static final int PROVIDER_MAX_RETRIES = 10;
    private static final long PROVIDER_TEST_DELAY = 4000;

    private BaseActivity mActivity;

@@ -190,6 +194,9 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On

    private DirectoryState mLocalState;

    private Handler mHandler;
    private Runnable mProviderTestRunnable;

    // 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.
    private @Nullable Bundle mRestoredState;
@@ -225,15 +232,91 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
            final String action = intent.getAction();
            if (isManagedProfileAction(action)) {
                UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
                if (Objects.equal(mActivity.getSelectedUser(), UserId.of(userHandle))) {
                UserId userId = UserId.of(userHandle);
                if (Objects.equal(mActivity.getSelectedUser(), userId)) {
                    // We only need to refresh the layout when the selected user is equal to the
                    // received profile user.
                    if (Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
                        // If the managed profile is turned off, we need to refresh the directory
                        // to update the UI to show an appropriate error message.
                        if (mProviderTestRunnable != null) {
                            mHandler.removeCallbacks(mProviderTestRunnable);
                            mProviderTestRunnable = null;
                        }
                        onRefresh();
                        return;
                    }

                    // When the managed profile becomes available, the provider may not be available
                    // immediately, we need to check if it is ready before we reload the content.
                    if (Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
                        checkUriAndScheduleCheckIfNeeded(userId);
                    }
                }
            }
        }
    };

    private void checkUriAndScheduleCheckIfNeeded(UserId userId) {
        RootInfo currentRoot = mActivity.getCurrentRoot();
        DocumentInfo currentDoc = mActivity.getDisplayState().stack.peek();
        Uri uri = getCurrentUri(currentRoot, currentDoc);
        if (isProviderAvailable(uri, userId) || mActivity.isInRecents()) {
            if (mProviderTestRunnable != null) {
                mHandler.removeCallbacks(mProviderTestRunnable);
                mProviderTestRunnable = null;
            }
            mHandler.post(() -> onRefresh());
        } else {
            checkUriWithDelay(/* numOfRetries= */1, uri, userId);
        }
    }

    private void checkUriWithDelay(int numOfRetries, Uri uri, UserId userId) {
        mProviderTestRunnable = () -> {
            RootInfo currentRoot = mActivity.getCurrentRoot();
            DocumentInfo currentDoc = mActivity.getDisplayState().stack.peek();
            if (mActivity.getSelectedUser().equals(userId)
                    && uri.equals(getCurrentUri(currentRoot, currentDoc))) {
                if (isProviderAvailable(uri, userId)
                        || userId.isQuietModeEnabled(mActivity)
                        || numOfRetries >= PROVIDER_MAX_RETRIES) {
                    // We stop the recursive check when
                    // 1. the provider is available
                    // 2. the profile is in quiet mode, i.e. provider will not be available
                    // 3. after maximum retries
                    onRefresh();
                    mProviderTestRunnable = null;
                } else {
                    Log.d(TAG, "Provider is not available. Retry after " + PROVIDER_TEST_DELAY);
                    checkUriWithDelay(numOfRetries + 1, uri, userId);
                }
            }
        };
        mHandler.postDelayed(mProviderTestRunnable, PROVIDER_TEST_DELAY);
    }

    private Uri getCurrentUri(RootInfo root, @Nullable DocumentInfo doc) {
        String authority = doc == null ? root.authority : doc.authority;
        String documentId = doc == null ? root.documentId : doc.documentId;
        return DocumentsContract.buildDocumentUri(authority, documentId);
    }

    private boolean isProviderAvailable(Uri uri, UserId userId) {
        try (ContentProviderClient userClient =
                     DocumentsApplication.acquireUnstableProviderOrThrow(
                             userId.getContentResolver(mActivity), uri.getAuthority())) {
            Cursor testCursor = userClient.query(uri, /* projection= */ null,
                    /* queryArgs= */null, /* cancellationSignal= */ null);
            if (testCursor != null) {
                return true;
            }
        } catch (Exception e) {
            // Provider is not available. Ignore.
        }
        return false;
    }

    private static boolean isManagedProfileAction(String action) {
        return Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)
                || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action);
@@ -243,6 +326,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        mHandler = new Handler(Looper.getMainLooper());
        mActivity = (BaseActivity) getActivity();
        final View view = inflater.inflate(R.layout.fragment_directory, container, false);

@@ -302,6 +386,9 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
        mInjector.actions.unregisterDisplayStateChangedListener(mOnDisplayStateChanged);
        if (mState.supportsCrossProfile()) {
            LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mReceiver);
            if (mProviderTestRunnable != null) {
                mHandler.removeCallbacks(mProviderTestRunnable);
            }
        }

        // Cancel any outstanding thumbnail requests
@@ -1206,7 +1293,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
        }

        final DocumentInfo doc = mActivity.getCurrentDirectory();
        if (doc == null) {
        if (doc == null && !mActivity.getSelectedUser().isQuietModeEnabled(mActivity)) {
            // If there is no root doc, try to reload the root doc from root info.
            Log.w(TAG, "No root document. Try to get root document.");
            getRootDocumentAndMaybeRefreshDocument();