Loading services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +4 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import static android.os.UserHandle.getCallingUserId; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.Preconditions.checkState; import static com.android.server.companion.association.DisassociationProcessor.REASON_API; import static com.android.server.companion.association.DisassociationProcessor.REASON_PKG_DATA_CLEARED; import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage; Loading Loading @@ -250,7 +252,7 @@ public class CompanionDeviceManagerService extends SystemService { + packageName + "]. Cleaning up CDM data..."); for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED); } mCompanionAppBinder.onPackageChanged(userId); Loading Loading @@ -426,7 +428,7 @@ public class CompanionDeviceManagerService extends SystemService { @Override public void disassociate(int associationId) { mDisassociationProcessor.disassociate(associationId); mDisassociationProcessor.disassociate(associationId, REASON_API); } @Override Loading services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +4 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.companion; import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC; import static com.android.server.companion.association.DisassociationProcessor.REASON_SHELL; import android.companion.AssociationInfo; import android.companion.ContextSyncMessage; import android.companion.Flags; Loading Loading @@ -122,7 +124,7 @@ class CompanionDeviceShellCommand extends ShellCommand { if (association == null) { out.println("Association doesn't exist."); } else { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL); } } break; Loading @@ -132,7 +134,7 @@ class CompanionDeviceShellCommand extends ShellCommand { final List<AssociationInfo> userAssociations = mAssociationStore.getAssociationsByUser(userId); for (AssociationInfo association : userAssociations) { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL); } } break; Loading services/companion/java/com/android/server/companion/association/AssociationDiskStore.java +42 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; Loading Loading @@ -164,6 +165,7 @@ public final class AssociationDiskStore { private static final String FILE_NAME_LEGACY = "companion_device_manager_associations.xml"; private static final String FILE_NAME = "companion_device_manager.xml"; private static final String FILE_NAME_LAST_REMOVED_ASSOCIATION = "last_removed_association.txt"; private static final String XML_TAG_STATE = "state"; private static final String XML_TAG_ASSOCIATIONS = "associations"; Loading Loading @@ -268,6 +270,46 @@ public final class AssociationDiskStore { } } /** * Read the last removed association from disk. */ public String readLastRemovedAssociation(@UserIdInt int userId) { final AtomicFile file = createStorageFileForUser( userId, FILE_NAME_LAST_REMOVED_ASSOCIATION); StringBuilder sb = new StringBuilder(); int c; try (FileInputStream fis = file.openRead()) { while ((c = fis.read()) != -1) { sb.append((char) c); } fis.close(); return sb.toString(); } catch (FileNotFoundException e) { Slog.e(TAG, "File " + file + " for user=" + userId + " doesn't exist."); return null; } catch (IOException e) { Slog.e(TAG, "Can't read file " + file + " for user=" + userId); return null; } } /** * Write the last removed association to disk. */ public void writeLastRemovedAssociation(AssociationInfo association, String reason) { Slog.i(TAG, "Writing last removed association=" + association.getId() + " to disk..."); final AtomicFile file = createStorageFileForUser( association.getUserId(), FILE_NAME_LAST_REMOVED_ASSOCIATION); writeToFileSafely(file, out -> { out.write(String.valueOf(System.currentTimeMillis()).getBytes()); out.write(' '); out.write(reason.getBytes()); out.write(' '); out.write(association.toString().getBytes()); }); } @NonNull private static Associations readAssociationsFromFile(@UserIdInt int userId, @NonNull AtomicFile file, @NonNull String rootTag) { Loading services/companion/java/com/android/server/companion/association/AssociationStore.java +11 −1 Original line number Diff line number Diff line Loading @@ -276,7 +276,7 @@ public class AssociationStore { /** * Remove an association. */ public void removeAssociation(int id) { public void removeAssociation(int id, String reason) { Slog.i(TAG, "Removing association id=[" + id + "]..."); final AssociationInfo association; Loading @@ -291,6 +291,8 @@ public class AssociationStore { writeCacheToDisk(association.getUserId()); mDiskStore.writeLastRemovedAssociation(association, reason); Slog.i(TAG, "Done removing association."); } Loading Loading @@ -525,6 +527,14 @@ public class AssociationStore { out.append(" ").append(a.toString()).append('\n'); } } out.append("Last Removed Association:\n"); for (UserInfo user : mUserManager.getAliveUsers()) { String lastRemovedAssociation = mDiskStore.readLastRemovedAssociation(user.id); if (lastRemovedAssociation != null) { out.append(" ").append(lastRemovedAssociation).append('\n'); } } } private void broadcastChange(@ChangeType int changeType, AssociationInfo association) { Loading services/companion/java/com/android/server/companion/association/DisassociationProcessor.java +14 −7 Original line number Diff line number Diff line Loading @@ -47,6 +47,13 @@ import com.android.server.companion.transport.CompanionTransportManager; @SuppressLint("LongLogTag") public class DisassociationProcessor { public static final String REASON_REVOKED = "revoked"; public static final String REASON_SELF_IDLE = "self-idle"; public static final String REASON_SHELL = "shell"; public static final String REASON_LEGACY = "legacy"; public static final String REASON_API = "api"; public static final String REASON_PKG_DATA_CLEARED = "pkg-data-cleared"; private static final String TAG = "CDM_DisassociationProcessor"; private static final String SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW = Loading Loading @@ -94,7 +101,7 @@ public class DisassociationProcessor { * Disassociate an association by id. */ // TODO: also revoke notification access public void disassociate(int id) { public void disassociate(int id, String reason) { Slog.i(TAG, "Disassociating id=[" + id + "]..."); final AssociationInfo association = mAssociationStore.getAssociationWithCallerChecks(id); Loading Loading @@ -126,7 +133,7 @@ public class DisassociationProcessor { // Association cleanup. mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, id); mAssociationStore.removeAssociation(association.getId()); mAssociationStore.removeAssociation(association.getId(), reason); // If role is not in use by other associations, revoke the role. // Do not need to remove the system role since it was pre-granted by the system. Loading @@ -151,7 +158,7 @@ public class DisassociationProcessor { } /** * @deprecated Use {@link #disassociate(int)} instead. * @deprecated Use {@link #disassociate(int, String)} instead. */ @Deprecated public void disassociate(int userId, String packageName, String macAddress) { Loading @@ -165,7 +172,7 @@ public class DisassociationProcessor { mAssociationStore.getAssociationWithCallerChecks(association.getId()); disassociate(association.getId()); disassociate(association.getId(), REASON_LEGACY); } @SuppressLint("MissingPermission") Loading Loading @@ -223,7 +230,7 @@ public class DisassociationProcessor { Slog.i(TAG, "Removing inactive self-managed association=[" + association.toShortString() + "]."); disassociate(id); disassociate(id, REASON_SELF_IDLE); } } Loading @@ -234,7 +241,7 @@ public class DisassociationProcessor { * * Lastly remove the role holder for the revoked associations for the same packages. * * @see #disassociate(int) * @see #disassociate(int, String) */ private class OnPackageVisibilityChangeListener implements ActivityManager.OnUidImportanceListener { Loading @@ -260,7 +267,7 @@ public class DisassociationProcessor { int userId = UserHandle.getUserId(uid); for (AssociationInfo association : mAssociationStore.getRevokedAssociations(userId, packageName)) { disassociate(association.getId()); disassociate(association.getId(), REASON_REVOKED); } if (mAssociationStore.getRevokedAssociations().isEmpty()) { Loading Loading
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +4 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import static android.os.UserHandle.getCallingUserId; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.Preconditions.checkState; import static com.android.server.companion.association.DisassociationProcessor.REASON_API; import static com.android.server.companion.association.DisassociationProcessor.REASON_PKG_DATA_CLEARED; import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage; Loading Loading @@ -250,7 +252,7 @@ public class CompanionDeviceManagerService extends SystemService { + packageName + "]. Cleaning up CDM data..."); for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED); } mCompanionAppBinder.onPackageChanged(userId); Loading Loading @@ -426,7 +428,7 @@ public class CompanionDeviceManagerService extends SystemService { @Override public void disassociate(int associationId) { mDisassociationProcessor.disassociate(associationId); mDisassociationProcessor.disassociate(associationId, REASON_API); } @Override Loading
services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +4 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.companion; import static android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC; import static com.android.server.companion.association.DisassociationProcessor.REASON_SHELL; import android.companion.AssociationInfo; import android.companion.ContextSyncMessage; import android.companion.Flags; Loading Loading @@ -122,7 +124,7 @@ class CompanionDeviceShellCommand extends ShellCommand { if (association == null) { out.println("Association doesn't exist."); } else { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL); } } break; Loading @@ -132,7 +134,7 @@ class CompanionDeviceShellCommand extends ShellCommand { final List<AssociationInfo> userAssociations = mAssociationStore.getAssociationsByUser(userId); for (AssociationInfo association : userAssociations) { mDisassociationProcessor.disassociate(association.getId()); mDisassociationProcessor.disassociate(association.getId(), REASON_SHELL); } } break; Loading
services/companion/java/com/android/server/companion/association/AssociationDiskStore.java +42 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; Loading Loading @@ -164,6 +165,7 @@ public final class AssociationDiskStore { private static final String FILE_NAME_LEGACY = "companion_device_manager_associations.xml"; private static final String FILE_NAME = "companion_device_manager.xml"; private static final String FILE_NAME_LAST_REMOVED_ASSOCIATION = "last_removed_association.txt"; private static final String XML_TAG_STATE = "state"; private static final String XML_TAG_ASSOCIATIONS = "associations"; Loading Loading @@ -268,6 +270,46 @@ public final class AssociationDiskStore { } } /** * Read the last removed association from disk. */ public String readLastRemovedAssociation(@UserIdInt int userId) { final AtomicFile file = createStorageFileForUser( userId, FILE_NAME_LAST_REMOVED_ASSOCIATION); StringBuilder sb = new StringBuilder(); int c; try (FileInputStream fis = file.openRead()) { while ((c = fis.read()) != -1) { sb.append((char) c); } fis.close(); return sb.toString(); } catch (FileNotFoundException e) { Slog.e(TAG, "File " + file + " for user=" + userId + " doesn't exist."); return null; } catch (IOException e) { Slog.e(TAG, "Can't read file " + file + " for user=" + userId); return null; } } /** * Write the last removed association to disk. */ public void writeLastRemovedAssociation(AssociationInfo association, String reason) { Slog.i(TAG, "Writing last removed association=" + association.getId() + " to disk..."); final AtomicFile file = createStorageFileForUser( association.getUserId(), FILE_NAME_LAST_REMOVED_ASSOCIATION); writeToFileSafely(file, out -> { out.write(String.valueOf(System.currentTimeMillis()).getBytes()); out.write(' '); out.write(reason.getBytes()); out.write(' '); out.write(association.toString().getBytes()); }); } @NonNull private static Associations readAssociationsFromFile(@UserIdInt int userId, @NonNull AtomicFile file, @NonNull String rootTag) { Loading
services/companion/java/com/android/server/companion/association/AssociationStore.java +11 −1 Original line number Diff line number Diff line Loading @@ -276,7 +276,7 @@ public class AssociationStore { /** * Remove an association. */ public void removeAssociation(int id) { public void removeAssociation(int id, String reason) { Slog.i(TAG, "Removing association id=[" + id + "]..."); final AssociationInfo association; Loading @@ -291,6 +291,8 @@ public class AssociationStore { writeCacheToDisk(association.getUserId()); mDiskStore.writeLastRemovedAssociation(association, reason); Slog.i(TAG, "Done removing association."); } Loading Loading @@ -525,6 +527,14 @@ public class AssociationStore { out.append(" ").append(a.toString()).append('\n'); } } out.append("Last Removed Association:\n"); for (UserInfo user : mUserManager.getAliveUsers()) { String lastRemovedAssociation = mDiskStore.readLastRemovedAssociation(user.id); if (lastRemovedAssociation != null) { out.append(" ").append(lastRemovedAssociation).append('\n'); } } } private void broadcastChange(@ChangeType int changeType, AssociationInfo association) { Loading
services/companion/java/com/android/server/companion/association/DisassociationProcessor.java +14 −7 Original line number Diff line number Diff line Loading @@ -47,6 +47,13 @@ import com.android.server.companion.transport.CompanionTransportManager; @SuppressLint("LongLogTag") public class DisassociationProcessor { public static final String REASON_REVOKED = "revoked"; public static final String REASON_SELF_IDLE = "self-idle"; public static final String REASON_SHELL = "shell"; public static final String REASON_LEGACY = "legacy"; public static final String REASON_API = "api"; public static final String REASON_PKG_DATA_CLEARED = "pkg-data-cleared"; private static final String TAG = "CDM_DisassociationProcessor"; private static final String SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW = Loading Loading @@ -94,7 +101,7 @@ public class DisassociationProcessor { * Disassociate an association by id. */ // TODO: also revoke notification access public void disassociate(int id) { public void disassociate(int id, String reason) { Slog.i(TAG, "Disassociating id=[" + id + "]..."); final AssociationInfo association = mAssociationStore.getAssociationWithCallerChecks(id); Loading Loading @@ -126,7 +133,7 @@ public class DisassociationProcessor { // Association cleanup. mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, id); mAssociationStore.removeAssociation(association.getId()); mAssociationStore.removeAssociation(association.getId(), reason); // If role is not in use by other associations, revoke the role. // Do not need to remove the system role since it was pre-granted by the system. Loading @@ -151,7 +158,7 @@ public class DisassociationProcessor { } /** * @deprecated Use {@link #disassociate(int)} instead. * @deprecated Use {@link #disassociate(int, String)} instead. */ @Deprecated public void disassociate(int userId, String packageName, String macAddress) { Loading @@ -165,7 +172,7 @@ public class DisassociationProcessor { mAssociationStore.getAssociationWithCallerChecks(association.getId()); disassociate(association.getId()); disassociate(association.getId(), REASON_LEGACY); } @SuppressLint("MissingPermission") Loading Loading @@ -223,7 +230,7 @@ public class DisassociationProcessor { Slog.i(TAG, "Removing inactive self-managed association=[" + association.toShortString() + "]."); disassociate(id); disassociate(id, REASON_SELF_IDLE); } } Loading @@ -234,7 +241,7 @@ public class DisassociationProcessor { * * Lastly remove the role holder for the revoked associations for the same packages. * * @see #disassociate(int) * @see #disassociate(int, String) */ private class OnPackageVisibilityChangeListener implements ActivityManager.OnUidImportanceListener { Loading @@ -260,7 +267,7 @@ public class DisassociationProcessor { int userId = UserHandle.getUserId(uid); for (AssociationInfo association : mAssociationStore.getRevokedAssociations(userId, packageName)) { disassociate(association.getId()); disassociate(association.getId(), REASON_REVOKED); } if (mAssociationStore.getRevokedAssociations().isEmpty()) { Loading