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

Commit 29fdd38b authored by Priyanka Advani's avatar Priyanka Advani Committed by Android (Google) Code Review
Browse files

Revert "[CDM][Refactoring 3/N] Consolidate association cache and disk"

This reverts commit 10fcbd0a.

Reason for revert: Droid-monitored triggered revert due to likely culprit for breakages in b/329682644, b/329697378. Will be verifying through ABTD for confirmation and before submitting the revert.

Change-Id: Ia900b37eb149ece51647e7e0710751bfb02f854e
parent 10fcbd0a
Loading
Loading
Loading
Loading
+0 −8
Original line number Original line Diff line number Diff line
@@ -251,14 +251,6 @@ public final class AssociationInfo implements Parcelable {
        return mPending;
        return mPending;
    }
    }


    /**
     * @return true if the association is not revoked nor pending
     * @hide
     */
    public boolean isActive() {
        return !mRevoked && !mPending;
    }

    /**
    /**
     * @return the last time self reported disconnected for selfManaged only.
     * @return the last time self reported disconnected for selfManaged only.
     * @hide
     * @hide
+67 −54
Original line number Original line Diff line number Diff line
@@ -18,8 +18,7 @@ package com.android.server.companion;


import static android.os.UserHandle.getCallingUserId;
import static android.os.UserHandle.getCallingUserId;


import static com.android.server.companion.association.AssociationDiskStore.readAssociationsFromPayload;
import static com.android.server.companion.CompanionDeviceManagerService.PerUserAssociationSet;
import static com.android.server.companion.utils.RolesUtils.addRoleHolderForAssociation;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
@@ -27,50 +26,62 @@ import android.annotation.UserIdInt;
import android.companion.AssociationInfo;
import android.companion.AssociationInfo;
import android.companion.Flags;
import android.companion.Flags;
import android.companion.datatransfer.SystemDataTransferRequest;
import android.companion.datatransfer.SystemDataTransferRequest;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.CollectionUtils;
import com.android.server.companion.association.AssociationDiskStore;
import com.android.server.companion.association.AssociationDiskStore;
import com.android.server.companion.association.AssociationRequestsProcessor;
import com.android.server.companion.association.AssociationRequestsProcessor;
import com.android.server.companion.association.AssociationStore;
import com.android.server.companion.association.AssociationStore;
import com.android.server.companion.association.Associations;
import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;
import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;


import java.nio.ByteBuffer;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Predicate;


@SuppressLint("LongLogTag")
@SuppressLint("LongLogTag")
class BackupRestoreProcessor {
class BackupRestoreProcessor {
    private static final String TAG = "CDM_BackupRestoreProcessor";
    static final String TAG = "CDM_BackupRestoreProcessor";
    private static final int BACKUP_AND_RESTORE_VERSION = 0;
    private static final int BACKUP_AND_RESTORE_VERSION = 0;


    private final Context mContext;
    @NonNull
    @NonNull
    private final PackageManagerInternal mPackageManagerInternal;
    private final CompanionDeviceManagerService mService;
    @NonNull
    private final PackageManagerInternal mPackageManager;
    @NonNull
    @NonNull
    private final AssociationStore mAssociationStore;
    private final AssociationStore mAssociationStore;
    @NonNull
    @NonNull
    private final AssociationDiskStore mAssociationDiskStore;
    private final AssociationDiskStore mPersistentStore;
    @NonNull
    @NonNull
    private final SystemDataTransferRequestStore mSystemDataTransferRequestStore;
    private final SystemDataTransferRequestStore mSystemDataTransferRequestStore;
    @NonNull
    @NonNull
    private final AssociationRequestsProcessor mAssociationRequestsProcessor;
    private final AssociationRequestsProcessor mAssociationRequestsProcessor;


    BackupRestoreProcessor(@NonNull Context context,
    /**
                           @NonNull PackageManagerInternal packageManagerInternal,
     * A structure that consists of a set of restored associations that are pending corresponding
     * companion app to be installed.
     */
    @GuardedBy("mAssociationsPendingAppInstall")
    private final PerUserAssociationSet mAssociationsPendingAppInstall =
            new PerUserAssociationSet();

    BackupRestoreProcessor(@NonNull CompanionDeviceManagerService service,
                           @NonNull AssociationStore associationStore,
                           @NonNull AssociationStore associationStore,
                           @NonNull AssociationDiskStore associationDiskStore,
                           @NonNull AssociationDiskStore persistentStore,
                           @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore,
                           @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore,
                           @NonNull AssociationRequestsProcessor associationRequestsProcessor) {
                           @NonNull AssociationRequestsProcessor associationRequestsProcessor) {
        mContext = context;
        mService = service;
        mPackageManagerInternal = packageManagerInternal;
        mPackageManager = service.mPackageManagerInternal;
        mAssociationStore = associationStore;
        mAssociationStore = associationStore;
        mAssociationDiskStore = associationDiskStore;
        mPersistentStore = persistentStore;
        mSystemDataTransferRequestStore = systemDataTransferRequestStore;
        mSystemDataTransferRequestStore = systemDataTransferRequestStore;
        mAssociationRequestsProcessor = associationRequestsProcessor;
        mAssociationRequestsProcessor = associationRequestsProcessor;
    }
    }
