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

Commit 4253ae01 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/28152617',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/28152617', 'googleplex-android-review.googlesource.com/28578601', 'googleplex-android-review.googlesource.com/28320343', 'googleplex-android-review.googlesource.com/28920239'] into 24Q3-release.

Change-Id: I172d409abe0eaea187feaf39d88e21e5c46e342d
parents a74d50c7 68eb5dc1
Loading
Loading
Loading
Loading
+68 −11
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.externalstorage;

import static java.util.regex.Pattern.CASE_INSENSITIVE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.usage.StorageStatsManager;
@@ -61,12 +59,15 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Presents content of the shared (a.k.a. "external") storage.
@@ -89,12 +90,9 @@ public class ExternalStorageProvider extends FileSystemProvider {
    private static final Uri BASE_URI =
            new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build();

    /**
     * Regex for detecting {@code /Android/data/}, {@code /Android/obb/} and
     * {@code /Android/sandbox/} along with all their subdirectories and content.
     */
    private static final Pattern PATTERN_RESTRICTED_ANDROID_SUBTREES =
            Pattern.compile("^Android/(?:data|obb|sandbox)(?:/.+)?", CASE_INSENSITIVE);
    private static final String PRIMARY_EMULATED_STORAGE_PATH = "/storage/emulated/";

    private static final String STORAGE_PATH = "/storage/";

    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
@@ -309,10 +307,69 @@ public class ExternalStorageProvider extends FileSystemProvider {
            return false;
        }

        final String path = getPathFromDocId(documentId);
        return PATTERN_RESTRICTED_ANDROID_SUBTREES.matcher(path).matches();
        try {
            final RootInfo root = getRootFromDocId(documentId);
            final String canonicalPath = getPathFromDocId(documentId);
            return isRestrictedPath(root.rootId, canonicalPath);
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * Based on the given root id and path, we restrict path access if file is Android/data or
     * Android/obb or Android/sandbox or one of their subdirectories.
     *
     * @param canonicalPath of the file
     * @return true if path is restricted
     */
    private boolean isRestrictedPath(String rootId, String canonicalPath) {
        if (rootId == null || canonicalPath == null) {
            return true;
        }

        final String rootPath;
        if (rootId.equalsIgnoreCase(ROOT_ID_PRIMARY_EMULATED)) {
            // Creates "/storage/emulated/<user-id>"
            rootPath = PRIMARY_EMULATED_STORAGE_PATH + UserHandle.myUserId();
        } else {
            // Creates "/storage/<volume-uuid>"
            rootPath = STORAGE_PATH + rootId;
        }
        List<java.nio.file.Path> restrictedPathList = Arrays.asList(
                Paths.get(rootPath, "Android", "data"),
                Paths.get(rootPath, "Android", "obb"),
                Paths.get(rootPath, "Android", "sandbox"));
        // We need to identify restricted parent paths which actually exist on the device
        List<java.nio.file.Path> validRestrictedPathsToCheck = restrictedPathList.stream().filter(
                Files::exists).collect(Collectors.toList());

        boolean isRestricted = false;
        java.nio.file.Path filePathToCheck = Paths.get(rootPath, canonicalPath);
        try {
            while (filePathToCheck != null) {
                for (java.nio.file.Path restrictedPath : validRestrictedPathsToCheck) {
                    if (Files.isSameFile(restrictedPath, filePathToCheck)) {
                        isRestricted = true;
                        Log.v(TAG, "Restricting access for path: " + filePathToCheck);
                        break;
                    }
                }
                if (isRestricted) {
                    break;
                }

                filePathToCheck = filePathToCheck.getParent();
            }
        } catch (Exception e) {
            Log.w(TAG, "Error in checking file equality check.", e);
            isRestricted = true;
        }

        return isRestricted;
    }


    /**
     * Check that the directory is the root of storage or blocked file from tree.
     * <p>
+4 −0
Original line number Diff line number Diff line
@@ -1234,6 +1234,10 @@ public class AccountManagerService
                            obsoleteAuthType.add(type);
                            // And delete it from the TABLE_META
                            accountsDb.deleteMetaByAuthTypeAndUid(type, uid);
                        } else if (knownUid != null && knownUid != uid) {
                            Slog.w(TAG, "authenticator no longer exist for type " + type);
                            obsoleteAuthType.add(type);
                            accountsDb.deleteMetaByAuthTypeAndUid(type, uid);
                        }
                    }
                }
+5 −1
Original line number Diff line number Diff line
@@ -686,6 +686,9 @@ final class InstallPackageHelper {
                    (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
            final boolean fullApp =
                    (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
            final boolean isPackageDeviceAdmin = mPm.isPackageDeviceAdmin(packageName, userId);
            final boolean isProtectedPackage = mPm.mProtectedPackages != null
                    && mPm.mProtectedPackages.isPackageStateProtected(userId, packageName);

            // writer
            synchronized (mPm.mLock) {
@@ -694,7 +697,8 @@ final class InstallPackageHelper {
                if (pkgSetting == null || pkgSetting.getPkg() == null) {
                    return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
                }
                if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp())) {
                if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp()
                        || isPackageDeviceAdmin || isProtectedPackage)) {
                    return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
                }
                if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
+9 −4
Original line number Diff line number Diff line
@@ -78,9 +78,9 @@ import android.os.storage.StorageVolume;
import android.provider.Settings;
import android.service.usb.UsbDeviceManagerProto;
import android.service.usb.UsbHandlerProto;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.text.TextUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -838,7 +838,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
            }
        }

        private void notifyAccessoryModeExit(int operationId) {
        protected void notifyAccessoryModeExit(int operationId) {
            // make sure accessory mode is off
            // and restore default functions
            Slog.d(TAG, "exited USB accessory mode");
@@ -2271,9 +2271,14 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
                     */
                    operationId = sUsbOperationCount.incrementAndGet();
                    if (msg.arg1 != 1) {
                        // Set this since default function may be selected from Developer options
                        if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
                            notifyAccessoryModeExit(operationId);
                        } else {
                            // Set this since default function may be selected from Developer
                            // options
                            setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
                        }
                    }
                    break;
                case MSG_GADGET_HAL_REGISTERED:
                    boolean preexisting = msg.arg1 == 1;