• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.adservices.rollback;
18 
19 import android.annotation.NonNull;
20 import android.app.adservices.AdServicesManager;
21 import android.util.ArrayMap;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 import com.android.server.adservices.LogUtil;
25 import com.android.server.adservices.common.BooleanFileDatastore;
26 
27 import java.io.IOException;
28 import java.util.Map;
29 import java.util.Objects;
30 
31 /**
32  * Manager to store information on handling a rollback of the AdServices module. We will have one
33  * RollbackHandlingManager instance per user.
34  *
35  * @hide
36  */
37 public final class RollbackHandlingManager {
38     static final String STORAGE_XML_IDENTIFIER = "RollbackHandlingStorageIdentifier.xml";
39 
40     static final String MSMT_FILE_PREFIX = "Measurement";
41 
42     static final String DELETION_OCCURRED_KEY = "deletion_occurred";
43 
44     static final String VERSION_KEY = "adservices_version";
45 
46     private final String mDatastoreDir;
47     private final int mPackageVersion;
48 
49     private final Map<Integer, BooleanFileDatastore> mBooleanFileDatastoreMap = new ArrayMap<>();
50 
RollbackHandlingManager(@onNull String datastoreDir, int packageVersion)51     private RollbackHandlingManager(@NonNull String datastoreDir, int packageVersion) {
52         Objects.requireNonNull(datastoreDir);
53 
54         mDatastoreDir = datastoreDir;
55         mPackageVersion = packageVersion;
56     }
57 
58     /** Create a RollbackHandlingManager with base directory and for userIdentifier */
59     @NonNull
createRollbackHandlingManager( @onNull String baseDir, int userIdentifier, int packageVersion)60     public static RollbackHandlingManager createRollbackHandlingManager(
61             @NonNull String baseDir, int userIdentifier, int packageVersion) throws IOException {
62         Objects.requireNonNull(baseDir, "Base dir must be provided.");
63 
64         // The data store is in the directore with the following path:
65         // /data/system/adservices/{user_id}/rollback/
66         String rollbackHandlingDataStoreDir =
67                 RollbackHandlingDatastoreLocationHelper.getRollbackHandlingDataStoreDirAndCreateDir(
68                         baseDir, userIdentifier);
69 
70         return new RollbackHandlingManager(rollbackHandlingDataStoreDir, packageVersion);
71     }
72 
73     @VisibleForTesting
getOrCreateBooleanFileDatastore( @dServicesManager.DeletionApiType int deletionApiType)74     BooleanFileDatastore getOrCreateBooleanFileDatastore(
75             @AdServicesManager.DeletionApiType int deletionApiType) throws IOException {
76         synchronized (this) {
77             BooleanFileDatastore datastore = mBooleanFileDatastoreMap.get(deletionApiType);
78             if (datastore == null) {
79                 if (deletionApiType == AdServicesManager.MEASUREMENT_DELETION) {
80                     datastore =
81                             new BooleanFileDatastore(
82                                     mDatastoreDir,
83                                     MSMT_FILE_PREFIX + STORAGE_XML_IDENTIFIER,
84                                     mPackageVersion,
85                                     VERSION_KEY);
86                 }
87                 mBooleanFileDatastoreMap.put(deletionApiType, datastore);
88                 datastore.initialize();
89             }
90             return datastore;
91         }
92     }
93 
94     /** Saves that a deletion of AdServices data occurred to the storage. */
recordAdServicesDataDeletion(@dServicesManager.DeletionApiType int deletionType)95     public void recordAdServicesDataDeletion(@AdServicesManager.DeletionApiType int deletionType)
96             throws IOException {
97         BooleanFileDatastore datastore = getOrCreateBooleanFileDatastore(deletionType);
98         synchronized (this) {
99             try {
100                 datastore.put(DELETION_OCCURRED_KEY, /* value */ true);
101             } catch (IOException e) {
102                 LogUtil.e(e, "Record deletion failed due to IOException thrown by Datastore.");
103             }
104         }
105     }
106 
107     /** Returns information about whether a deletion of AdServices data occurred. */
wasAdServicesDataDeleted(@dServicesManager.DeletionApiType int deletionType)108     public boolean wasAdServicesDataDeleted(@AdServicesManager.DeletionApiType int deletionType)
109             throws IOException {
110         BooleanFileDatastore datastore = getOrCreateBooleanFileDatastore(deletionType);
111         synchronized (this) {
112             return datastore.get(DELETION_OCCURRED_KEY, /* defaultValue */ false);
113         }
114     }
115 
116     /** Returns the previous version number saved in the datastore file. */
getPreviousStoredVersion(@dServicesManager.DeletionApiType int deletionType)117     public int getPreviousStoredVersion(@AdServicesManager.DeletionApiType int deletionType)
118             throws IOException {
119         BooleanFileDatastore datastore = getOrCreateBooleanFileDatastore(deletionType);
120         return datastore.getPreviousStoredVersion();
121     }
122 
123     /**
124      * Deletes the previously stored information about whether a deletion of AdServices data
125      * occurred.
126      */
resetAdServicesDataDeletion(@dServicesManager.DeletionApiType int deletionType)127     public void resetAdServicesDataDeletion(@AdServicesManager.DeletionApiType int deletionType)
128             throws IOException {
129         BooleanFileDatastore datastore = getOrCreateBooleanFileDatastore(deletionType);
130         synchronized (this) {
131             try {
132                 datastore.put(DELETION_OCCURRED_KEY, /* value */ false);
133             } catch (IOException e) {
134                 LogUtil.e(
135                         e, "Reset deletion status failed due to IOException thrown by Datastore.");
136             }
137         }
138     }
139 
140     /** tesrDown method used for testing only. */
141     @VisibleForTesting
tearDownForTesting()142     public void tearDownForTesting() {
143         synchronized (this) {
144             mBooleanFileDatastoreMap.clear();
145         }
146     }
147 }
148