1 /* 2 * Copyright (C) 2022 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.adservices.service.measurement.aggregation; 18 19 import android.annotation.Nullable; 20 21 import com.android.adservices.service.Flags; 22 import com.android.adservices.service.measurement.FilterMap; 23 import com.android.adservices.service.measurement.util.Filter; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 import java.util.Objects; 28 import java.util.Optional; 29 30 /** 31 * POJO for AggregatableAttributionTrigger. 32 */ 33 public class AggregatableAttributionTrigger { 34 35 private List<AggregateTriggerData> mTriggerData; 36 @Nullable private List<AggregatableNamedBudget> mNamedBudgets; 37 @Nullable private List<AggregatableValuesConfig> mValueConfigs; 38 private Optional<List<AggregateDeduplicationKey>> mAggregateDeduplicationKeys; 39 AggregatableAttributionTrigger()40 private AggregatableAttributionTrigger() { 41 mTriggerData = new ArrayList<>(); 42 } 43 44 @Override equals(Object obj)45 public boolean equals(Object obj) { 46 if (!(obj instanceof AggregatableAttributionTrigger)) { 47 return false; 48 } 49 AggregatableAttributionTrigger attributionTrigger = (AggregatableAttributionTrigger) obj; 50 return Objects.equals(mTriggerData, attributionTrigger.mTriggerData) 51 && Objects.equals(mValueConfigs, attributionTrigger.mValueConfigs) 52 && Objects.equals(mNamedBudgets, attributionTrigger.mNamedBudgets); 53 } 54 55 @Override hashCode()56 public int hashCode() { 57 return Objects.hash(mTriggerData, mNamedBudgets, mValueConfigs); 58 } 59 60 /** 61 * Returns all trigger_data which define individual conversion data that we want to add to 62 * the conversion side aggregation key. 63 */ getTriggerData()64 public List<AggregateTriggerData> getTriggerData() { 65 return mTriggerData; 66 } 67 68 /** 69 * Returns a list of AggregatableValuesConfig that contains values, filters, and not_filters for 70 * each aggregatable_source. 71 */ 72 @Nullable getValueConfigs()73 public List<AggregatableValuesConfig> getValueConfigs() { 74 return mValueConfigs; 75 } 76 77 /** Returns De-deuplication keys for Aggregate Report Creation. */ getAggregateDeduplicationKeys()78 public Optional<List<AggregateDeduplicationKey>> getAggregateDeduplicationKeys() { 79 return mAggregateDeduplicationKeys; 80 } 81 82 /** 83 * Returns a list of AggregatableNamedBudget that contains name, filters, and not_filters for 84 * each budget. 85 */ 86 @Nullable getNamedBudgets()87 public List<AggregatableNamedBudget> getNamedBudgets() { 88 return mNamedBudgets; 89 } 90 91 /** 92 * Extract an {@link AggregateDeduplicationKey} from the aggregateDeduplicationKeys. 93 * 94 * @param sourceFilterMap the source filter map of the AggregatableAttributionSource. 95 */ maybeExtractDedupKey( FilterMap sourceFilterMap, Flags flags)96 public Optional<AggregateDeduplicationKey> maybeExtractDedupKey( 97 FilterMap sourceFilterMap, Flags flags) { 98 if (getAggregateDeduplicationKeys().isEmpty()) return Optional.empty(); 99 100 Filter filter = new Filter(flags); 101 for (AggregateDeduplicationKey key : getAggregateDeduplicationKeys().get()) { 102 if (sourceFilterMap.isEmpty(flags)) { 103 return Optional.of(key); 104 } 105 if (key.getFilterSet().isPresent() 106 && !filter.isFilterMatch(sourceFilterMap, key.getFilterSet().get(), true)) { 107 continue; 108 } 109 110 if (key.getNotFilterSet().isPresent() 111 && !filter.isFilterMatch(sourceFilterMap, key.getNotFilterSet().get(), false)) { 112 continue; 113 } 114 if (key.getDeduplicationKey().isEmpty()) { 115 return Optional.empty(); 116 } 117 return Optional.of(key); 118 } 119 return Optional.empty(); 120 } 121 122 /** 123 * Extract the value for key "name" from the {@link AggregatableNamedBudget} 124 * aggregatableNamedBudget. 125 * 126 * @param sourceFilterMap the source filter map of the AggregatableAttributionSource. 127 */ maybeExtractNamedBudget(FilterMap sourceFilterMap, Flags flags)128 public Optional<String> maybeExtractNamedBudget(FilterMap sourceFilterMap, Flags flags) { 129 if (getNamedBudgets() == null || getNamedBudgets().isEmpty()) { 130 return Optional.empty(); 131 } 132 133 if (sourceFilterMap.isEmpty(flags)) { 134 return Optional.of(getNamedBudgets().get(0).getName()); 135 } 136 Filter filter = new Filter(flags); 137 for (AggregatableNamedBudget aggregatableNamedBudget : getNamedBudgets()) { 138 if (aggregatableNamedBudget.getFilterSet() != null 139 && !filter.isFilterMatch( 140 sourceFilterMap, 141 aggregatableNamedBudget.getFilterSet(), 142 /* isFilter= */ true)) { 143 continue; 144 } 145 146 if (aggregatableNamedBudget.getNotFilterSet() != null 147 && !filter.isFilterMatch( 148 sourceFilterMap, 149 aggregatableNamedBudget.getNotFilterSet(), 150 /* isFilter= */ false)) { 151 continue; 152 } 153 return Optional.of(aggregatableNamedBudget.getName()); 154 } 155 return Optional.empty(); 156 } 157 158 /** 159 * Builder for {@link AggregatableAttributionTrigger}. 160 */ 161 public static final class Builder { 162 private final AggregatableAttributionTrigger mBuilding; 163 Builder()164 public Builder() { 165 mBuilding = new AggregatableAttributionTrigger(); 166 } 167 168 /** 169 * See {@link AggregatableAttributionTrigger#getTriggerData()}. 170 */ setTriggerData(List<AggregateTriggerData> triggerData)171 public Builder setTriggerData(List<AggregateTriggerData> triggerData) { 172 mBuilding.mTriggerData = triggerData; 173 return this; 174 } 175 176 /** See {@link AggregatableAttributionTrigger#getValueConfigs()}. */ setValueConfigs(@ullable List<AggregatableValuesConfig> mValueConfigs)177 public Builder setValueConfigs(@Nullable List<AggregatableValuesConfig> mValueConfigs) { 178 mBuilding.mValueConfigs = mValueConfigs; 179 return this; 180 } 181 182 /** See {@link AggregatableAttributionTrigger#getAggregateDeduplicationKeys()}. */ setAggregateDeduplicationKeys(List<AggregateDeduplicationKey> keys)183 public Builder setAggregateDeduplicationKeys(List<AggregateDeduplicationKey> keys) { 184 mBuilding.mAggregateDeduplicationKeys = Optional.of(keys); 185 return this; 186 } 187 188 /** See {@link AggregatableAttributionTrigger#getNamedBudgets()} ()} ()}. */ setNamedBudgets(List<AggregatableNamedBudget> namedBudgets)189 public Builder setNamedBudgets(List<AggregatableNamedBudget> namedBudgets) { 190 mBuilding.mNamedBudgets = namedBudgets; 191 return this; 192 } 193 194 /** 195 * Build the {@link AggregatableAttributionTrigger}. 196 */ build()197 public AggregatableAttributionTrigger build() { 198 return mBuilding; 199 } 200 } 201 } 202