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.adservices.service.customaudience; 18 19 import static android.adservices.common.AdFilters.APP_INSTALL_FIELD_NAME; 20 import static android.adservices.common.AdFilters.FREQUENCY_CAP_FIELD_NAME; 21 22 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.AD_COUNTERS_KEY; 23 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.AD_FILTERS_KEY; 24 25 import android.adservices.common.AdFilters; 26 import android.adservices.common.AppInstallFilters; 27 import android.adservices.common.FrequencyCapFilters; 28 29 import com.android.adservices.LoggerFactory; 30 import com.android.adservices.data.common.DBAdData; 31 32 import org.json.JSONArray; 33 import org.json.JSONException; 34 import org.json.JSONObject; 35 36 import java.util.HashSet; 37 import java.util.Set; 38 /** Factory for ReadFiltersFromJsonStrategys */ 39 public class ReadFiltersFromJsonStrategyFactory { 40 private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); 41 42 private static class FilteringEnabledStrategy implements ReadFiltersFromJsonStrategy { 43 private final ReadFrequencyCapFiltersFromJsonStrategy 44 mReadFrequencyCapFiltersFromJsonStrategy; 45 private final ReadAppInstallFiltersFromJsonStrategy mReadAppInstallFiltersFromJsonStrategy; 46 FilteringEnabledStrategy( boolean frequencyCapFilteringEnabled, boolean appInstallFilteringEnabled)47 FilteringEnabledStrategy( 48 boolean frequencyCapFilteringEnabled, boolean appInstallFilteringEnabled) { 49 if (frequencyCapFilteringEnabled) { 50 mReadFrequencyCapFiltersFromJsonStrategy = 51 new FrequencyCapFilteringEnabledStrategy(); 52 } else { 53 mReadFrequencyCapFiltersFromJsonStrategy = 54 new FrequencyCapFilteringDisabledStrategy(); 55 } 56 57 if (appInstallFilteringEnabled) { 58 mReadAppInstallFiltersFromJsonStrategy = new AppInstallFilteringEnabledStrategy(); 59 } else { 60 mReadAppInstallFiltersFromJsonStrategy = new AppInstallFilteringDisabledStrategy(); 61 } 62 } 63 64 /** 65 * Adds filtering fields to the provided AdData builder. 66 * 67 * @param adDataBuilder the AdData builder to modify. 68 * @param adDataJsonObj the AdData JSON to extract from 69 * @throws JSONException if the key is found but the schema is incorrect 70 * @throws NullPointerException if the key found by the field is null 71 */ 72 @Override readFilters(DBAdData.Builder adDataBuilder, JSONObject adDataJsonObj)73 public void readFilters(DBAdData.Builder adDataBuilder, JSONObject adDataJsonObj) 74 throws JSONException, NullPointerException, IllegalArgumentException { 75 mReadFrequencyCapFiltersFromJsonStrategy.readAdCounterKeys( 76 adDataJsonObj, adDataBuilder); 77 AdFilters adFilters = null; 78 if (adDataJsonObj.has(AD_FILTERS_KEY)) { 79 AdFilters.Builder builder = new AdFilters.Builder(); 80 JSONObject adFiltersObject = adDataJsonObj.getJSONObject(AD_FILTERS_KEY); 81 mReadFrequencyCapFiltersFromJsonStrategy.readFrequencyCapFilters( 82 adFiltersObject, builder); 83 mReadAppInstallFiltersFromJsonStrategy.readAppInstallFilters( 84 adFiltersObject, builder); 85 adFilters = builder.build(); 86 } 87 adDataBuilder.setAdFilters(adFilters); 88 } 89 } 90 91 private static class FilteringDisabledStrategy implements ReadFiltersFromJsonStrategy { 92 /** 93 * Does nothing. 94 * 95 * @param adDataBuilder unused 96 * @param adDataJsonObj unused 97 */ 98 @Override readFilters(DBAdData.Builder adDataBuilder, JSONObject adDataJsonObj)99 public void readFilters(DBAdData.Builder adDataBuilder, JSONObject adDataJsonObj) {} 100 } 101 102 private static class FrequencyCapFilteringEnabledStrategy 103 implements ReadFrequencyCapFiltersFromJsonStrategy { 104 105 @Override readAdCounterKeys(JSONObject json, DBAdData.Builder adDataBuilder)106 public void readAdCounterKeys(JSONObject json, DBAdData.Builder adDataBuilder) 107 throws JSONException { 108 Set<Integer> adCounterKeys = new HashSet<>(); 109 if (json.has(AD_COUNTERS_KEY)) { 110 JSONArray counterKeys = json.getJSONArray(AD_COUNTERS_KEY); 111 for (int i = 0; i < counterKeys.length(); i++) { 112 adCounterKeys.add(counterKeys.getInt(i)); 113 } 114 } 115 adDataBuilder.setAdCounterKeys(adCounterKeys); 116 } 117 118 @Override readFrequencyCapFilters(JSONObject json, AdFilters.Builder builder)119 public void readFrequencyCapFilters(JSONObject json, AdFilters.Builder builder) 120 throws JSONException { 121 if (json.has(FREQUENCY_CAP_FIELD_NAME)) { 122 builder.setFrequencyCapFilters( 123 FrequencyCapFilters.fromJson(json.getJSONObject(FREQUENCY_CAP_FIELD_NAME))); 124 } 125 } 126 } 127 128 private static class FrequencyCapFilteringDisabledStrategy 129 implements ReadFrequencyCapFiltersFromJsonStrategy { 130 131 @Override readAdCounterKeys(JSONObject json, DBAdData.Builder adDataBuilder)132 public void readAdCounterKeys(JSONObject json, DBAdData.Builder adDataBuilder) 133 throws JSONException { 134 sLogger.v("Frequency cap filtering is disabled, reading fcap filters is a no op"); 135 } 136 137 @Override readFrequencyCapFilters(JSONObject json, AdFilters.Builder builder)138 public void readFrequencyCapFilters(JSONObject json, AdFilters.Builder builder) 139 throws JSONException { 140 sLogger.v("Frequency cap filtering is disabled, reading fcap filters is a no op"); 141 } 142 } 143 144 private static class AppInstallFilteringEnabledStrategy 145 implements ReadAppInstallFiltersFromJsonStrategy { 146 147 @Override readAppInstallFilters(JSONObject json, AdFilters.Builder builder)148 public void readAppInstallFilters(JSONObject json, AdFilters.Builder builder) 149 throws JSONException { 150 if (json.has(APP_INSTALL_FIELD_NAME)) { 151 builder.setAppInstallFilters( 152 AppInstallFilters.fromJson(json.getJSONObject(APP_INSTALL_FIELD_NAME))); 153 } 154 } 155 } 156 157 private static class AppInstallFilteringDisabledStrategy 158 implements ReadAppInstallFiltersFromJsonStrategy { 159 160 @Override readAppInstallFilters(JSONObject json, AdFilters.Builder builder)161 public void readAppInstallFilters(JSONObject json, AdFilters.Builder builder) 162 throws JSONException { 163 sLogger.v("App install filtering is disabled, reading app install filters is a no op"); 164 } 165 } 166 167 /** 168 * Returns the appropriate ReadFiltersFromJsonStrategy based whether filtering is enabled 169 * 170 * @param frequencyCapFilteringEnabled Should be true if frequency cap filtering is enabled. 171 * @param appInstallFilteringEnabled Should be true if app install filtering is enabled. 172 * @return An implementation of ReadFiltersFromJsonStrategy 173 */ getStrategy( boolean frequencyCapFilteringEnabled, boolean appInstallFilteringEnabled)174 public static ReadFiltersFromJsonStrategy getStrategy( 175 boolean frequencyCapFilteringEnabled, boolean appInstallFilteringEnabled) { 176 if (frequencyCapFilteringEnabled || appInstallFilteringEnabled) { 177 return new FilteringEnabledStrategy( 178 frequencyCapFilteringEnabled, appInstallFilteringEnabled); 179 } 180 return new FilteringDisabledStrategy(); 181 } 182 } 183