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

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

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

Merge cherrypicks of ['googleplex-android-review.googlesource.com/30800649', 'googleplex-android-review.googlesource.com/30814870', 'googleplex-android-review.googlesource.com/31215755', 'googleplex-android-review.googlesource.com/30961573', 'googleplex-android-review.googlesource.com/31236504', 'googleplex-android-review.googlesource.com/31440406', 'googleplex-android-review.googlesource.com/31488916', 'googleplex-android-review.googlesource.com/31418596'] into 25Q1-release.

Change-Id: Ia51f979c418f7df5e3fc6b5bf5780ced1befffeb
parents 89062fc2 29217e3f
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -475,10 +475,10 @@ public class BaseBundle {
            map.erase();
            map.ensureCapacity(count);
        }
        int numLazyValues = 0;
        int[] numLazyValues = new int[]{0};
        try {
            numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
                    /* lazy */ ownsParcel, mClassLoader);
            parcelledData.readArrayMap(map, count, !parcelledByNative,
                    /* lazy */ ownsParcel, mClassLoader, numLazyValues);
        } catch (BadParcelableException e) {
            if (sShouldDefuse) {
                Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -489,14 +489,14 @@ public class BaseBundle {
        } finally {
            mWeakParcelledData = null;
            if (ownsParcel) {
                if (numLazyValues == 0) {
                if (numLazyValues[0] == 0) {
                    recycleParcel(parcelledData);
                } else {
                    mWeakParcelledData = new WeakReference<>(parcelledData);
                }
            }

            mLazyValues = numLazyValues;
            mLazyValues = numLazyValues[0];
            mParcelledByNative = false;
            mMap = map;
            // Set field last as it is volatile
+5 −7
Original line number Diff line number Diff line
@@ -5538,7 +5538,7 @@ public final class Parcel {

    private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
            int size, @Nullable ClassLoader loader) {
        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader, null);
    }

    /**
@@ -5548,17 +5548,16 @@ public final class Parcel {
     * @param lazy   Whether to populate the map with lazy {@link Function} objects for
     *               length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
     *               details.
     * @return a count of the lazy values in the map
     * @param lazyValueCount number of lazy values added here
     * @hide
     */
    int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
            boolean lazy, @Nullable ClassLoader loader) {
        int lazyValues = 0;
    void readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
            boolean lazy, @Nullable ClassLoader loader, int[] lazyValueCount) {
        while (size > 0) {
            String key = readString();
            Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
            if (value instanceof LazyValue) {
                lazyValues++;
                lazyValueCount[0]++;
            }
            if (sorted) {
                map.append(key, value);
@@ -5570,7 +5569,6 @@ public final class Parcel {
        if (sorted) {
            map.validate();
        }
        return lazyValues;
    }

    /**
+49 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
import static android.content.ContentProvider.getUriWithoutUserId;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -40,7 +41,9 @@ import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.IUriGrantsManager;
import android.app.SharedElementCallback;
import android.app.UriGrantsManager;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
@@ -77,6 +80,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
@@ -86,6 +90,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
@@ -692,7 +697,11 @@ public class ChooserActivity extends ResolverActivity implements
                    targets = null;
                    break;
                }
                targets[i] = (ChooserTarget) pa[i];
                ChooserTarget chooserTarget = (ChooserTarget) pa[i];
                if (!hasValidIcon(chooserTarget)) {
                    chooserTarget = removeIcon(chooserTarget);
                }
                targets[i] = chooserTarget;
            }
            mCallerChooserTargets = targets;
        }
@@ -4214,4 +4223,43 @@ public class ChooserActivity extends ResolverActivity implements
    private boolean shouldNearbyShareBeIncludedAsActionButton() {
        return !shouldNearbyShareBeFirstInRankedRow();
    }

    private boolean hasValidIcon(ChooserTarget target) {
        Icon icon = target.getIcon();
        if (icon == null) {
            return true;
        }
        if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
            Uri uri = icon.getUri();
            try {
                getUriGrantsManager().checkGrantUriPermission_ignoreNonSystem(
                        getLaunchedFromUid(),
                        getPackageName(),
                        getUriWithoutUserId(uri),
                        Intent.FLAG_GRANT_READ_URI_PERMISSION,
                        getUserIdFromUri(uri)
                );
            } catch (SecurityException | RemoteException e) {
                Log.e(TAG, "Failed to get URI permission for: " + uri, e);
                return false;
            }
        }
        return true;
    }

    private IUriGrantsManager getUriGrantsManager() {
        return UriGrantsManager.getService();
    }

    private static ChooserTarget removeIcon(ChooserTarget target) {
        if (target == null) {
            return null;
        }
        return new ChooserTarget(
                target.getTitle(),
                null,
                target.getScore(),
                target.getComponentName(),
                target.getIntentExtras());
    }
}
+19 −8
Original line number Diff line number Diff line
@@ -599,24 +599,35 @@ public class IntentForwarderActivity extends Activity {
                Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
        sanitizeIntent(forwardIntent);

        Intent intentToCheck = forwardIntent;
        if (Intent.ACTION_CHOOSER.equals(forwardIntent.getAction())) {
        if (!canForwardInner(forwardIntent, sourceUserId, targetUserId, packageManager,
                contentResolver)) {
            return null;
        }
        if (forwardIntent.getSelector() != null) {
            intentToCheck = forwardIntent.getSelector();
            sanitizeIntent(forwardIntent.getSelector());
            if (!canForwardInner(forwardIntent.getSelector(), sourceUserId, targetUserId,
                    packageManager, contentResolver)) {
                return null;
            }
        }
        return forwardIntent;
    }

    private static boolean canForwardInner(Intent intent, int sourceUserId, int targetUserId,
            IPackageManager packageManager, ContentResolver contentResolver) {
        if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
            return false;
        }
        String resolvedType = intentToCheck.resolveTypeIfNeeded(contentResolver);
        sanitizeIntent(intentToCheck);
        String resolvedType = intent.resolveTypeIfNeeded(contentResolver);
        try {
            if (packageManager.canForwardTo(
                    intentToCheck, resolvedType, sourceUserId, targetUserId)) {
                return forwardIntent;
                    intent, resolvedType, sourceUserId, targetUserId)) {
                return true;
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "PackageManagerService is dead?");
        }
        return null;
        return false;
    }

    /**
+57 −32
Original line number Diff line number Diff line
@@ -603,7 +603,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
    /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */
    private static final class PackageVerificationResult {

        final RestrictionBypass bypass;
@@ -3086,10 +3086,10 @@ public class AppOpsService extends IAppOpsService.Stub {
    public int checkPackage(int uid, String packageName) {
        Objects.requireNonNull(packageName);
        try {
            verifyAndGetBypass(uid, packageName, null, null, true);
            verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
            // When the caller is the system, it's possible that the packageName is the special
            // one (e.g., "root") which isn't actually existed.
            if (resolveUid(packageName) == uid
            if (resolveNonAppUid(packageName) == uid
                    || (isPackageExisted(packageName)
                            && !filterAppAccessUnlocked(packageName, UserHandle.getUserId(uid)))) {
                return AppOpsManager.MODE_ALLOWED;
@@ -3288,7 +3288,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            boolean shouldCollectMessage) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
            if (!pvr.isAttributionTagValid) {
                attributionTag = null;
            }
@@ -3875,7 +3875,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            // Test if the proxied operation will succeed before starting the proxy operation
            final SyncNotedAppOp testProxiedOp = startOperationDryRun(code,
                    proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag,
                    proxiedVirtualDeviceId, resolvedProxyPackageName, proxiedFlags,
                    proxiedVirtualDeviceId, proxyUid, resolvedProxyPackageName, proxiedFlags,
                    startIfModeDefault);

            if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) {
@@ -3915,7 +3915,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            int attributionChainId) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
            if (!pvr.isAttributionTagValid) {
                attributionTag = null;
            }
@@ -4042,11 +4042,11 @@ public class AppOpsService extends IAppOpsService.Stub {
     */
    private SyncNotedAppOp startOperationDryRun(int code, int uid,
            @NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId,
            String proxyPackageName, @OpFlags int flags,
            int proxyUid, String proxyPackageName, @OpFlags int flags,
            boolean startIfModeDefault) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
            if (!pvr.isAttributionTagValid) {
                attributionTag = null;
            }
@@ -4601,14 +4601,18 @@ public class AppOpsService extends IAppOpsService.Stub {
    private boolean isSpecialPackage(int callingUid, @Nullable String packageName) {
        final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName);
        return callingUid == Process.SYSTEM_UID
                || resolveUid(resolvedPackage) != Process.INVALID_UID;
                || resolveNonAppUid(resolvedPackage) != Process.INVALID_UID;
    }

    private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) {
        if (attributionSource.getUid() != Binder.getCallingUid()
                && attributionSource.isTrusted(mContext)) {
            // if there is a next attribution source, it must be trusted, as well.
            if (attributionSource.getNext() == null
                    || attributionSource.getNext().isTrusted(mContext)) {
                return true;
            }
        }
        return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), null)
                == PackageManager.PERMISSION_GRANTED;
@@ -4702,19 +4706,20 @@ public class AppOpsService extends IAppOpsService.Stub {
    }

    /**
     * @see #verifyAndGetBypass(int, String, String, String, boolean)
     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag) {
        return verifyAndGetBypass(uid, packageName, attributionTag, null);
        return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
    }

    /**
     * @see #verifyAndGetBypass(int, String, String, String, boolean)
     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag, @Nullable String proxyPackageName) {
        return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false);
            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
        return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
                false);
    }

    /**
@@ -4725,14 +4730,15 @@ public class AppOpsService extends IAppOpsService.Stub {
     * @param uid The uid the package belongs to
     * @param packageName The package the might belong to the uid
     * @param attributionTag attribution tag or {@code null} if no need to verify
     * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
     * @param proxyUid The proxy uid, from which the attribution tag is to be pulled
     * @param proxyPackageName The proxy package, from which the attribution tag may be pulled
     * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
     *
     * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
     *         attribution tag is valid
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag, @Nullable String proxyPackageName,
            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
            boolean suppressErrorLogs) {
        if (uid == Process.ROOT_UID) {
            // For backwards compatibility, don't check package name for root UID.
@@ -4776,34 +4782,47 @@ public class AppOpsService extends IAppOpsService.Stub {

        int callingUid = Binder.getCallingUid();

        // Allow any attribution tag for resolvable uids
        int pkgUid;
        // Allow any attribution tag for resolvable, non-app uids
        int nonAppUid;
        if (Objects.equals(packageName, "com.android.shell")) {
            // Special case for the shell which is a package but should be able
            // to bypass app attribution tag restrictions.
            pkgUid = Process.SHELL_UID;
            nonAppUid = Process.SHELL_UID;
        } else {
            pkgUid = resolveUid(packageName);
            nonAppUid = resolveNonAppUid(packageName);
        }
        if (pkgUid != Process.INVALID_UID) {
            if (pkgUid != UserHandle.getAppId(uid)) {
        if (nonAppUid != Process.INVALID_UID) {
            if (nonAppUid != UserHandle.getAppId(uid)) {
                if (!suppressErrorLogs) {
                    Slog.e(TAG, "Bad call made by uid " + callingUid + ". "
                                + "Package \"" + packageName + "\" does not belong to uid " + uid
                                + ".");
                }
                String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
                throw new SecurityException("Specified package \"" + packageName + "\" under uid "
                        +  UserHandle.getAppId(uid) + otherUidMessage);
                String otherUidMessage =
                            DEBUG ? " but it is really " + nonAppUid : " but it is not";
                throw new SecurityException("Specified package \"" + packageName
                            + "\" under uid " +  UserHandle.getAppId(uid) + otherUidMessage);
            }
            // We only allow bypassing the attribution tag verification if the proxy is a
            // system app (or is null), in order to prevent abusive apps clogging the appops
            // system with unlimited attribution tags via proxy calls.
            boolean proxyIsSystemAppOrNull = true;
            if (proxyPackageName != null) {
                int proxyAppId = UserHandle.getAppId(proxyUid);
                if (proxyAppId >= Process.FIRST_APPLICATION_UID) {
                    proxyIsSystemAppOrNull =
                            mPackageManagerInternal.isSystemPackage(proxyPackageName);
                }
            }
            return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
                    /* isAttributionTagValid */ true);
                    /* isAttributionTagValid */ proxyIsSystemAppOrNull);
        }

        int userId = UserHandle.getUserId(uid);
        RestrictionBypass bypass = null;
        boolean isAttributionTagValid = false;

        int pkgUid = nonAppUid;
        final long ident = Binder.clearCallingIdentity();
        try {
            PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
@@ -5594,7 +5613,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            if (nonpackageUid != -1) {
                packageName = null;
            } else {
                packageUid = resolveUid(packageName);
                packageUid = resolveNonAppUid(packageName);
                if (packageUid < 0) {
                    packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
                            PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -6694,11 +6713,17 @@ public class AppOpsService extends IAppOpsService.Stub {
                if (restricted && attrOp.isRunning()) {
                    attrOp.pause();
                } else if (attrOp.isPaused()) {
                    RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag)
                            .bypass;
                    if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag,
                            Context.DEVICE_ID_DEFAULT, bypass, false)) {
                        // Only resume if there are no other restrictions remaining on this op
                        attrOp.resume();
                    }
                }
            }
        }
    }

    private void notifyWatchersOnDefaultDevice(int code, int uid) {
        ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
@@ -7143,7 +7168,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    private static int resolveUid(String packageName)  {
    private static int resolveNonAppUid(String packageName)  {
        if (packageName == null) {
            return Process.INVALID_UID;
        }
Loading