@@ -82,9 +93,9 @@ class BackupRestoreProcessor {
     * | (4) SystemDataTransferRequest length | SystemDataTransferRequest XML (without userId)|
     * | (4) SystemDataTransferRequest length | SystemDataTransferRequest XML (without userId)|
     */
     */
    byte[] getBackupPayload(int userId) {
    byte[] getBackupPayload(int userId) {
        Slog.i(TAG, "getBackupPayload() userId=[" + userId + "].");
        // Persist state first to generate an up-to-date XML file

        mService.persistStateForUser(userId);
        byte[] associationsPayload = mAssociationDiskStore.getBackupPayload(userId);
        byte[] associationsPayload = mPersistentStore.getBackupPayload(userId);
        int associationsPayloadLength = associationsPayload.length;
        int associationsPayloadLength = associationsPayload.length;


        // System data transfer requests are persisted up-to-date already
        // System data transfer requests are persisted up-to-date already
@@ -108,9 +119,6 @@ class BackupRestoreProcessor {
     * Create new associations and system data transfer request consents using backed up payload.
     * Create new associations and system data transfer request consents using backed up payload.
     */
     */
    void applyRestoredPayload(byte[] payload, int userId) {
    void applyRestoredPayload(byte[] payload, int userId) {
        Slog.i(TAG, "applyRestoredPayload() userId=[" + userId + "], payload size=["
                + payload.length + "].");

        ByteBuffer buffer = ByteBuffer.wrap(payload);
        ByteBuffer buffer = ByteBuffer.wrap(payload);


        // Make sure that payload version matches current version to ensure proper deserialization
        // Make sure that payload version matches current version to ensure proper deserialization
@@ -123,8 +131,9 @@ class BackupRestoreProcessor {
        // Read the bytes containing backed-up associations
        // Read the bytes containing backed-up associations
        byte[] associationsPayload = new byte[buffer.getInt()];
        byte[] associationsPayload = new byte[buffer.getInt()];
        buffer.get(associationsPayload);
        buffer.get(associationsPayload);
        final Associations restoredAssociations = readAssociationsFromPayload(
        final Set<AssociationInfo> restoredAssociations = new HashSet<>();
                associationsPayload, userId);
        mPersistentStore.readStateFromPayload(associationsPayload, userId,
                restoredAssociations, new HashMap<>());


        // Read the bytes containing backed-up system data transfer requests user consent
        // Read the bytes containing backed-up system data transfer requests user consent
        byte[] requestsPayload = new byte[buffer.getInt()];
        byte[] requestsPayload = new byte[buffer.getInt()];
@@ -133,13 +142,13 @@ class BackupRestoreProcessor {
                mSystemDataTransferRequestStore.readRequestsFromPayload(requestsPayload, userId);
                mSystemDataTransferRequestStore.readRequestsFromPayload(requestsPayload, userId);


        // Get a list of installed packages ahead of time.
        // Get a list of installed packages ahead of time.
        List<ApplicationInfo> installedApps = mPackageManagerInternal.getInstalledApplications(
        List<ApplicationInfo> installedApps = mPackageManager.getInstalledApplications(
                0, userId, getCallingUserId());
                0, userId, getCallingUserId());


        // Restored device may have a different user ID than the backed-up user's user-ID. Since
        // Restored device may have a different user ID than the backed-up user's user-ID. Since
        // association ID is dependent on the user ID, restored associations must account for
        // association ID is dependent on the user ID, restored associations must account for
        // this potential difference on their association IDs.
        // this potential difference on their association IDs.
        for (AssociationInfo restored : restoredAssociations.getAssociations()) {
        for (AssociationInfo restored : restoredAssociations) {
            // Don't restore a revoked association. Since they weren't added to the device being
            // Don't restore a revoked association. Since they weren't added to the device being
            // restored in the first place, there is no need to worry about revoking a role that
            // restored in the first place, there is no need to worry about revoking a role that
            // was never granted either.
            // was never granted either.
@@ -159,9 +168,10 @@ class BackupRestoreProcessor {


            // Create a new association reassigned to this user and a valid association ID
            // Create a new association reassigned to this user and a valid association ID
            final String packageName = restored.getPackageName();
            final String packageName = restored.getPackageName();
            final int newId = mAssociationStore.getNextId(userId);
            final int newId = mService.getNewAssociationIdForPackage(userId, packageName);
            AssociationInfo newAssociation = new AssociationInfo.Builder(newId, userId, packageName,
            AssociationInfo newAssociation =
                    restored).build();
                    new AssociationInfo.Builder(newId, userId, packageName, restored)
                            .build();


            // Check if the companion app for this association is already installed, then do one
            // Check if the companion app for this association is already installed, then do one
            // of the following:
            // of the following:
@@ -169,15 +179,13 @@ class BackupRestoreProcessor {
            // the role attached to this association to the app.
            // the role attached to this association to the app.
            // (2) If the app isn't yet installed, then add this association to the list of pending
            // (2) If the app isn't yet installed, then add this association to the list of pending
            // associations to be added when the package is installed in the future.
            // associations to be added when the package is installed in the future.
            boolean isPackageInstalled = installedApps.stream().anyMatch(
            boolean isPackageInstalled = installedApps.stream()
                    app -> packageName.equals(app.packageName));
                    .anyMatch(app -> packageName.equals(app.packageName));
            if (isPackageInstalled) {
            if (isPackageInstalled) {
                mAssociationRequestsProcessor.maybeGrantRoleAndStoreAssociation(newAssociation,
                mAssociationRequestsProcessor.maybeGrantRoleAndStoreAssociation(newAssociation,
                        null, null);
                        null, null);
            } else {
            } else {
                newAssociation = (new AssociationInfo.Builder(newAssociation)).setPending(true)
                addToPendingAppInstall(newAssociation);
                        .build();
                mAssociationStore.addAssociation(newAssociation);
            }
            }


            // Re-map restored system data transfer requests to newly created associations
            // Re-map restored system data transfer requests to newly created associations
@@ -187,27 +195,32 @@ class BackupRestoreProcessor {
                mSystemDataTransferRequestStore.writeRequest(userId, newRequest);
                mSystemDataTransferRequestStore.writeRequest(userId, newRequest);
            }
            }
        }
        }
    }


    public void restorePendingAssociations(int userId, String packageName) {
        // Persist restored state.
        List<AssociationInfo> pendingAssociations = mAssociationStore.getPendingAssociations(userId,
        mService.persistStateForUser(userId);
                packageName);
        if (!pendingAssociations.isEmpty()) {
            Slog.i(TAG, "Found pending associations for package=[" + packageName
                    + "]. Restoring...");
    }
    }
        for (AssociationInfo association : pendingAssociations) {

            AssociationInfo newAssociation = new AssociationInfo.Builder(association)
    void addToPendingAppInstall(@NonNull AssociationInfo association) {
                    .setPending(false)
        association = (new AssociationInfo.Builder(association))
                .setPending(true)
                .build();
                .build();
            addRoleHolderForAssociation(mContext, newAssociation, success -> {

                if (success) {
        synchronized (mAssociationsPendingAppInstall) {
                    mAssociationStore.updateAssociation(newAssociation);
            mAssociationsPendingAppInstall.forUser(association.getUserId()).add(association);
                    Slog.i(TAG, "Association=[" + association + "] is restored.");
                } else {
                    Slog.e(TAG, "Failed to restore association=[" + association + "].");
        }
        }
            });
    }

    void removeFromPendingAppInstall(@NonNull AssociationInfo association) {
        synchronized (mAssociationsPendingAppInstall) {
            mAssociationsPendingAppInstall.forUser(association.getUserId()).remove(association);
        }
    }

    @NonNull
    Set<AssociationInfo> getAssociationsPendingAppInstallForUser(@UserIdInt int userId) {
        synchronized (mAssociationsPendingAppInstall) {
            // Return a copy.
            return new ArraySet<>(mAssociationsPendingAppInstall.forUser(userId));
        }
        }
    }
    }


@@ -218,7 +231,7 @@ class BackupRestoreProcessor {
    private boolean handleCollision(@UserIdInt int userId,
    private boolean handleCollision(@UserIdInt int userId,
            AssociationInfo restored,
            AssociationInfo restored,
            List<SystemDataTransferRequest> restoredRequests) {
            List<SystemDataTransferRequest> restoredRequests) {
        List<AssociationInfo> localAssociations = mAssociationStore.getActiveAssociationsByPackage(
        List<AssociationInfo> localAssociations = mAssociationStore.getAssociationsForPackage(
                restored.getUserId(), restored.getPackageName());
                restored.getUserId(), restored.getPackageName());
        Predicate<AssociationInfo> isSameDevice = associationInfo -> {
        Predicate<AssociationInfo> isSameDevice = associationInfo -> {
            boolean matchesMacAddress = Objects.equals(
            boolean matchesMacAddress = Objects.equals(
@@ -235,7 +248,7 @@ class BackupRestoreProcessor {
            return false;
            return false;
        }
        }


        Slog.d(TAG, "Conflict detected with association id=" + local.getId()
        Log.d(TAG, "Conflict detected with association id=" + local.getId()
                + " while restoring CDM backup. Keeping local association.");
                + " while restoring CDM backup. Keeping local association.");


        List<SystemDataTransferRequest> localRequests = mSystemDataTransferRequestStore
        List<SystemDataTransferRequest> localRequests = mSystemDataTransferRequestStore
@@ -253,8 +266,8 @@ class BackupRestoreProcessor {
                continue;
                continue;
            }
            }


            Slog.d(TAG, "Restoring " + restoredRequest.getClass().getSimpleName()
            Log.d(TAG, "Restoring " + restoredRequest.getClass().getSimpleName()
                    + " to an existing association id=[" + local.getId() + "].");
                    + " to an existing association id=" + local.getId() + ".");


            SystemDataTransferRequest newRequest =
            SystemDataTransferRequest newRequest =
                    restoredRequest.copyWithNewId(local.getId());
                    restoredRequest.copyWithNewId(local.getId());
+2 −2
Original line number Original line Diff line number Diff line
@@ -397,7 +397,7 @@ public class CompanionApplicationController {
        // First, disable hint mode for Auto profile and mark not BOUND for primary service ONLY.
        // First, disable hint mode for Auto profile and mark not BOUND for primary service ONLY.
        if (isPrimary) {
        if (isPrimary) {
            final List<AssociationInfo> associations =
            final List<AssociationInfo> associations =
                    mAssociationStore.getActiveAssociationsByPackage(userId, packageName);
                    mAssociationStore.getAssociationsForPackage(userId, packageName);


            for (AssociationInfo association : associations) {
            for (AssociationInfo association : associations) {
                final String deviceProfile = association.getDeviceProfile();
                final String deviceProfile = association.getDeviceProfile();
@@ -442,7 +442,7 @@ public class CompanionApplicationController {
                mObservableUuidStore.getObservableUuidsForPackage(userId, packageName);
                mObservableUuidStore.getObservableUuidsForPackage(userId, packageName);


        for (AssociationInfo ai :
        for (AssociationInfo ai :
                mAssociationStore.getActiveAssociationsByPackage(userId, packageName)) {
                mAssociationStore.getAssociationsForPackage(userId, packageName)) {
            final int associationId = ai.getId();
            final int associationId = ai.getId();
            stillAssociated = true;
            stillAssociated = true;
            if (ai.isSelfManaged()) {
            if (ai.isSelfManaged()) {
+394 −104

File changed.

Preview size limit exceeded, changes collapsed.

+16 −15
Original line number Original line Diff line number Diff line
@@ -33,8 +33,8 @@ import android.util.Base64;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoOutputStream;


import com.android.server.companion.association.AssociationRequestsProcessor;
import com.android.server.companion.association.AssociationRequestsProcessor;
import com.android.server.companion.association.AssociationRevokeProcessor;
import com.android.server.companion.association.AssociationStore;
import com.android.server.companion.association.AssociationStore;
import com.android.server.companion.association.DisassociationProcessor;
import com.android.server.companion.datatransfer.SystemDataTransferProcessor;
import com.android.server.companion.datatransfer.SystemDataTransferProcessor;
import com.android.server.companion.datatransfer.contextsync.BitmapUtils;
import com.android.server.companion.datatransfer.contextsync.BitmapUtils;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController;
@@ -49,7 +49,7 @@ class CompanionDeviceShellCommand extends ShellCommand {
    private static final String TAG = "CDM_CompanionDeviceShellCommand";
    private static final String TAG = "CDM_CompanionDeviceShellCommand";


    private final CompanionDeviceManagerService mService;
    private final CompanionDeviceManagerService mService;
    private final DisassociationProcessor mDisassociationProcessor;
    private final AssociationRevokeProcessor mRevokeProcessor;
    private final AssociationStore mAssociationStore;
    private final AssociationStore mAssociationStore;
    private final CompanionDevicePresenceMonitor mDevicePresenceMonitor;
    private final CompanionDevicePresenceMonitor mDevicePresenceMonitor;
    private final CompanionTransportManager mTransportManager;
    private final CompanionTransportManager mTransportManager;
@@ -65,7 +65,7 @@ class CompanionDeviceShellCommand extends ShellCommand {
            SystemDataTransferProcessor systemDataTransferProcessor,
            SystemDataTransferProcessor systemDataTransferProcessor,
            AssociationRequestsProcessor associationRequestsProcessor,
            AssociationRequestsProcessor associationRequestsProcessor,
            BackupRestoreProcessor backupRestoreProcessor,
            BackupRestoreProcessor backupRestoreProcessor,
            DisassociationProcessor disassociationProcessor) {
            AssociationRevokeProcessor revokeProcessor) {
        mService = service;
        mService = service;
        mAssociationStore = associationStore;
        mAssociationStore = associationStore;
        mDevicePresenceMonitor = devicePresenceMonitor;
        mDevicePresenceMonitor = devicePresenceMonitor;
@@ -73,7 +73,7 @@ class CompanionDeviceShellCommand extends ShellCommand {
        mSystemDataTransferProcessor = systemDataTransferProcessor;
        mSystemDataTransferProcessor = systemDataTransferProcessor;
        mAssociationRequestsProcessor = associationRequestsProcessor;
        mAssociationRequestsProcessor = associationRequestsProcessor;
        mBackupRestoreProcessor = backupRestoreProcessor;
        mBackupRestoreProcessor = backupRestoreProcessor;
        mDisassociationProcessor = disassociationProcessor;
        mRevokeProcessor = revokeProcessor;
    }
    }


    @Override
    @Override
@@ -105,15 +105,12 @@ class CompanionDeviceShellCommand extends ShellCommand {
                case "list": {
                case "list": {
                    final int userId = getNextIntArgRequired();
                    final int userId = getNextIntArgRequired();
                    final List<AssociationInfo> associationsForUser =
                    final List<AssociationInfo> associationsForUser =
                            mAssociationStore.getActiveAssociationsByUser(userId);
                            mAssociationStore.getAssociationsForUser(userId);
                    final int maxId = mAssociationStore.getMaxId(userId);
                    out.println("Max ID: " + maxId);
                    out.println("Association ID | Package Name | Mac Address");
                    for (AssociationInfo association : associationsForUser) {
                    for (AssociationInfo association : associationsForUser) {
                        // TODO(b/212535524): use AssociationInfo.toShortString(), once it's not
                        // TODO(b/212535524): use AssociationInfo.toShortString(), once it's not
                        //  longer referenced in tests.
                        //  longer referenced in tests.
                        out.println(association.getId() + " | " + association.getPackageName()
                        out.println(association.getPackageName() + " "
                                + " | " + association.getDeviceMacAddress());
                                + association.getDeviceMacAddress() + " " + association.getId());
                    }
                    }
                }
                }
                break;
                break;
@@ -135,24 +132,28 @@ class CompanionDeviceShellCommand extends ShellCommand {
                    final String address = getNextArgRequired();
                    final String address = getNextArgRequired();
                    final AssociationInfo association =
                    final AssociationInfo association =
                            mService.getAssociationWithCallerChecks(userId, packageName, address);
                            mService.getAssociationWithCallerChecks(userId, packageName, address);
                    mDisassociationProcessor.disassociate(association.getId());
                    if (association != null) {
                        mRevokeProcessor.disassociateInternal(association.getId());
                    }
                }
                }
                break;
                break;


                case "disassociate-all": {
                case "disassociate-all": {
                    final int userId = getNextIntArgRequired();
                    final int userId = getNextIntArgRequired();
                    final String packageName = getNextArgRequired();
                    final List<AssociationInfo> userAssociations =
                    final List<AssociationInfo> userAssociations =
                            mAssociationStore.getAssociationsByUser(userId);
                            mAssociationStore.getAssociationsForPackage(userId, packageName);
                    for (AssociationInfo association : userAssociations) {
                    for (AssociationInfo association : userAssociations) {
                        if (sanitizeWithCallerChecks(mService.getContext(), association) != null) {
                        if (sanitizeWithCallerChecks(mService.getContext(), association) != null) {
                            mDisassociationProcessor.disassociate(association.getId());
                            mRevokeProcessor.disassociateInternal(association.getId());
                        }
                        }
                    }
                    }
                }
                }
                break;
                break;


                case "refresh-cache":
                case "clear-association-memory-cache":
                    mAssociationStore.refreshCache();
                    mService.persistState();
                    mService.loadAssociationsFromDisk();
                    break;
                    break;


                case "simulate-device-appeared":
                case "simulate-device-appeared":
Loading