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

Commit d8c64f5e authored by Kelvin Kwan's avatar Kelvin Kwan
Browse files

Load RootInfo with current user and store information in it.

Test: atest DocumentsUIGoogleTests
Test: upgrade app
Bug: 148263330

Change-Id: Ie3da7bcd4a1be3c1d0a30814839fce5b31457430
parent 81870e9f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.documentsui.base.Providers;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
import com.android.documentsui.dirlist.AnimationView;
import com.android.documentsui.dirlist.AnimationView.AnimationType;
import com.android.documentsui.dirlist.FocusHandler;
@@ -591,7 +592,8 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA

    protected final void loadDeviceRoot() {
        mActivity.onRootPicked(
                mProviders.getRootOneshot(Providers.AUTHORITY_STORAGE, Providers.ROOT_ID_DEVICE));
                mProviders.getRootOneshot(UserId.DEFAULT_USER, Providers.AUTHORITY_STORAGE,
                        Providers.ROOT_ID_DEVICE));
    }

    protected final void loadHomeDir() {
+7 −4
Original line number Diff line number Diff line
@@ -16,17 +16,19 @@

package com.android.documentsui;

import androidx.annotation.Nullable;
import android.app.Activity;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Path;
import android.util.Log;

import androidx.annotation.Nullable;

import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.PairedTask;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.UserId;
import com.android.documentsui.roots.ProvidersAccess;

import java.util.List;
@@ -97,10 +99,11 @@ public class LoadDocStackTask extends PairedTask<Activity, Uri, DocumentStack> {
            throw new IllegalStateException("Provider doesn't provider root id.");
        }

        RootInfo root = mProviders.getRootOneshot(authority, path.getRootId());
        RootInfo root = mProviders.getRootOneshot(UserId.DEFAULT_USER, authority, path.getRootId());
        if (root == null) {
            throw new IllegalStateException("Failed to load root for authority: " + authority +
                    " and root ID: " + path.getRootId() + ".");
            throw new IllegalStateException(
                    "Failed to load root on user " + root.userId + " for authority: " + authority
                            + " and root ID: " + path.getRootId() + ".");
        }

        List<DocumentInfo> docs = mDocs.getDocuments(authority, path.getPath());
+2 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Providers;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
import com.android.documentsui.files.LauncherActivity;
import com.android.documentsui.picker.PickResult;
import com.android.documentsui.roots.ProvidersAccess;
@@ -340,7 +341,7 @@ public final class Metrics {
                context.getContentResolver(), Providers.AUTHORITY_STORAGE)) {
            final Path path = DocumentsContract.findDocumentPath(wrap(client), docUri);
            final ProvidersAccess providers = DocumentsApplication.getProvidersCache(context);
            final RootInfo root = providers.getRootOneshot(
            final RootInfo root = providers.getRootOneshot(UserId.DEFAULT_USER,
                    Providers.AUTHORITY_STORAGE, path.getRootId());
            isInternal = !root.supportsEject();
        } catch (FileNotFoundException | RemoteException | RuntimeException e) {
+16 −4
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
    // private static final int VERSION_INIT = 1; // Not used anymore
    private static final int VERSION_DROP_TYPE = 2;
    private static final int VERSION_SEARCH_TYPE = 3;
    private static final int VERSION_USER_ID = 4;

    // The values of these constants determine the sort order of various roots in the RootsFragment.
    @IntDef(flag = false, value = {
@@ -87,6 +88,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
    public static final int TYPE_USB = 10;
    public static final int TYPE_OTHER = 11;

    public UserId userId;
    public String authority;
    public String rootId;
    public int flags;
@@ -112,6 +114,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {

    @Override
    public void reset() {
        userId = UserId.UNSPECIFIED_USER;
        authority = null;
        rootId = null;
        flags = 0;
@@ -133,7 +136,12 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
    public void read(DataInputStream in) throws IOException {
        final int version = in.readInt();
        switch (version) {
            case VERSION_USER_ID:
                userId = UserId.read(in);
            case VERSION_SEARCH_TYPE:
                if (version < VERSION_USER_ID) {
                    userId = UserId.CURRENT_USER;
                }
                queryArgs = DurableUtils.readNullableString(in);
            case VERSION_DROP_TYPE:
                authority = DurableUtils.readNullableString(in);
@@ -154,7 +162,8 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {

    @Override
    public void write(DataOutputStream out) throws IOException {
        out.writeInt(VERSION_SEARCH_TYPE);
        out.writeInt(VERSION_USER_ID);
        UserId.write(out, userId);
        DurableUtils.writeNullableString(out, queryArgs);
        DurableUtils.writeNullableString(out, authority);
        DurableUtils.writeNullableString(out, rootId);
@@ -191,8 +200,9 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
        }
    };

    public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
    public static RootInfo fromRootsCursor(UserId userId, String authority, Cursor cursor) {
        final RootInfo root = new RootInfo();
        root.userId = userId;
        root.authority = authority;
        root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID);
        root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS);
@@ -430,7 +440,8 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {

        if (o instanceof RootInfo) {
            RootInfo other = (RootInfo) o;
            return Objects.equals(authority, other.authority)
            return Objects.equals(userId, other.userId)
                    && Objects.equals(authority, other.authority)
                    && Objects.equals(rootId, other.rootId);
        }

@@ -439,7 +450,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {

    @Override
    public int hashCode() {
        return Objects.hash(authority, rootId);
        return Objects.hash(userId, authority, rootId);
    }

    @Override
@@ -461,6 +472,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
    @Override
    public String toString() {
        return "Root{"
                + "userId=" + userId
                + "authority=" + authority
                + ", rootId=" + rootId
                + ", title=" + title
+151 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.base;

import static androidx.core.util.Preconditions.checkNotNull;

import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.UserHandle;

import androidx.annotation.VisibleForTesting;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ProtocolException;
import java.util.Objects;
/**
 * Representation of a {@link UserHandle}.
 */
public final class UserId {

    // A unspecified user is used as when the user's value is uninitialized. e.g. rootInfo.reset()
    public static UserId UNSPECIFIED_USER = UserId.of(UserHandle.of(-1000));
    // A current user represents the user of the app's process. It is mainly used for comparison.
    public static UserId CURRENT_USER = UserId.of(Process.myUserHandle());
    // A default user represents the user of the app's process. It is mainly used for operation
    // which supports only the current user only.
    public static UserId DEFAULT_USER = CURRENT_USER;

    private static final int VERSION_INIT = 1;

    private final UserHandle mUserHandle;

    private UserId(UserHandle userHandle) {
        checkNotNull(userHandle);
        mUserHandle = userHandle;
    }

    /**
     * Returns a {@link UserId} for a given {@link UserHandle}.
     */
    @VisibleForTesting
    static UserId of(UserHandle userHandle) {
        return new UserId(userHandle);
    }

    /**
     * Returns the given context if the user is the current user or unspecified. Otherwise, returns
     * an "android" package context as the user.
     *
     * @throws IllegalStateException if android package of the other user does not exist
     */
    @VisibleForTesting
    Context asContext(Context context) {
        if (CURRENT_USER.equals(this) || isUnspecified()) {
            return context;
        }
        try {
            return context.createPackageContextAsUser("android", /* flags= */ 0, mUserHandle);
        } catch (PackageManager.NameNotFoundException e) {
            throw new IllegalStateException("android package not found.");
        }
    }

    /**
     * Return a package manager instance of this user.
     */
    public PackageManager getPackageManager(Context context) {
        return asContext(context).getPackageManager();
    }

    /**
     * Return a content resolver instance of this user.
     */
    public ContentResolver getContentResolver(Context context) {
        return asContext(context).getContentResolver();
    }

    private boolean isUnspecified() {
        return UNSPECIFIED_USER.equals(this);
    }

    @Override
    public String toString() {
        return "UserId{"
                + (isUnspecified() ? "UNSPECIFIED" : mUserHandle.getIdentifier())
                + "}";
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }

        if (this == o) {
            return true;
        }

        if (o instanceof UserId) {
            UserId other = (UserId) o;
            return Objects.equals(mUserHandle, other.mUserHandle);
        }

        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mUserHandle);
    }

    /**
     * Reads a {@link UserId} from an input stream.
     */
    public static UserId read(DataInputStream in) throws IOException {
        final int version = in.readInt();
        switch (version) {
            case VERSION_INIT:
                int userId = in.readInt();
                return UserId.of(UserHandle.of(userId));
            default:
                throw new ProtocolException("Unknown version " + version);
        }
    }

    /**
     * Writes a {@link UserId} to an output stream.
     */
    public static void write(DataOutputStream out, UserId userId) throws IOException {
        out.writeInt(VERSION_INIT);
        out.writeInt(userId.mUserHandle.getIdentifier());
    }
}
Loading