Loading core/java/android/companion/AssociationInfo.java +23 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,29 @@ public final class AssociationInfo implements Parcelable { mSystemDataSyncFlags = info.mSystemDataSyncFlags; } /** * This builder is used specifically to create a new association to be restored to a device * that is potentially using a different user ID from the backed-up device. * * @hide */ public Builder(int id, int userId, @NonNull String packageName, AssociationInfo info) { mId = id; mUserId = userId; mPackageName = packageName; mTag = info.mTag; mDeviceMacAddress = info.mDeviceMacAddress; mDisplayName = info.mDisplayName; mDeviceProfile = info.mDeviceProfile; mAssociatedDevice = info.mAssociatedDevice; mSelfManaged = info.mSelfManaged; mNotifyOnDeviceNearby = info.mNotifyOnDeviceNearby; mRevoked = info.mRevoked; mTimeApprovedMs = info.mTimeApprovedMs; mLastTimeConnectedMs = info.mLastTimeConnectedMs; mSystemDataSyncFlags = info.mSystemDataSyncFlags; } /** @hide */ @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) @TestApi Loading core/java/android/companion/datatransfer/PermissionSyncRequest.java +9 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,15 @@ public class PermissionSyncRequest extends SystemDataTransferRequest implements super(in); } /** @hide */ @Override public PermissionSyncRequest copyWithNewId(int associationId) { PermissionSyncRequest newRequest = new PermissionSyncRequest(associationId); newRequest.mUserId = this.mUserId; newRequest.mUserConsented = this.mUserConsented; return newRequest; } /** @hide */ @NonNull public static final Creator<PermissionSyncRequest> CREATOR = Loading core/java/android/companion/datatransfer/SystemDataTransferRequest.java +11 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,15 @@ public abstract class SystemDataTransferRequest { public int describeContents() { return 0; } /** * Creates a copy of itself with new association ID. * * This method must be implemented to ensure that backup-and-restore can correctly re-map * the restored requests to the restored associations that can potentially have different * IDs than what was originally backed up. * * @hide */ public abstract SystemDataTransferRequest copyWithNewId(int associationId); } services/companion/java/com/android/server/companion/BackupRestoreProcessor.java 0 → 100644 +241 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.server.companion; import static android.os.UserHandle.getCallingUserId; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.companion.AssociationInfo; import android.companion.Flags; import android.companion.datatransfer.SystemDataTransferRequest; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.util.Log; import android.util.Slog; import com.android.internal.util.CollectionUtils; import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.function.Predicate; @SuppressLint("LongLogTag") class BackupRestoreProcessor { static final String TAG = "CDM_BackupRestoreProcessor"; private static final int BACKUP_AND_RESTORE_VERSION = 0; @NonNull private final CompanionDeviceManagerService mService; @NonNull private final PackageManagerInternal mPackageManager; @NonNull private final AssociationStoreImpl mAssociationStore; @NonNull private final PersistentDataStore mPersistentStore; @NonNull private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; @NonNull private final AssociationRequestsProcessor mAssociationRequestsProcessor; BackupRestoreProcessor(@NonNull CompanionDeviceManagerService service, @NonNull AssociationStoreImpl associationStore, @NonNull PersistentDataStore persistentStore, @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore, @NonNull AssociationRequestsProcessor associationRequestsProcessor) { mService = service; mPackageManager = service.mPackageManagerInternal; mAssociationStore = associationStore; mPersistentStore = persistentStore; mSystemDataTransferRequestStore = systemDataTransferRequestStore; mAssociationRequestsProcessor = associationRequestsProcessor; } /** * Generate CDM state payload to be backed up. * Backup payload is formatted as following: * | (4) payload version | (4) AssociationInfo length | AssociationInfo XML * | (4) SystemDataTransferRequest length | SystemDataTransferRequest XML (without userId)| */ byte[] getBackupPayload(int userId) { // Persist state first to generate an up-to-date XML file mService.persistStateForUser(userId); byte[] associationsPayload = mPersistentStore.getBackupPayload(userId); int associationsPayloadLength = associationsPayload.length; // System data transfer requests are persisted up-to-date already byte[] requestsPayload = mSystemDataTransferRequestStore.getBackupPayload(userId); int requestsPayloadLength = requestsPayload.length; int payloadSize = /* 3 integers */ 12 + associationsPayloadLength + requestsPayloadLength; return ByteBuffer.allocate(payloadSize) .putInt(BACKUP_AND_RESTORE_VERSION) .putInt(associationsPayloadLength) .put(associationsPayload) .putInt(requestsPayloadLength) .put(requestsPayload) .array(); } /** * Create new associations and system data transfer request consents using backed up payload. */ void applyRestoredPayload(byte[] payload, int userId) { ByteBuffer buffer = ByteBuffer.wrap(payload); // Make sure that payload version matches current version to ensure proper deserialization int version = buffer.getInt(); if (version != BACKUP_AND_RESTORE_VERSION) { Slog.e(TAG, "Unsupported backup payload version"); return; } // Read the bytes containing backed-up associations byte[] associationsPayload = new byte[buffer.getInt()]; buffer.get(associationsPayload); final Set<AssociationInfo> restoredAssociations = new HashSet<>(); mPersistentStore.readStateFromPayload(associationsPayload, userId, restoredAssociations, new HashMap<>()); // Read the bytes containing backed-up system data transfer requests user consent byte[] requestsPayload = new byte[buffer.getInt()]; buffer.get(requestsPayload); List<SystemDataTransferRequest> restoredRequestsForUser = mSystemDataTransferRequestStore.readRequestsFromPayload(requestsPayload); // Get a list of installed packages ahead of time. List<ApplicationInfo> installedApps = mPackageManager.getInstalledApplications( 0, userId, getCallingUserId()); // 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 // this potential difference on their association IDs. for (AssociationInfo restored : restoredAssociations) { // 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 // was never granted either. if (restored.isRevoked()) { continue; } // Filter restored requests for those that belong to the restored association. List<SystemDataTransferRequest> restoredRequests = CollectionUtils.filter( restoredRequestsForUser, it -> it.getAssociationId() == restored.getId()); // Handle collision: If a local association belonging to the same package already exists // and their tags match, then keep the local one in favor of creating a new association. if (handleCollision(userId, restored, restoredRequests)) { continue; } // Create a new association reassigned to this user and a valid association ID final String packageName = restored.getPackageName(); final int newId = mService.getNewAssociationIdForPackage(userId, packageName); AssociationInfo newAssociation = new AssociationInfo.Builder(newId, userId, packageName, restored) .build(); // Check if the companion app for this association is already installed, then do one // of the following: // (1) If the app is already installed, then go ahead and add this association and grant // 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 // associations to be added when the package is installed in the future. boolean isPackageInstalled = installedApps.stream() .anyMatch(app -> packageName.equals(app.packageName)); if (isPackageInstalled) { mAssociationRequestsProcessor.maybeGrantRoleAndStoreAssociation(newAssociation, null, null); } else { // TODO(b/314992577): Check if package is installed before granting } // Re-map restored system data transfer requests to newly created associations for (SystemDataTransferRequest restoredRequest : restoredRequests) { SystemDataTransferRequest newRequest = restoredRequest.copyWithNewId(newId); newRequest.setUserId(userId); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } } // Persist restored state. mService.persistStateForUser(userId); } /** * Detects and handles collision between restored association and local association. Returns * true if there has been a collision and false otherwise. */ private boolean handleCollision(@UserIdInt int userId, AssociationInfo restored, List<SystemDataTransferRequest> restoredRequests) { List<AssociationInfo> localAssociations = mAssociationStore.getAssociationsForPackage( restored.getUserId(), restored.getPackageName()); Predicate<AssociationInfo> isSameDevice = associationInfo -> { boolean matchesMacAddress = Objects.equals( associationInfo.getDeviceMacAddress(), restored.getDeviceMacAddress()); boolean matchesTag = !Flags.associationTag() || Objects.equals(associationInfo.getTag(), restored.getTag()); return matchesMacAddress && matchesTag; }; AssociationInfo local = CollectionUtils.find(localAssociations, isSameDevice); // No collision detected if (local == null) { return false; } Log.d(TAG, "Conflict detected with association id=" + local.getId() + " while restoring CDM backup. Keeping local association."); List<SystemDataTransferRequest> localRequests = mSystemDataTransferRequestStore .readRequestsByAssociationId(userId, local.getId()); // If local association doesn't have any existing system data transfer request of same type // attached, then restore corresponding request onto the local association. Otherwise, keep // the locally stored request. for (SystemDataTransferRequest restoredRequest : restoredRequests) { boolean requestTypeExists = CollectionUtils.any(localRequests, request -> request.getDataType() == restoredRequest.getDataType()); // This type of request consent already exists for the association. if (requestTypeExists) { continue; } Log.d(TAG, "Restoring " + restoredRequest.getClass().getSimpleName() + " to an existing association id=" + local.getId() + "."); SystemDataTransferRequest newRequest = restoredRequest.copyWithNewId(local.getId()); newRequest.setUserId(userId); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } return true; } } services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +21 −5 Original line number Diff line number Diff line Loading @@ -164,6 +164,7 @@ public class CompanionDeviceManagerService extends SystemService { private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private AssociationRequestsProcessor mAssociationRequestsProcessor; private SystemDataTransferProcessor mSystemDataTransferProcessor; private BackupRestoreProcessor mBackupRestoreProcessor; private CompanionDevicePresenceMonitor mDevicePresenceMonitor; private CompanionApplicationController mCompanionAppController; private CompanionTransportManager mTransportManager; Loading Loading @@ -256,6 +257,9 @@ public class CompanionDeviceManagerService extends SystemService { mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); mBackupRestoreProcessor = new BackupRestoreProcessor( /* cdmService */ this, mAssociationStore, mPersistentStore, mSystemDataTransferRequestStore, mAssociationRequestsProcessor); // TODO(b/279663946): move context sync to a dedicated system service mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager); Loading Loading @@ -501,7 +505,7 @@ public class CompanionDeviceManagerService extends SystemService { updateAtm(userId, updatedAssociations); } private void persistStateForUser(@UserIdInt int userId) { void persistStateForUser(@UserIdInt int userId) { // We want to store both active associations and the revoked (removed) association that we // are keeping around for the final clean-up (delayed role holder removal). final List<AssociationInfo> allAssociations; Loading Loading @@ -577,6 +581,11 @@ public class CompanionDeviceManagerService extends SystemService { mCompanionAppController.onPackagesChanged(userId); } private void onPackageAddedInternal(@UserIdInt int userId, @NonNull String packageName) { if (DEBUG) Log.i(TAG, "onPackageAddedInternal() u" + userId + "/" + packageName); // TODO(b/314992577): Retroactively grant roles for restored associations } // Revoke associations if the selfManaged companion device does not connect for 3 months. void removeInactiveSelfManagedAssociations() { final long currentTime = System.currentTimeMillis(); Loading Loading @@ -1052,13 +1061,14 @@ public class CompanionDeviceManagerService extends SystemService { @Override public byte[] getBackupPayload(int userId) { // TODO(b/286124853): back up CDM data return new byte[0]; Log.i(TAG, "getBackupPayload() userId=" + userId); return mBackupRestoreProcessor.getBackupPayload(userId); } @Override public void applyRestoredPayload(byte[] payload, int userId) { // TODO(b/286124853): restore CDM data Log.i(TAG, "applyRestoredPayload() userId=" + userId); mBackupRestoreProcessor.applyRestoredPayload(payload, userId); } @Override Loading @@ -1067,7 +1077,8 @@ public class CompanionDeviceManagerService extends SystemService { @NonNull String[] args) { return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, mAssociationRequestsProcessor) mSystemDataTransferProcessor, mAssociationRequestsProcessor, mBackupRestoreProcessor) .exec(this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args); } Loading Loading @@ -1499,6 +1510,11 @@ public class CompanionDeviceManagerService extends SystemService { public void onPackageModified(String packageName) { onPackageModifiedInternal(getChangingUserId(), packageName); } @Override public void onPackageAdded(String packageName, int uid) { onPackageAddedInternal(getChangingUserId(), packageName); } }; static int getFirstAssociationIdForUser(@UserIdInt int userId) { Loading Loading
core/java/android/companion/AssociationInfo.java +23 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,29 @@ public final class AssociationInfo implements Parcelable { mSystemDataSyncFlags = info.mSystemDataSyncFlags; } /** * This builder is used specifically to create a new association to be restored to a device * that is potentially using a different user ID from the backed-up device. * * @hide */ public Builder(int id, int userId, @NonNull String packageName, AssociationInfo info) { mId = id; mUserId = userId; mPackageName = packageName; mTag = info.mTag; mDeviceMacAddress = info.mDeviceMacAddress; mDisplayName = info.mDisplayName; mDeviceProfile = info.mDeviceProfile; mAssociatedDevice = info.mAssociatedDevice; mSelfManaged = info.mSelfManaged; mNotifyOnDeviceNearby = info.mNotifyOnDeviceNearby; mRevoked = info.mRevoked; mTimeApprovedMs = info.mTimeApprovedMs; mLastTimeConnectedMs = info.mLastTimeConnectedMs; mSystemDataSyncFlags = info.mSystemDataSyncFlags; } /** @hide */ @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) @TestApi Loading
core/java/android/companion/datatransfer/PermissionSyncRequest.java +9 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,15 @@ public class PermissionSyncRequest extends SystemDataTransferRequest implements super(in); } /** @hide */ @Override public PermissionSyncRequest copyWithNewId(int associationId) { PermissionSyncRequest newRequest = new PermissionSyncRequest(associationId); newRequest.mUserId = this.mUserId; newRequest.mUserConsented = this.mUserConsented; return newRequest; } /** @hide */ @NonNull public static final Creator<PermissionSyncRequest> CREATOR = Loading
core/java/android/companion/datatransfer/SystemDataTransferRequest.java +11 −0 Original line number Diff line number Diff line Loading @@ -103,4 +103,15 @@ public abstract class SystemDataTransferRequest { public int describeContents() { return 0; } /** * Creates a copy of itself with new association ID. * * This method must be implemented to ensure that backup-and-restore can correctly re-map * the restored requests to the restored associations that can potentially have different * IDs than what was originally backed up. * * @hide */ public abstract SystemDataTransferRequest copyWithNewId(int associationId); }
services/companion/java/com/android/server/companion/BackupRestoreProcessor.java 0 → 100644 +241 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.server.companion; import static android.os.UserHandle.getCallingUserId; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.companion.AssociationInfo; import android.companion.Flags; import android.companion.datatransfer.SystemDataTransferRequest; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.util.Log; import android.util.Slog; import com.android.internal.util.CollectionUtils; import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.function.Predicate; @SuppressLint("LongLogTag") class BackupRestoreProcessor { static final String TAG = "CDM_BackupRestoreProcessor"; private static final int BACKUP_AND_RESTORE_VERSION = 0; @NonNull private final CompanionDeviceManagerService mService; @NonNull private final PackageManagerInternal mPackageManager; @NonNull private final AssociationStoreImpl mAssociationStore; @NonNull private final PersistentDataStore mPersistentStore; @NonNull private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; @NonNull private final AssociationRequestsProcessor mAssociationRequestsProcessor; BackupRestoreProcessor(@NonNull CompanionDeviceManagerService service, @NonNull AssociationStoreImpl associationStore, @NonNull PersistentDataStore persistentStore, @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore, @NonNull AssociationRequestsProcessor associationRequestsProcessor) { mService = service; mPackageManager = service.mPackageManagerInternal; mAssociationStore = associationStore; mPersistentStore = persistentStore; mSystemDataTransferRequestStore = systemDataTransferRequestStore; mAssociationRequestsProcessor = associationRequestsProcessor; } /** * Generate CDM state payload to be backed up. * Backup payload is formatted as following: * | (4) payload version | (4) AssociationInfo length | AssociationInfo XML * | (4) SystemDataTransferRequest length | SystemDataTransferRequest XML (without userId)| */ byte[] getBackupPayload(int userId) { // Persist state first to generate an up-to-date XML file mService.persistStateForUser(userId); byte[] associationsPayload = mPersistentStore.getBackupPayload(userId); int associationsPayloadLength = associationsPayload.length; // System data transfer requests are persisted up-to-date already byte[] requestsPayload = mSystemDataTransferRequestStore.getBackupPayload(userId); int requestsPayloadLength = requestsPayload.length; int payloadSize = /* 3 integers */ 12 + associationsPayloadLength + requestsPayloadLength; return ByteBuffer.allocate(payloadSize) .putInt(BACKUP_AND_RESTORE_VERSION) .putInt(associationsPayloadLength) .put(associationsPayload) .putInt(requestsPayloadLength) .put(requestsPayload) .array(); } /** * Create new associations and system data transfer request consents using backed up payload. */ void applyRestoredPayload(byte[] payload, int userId) { ByteBuffer buffer = ByteBuffer.wrap(payload); // Make sure that payload version matches current version to ensure proper deserialization int version = buffer.getInt(); if (version != BACKUP_AND_RESTORE_VERSION) { Slog.e(TAG, "Unsupported backup payload version"); return; } // Read the bytes containing backed-up associations byte[] associationsPayload = new byte[buffer.getInt()]; buffer.get(associationsPayload); final Set<AssociationInfo> restoredAssociations = new HashSet<>(); mPersistentStore.readStateFromPayload(associationsPayload, userId, restoredAssociations, new HashMap<>()); // Read the bytes containing backed-up system data transfer requests user consent byte[] requestsPayload = new byte[buffer.getInt()]; buffer.get(requestsPayload); List<SystemDataTransferRequest> restoredRequestsForUser = mSystemDataTransferRequestStore.readRequestsFromPayload(requestsPayload); // Get a list of installed packages ahead of time. List<ApplicationInfo> installedApps = mPackageManager.getInstalledApplications( 0, userId, getCallingUserId()); // 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 // this potential difference on their association IDs. for (AssociationInfo restored : restoredAssociations) { // 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 // was never granted either. if (restored.isRevoked()) { continue; } // Filter restored requests for those that belong to the restored association. List<SystemDataTransferRequest> restoredRequests = CollectionUtils.filter( restoredRequestsForUser, it -> it.getAssociationId() == restored.getId()); // Handle collision: If a local association belonging to the same package already exists // and their tags match, then keep the local one in favor of creating a new association. if (handleCollision(userId, restored, restoredRequests)) { continue; } // Create a new association reassigned to this user and a valid association ID final String packageName = restored.getPackageName(); final int newId = mService.getNewAssociationIdForPackage(userId, packageName); AssociationInfo newAssociation = new AssociationInfo.Builder(newId, userId, packageName, restored) .build(); // Check if the companion app for this association is already installed, then do one // of the following: // (1) If the app is already installed, then go ahead and add this association and grant // 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 // associations to be added when the package is installed in the future. boolean isPackageInstalled = installedApps.stream() .anyMatch(app -> packageName.equals(app.packageName)); if (isPackageInstalled) { mAssociationRequestsProcessor.maybeGrantRoleAndStoreAssociation(newAssociation, null, null); } else { // TODO(b/314992577): Check if package is installed before granting } // Re-map restored system data transfer requests to newly created associations for (SystemDataTransferRequest restoredRequest : restoredRequests) { SystemDataTransferRequest newRequest = restoredRequest.copyWithNewId(newId); newRequest.setUserId(userId); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } } // Persist restored state. mService.persistStateForUser(userId); } /** * Detects and handles collision between restored association and local association. Returns * true if there has been a collision and false otherwise. */ private boolean handleCollision(@UserIdInt int userId, AssociationInfo restored, List<SystemDataTransferRequest> restoredRequests) { List<AssociationInfo> localAssociations = mAssociationStore.getAssociationsForPackage( restored.getUserId(), restored.getPackageName()); Predicate<AssociationInfo> isSameDevice = associationInfo -> { boolean matchesMacAddress = Objects.equals( associationInfo.getDeviceMacAddress(), restored.getDeviceMacAddress()); boolean matchesTag = !Flags.associationTag() || Objects.equals(associationInfo.getTag(), restored.getTag()); return matchesMacAddress && matchesTag; }; AssociationInfo local = CollectionUtils.find(localAssociations, isSameDevice); // No collision detected if (local == null) { return false; } Log.d(TAG, "Conflict detected with association id=" + local.getId() + " while restoring CDM backup. Keeping local association."); List<SystemDataTransferRequest> localRequests = mSystemDataTransferRequestStore .readRequestsByAssociationId(userId, local.getId()); // If local association doesn't have any existing system data transfer request of same type // attached, then restore corresponding request onto the local association. Otherwise, keep // the locally stored request. for (SystemDataTransferRequest restoredRequest : restoredRequests) { boolean requestTypeExists = CollectionUtils.any(localRequests, request -> request.getDataType() == restoredRequest.getDataType()); // This type of request consent already exists for the association. if (requestTypeExists) { continue; } Log.d(TAG, "Restoring " + restoredRequest.getClass().getSimpleName() + " to an existing association id=" + local.getId() + "."); SystemDataTransferRequest newRequest = restoredRequest.copyWithNewId(local.getId()); newRequest.setUserId(userId); mSystemDataTransferRequestStore.writeRequest(userId, newRequest); } return true; } }
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +21 −5 Original line number Diff line number Diff line Loading @@ -164,6 +164,7 @@ public class CompanionDeviceManagerService extends SystemService { private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private AssociationRequestsProcessor mAssociationRequestsProcessor; private SystemDataTransferProcessor mSystemDataTransferProcessor; private BackupRestoreProcessor mBackupRestoreProcessor; private CompanionDevicePresenceMonitor mDevicePresenceMonitor; private CompanionApplicationController mCompanionAppController; private CompanionTransportManager mTransportManager; Loading Loading @@ -256,6 +257,9 @@ public class CompanionDeviceManagerService extends SystemService { mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); mBackupRestoreProcessor = new BackupRestoreProcessor( /* cdmService */ this, mAssociationStore, mPersistentStore, mSystemDataTransferRequestStore, mAssociationRequestsProcessor); // TODO(b/279663946): move context sync to a dedicated system service mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager); Loading Loading @@ -501,7 +505,7 @@ public class CompanionDeviceManagerService extends SystemService { updateAtm(userId, updatedAssociations); } private void persistStateForUser(@UserIdInt int userId) { void persistStateForUser(@UserIdInt int userId) { // We want to store both active associations and the revoked (removed) association that we // are keeping around for the final clean-up (delayed role holder removal). final List<AssociationInfo> allAssociations; Loading Loading @@ -577,6 +581,11 @@ public class CompanionDeviceManagerService extends SystemService { mCompanionAppController.onPackagesChanged(userId); } private void onPackageAddedInternal(@UserIdInt int userId, @NonNull String packageName) { if (DEBUG) Log.i(TAG, "onPackageAddedInternal() u" + userId + "/" + packageName); // TODO(b/314992577): Retroactively grant roles for restored associations } // Revoke associations if the selfManaged companion device does not connect for 3 months. void removeInactiveSelfManagedAssociations() { final long currentTime = System.currentTimeMillis(); Loading Loading @@ -1052,13 +1061,14 @@ public class CompanionDeviceManagerService extends SystemService { @Override public byte[] getBackupPayload(int userId) { // TODO(b/286124853): back up CDM data return new byte[0]; Log.i(TAG, "getBackupPayload() userId=" + userId); return mBackupRestoreProcessor.getBackupPayload(userId); } @Override public void applyRestoredPayload(byte[] payload, int userId) { // TODO(b/286124853): restore CDM data Log.i(TAG, "applyRestoredPayload() userId=" + userId); mBackupRestoreProcessor.applyRestoredPayload(payload, userId); } @Override Loading @@ -1067,7 +1077,8 @@ public class CompanionDeviceManagerService extends SystemService { @NonNull String[] args) { return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, mAssociationRequestsProcessor) mSystemDataTransferProcessor, mAssociationRequestsProcessor, mBackupRestoreProcessor) .exec(this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args); } Loading Loading @@ -1499,6 +1510,11 @@ public class CompanionDeviceManagerService extends SystemService { public void onPackageModified(String packageName) { onPackageModifiedInternal(getChangingUserId(), packageName); } @Override public void onPackageAdded(String packageName, int uid) { onPackageAddedInternal(getChangingUserId(), packageName); } }; static int getFirstAssociationIdForUser(@UserIdInt int userId) { Loading