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.observations;
18 
19 import static java.util.Objects.requireNonNull;
20 
21 import android.annotation.NonNull;
22 
23 import com.android.cobalt.data.EventVector;
24 
25 import com.google.cobalt.AggregateValue;
26 import com.google.cobalt.MetricDefinition;
27 import com.google.cobalt.PrivateIndexObservation;
28 import com.google.cobalt.ReportDefinition;
29 
30 import java.security.SecureRandom;
31 
32 /**
33  * Encodes an integer event as an {@link PrivateIndexObservation}.
34  *
35  * <p>Note, this encoder expects input {@link AggregateValue} objects to have an inner integer value
36  * set and will use 0 if not.
37  */
38 final class PrivateIntegerEncoder implements PrivateObservationGenerator.Encoder {
39     private final MetricDefinition mMetric;
40     private final ReportDefinition mReport;
41     private final SecureRandom mSecureRandom;
42 
PrivateIntegerEncoder( @onNull SecureRandom secureRandom, @NonNull MetricDefinition metric, @NonNull ReportDefinition report)43     PrivateIntegerEncoder(
44             @NonNull SecureRandom secureRandom,
45             @NonNull MetricDefinition metric,
46             @NonNull ReportDefinition report) {
47         this.mSecureRandom = requireNonNull(secureRandom);
48         this.mMetric = requireNonNull(metric);
49         this.mReport = requireNonNull(report);
50     }
51 
52     /**
53      * Encodes one event and aggregated value as a single private observation.
54      *
55      * @param eventVector the event vector to encode
56      * @param aggregateValue the aggregated value to encode
57      * @return the privacy encoded observation
58      */
59     @Override
encode(EventVector eventVector, AggregateValue aggregateValue)60     public PrivateIndexObservation encode(EventVector eventVector, AggregateValue aggregateValue) {
61         int maxEventVectorIndex =
62                 PrivateIndexCalculations.getNumEventVectors(mMetric.getMetricDimensionsList()) - 1;
63         int eventVectorIndex = PrivateIndexCalculations.eventVectorToIndex(eventVector, mMetric);
64 
65         long clippedValue =
66                 PrivateIndexCalculations.clipValue(aggregateValue.getIntegerValue(), mReport);
67         int clippedValueIndex =
68                 PrivateIndexCalculations.longToIndex(
69                         clippedValue,
70                         mReport.getMinValue(),
71                         mReport.getMaxValue(),
72                         mReport.getNumIndexPoints(),
73                         mSecureRandom);
74         int privateIndex =
75                 PrivateIndexCalculations.valueAndEventVectorIndicesToIndex(
76                         clippedValueIndex, eventVectorIndex, maxEventVectorIndex);
77         return PrivateIndexObservation.newBuilder().setIndex(privateIndex).build();
78     }
79 }
80