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

Commit 336af62f authored by Guojing Yuan's avatar Guojing Yuan Committed by Automerger Merge Worker
Browse files

Merge "[CDM perm sync] Skip user consent for the same OEM devices" into udc-qpr-dev am: 33be01e8

parents 5829f3ff 33be01e8
Loading
Loading
Loading
Loading
+1 −68
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.net.MacAddress;
import android.os.Binder;
import android.os.Bundle;
@@ -56,16 +55,9 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.util.Log;
import android.util.PackageUtils;
import android.util.Slog;

import com.android.internal.util.ArrayUtils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Class responsible for handling incoming {@link AssociationRequest}s.
@@ -447,31 +439,6 @@ class AssociationRequestsProcessor {
    };

    private boolean mayAssociateWithoutPrompt(@NonNull String packageName, @UserIdInt int userId) {
        // Below we check if the requesting package is allowlisted (usually by the OEM) for creating
        // CDM associations without user confirmation (prompt).
        // For this we'll check to config arrays:
        // - com.android.internal.R.array.config_companionDevicePackages
        // and
        // - com.android.internal.R.array.config_companionDeviceCerts.
        // Both arrays are expected to contain similar number of entries.
        // config_companionDevicePackages contains package names of the allowlisted packages.
        // config_companionDeviceCerts contains SHA256 digests of the signatures of the
        // corresponding packages.
        // If a package may be signed with one of several certificates, its package name would
        // appear multiple times in the config_companionDevicePackages, with different entries
        // (one for each of the valid signing certificates) at the corresponding positions in
        // config_companionDeviceCerts.
        final String[] allowlistedPackages = mContext.getResources()
                .getStringArray(com.android.internal.R.array.config_companionDevicePackages);
        if (!ArrayUtils.contains(allowlistedPackages, packageName)) {
            if (DEBUG) {
                Log.d(TAG, packageName + " is not allowlisted for creating associations "
                        + "without user confirmation (prompt)");
                Log.v(TAG, "Allowlisted packages=" + Arrays.toString(allowlistedPackages));
            }
            return false;
        }

        // Throttle frequent associations
        final long now = System.currentTimeMillis();
        final List<AssociationInfo> associationForPackage =
@@ -491,40 +458,6 @@ class AssociationRequestsProcessor {
            }
        }

        final String[] allowlistedPackagesSignatureDigests = mContext.getResources()
                .getStringArray(com.android.internal.R.array.config_companionDeviceCerts);
        final Set<String> allowlistedSignatureDigestsForRequestingPackage = new HashSet<>();
        for (int i = 0; i < allowlistedPackages.length; i++) {
            if (allowlistedPackages[i].equals(packageName)) {
                final String digest = allowlistedPackagesSignatureDigests[i].replaceAll(":", "");
                allowlistedSignatureDigestsForRequestingPackage.add(digest);
            }
        }

        final Signature[] requestingPackageSignatures = mPackageManager.getPackage(packageName)
                .getSigningDetails().getSignatures();
        final String[] requestingPackageSignatureDigests =
                PackageUtils.computeSignaturesSha256Digests(requestingPackageSignatures);

        boolean requestingPackageSignatureAllowlisted = false;
        for (String signatureDigest : requestingPackageSignatureDigests) {
            if (allowlistedSignatureDigestsForRequestingPackage.contains(signatureDigest)) {
                requestingPackageSignatureAllowlisted = true;
                break;
            }
        }

        if (!requestingPackageSignatureAllowlisted) {
            Slog.w(TAG, "Certificate mismatch for allowlisted package " + packageName);
            if (DEBUG) {
                Log.d(TAG, "  > allowlisted signatures for " + packageName + ": ["
                        + String.join(", ", allowlistedSignatureDigestsForRequestingPackage)
                        + "]");
                Log.d(TAG, "  > actual signatures for " + packageName + ": "
                        + Arrays.toString(requestingPackageSignatureDigests));
            }
        }

        return requestingPackageSignatureAllowlisted;
        return PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName);
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -244,7 +244,8 @@ public class CompanionDeviceManagerService extends SystemService {
        mCompanionAppController = new CompanionApplicationController(
                context, mAssociationStore, mDevicePresenceMonitor);
        mTransportManager = new CompanionTransportManager(context, mAssociationStore);
        mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mAssociationStore,
        mSystemDataTransferProcessor = new SystemDataTransferProcessor(this,
                mPackageManagerInternal, mAssociationStore,
                mSystemDataTransferRequestStore, mTransportManager);
        // TODO(b/279663946): move context sync to a dedicated system service
        mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager);
+75 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
import static android.content.pm.PackageManager.GET_CONFIGURATIONS;
import static android.content.pm.PackageManager.GET_PERMISSIONS;

import static com.android.server.companion.CompanionDeviceManagerService.DEBUG;
import static com.android.server.companion.CompanionDeviceManagerService.TAG;

import android.Manifest;
@@ -35,20 +36,28 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.os.Binder;
import android.util.Log;
import android.util.Slog;

import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Utility methods for working with {@link PackageInfo}-s.
 */
final class PackageUtils {
public final class PackageUtils {
    private static final Intent COMPANION_SERVICE_INTENT =
            new Intent(CompanionDeviceService.SERVICE_INTERFACE);
    private static final String PROPERTY_PRIMARY_TAG =
@@ -141,4 +150,69 @@ final class PackageUtils {
            return false;
        }
    }

