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

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

Merge "Fetch roots from all users and filter them by action"

parents dae5fe21 c8b0001f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ public abstract class BaseActivity
    protected Injector<?> mInjector;

    protected ProvidersCache mProviders;
    protected UserIdManager mUserIdManager;
    protected DocumentsAccess mDocs;
    protected DrawerController mDrawer;

@@ -152,6 +153,7 @@ public abstract class BaseActivity
        mDrawer = DrawerController.create(this, mInjector.config);
        Metrics.logActivityLaunch(mState, intent);

        mUserIdManager = DocumentsApplication.getUserIdManager(this);
        mProviders = DocumentsApplication.getProvidersCache(this);
        mDocs = DocumentsAccess.create(this);

+10 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.text.format.DateUtils;
import android.util.Log;

import com.android.documentsui.base.Lookup;
import com.android.documentsui.base.UserId;
import com.android.documentsui.clipping.ClipStorage;
import com.android.documentsui.clipping.ClipStore;
import com.android.documentsui.clipping.DocumentClipper;
@@ -48,6 +49,7 @@ public class DocumentsApplication extends Application {
    private ClipStorage mClipStore;
    private DocumentClipper mClipper;
    private DragAndDropManager mDragAndDropManager;
    private UserIdManager mUserIdManager;
    private Lookup<String, String> mFileTypeLookup;

    public static ProvidersCache getProvidersCache(Context context) {
@@ -78,6 +80,10 @@ public class DocumentsApplication extends Application {
        return ((DocumentsApplication) context.getApplicationContext()).mClipStore;
    }

    public static UserIdManager getUserIdManager(Context context) {
        return ((DocumentsApplication) context.getApplicationContext()).mUserIdManager;
    }

    public static DragAndDropManager getDragAndDropManager(Context context) {
        return ((DocumentsApplication) context.getApplicationContext()).mDragAndDropManager;
    }
@@ -105,7 +111,9 @@ public class DocumentsApplication extends Application {
            Log.w(TAG, "Can't obtain OverlayManager from System Service!");
        }

        mProviders = new ProvidersCache(this);
        mUserIdManager = UserIdManager.create(this);

        mProviders = new ProvidersCache(this, mUserIdManager);
        mProviders.updateAsync(false);

        mThumbnailCache = new ThumbnailCache(memoryClassBytes / 4);
@@ -148,7 +156,7 @@ public class DocumentsApplication extends Application {
            final Uri data = intent.getData();
            if (data != null) {
                final String packageName = data.getSchemeSpecificPart();
                mProviders.updatePackageAsync(packageName);
                mProviders.updatePackageAsync(UserId.DEFAULT_USER, packageName);
            } else {
                mProviders.updateAsync(true);
            }
+2 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import androidx.legacy.app.ActionBarDrawerToggle;

import com.android.documentsui.base.Display;
import com.android.documentsui.base.Providers;
import com.android.documentsui.base.UserId;

/**
 * A facade over the various pieces comprising "roots fragment in a Drawer".
@@ -204,7 +205,7 @@ public abstract class DrawerController implements DrawerListener {
            mToggle.onDrawerOpened(drawerView);
            // Update the information for Storage's root
            DocumentsApplication.getProvidersCache(drawerView.getContext()).updateAuthorityAsync(
                    Providers.AUTHORITY_STORAGE);
                    UserId.DEFAULT_USER, Providers.AUTHORITY_STORAGE);
        }

        @Override
+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;

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

import static com.android.documentsui.base.SharedMinimal.DEBUG;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.core.os.BuildCompat;

import com.android.documentsui.base.UserId;

import java.util.ArrayList;
import java.util.List;


/**
 * Interface to query user ids.
 */
public interface UserIdManager {

    /**
     * Returns the {@UserId} of each profile which should be queried for documents. This
     * will always include {@link UserId#CURRENT_USER}.
     */
    List<UserId> getUserIds();

    /**
     * Creates an implementation of {@link UserIdManager}.
     */
    static UserIdManager create(Context context) {
        return new RuntimeUserIdManager(context);
    }

    /**
     * Implementation of {@link UserIdManager}.
     */
    final class RuntimeUserIdManager implements UserIdManager {

        private static final String TAG = "UserIdManager";

        private static final boolean ENABLE_MULTI_PROFILES = false; // compile-time feature flag

        private final Context mContext;
        private final UserId mCurrentUser;
        private final boolean mIsDeviceSupported;

        private RuntimeUserIdManager(Context context) {
            this(context, UserId.CURRENT_USER,
                    ENABLE_MULTI_PROFILES && isDeviceSupported(context));
        }

        @VisibleForTesting
        RuntimeUserIdManager(Context context, UserId currentUser, boolean isDeviceSupported) {
            mContext = context.getApplicationContext();
            mCurrentUser = checkNotNull(currentUser);
            mIsDeviceSupported = isDeviceSupported;
        }

        @Override
        public List<UserId> getUserIds() {
            final List<UserId> result = new ArrayList<>();
            result.add(mCurrentUser);

            // If the feature is disabled, return a list just containing the current user.
            if (!mIsDeviceSupported) {
                return result;
            }

            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
            if (userManager == null) {
                Log.e(TAG, "cannot obtain user manager");
                return result;
            }

            final List<UserHandle> userProfiles = userManager.getUserProfiles();
            if (userProfiles.size() < 2) {
                return result;
            }

            UserId systemUser = null;
            UserId managedUser = null;
            for (UserHandle userHandle : userProfiles) {
                if (userHandle.isSystem()) {
                    systemUser = UserId.of(userHandle);
                    continue;
                }
                if (managedUser == null
                        && userManager.isManagedProfile(userHandle.getIdentifier())) {
                    managedUser = UserId.of(userHandle);
                }
            }

            if (mCurrentUser.isSystem()) {
                // 1. If the current user is system (personal), add the managed user.
                if (managedUser != null) {
                    result.add(managedUser);
                }
            } else if (mCurrentUser.isManagedProfile(userManager)) {
                // 2. If the current user is a managed user, add the personal user.
                // Since we don't have MANAGED_USERS permission to get the parent user, we will
                // treat the system as personal although the system can theoretically in the profile
                // group but not being the parent user(personal) of the managed user.
                if (systemUser != null) {
                    result.add(0, systemUser);
                }
            } else {
                // 3. If we cannot resolve the users properly, we will disable the cross-profile
                // feature by returning just the current user.
                if (DEBUG) {
                    Log.w(TAG, "The current user " + UserId.CURRENT_USER
                            + " is neither system nor managed user. has system user: "
                            + (systemUser != null));
                }
            }
            return result;
        }

        private static boolean isDeviceSupported(Context context) {
            // The feature requires Android R DocumentsContract APIs and INTERACT_ACROSS_USERS
            // permission.
            return (BuildCompat.isAtLeastR()
                    || (Build.VERSION.CODENAME.equals("REL") && Build.VERSION.SDK_INT >= 30))
                    && context.checkSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS)
                    == PackageManager.PERMISSION_GRANTED;
        }
    }
}
+60 −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;

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

import com.android.documentsui.base.UserId;

import java.util.Objects;

/**
 * Data class storing a user id and a package name.
 */
public class UserPackage {
    final UserId userId;
    final String packageName;

    public UserPackage(UserId userId, String packageName) {
        this.userId = checkNotNull(userId);
        this.packageName = checkNotNull(packageName);
    }

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

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

        if (o instanceof UserPackage) {
            UserPackage other = (UserPackage) o;
            return Objects.equals(userId, other.userId)
                    && Objects.equals(packageName, other.packageName);
        }

        return false;
    }

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