• 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.cobalt.data;
18 
19 import androidx.annotation.NonNull;
20 import androidx.room.ColumnInfo;
21 import androidx.room.Dao;
22 import androidx.room.Embedded;
23 import androidx.room.Insert;
24 import androidx.room.MapInfo;
25 import androidx.room.OnConflictStrategy;
26 import androidx.room.Query;
27 
28 import com.android.internal.annotations.VisibleForTesting;
29 
30 import com.google.auto.value.AutoValue;
31 import com.google.auto.value.AutoValue.CopyAnnotations;
32 import com.google.cobalt.AggregateValue;
33 import com.google.cobalt.SystemProfile;
34 import com.google.cobalt.UnencryptedObservationBatch;
35 
36 import java.time.Instant;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Optional;
40 
41 /** Data Access Object offering database operations only required in tests. */
42 @Dao
43 @VisibleForTesting
44 public abstract class TestOnlyDao {
45 
46     /** Helper class for retrieving rows of the AggregateStore table. */
47     @AutoValue
48     @CopyAnnotations
49     public abstract static class AggregateStoreTableRow {
50         /** Get a builder for the row. */
builder()51         public static Builder builder() {
52             return new AutoValue_TestOnlyDao_AggregateStoreTableRow.Builder();
53         }
54 
55         /** Builder class for creating an AggregateStoreTableRow. */
56         @AutoValue.Builder
57         public abstract static class Builder {
58             /** Set the report key for the row. */
setReportKey(ReportKey reportKey)59             public abstract Builder setReportKey(ReportKey reportKey);
60 
61             /** Set the event vector for the row. */
setEventVector(EventVector value)62             public abstract Builder setEventVector(EventVector value);
63 
64             /** Set the system profile for the row. */
setSystemProfile(SystemProfile value)65             public abstract Builder setSystemProfile(SystemProfile value);
66 
67             /** Set the day index for the row. */
setDayIndex(int value)68             public abstract Builder setDayIndex(int value);
69 
70             /** Set the aggregate value for the row. */
setAggregateValue(AggregateValue value)71             public abstract Builder setAggregateValue(AggregateValue value);
72 
73             /** Build the row. */
build()74             public abstract AggregateStoreTableRow build();
75         }
76 
77         /** Create a new row. */
create( ReportKey reportKey, int dayIndex, EventVector eventVector, SystemProfile systemProfile, AggregateValue aggregateValue)78         public static AggregateStoreTableRow create(
79                 ReportKey reportKey,
80                 int dayIndex,
81                 EventVector eventVector,
82                 SystemProfile systemProfile,
83                 AggregateValue aggregateValue) {
84             return builder()
85                     .setReportKey(reportKey)
86                     .setDayIndex(dayIndex)
87                     .setEventVector(eventVector)
88                     .setSystemProfile(systemProfile)
89                     .setAggregateValue(aggregateValue)
90                     .build();
91         }
92 
93         /** Get the report key of the row. */
94         @CopyAnnotations
95         @Embedded
96         @NonNull
reportKey()97         public abstract ReportKey reportKey();
98 
99         /** Get the event vector of the row. */
100         @CopyAnnotations
101         @ColumnInfo(name = "event_vector")
102         @NonNull
eventVector()103         public abstract EventVector eventVector();
104 
105         /** Get the system profile of the row. */
106         @CopyAnnotations
107         @ColumnInfo(name = "system_profile")
108         @NonNull
systemProfile()109         public abstract SystemProfile systemProfile();
110 
111         /** Get the day index of the row. */
112         @CopyAnnotations
113         @ColumnInfo(name = "day_index")
dayIndex()114         public abstract int dayIndex();
115 
116         /** Get the aggregate value of the row. */
117         @CopyAnnotations
118         @ColumnInfo(name = "aggregate_value")
119         @NonNull
aggregateValue()120         public abstract AggregateValue aggregateValue();
121     }
122 
123     /** Get all the aggregate data from the database. */
124     @Query(
125             "SELECT customer_id, project_id, metric_id, report_id, day_index, event_vector, "
126                     + "system_profile, aggregate_value FROM AggregateStore INNER JOIN "
127                     + "SystemProfiles ON AggregateStore.system_profile_hash = SystemProfiles"
128                     + ".system_profile_hash "
129                     + "ORDER BY customer_id, project_id, metric_id, report_id, day_index, "
130                     + "event_vector, AggregateStore.system_profile_hash, aggregate_value")
getAllAggregates()131     public abstract List<AggregateStoreTableRow> getAllAggregates();
132 
133     /** Insert and aggregate value row. */
insertAggregateValue(AggregateStoreTableRow aggregateStoreTableRow)134     public void insertAggregateValue(AggregateStoreTableRow aggregateStoreTableRow) {
135         long systemProfileHash =
136                 SystemProfileEntity.getSystemProfileHash(aggregateStoreTableRow.systemProfile());
137         insertLastSentDayIndex(ReportEntity.create(aggregateStoreTableRow.reportKey()));
138         insertSystemProfile(
139                 SystemProfileEntity.create(
140                         systemProfileHash, aggregateStoreTableRow.systemProfile()));
141         insertAggregateValue(
142                 AggregateStoreEntity.create(
143                         aggregateStoreTableRow.reportKey(),
144                         aggregateStoreTableRow.dayIndex(),
145                         aggregateStoreTableRow.eventVector(),
146                         systemProfileHash,
147                         aggregateStoreTableRow.aggregateValue()));
148     }
149 
150     /**
151      * Insert the day a report was last sent.
152      *
153      * @param reportKey the report
154      * @param dayIndex the day
155      */
156     @Insert(onConflict = OnConflictStrategy.IGNORE)
insertLastSentDayIndex(ReportKey reportKey, int dayIndex)157     public Void insertLastSentDayIndex(ReportKey reportKey, int dayIndex) {
158         return insertLastSentDayIndex(ReportEntity.create(reportKey, dayIndex));
159     }
160 
161     @Insert(onConflict = OnConflictStrategy.IGNORE)
insertLastSentDayIndex(ReportEntity reportEntity)162     abstract Void insertLastSentDayIndex(ReportEntity reportEntity);
163 
164     @Insert(onConflict = OnConflictStrategy.IGNORE)
insertSystemProfile(SystemProfileEntity systemProfileEntity)165     abstract Void insertSystemProfile(SystemProfileEntity systemProfileEntity);
166 
167     @Insert(onConflict = OnConflictStrategy.ROLLBACK)
insertAggregateValue(AggregateStoreEntity aggregateStoreEntity)168     abstract Void insertAggregateValue(AggregateStoreEntity aggregateStoreEntity);
169 
170     /** Get the time Cobalt was enabled. */
getInitialEnabledTime()171     public Optional<Instant> getInitialEnabledTime() {
172         return Optional.ofNullable(
173                         queryEnablementTimes().get(GlobalValueEntity.Key.INITIAL_ENABLED_TIME))
174                 .map(GlobalValueEntity::timeFromDbString);
175     }
176 
177     /** Get the time Cobalt was disabled. */
getStartDisabledTime()178     public Optional<Instant> getStartDisabledTime() {
179         return Optional.ofNullable(
180                         queryEnablementTimes().get(GlobalValueEntity.Key.INITIAL_DISABLED_TIME))
181                 .map(GlobalValueEntity::timeFromDbString);
182     }
183 
184     @MapInfo(keyColumn = "key", valueColumn = "value")
185     @Query(
186             "SELECT * FROM GlobalValues WHERE key IN ('INITIAL_ENABLED_TIME',"
187                     + " 'INITIAL_DISABLED_TIME')")
queryEnablementTimes()188     abstract Map<GlobalValueEntity.Key, String> queryEnablementTimes();
189 
190     /**
191      * Return the day a report was last sent, if in the reports table.
192      *
193      * @param reportKey the report
194      * @return the last sent day index, if found
195      */
queryLastSentDayIndex(ReportKey reportKey)196     public Optional<Integer> queryLastSentDayIndex(ReportKey reportKey) {
197         return queryLastSentDayIndex(
198                 reportKey.customerId(),
199                 reportKey.projectId(),
200                 reportKey.metricId(),
201                 reportKey.reportId());
202     }
203 
204     /**
205      * Return the day a report was last sent, if in the reports table.
206      *
207      * @param customerId the customer id for the report
208      * @param projectId the project id for the report
209      * @param metricId the metric id for the report
210      * @param reportId the report id for the report
211      * @return the last sent day index, if found
212      */
213     @Query(
214             "SELECT last_sent_day_index "
215                     + "FROM Reports "
216                     + "WHERE customer_id = :customerId "
217                     + "AND project_id = :projectId "
218                     + "AND metric_id = :metricId "
219                     + "AND report_id = :reportId")
queryLastSentDayIndex( long customerId, long projectId, long metricId, long reportId)220     abstract Optional<Integer> queryLastSentDayIndex(
221             long customerId, long projectId, long metricId, long reportId);
222 
223     /** Delete all reports from the report store. */
224     @VisibleForTesting
225     @Query("DELETE FROM Reports")
deleteAllReports()226     public abstract void deleteAllReports();
227 
228     /** Get all the repory keys in the report store. */
229     @VisibleForTesting
230     @Query("SELECT customer_id, project_id, metric_id, report_id FROM Reports")
getReportKeys()231     public abstract List<ReportKey> getReportKeys();
232 
233     /** Get all the unencrypted observation batches in the observation store. */
234     @VisibleForTesting
235     @Query("SELECT unencrypted_observation_batch FROM ObservationStore")
getObservationBatches()236     public abstract List<UnencryptedObservationBatch> getObservationBatches();
237 
238     /** Get all the report ids in the aggregate store. */
239     @VisibleForTesting
240     @Query("SELECT report_id from AggregateStore")
getAggregatedReportIds()241     public abstract List<Integer> getAggregatedReportIds();
242 
243     /** Get all the day indices in the aggregate store. */
244     @VisibleForTesting
245     @Query("SELECT day_index from AggregateStore")
getDayIndices()246     public abstract List<Integer> getDayIndices();
247 
248     /** Get all string hashes in the string hash store. */
249     @VisibleForTesting
250     @Query("SELECT * FROM StringHashes")
getStringHashes()251     public abstract List<StringHashEntity> getStringHashes();
252 
253     /** Gets all system profiles from the system profile table. */
254     @VisibleForTesting
255     @Query("SELECT * FROM SystemProfiles")
getSystemProfiles()256     public abstract List<SystemProfileEntity> getSystemProfiles();
257 }
258