    /**
     * Check if the package is allowlisted in the overlay config.
     * For this we'll check to config arrays:
     *   - com.android.internal.R.array.config_companionDevicePackages
     * and
     *   - com.android.internal.R.array.config_companionDeviceCerts.
     * Both arrays are expected to contain similar number of entries.
     * config_companionDevicePackages contains package names of the allowlisted packages.
     * config_companionDeviceCerts contains SHA256 digests of the signatures of the
     * corresponding packages.
     * If a package is signed with one of several certificates, its package name would
     * appear multiple times in the config_companionDevicePackages, with different entries
     * (one for each of the valid signing certificates) at the corresponding positions in
     * config_companionDeviceCerts.
     */
    public static boolean isPackageAllowlisted(Context context,
            PackageManagerInternal packageManagerInternal, @NonNull String packageName) {
        final String[] allowlistedPackages = context.getResources()
                .getStringArray(com.android.internal.R.array.config_companionDevicePackages);
        if (!ArrayUtils.contains(allowlistedPackages, packageName)) {
            if (DEBUG) {
                Log.d(TAG, packageName + " is not allowlisted.");
            }
            return false;
        }

        final String[] allowlistedPackagesSignatureDigests = context.getResources()
                .getStringArray(com.android.internal.R.array.config_companionDeviceCerts);
        final Set<String> allowlistedSignatureDigestsForRequestingPackage = new HashSet<>();
        for (int i = 0; i < allowlistedPackages.length; i++) {
            if (allowlistedPackages[i].equals(packageName)) {
                final String digest = allowlistedPackagesSignatureDigests[i].replaceAll(":", "");
                allowlistedSignatureDigestsForRequestingPackage.add(digest);
            }
        }

        final Signature[] requestingPackageSignatures = packageManagerInternal.getPackage(
                        packageName)
                .getSigningDetails().getSignatures();
        final String[] requestingPackageSignatureDigests =
                android.util.PackageUtils.computeSignaturesSha256Digests(
                        requestingPackageSignatures);

        boolean requestingPackageSignatureAllowlisted = false;
        for (String signatureDigest : requestingPackageSignatureDigests) {
            if (allowlistedSignatureDigestsForRequestingPackage.contains(signatureDigest)) {
                requestingPackageSignatureAllowlisted = true;
                break;
            }
        }

        if (!requestingPackageSignatureAllowlisted) {
            Slog.w(TAG, "Certificate mismatch for allowlisted package " + packageName);
            if (DEBUG) {
                Log.d(TAG, "  > allowlisted signatures for " + packageName + ": ["
                        + String.join(", ", allowlistedSignatureDigestsForRequestingPackage)
                        + "]");
                Log.d(TAG, "  > actual signatures for " + packageName + ": "
                        + Arrays.toString(requestingPackageSignatureDigests));
            }
        }

        return requestingPackageSignatureAllowlisted;
    }
}
+32 −16
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.companion.datatransfer.SystemDataTransferRequest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -50,6 +51,7 @@ import android.util.Slog;

import com.android.server.companion.AssociationStore;
import com.android.server.companion.CompanionDeviceManagerService;
import com.android.server.companion.PackageUtils;
import com.android.server.companion.PermissionsUtils;
import com.android.server.companion.transport.CompanionTransportManager;

@@ -80,6 +82,7 @@ public class SystemDataTransferProcessor {
                    ".CompanionDeviceDataTransferActivity");

    private final Context mContext;
    private final PackageManagerInternal mPackageManager;
    private final AssociationStore mAssociationStore;
    private final SystemDataTransferRequestStore mSystemDataTransferRequestStore;
    private final CompanionTransportManager mTransportManager;
@@ -87,10 +90,12 @@ public class SystemDataTransferProcessor {
    private final ExecutorService mExecutor;

    public SystemDataTransferProcessor(CompanionDeviceManagerService service,
            PackageManagerInternal packageManager,
            AssociationStore associationStore,
            SystemDataTransferRequestStore systemDataTransferRequestStore,
            CompanionTransportManager transportManager) {
        mContext = service.getContext();
        mPackageManager = packageManager;
        mAssociationStore = associationStore;
        mSystemDataTransferRequestStore = systemDataTransferRequestStore;
        mTransportManager = transportManager;
@@ -131,6 +136,11 @@ public class SystemDataTransferProcessor {
     */
    public PendingIntent buildPermissionTransferUserConsentIntent(String packageName,
            @UserIdInt int userId, int associationId) {
        if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) {
            Slog.i(LOG_TAG, "User consent Intent should be skipped. Returning null.");
            return null;
        }

        final AssociationInfo association = resolveAssociation(packageName, userId, associationId);

        Slog.i(LOG_TAG, "Creating permission sync intent for userId [" + userId
@@ -174,12 +184,16 @@ public class SystemDataTransferProcessor {
        final AssociationInfo association = resolveAssociation(packageName, userId, associationId);

        // Check if the request has been consented by the user.
        if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) {
            Slog.i(LOG_TAG, "Skip user consent check due to the same OEM package.");
        } else {
            List<SystemDataTransferRequest> storedRequests =
                    mSystemDataTransferRequestStore.readRequestsByAssociationId(userId,
                            associationId);
            boolean hasConsented = false;
            for (SystemDataTransferRequest storedRequest : storedRequests) {
            if (storedRequest instanceof PermissionSyncRequest && storedRequest.isUserConsented()) {
                if (storedRequest instanceof PermissionSyncRequest
                        && storedRequest.isUserConsented()) {
                    hasConsented = true;
                    break;
                }
@@ -189,9 +203,11 @@ public class SystemDataTransferProcessor {
                Slog.e(LOG_TAG, message);
                try {
                    callback.onError(message);
            } catch (RemoteException ignored) { }
                } catch (RemoteException ignored) {
                }
                return;
            }
        }

        // Start permission sync
        final long callingIdentityToken = Binder.clearCallingIdentity();
+1 −0
Original line number Diff line number Diff line
include /services/companion/java/com/android/server/companion/OWNERS
 No newline at end of file
Loading