diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java index ef3aa7fea1b54..3c8c3cb8f8420 100644 --- a/services/companion/java/com/android/server/companion/PersistentDataStore.java +++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java @@ -67,17 +67,20 @@ import java.util.concurrent.ConcurrentMap; * The class responsible for persisting Association records and other related information (such as * previously used IDs) to a disk, and reading the data back from the disk. * - * Before Android T the data was stored to `companion_device_manager_associations.xml` file in - * {@link Environment#getUserSystemDirectory(int)} - * (eg. `/data/system/users/0/companion_device_manager_associations.xml`) - * @see #getBaseLegacyStorageFileForUser(int) + *
+ * Before Android T the data was stored in "companion_device_manager_associations.xml" file in + * {@link Environment#getUserSystemDirectory(int) /data/system/user/}. * - * Before Android T the data was stored using the v0 schema. + * See {@link #getBaseLegacyStorageFileForUser(int) getBaseLegacyStorageFileForUser()}. * - * @see #readAssociationsV0(TypedXmlPullParser, int, Collection) - * @see #readAssociationV0(TypedXmlPullParser, int, int, Collection) + *
+ * Before Android T the data was stored using the v0 schema. See: + *
{@code
*
*
* }
*
+ * + * Since Android T the data is stored to "companion_device_manager.xml" file in + * {@link Environment#getDataSystemDeDirectory(int) /data/system_de/}. * - * Since Android T the data is stored to `companion_device_manager.xml` file in - * {@link Environment#getDataSystemDeDirectory(int)}. - * (eg. `/data/system_de/0/companion_device_manager.xml`) - * @see #getBaseStorageFileForUser(int) - + * See {@link #getBaseStorageFileForUser(int) getBaseStorageFileForUser()} + * + *
* Since Android T the data is stored using the v1 schema. - * In the v1 schema, a list of the previously used IDs is storead along with the association + * + * In the v1 schema, a list of the previously used IDs is stored along with the association * records. - * V1 schema adds a new optional `display_name` attribute, and makes the `mac_address` attribute + * + * V1 schema adds a new optional "display_name" attribute, and makes the "mac_address" attribute * optional. + *
{@code
*
*
@@ -206,6 +213,8 @@ final class PersistentDataStore {
final AtomicFile file = getStorageFileForUser(userId);
if (DEBUG) Slog.d(LOG_TAG, " > File=" + file.getBaseFile().getPath());
+ // getStorageFileForUser() ALWAYS returns the SAME OBJECT, which allows us to synchronize
+ // accesses to the file on the file system using this AtomicFile object.
synchronized (file) {
File legacyBaseFile = null;
final AtomicFile readFrom;
@@ -269,6 +278,8 @@ final class PersistentDataStore {
final AtomicFile file = getStorageFileForUser(userId);
if (DEBUG) Slog.d(LOG_TAG, " > File=" + file.getBaseFile().getPath());
+ // getStorageFileForUser() ALWAYS returns the SAME OBJECT, which allows us to synchronize
+ // accesses to the file on the file system using this AtomicFile object.
synchronized (file) {
persistStateToFileLocked(file, associations, previouslyUsedIdsPerPackage);
}
@@ -329,6 +340,13 @@ final class PersistentDataStore {
});
}
+ /**
+ * Creates and caches {@link AtomicFile} object that represents the back-up file for the given
+ * user.
+ *
+ * IMPORTANT: the method will ALWAYS return the same {@link AtomicFile} object, which makes it
+ * possible to synchronize reads and writes to the file using the returned object.
+ */
private @NonNull AtomicFile getStorageFileForUser(@UserIdInt int userId) {
return mUserIdToStorageFile.computeIfAbsent(userId,
u -> new AtomicFile(getBaseStorageFileForUser(userId)));