Add backend for setAppInstallAdvertisers

Bug: 265469079
Test: atest
Change-Id: I8072811032451d262d9ed0d454a7390e4f0c29a4
diff --git a/adservices/framework/java/android/adservices/adselection/SetAppInstallAdvertisersRequest.java b/adservices/framework/java/android/adservices/adselection/SetAppInstallAdvertisersRequest.java
index ff8d1ad..5af0b8e 100644
--- a/adservices/framework/java/android/adservices/adselection/SetAppInstallAdvertisersRequest.java
+++ b/adservices/framework/java/android/adservices/adselection/SetAppInstallAdvertisersRequest.java
@@ -23,7 +23,7 @@
 import java.util.Set;
 
 /**
- * Represent input parameters to the setAppInstallAdvertiser API.
+ * Represents input parameters to the setAppInstallAdvertiser API.
  *
  * @hide
  */
diff --git a/adservices/service-core/java/com/android/adservices/data/adselection/AppInstallDao.java b/adservices/service-core/java/com/android/adservices/data/adselection/AppInstallDao.java
index 5fe051c..9181a8e 100644
--- a/adservices/service-core/java/com/android/adservices/data/adselection/AppInstallDao.java
+++ b/adservices/service-core/java/com/android/adservices/data/adselection/AppInstallDao.java
@@ -23,24 +23,17 @@
 import androidx.room.Insert;
 import androidx.room.OnConflictStrategy;
 import androidx.room.Query;
+import androidx.room.Transaction;
 
 import java.util.List;
 
 /**
- * Data access object interface for running app install related queries.
+ * Data access object abstract class for running app install related queries.
  *
  * <p>Annotation will generate Room based SQLite Dao implementation.
  */
 @Dao
-public interface AppInstallDao {
-    /**
-     * Insert new buyer, package pairs which will allow the buyer to filter on the package. If the
-     * entry already exists, nothing is inserted or changed.
-     *
-     * @param appInstalls The buyer, package pairs to insert
-     */
-    @Insert(onConflict = OnConflictStrategy.IGNORE)
-    void insertAllAppInstallPermissions(@NonNull List<DBAppInstallPermissions> appInstalls);
+public abstract class AppInstallDao {
 
     /**
      * Checks if a buyer is allowed to filter a given package.
@@ -52,7 +45,18 @@
     @Query(
             "SELECT EXISTS(SELECT 1 FROM app_install WHERE buyer = :buyer"
                     + " AND package_name = :packageName)")
-    boolean canBuyerFilterPackage(@NonNull AdTechIdentifier buyer, @NonNull String packageName);
+    public abstract boolean canBuyerFilterPackage(
+            @NonNull AdTechIdentifier buyer, @NonNull String packageName);
+
+    /**
+     * Insert new buyer, package pairs which will allow the buyer to filter on the package. If the
+     * entry already exists, nothing is inserted or changed.
+     *
+     * @param appInstalls The buyer, package pairs to insert
+     */
+    @Insert(onConflict = OnConflictStrategy.IGNORE)
+    protected abstract void insertAllAppInstallPermissions(
+            @NonNull List<DBAppInstallPermissions> appInstalls);
 
     /**
      * Removes all entries associated with a package
@@ -60,5 +64,20 @@
      * @param packageName The name of the package.
      */
     @Query("DELETE FROM app_install WHERE package_name = :packageName")
-    int deleteByPackageName(@NonNull String packageName);
+    public abstract int deleteByPackageName(@NonNull String packageName);
+
+    /**
+     * Runs deleteByPackageName on the given packagename then insertAllAppInstallPermissions on the
+     * given list of DBAppInstallPermissions in a single transaction. Note that there is no that the
+     * package/packages in the DBAppInstallPermissions match the packageName parameter.
+     *
+     * @param packageName The package name to clear all entries for
+     * @param appInstalls The DBAppInstallPermissions to insert
+     */
+    @Transaction
+    public void setAdTechsForPackage(
+            @NonNull String packageName, @NonNull List<DBAppInstallPermissions> appInstalls) {
+        deleteByPackageName(packageName);
+        insertAllAppInstallPermissions(appInstalls);
+    }
 }
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
index 1769fd3..b3ad7f7 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
@@ -244,6 +244,7 @@
                                             inputParams.getCallerPackageName(),
                                             mFlags
                                                     .getEnforceForegroundStatusForFledgeRunAdSelection(),
+                                            true,
                                             mCallerUid,
                                             AdServicesStatsLog
                                                     .AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
index 1c72298..2b9f90b 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
@@ -59,6 +59,8 @@
 import com.android.adservices.concurrency.AdServicesExecutors;
 import com.android.adservices.data.adselection.AdSelectionDatabase;
 import com.android.adservices.data.adselection.AdSelectionEntryDao;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
 import com.android.adservices.data.customaudience.CustomAudienceDao;
 import com.android.adservices.data.customaudience.CustomAudienceDatabase;
 import com.android.adservices.service.Flags;
@@ -98,6 +100,7 @@
 public class AdSelectionServiceImpl extends AdSelectionService.Stub {
 
     @NonNull private final AdSelectionEntryDao mAdSelectionEntryDao;
+    @NonNull private final AppInstallDao mAppInstallDao;
     @NonNull private final CustomAudienceDao mCustomAudienceDao;
     @NonNull private final AdServicesHttpsClient mAdServicesHttpsClient;
     @NonNull private final ExecutorService mLightweightExecutor;
@@ -118,6 +121,7 @@
     @VisibleForTesting
     public AdSelectionServiceImpl(
             @NonNull AdSelectionEntryDao adSelectionEntryDao,
+            @NonNull AppInstallDao appInstallDao,
             @NonNull CustomAudienceDao customAudienceDao,
             @NonNull AdServicesHttpsClient adServicesHttpsClient,
             @NonNull DevContextFilter devContextFilter,
@@ -132,6 +136,7 @@
             @NonNull FledgeServiceFilter fledgeServiceFilter) {
         Objects.requireNonNull(context, "Context must be provided.");
         Objects.requireNonNull(adSelectionEntryDao);
+        Objects.requireNonNull(appInstallDao);
         Objects.requireNonNull(customAudienceDao);
         Objects.requireNonNull(adServicesHttpsClient);
         Objects.requireNonNull(devContextFilter);
@@ -142,6 +147,7 @@
         Objects.requireNonNull(flags);
 
         mAdSelectionEntryDao = adSelectionEntryDao;
+        mAppInstallDao = appInstallDao;
         mCustomAudienceDao = customAudienceDao;
         mAdServicesHttpsClient = adServicesHttpsClient;
         mDevContextFilter = devContextFilter;
@@ -165,6 +171,7 @@
     private AdSelectionServiceImpl(@NonNull Context context) {
         this(
                 AdSelectionDatabase.getInstance(context).adSelectionEntryDao(),
+                SharedStorageDatabase.getInstance(context).appInstallDao(),
                 CustomAudienceDatabase.getInstance(context).customAudienceDao(),
                 new AdServicesHttpsClient(
                         AdServicesExecutors.getBlockingExecutor(),
@@ -450,9 +457,16 @@
             throw exception;
         }
 
-        // TODO(b/265469079): Add Backend, and move logging/callback to backend
-        mAdServicesLogger.logFledgeApiCallStats(apiName, STATUS_SUCCESS, 0);
-        callback.onSuccess();
+        AppInstallAdvertisersSetter setter =
+                new AppInstallAdvertisersSetter(
+                        mAppInstallDao,
+                        mBackgroundExecutor,
+                        mAdServicesLogger,
+                        mFlags,
+                        mFledgeServiceFilter,
+                        ConsentManager.getInstance(mContext),
+                        getCallingUid(apiName));
+        setter.setAppInstallAdvertisers(request, callback);
     }
 
     @Override
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdvertiserSetValidator.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdvertiserSetValidator.java
new file mode 100644
index 0000000..ebe2bf8
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdvertiserSetValidator.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.service.adselection;
+
+import android.adservices.common.AdTechIdentifier;
+import android.annotation.NonNull;
+
+import com.android.adservices.service.common.AdTechIdentifierValidator;
+import com.android.adservices.service.common.Validator;
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.google.common.collect.ImmutableCollection;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Validation utility class for {@link
+ * android.adservices.adselection.AdSelectionManager#setAppInstallAdvertisers}'s AdTechIdentifier
+ * set
+ */
+public class AdvertiserSetValidator implements Validator<Set<AdTechIdentifier>> {
+
+    @VisibleForTesting
+    public static final String SET_SHOULD_NOT_EXCEED_MAX_SIZE =
+            "The sum of the size of the AdTechIdentifier Strings in the AdTechIdentifier set should"
+                    + " not exceed %d bytes";
+
+    // TODO(b/266976242) Move to PHFlag
+    @VisibleForTesting public static final int MAX_TOTAL_SIZE_BYTES = 5000;
+
+    private final AdTechIdentifierValidator mAdTechIdentifierValidator;
+
+    public AdvertiserSetValidator(AdTechIdentifierValidator adTechIdentifierValidator) {
+        mAdTechIdentifierValidator = adTechIdentifierValidator;
+    }
+
+    /**
+     * Validate a set of ad tech identifiers:
+     *
+     * <ul>
+     *   <li>The sum of the sizes of the AdTechIdentifier Strings in UTF+8 should be less than
+     *       MAX_TOTAL_SIZE_BYTES bytes.
+     *   <li>Each ad tech identifier should be valid.
+     * </ul>
+     *
+     * @param advertisers the set of AdTechIdentifiers to be validated.
+     */
+    @Override
+    public void addValidation(
+            @NonNull Set<AdTechIdentifier> advertisers,
+            @NonNull ImmutableCollection.Builder<String> violations) {
+        Objects.requireNonNull(violations);
+        Objects.requireNonNull(advertisers);
+        int totalSize = 0;
+        for (AdTechIdentifier advertiser : advertisers) {
+            String advertiserString = advertiser.toString();
+            totalSize += advertiserString.getBytes().length;
+            if (totalSize > MAX_TOTAL_SIZE_BYTES) {
+                violations.add(
+                        String.format(
+                                Locale.US, SET_SHOULD_NOT_EXCEED_MAX_SIZE, MAX_TOTAL_SIZE_BYTES));
+                // End validation early so we don't do extra work on oversized sets
+                break;
+            }
+            mAdTechIdentifierValidator.addValidation(advertiserString, violations);
+        }
+    }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AppInstallAdvertisersSetter.java b/adservices/service-core/java/com/android/adservices/service/adselection/AppInstallAdvertisersSetter.java
new file mode 100644
index 0000000..96daa93
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AppInstallAdvertisersSetter.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.service.adselection;
+
+import static com.android.adservices.service.common.Throttler.ApiKey.FLEDGE_API_SET_APP_INSTALL_ADVERTISERS;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS;
+
+import android.adservices.adselection.SetAppInstallAdvertisersCallback;
+import android.adservices.adselection.SetAppInstallAdvertisersInput;
+import android.adservices.common.AdServicesStatusUtils;
+import android.adservices.common.AdTechIdentifier;
+import android.adservices.common.FledgeErrorResponse;
+import android.annotation.NonNull;
+import android.os.Build;
+import android.os.LimitExceededException;
+import android.os.RemoteException;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.adservices.LogUtil;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.DBAppInstallPermissions;
+import com.android.adservices.service.Flags;
+import com.android.adservices.service.common.AdTechIdentifierValidator;
+import com.android.adservices.service.common.AppImportanceFilter.WrongCallingApplicationStateException;
+import com.android.adservices.service.common.FledgeAllowListsFilter;
+import com.android.adservices.service.common.FledgeAuthorizationFilter;
+import com.android.adservices.service.common.FledgeServiceFilter;
+import com.android.adservices.service.consent.ConsentManager;
+import com.android.adservices.service.stats.AdServicesLogger;
+
+import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+/** Encapsulates the Set App Install Advertisers logic */
+// TODO(b/269798827): Enable for R.
+@RequiresApi(Build.VERSION_CODES.S)
+public class AppInstallAdvertisersSetter {
+
+    private static final String AD_TECH_IDENTIFIER_ERROR_MESSAGE_SCOPE = "app install adtech set";
+    private static final String AD_TECH_IDENTIFIER_ERROR_MESSAGE_ROLE = "adtech";
+
+    @NonNull private final AppInstallDao mAppInstallDao;
+    @NonNull private final ListeningExecutorService mExecutorService;
+    @NonNull private final AdServicesLogger mAdServicesLogger;
+    @NonNull private final FledgeServiceFilter mFledgeServiceFilter;
+    @NonNull private final ConsentManager mConsentManager;
+    private final int mCallerUid;
+
+    public AppInstallAdvertisersSetter(
+            @NonNull AppInstallDao appInstallDao,
+            @NonNull ExecutorService executor,
+            @NonNull AdServicesLogger adServicesLogger,
+            @NonNull final Flags flags,
+            @NonNull final FledgeServiceFilter fledgeServiceFilter,
+            @NonNull final ConsentManager consentManager,
+            int callerUid) {
+        Objects.requireNonNull(appInstallDao);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(adServicesLogger);
+        Objects.requireNonNull(flags);
+        Objects.requireNonNull(fledgeServiceFilter);
+        Objects.requireNonNull(consentManager);
+
+        mAppInstallDao = appInstallDao;
+        mExecutorService = MoreExecutors.listeningDecorator(executor);
+        mAdServicesLogger = adServicesLogger;
+        mCallerUid = callerUid;
+        mFledgeServiceFilter = fledgeServiceFilter;
+        mConsentManager = consentManager;
+    }
+
+    /**
+     * Sets the app install advertisers for the caller.
+     *
+     * <p>Stores the association between the listed adtechs and the caller in the app install
+     * database.
+     *
+     * @param input object containing the package name of the caller and a list of adtechs
+     * @param callback callback function to be called in case of success or failure
+     */
+    public void setAppInstallAdvertisers(
+            @NonNull SetAppInstallAdvertisersInput input,
+            @NonNull SetAppInstallAdvertisersCallback callback) {
+        LogUtil.v("Executing setAppInstallAdvertisers API");
+
+        FluentFuture.from(
+                        mExecutorService.submit(
+                                () ->
+                                        doSetAppInstallAdvertisers(
+                                                input.getAdvertisers(),
+                                                input.getCallerPackageName())))
+                .addCallback(
+                        new FutureCallback<Void>() {
+                            @Override
+                            public void onSuccess(Void result) {
+                                LogUtil.v("SetAppInstallAdvertisers succeeded!");
+                                invokeSuccess(callback, AdServicesStatusUtils.STATUS_SUCCESS);
+                            }
+
+                            @Override
+                            public void onFailure(Throwable t) {
+                                LogUtil.e(t, "SetAppInstallAdvertisers invocation failed!");
+                                if (t instanceof ConsentManager.RevokedConsentException) {
+                                    invokeSuccess(
+                                            callback,
+                                            AdServicesStatusUtils.STATUS_USER_CONSENT_REVOKED);
+                                } else {
+                                    notifyFailureToCaller(callback, t);
+                                }
+                            }
+                        },
+                        mExecutorService);
+    }
+
+    /** Invokes the onFailure function from the callback and handles the exception. */
+    private void invokeFailure(
+            @NonNull SetAppInstallAdvertisersCallback callback,
+            int statusCode,
+            String errorMessage) {
+        int resultCode = AdServicesStatusUtils.STATUS_UNSET;
+        try {
+            callback.onFailure(
+                    new FledgeErrorResponse.Builder()
+                            .setStatusCode(statusCode)
+                            .setErrorMessage(errorMessage)
+                            .build());
+            resultCode = statusCode;
+        } catch (RemoteException e) {
+            // TODO(b/269724912) Unit test this block
+            LogUtil.e(e, "Unable to send failed result to the callback");
+            resultCode = AdServicesStatusUtils.STATUS_UNKNOWN_ERROR;
+            throw e.rethrowFromSystemServer();
+        } finally {
+            mAdServicesLogger.logFledgeApiCallStats(
+                    AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS, resultCode, 0);
+        }
+    }
+
+    /** Invokes the onSuccess function from the callback and handles the exception. */
+    private void invokeSuccess(@NonNull SetAppInstallAdvertisersCallback callback, int resultCode) {
+        try {
+            callback.onSuccess();
+        } catch (RemoteException e) {
+            // TODO(b/269724912) Unit test this block
+            LogUtil.e(e, "Unable to send successful result to the callback");
+            resultCode = AdServicesStatusUtils.STATUS_UNKNOWN_ERROR;
+            throw e.rethrowFromSystemServer();
+        } finally {
+            mAdServicesLogger.logFledgeApiCallStats(
+                    AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS, resultCode, 0);
+        }
+    }
+
+    private void notifyFailureToCaller(
+            @NonNull SetAppInstallAdvertisersCallback callback, @NonNull Throwable t) {
+        if (t instanceof IllegalArgumentException) {
+            invokeFailure(callback, AdServicesStatusUtils.STATUS_INVALID_ARGUMENT, t.getMessage());
+        } else if (t instanceof WrongCallingApplicationStateException) {
+            invokeFailure(callback, AdServicesStatusUtils.STATUS_BACKGROUND_CALLER, t.getMessage());
+        } else if (t instanceof FledgeAllowListsFilter.AppNotAllowedException) {
+            invokeFailure(
+                    callback, AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED, t.getMessage());
+        } else if (t instanceof FledgeAuthorizationFilter.CallerMismatchException) {
+            invokeFailure(callback, AdServicesStatusUtils.STATUS_UNAUTHORIZED, t.getMessage());
+        } else if (t instanceof LimitExceededException) {
+            invokeFailure(
+                    callback, AdServicesStatusUtils.STATUS_RATE_LIMIT_REACHED, t.getMessage());
+        } else {
+            invokeFailure(callback, AdServicesStatusUtils.STATUS_INTERNAL_ERROR, t.getMessage());
+        }
+    }
+
+    private Void doSetAppInstallAdvertisers(
+            Set<AdTechIdentifier> advertisers, String callerPackageName) {
+        validateRequest(advertisers, callerPackageName);
+
+        ArrayList<DBAppInstallPermissions> permissions = new ArrayList<>();
+        for (AdTechIdentifier advertiser : advertisers) {
+            permissions.add(
+                    new DBAppInstallPermissions.Builder()
+                            .setPackageName(callerPackageName)
+                            .setBuyer(advertiser)
+                            .build());
+        }
+        mAppInstallDao.setAdTechsForPackage(callerPackageName, permissions);
+        return null;
+    }
+
+    private void validateRequest(Set<AdTechIdentifier> advertisers, String callerPackageName) {
+        LogUtil.v("Validating setAppInstallAdvertisers Request");
+        mFledgeServiceFilter.filterRequest(
+                null,
+                callerPackageName,
+                true,
+                false,
+                mCallerUid,
+                AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS,
+                FLEDGE_API_SET_APP_INSTALL_ADVERTISERS);
+        (new AdvertiserSetValidator(
+                        new AdTechIdentifierValidator(
+                                AD_TECH_IDENTIFIER_ERROR_MESSAGE_SCOPE,
+                                AD_TECH_IDENTIFIER_ERROR_MESSAGE_ROLE)))
+                .validate(advertisers);
+        if (mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(callerPackageName)) {
+            throw new ConsentManager.RevokedConsentException();
+        }
+    }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/ImpressionReporter.java b/adservices/service-core/java/com/android/adservices/service/adselection/ImpressionReporter.java
index 59b6a87..4f2ff97 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/ImpressionReporter.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/ImpressionReporter.java
@@ -292,6 +292,7 @@
                                         requestParams.getCallerPackageName(),
                                         mFlags
                                                 .getEnforceForegroundStatusForFledgeReportImpression(),
+                                        true,
                                         mCallerUid,
                                         AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/InteractionReporter.java b/adservices/service-core/java/com/android/adservices/service/adselection/InteractionReporter.java
index ddacb35..287c219 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/InteractionReporter.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/InteractionReporter.java
@@ -143,6 +143,7 @@
                                                 callerPackageName,
                                                 mFlags
                                                         .getEnforceForegroundStatusForFledgeReportInteraction(),
+                                                true,
                                                 mCallerUid,
                                                 AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                                                 Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/OutcomeSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/OutcomeSelectionRunner.java
index 7946ba7..242a773 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/OutcomeSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/OutcomeSelectionRunner.java
@@ -224,6 +224,7 @@
                                             inputParams.getCallerPackageName(),
                                             mFlags
                                                     .getEnforceForegroundStatusForFledgeRunAdSelection(),
+                                            true,
                                             mCallerUid,
                                             AdServicesStatsLog
                                                     .AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AbstractFledgeServiceFilter.java b/adservices/service-core/java/com/android/adservices/service/common/AbstractFledgeServiceFilter.java
index 1b67e24..0a082a3 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AbstractFledgeServiceFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AbstractFledgeServiceFilter.java
@@ -171,6 +171,7 @@
      *     enrollment check will not be applied if it is null.
      * @param callerPackageName caller package name to be validated
      * @param enforceForeground whether to enforce a foreground check
+     * @param enforceConsent whether to enforce a consent check
      * @throws FledgeAuthorizationFilter.CallerMismatchException if the {@code callerPackageName} is
      *     not valid
      * @throws AppImportanceFilter.WrongCallingApplicationStateException if the foreground check is
@@ -187,6 +188,7 @@
             @Nullable AdTechIdentifier adTech,
             @NonNull String callerPackageName,
             boolean enforceForeground,
+            boolean enforceConsent,
             int callerUid,
             int apiName,
             @NonNull Throttler.ApiKey apiKey);
diff --git a/adservices/service-core/java/com/android/adservices/service/common/CustomAudienceServiceFilter.java b/adservices/service-core/java/com/android/adservices/service/common/CustomAudienceServiceFilter.java
index 93b01fb..5ed4da0 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/CustomAudienceServiceFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/CustomAudienceServiceFilter.java
@@ -61,6 +61,7 @@
      *     skipped.
      * @param callerPackageName caller package name to be validated
      * @param enforceForeground whether to enforce a foreground check
+     * @param enforceConsent currently unused in CustomAudienceServiceFilter
      * @param callerUid caller's uid from the Binder thread
      * @param apiName the id of the api being called
      * @param apiKey api-specific throttler key
@@ -79,6 +80,7 @@
             @Nullable AdTechIdentifier adTech,
             @NonNull String callerPackageName,
             boolean enforceForeground,
+            boolean enforceConsent,
             int callerUid,
             int apiName,
             @NonNull Throttler.ApiKey apiKey) {
diff --git a/adservices/service-core/java/com/android/adservices/service/common/FledgeServiceFilter.java b/adservices/service-core/java/com/android/adservices/service/common/FledgeServiceFilter.java
index 0e27a43..26beb20 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/FledgeServiceFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/FledgeServiceFilter.java
@@ -61,6 +61,8 @@
      *     enrollment check will not be applied if it is null.
      * @param callerPackageName caller package name to be validated
      * @param enforceForeground whether to enforce a foreground check
+     * @param enforceConsent Checks if the user has revoked global FLEDGE consent if set to true.
+     *     Should only be set to false if the caller is checking FLEDGE consent on their own.
      * @throws FledgeAuthorizationFilter.CallerMismatchException if the {@code callerPackageName} is
      *     not valid
      * @throws AppImportanceFilter.WrongCallingApplicationStateException if the foreground check is
@@ -78,6 +80,7 @@
             @Nullable AdTechIdentifier adTech,
             @NonNull String callerPackageName,
             boolean enforceForeground,
+            boolean enforceConsent,
             int callerUid,
             int apiName,
             @NonNull Throttler.ApiKey apiKey) {
@@ -93,6 +96,8 @@
             assertFledgeEnrollment(adTech, callerPackageName, apiName);
         }
         assertAppInAllowList(callerPackageName, apiName);
-        assertCallerHasUserConsent();
+        if (enforceConsent) {
+            assertCallerHasUserConsent();
+        }
     }
 }
diff --git a/adservices/service-core/java/com/android/adservices/service/common/Throttler.java b/adservices/service-core/java/com/android/adservices/service/common/Throttler.java
index b2e6d06..dddaef7 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/Throttler.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/Throttler.java
@@ -57,6 +57,9 @@
         // Key to throttle Select Ads API
         FLEDGE_API_SELECT_ADS,
 
+        // Key to throttle Set App Install Advertisers API
+        FLEDGE_API_SET_APP_INSTALL_ADVERTISERS,
+
         // Key to throttle Measurement Deletion Registration API
         MEASUREMENT_API_DELETION_REGISTRATION,
 
diff --git a/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
index b74c428..f31da39 100644
--- a/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
@@ -215,6 +215,7 @@
                         customAudience.getBuyer(),
                         ownerPackageName,
                         mFlags.getEnforceForegroundStatusForFledgeCustomAudience(),
+                        false,
                         callerUid,
                         apiName,
                         FLEDGE_API_JOIN_CUSTOM_AUDIENCE);
@@ -227,8 +228,6 @@
                     LogUtil.v("Joining custom audience");
                     mCustomAudienceImpl.joinCustomAudience(customAudience, ownerPackageName);
                     BackgroundFetchJobService.scheduleIfNeeded(mContext, mFlags, false);
-                    // TODO(b/233681870): Investigate implementation of actual failures
-                    //  in logs/metrics
                     resultCode = AdServicesStatusUtils.STATUS_SUCCESS;
                 } else {
                     LogUtil.v("Consent revoked");
@@ -335,6 +334,7 @@
                         buyer,
                         ownerPackageName,
                         mFlags.getEnforceForegroundStatusForFledgeCustomAudience(),
+                        false,
                         callerUid,
                         apiName,
                         FLEDGE_API_LEAVE_CUSTOM_AUDIENCE);
@@ -343,8 +343,6 @@
 
                 // Fail silently for revoked user consent
                 if (!mConsentManager.isFledgeConsentRevokedForApp(ownerPackageName)) {
-                    // TODO(b/233681870): Investigate implementation of actual failures
-                    //  in logs/metrics
                     mCustomAudienceImpl.leaveCustomAudience(ownerPackageName, buyer, name);
                     resultCode = AdServicesStatusUtils.STATUS_SUCCESS;
                 } else {
@@ -365,8 +363,6 @@
             }
 
             callback.onSuccess();
-            // TODO(b/233681870): Investigate implementation of actual failures in
-            //  logs/metrics
         } catch (Exception exception) {
             LogUtil.e(exception, "Unable to send result to the callback");
             resultCode = AdServicesStatusUtils.STATUS_INTERNAL_ERROR;
diff --git a/adservices/tests/unittest/fixtures/java/android/adservices/common/CommonFixture.java b/adservices/tests/unittest/fixtures/java/android/adservices/common/CommonFixture.java
index 81ed290..67d9dbb 100644
--- a/adservices/tests/unittest/fixtures/java/android/adservices/common/CommonFixture.java
+++ b/adservices/tests/unittest/fixtures/java/android/adservices/common/CommonFixture.java
@@ -54,6 +54,9 @@
             AdTechIdentifier.fromString("notenrolled.com");
     public static final AdTechIdentifier VALID_BUYER_1 = AdTechIdentifier.fromString("test.com");
     public static final AdTechIdentifier VALID_BUYER_2 = AdTechIdentifier.fromString("test2.com");
+    public static final AdTechIdentifier INVALID_EMPTY_BUYER = AdTechIdentifier.fromString("");
+    public static final Set<AdTechIdentifier> BUYER_SET =
+            new HashSet<>(Arrays.asList(VALID_BUYER_1, VALID_BUYER_2));
 
     public static Uri getUri(String authority, String path) {
         return Uri.parse(ValidatorUtil.HTTPS_SCHEME + "://" + authority + path);
diff --git a/adservices/tests/unittest/framework/src/android/adservices/adselection/SetAppInstallAdvertisersInputTest.java b/adservices/tests/unittest/framework/src/android/adservices/adselection/SetAppInstallAdvertisersInputTest.java
index 73e0b98..c9d85b0 100644
--- a/adservices/tests/unittest/framework/src/android/adservices/adselection/SetAppInstallAdvertisersInputTest.java
+++ b/adservices/tests/unittest/framework/src/android/adservices/adselection/SetAppInstallAdvertisersInputTest.java
@@ -73,7 +73,7 @@
     }
 
     @Test
-    public void testFailsToBuildWithNullAdSelectionConfig() {
+    public void testFailsToBuildWithNullAdvertisers() {
         assertThrows(
                 NullPointerException.class,
                 () -> {
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/adselection/AppInstallDaoTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/adselection/AppInstallDaoTest.java
index cebed7d..3e2dd5f 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/adselection/AppInstallDaoTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/adselection/AppInstallDaoTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.adservices.common.AdTechIdentifier;
+import android.adservices.common.CommonFixture;
 import android.content.Context;
 
 import androidx.room.Room;
@@ -33,10 +34,10 @@
 import java.util.Arrays;
 
 public class AppInstallDaoTest {
-    public static AdTechIdentifier BUYER_1 = AdTechIdentifier.fromString("example1.com");
-    public static AdTechIdentifier BUYER_2 = AdTechIdentifier.fromString("example2.com");
-    public static String PACKAGE_1 = "package1.app";
-    public static String PACKAGE_2 = "package2.app";
+    public static AdTechIdentifier BUYER_1 = CommonFixture.VALID_BUYER_1;
+    public static AdTechIdentifier BUYER_2 = CommonFixture.VALID_BUYER_2;
+    public static String PACKAGE_1 = CommonFixture.TEST_PACKAGE_NAME_1;
+    public static String PACKAGE_2 = CommonFixture.TEST_PACKAGE_NAME_2;
 
     private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
 
@@ -57,32 +58,33 @@
     }
 
     @Test
-    public void testInsertThenRead() {
-        mAppInstallDao.insertAllAppInstallPermissions(
-                Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
+    public void testSetThenRead() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1, Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
 
         assertTrue(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_1));
     }
 
     @Test
-    public void testInsertThenDelete() {
-        mAppInstallDao.insertAllAppInstallPermissions(
-                Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
+    public void testSetThenDelete() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1, Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
         assertEquals(1, mAppInstallDao.deleteByPackageName(PACKAGE_1));
     }
 
     @Test
-    public void testInsertThenDeleteThenRead() {
-        mAppInstallDao.insertAllAppInstallPermissions(
-                Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
+    public void testSetThenDeleteThenRead() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1, Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
         mAppInstallDao.deleteByPackageName(PACKAGE_1);
 
         assertFalse(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_1));
     }
 
     @Test
-    public void testInsertThenReadMultiple() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenReadMultiple() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_2, PACKAGE_2)));
@@ -92,19 +94,20 @@
     }
 
     @Test
-    public void testInsertThenReadMultipleSeparateCalls() {
-        mAppInstallDao.insertAllAppInstallPermissions(
-                Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
-        mAppInstallDao.insertAllAppInstallPermissions(
-                Arrays.asList(new DBAppInstallPermissions(BUYER_2, PACKAGE_2)));
+    public void testSetThenReadMultipleSeparateCalls() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1, Arrays.asList(new DBAppInstallPermissions(BUYER_1, PACKAGE_1)));
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_2, Arrays.asList(new DBAppInstallPermissions(BUYER_2, PACKAGE_2)));
 
         assertTrue(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_1));
         assertTrue(mAppInstallDao.canBuyerFilterPackage(BUYER_2, PACKAGE_2));
     }
 
     @Test
-    public void testInsertThenReadMultipleBuyers() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenReadMultipleBuyers() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_2, PACKAGE_1)));
@@ -113,8 +116,9 @@
     }
 
     @Test
-    public void testInsertThenDeleteMultipleBuyers() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenDeleteMultipleBuyers() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_2, PACKAGE_1)));
@@ -122,8 +126,9 @@
     }
 
     @Test
-    public void testInsertThenDeleteThenReadMultipleBuyers() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenDeleteThenReadMultipleBuyers() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_2, PACKAGE_1)));
@@ -133,8 +138,9 @@
     }
 
     @Test
-    public void testInsertThenReadMultiplePackages() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenReadMultiplePackages() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_2)));
@@ -143,8 +149,9 @@
     }
 
     @Test
-    public void testInsertThenDeleteThenReadMultiplePackages() {
-        mAppInstallDao.insertAllAppInstallPermissions(
+    public void testSetThenDeleteThenReadMultiplePackages() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
                 Arrays.asList(
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
                         new DBAppInstallPermissions(BUYER_1, PACKAGE_2)));
@@ -153,4 +160,18 @@
         assertFalse(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_1));
         assertFalse(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_2));
     }
+
+    @Test
+    public void testSetAdTechsForPackageDeletesExisting() {
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1,
+                Arrays.asList(
+                        new DBAppInstallPermissions(BUYER_1, PACKAGE_1),
+                        new DBAppInstallPermissions(BUYER_2, PACKAGE_2)));
+        mAppInstallDao.setAdTechsForPackage(
+                PACKAGE_1, Arrays.asList(new DBAppInstallPermissions(BUYER_2, PACKAGE_1)));
+        assertFalse(mAppInstallDao.canBuyerFilterPackage(BUYER_1, PACKAGE_1));
+        assertTrue(mAppInstallDao.canBuyerFilterPackage(BUYER_2, PACKAGE_2));
+        assertTrue(mAppInstallDao.canBuyerFilterPackage(BUYER_2, PACKAGE_1));
+    }
 }
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
index bfab081..57a7644 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
@@ -87,7 +87,9 @@
 import com.android.adservices.data.DbTestUtil;
 import com.android.adservices.data.adselection.AdSelectionDatabase;
 import com.android.adservices.data.adselection.AdSelectionEntryDao;
+import com.android.adservices.data.adselection.AppInstallDao;
 import com.android.adservices.data.adselection.DBAdSelectionOverride;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
 import com.android.adservices.data.common.DBAdData;
 import com.android.adservices.data.customaudience.CustomAudienceDao;
 import com.android.adservices.data.customaudience.CustomAudienceDatabase;
@@ -274,6 +276,7 @@
     private ExecutorService mBackgroundExecutorService;
     private ScheduledThreadPoolExecutor mScheduledExecutor;
     private CustomAudienceDao mCustomAudienceDao;
+    private AppInstallDao mAppInstallDao;
     @Spy private AdSelectionEntryDao mAdSelectionEntryDaoSpy;
     private AdServicesHttpsClient mAdServicesHttpsClient;
     private AdSelectionConfig mAdSelectionConfig;
@@ -294,6 +297,10 @@
                 Room.inMemoryDatabaseBuilder(mContext, AdSelectionDatabase.class)
                         .build()
                         .adSelectionEntryDao();
+        mAppInstallDao =
+                Room.inMemoryDatabaseBuilder(mContext, SharedStorageDatabase.class)
+                        .build()
+                        .appInstallDao();
 
         // Test applications don't have the required permissions to read config P/H flags, and
         // injecting mocked flags everywhere is annoying and non-trivial for static methods
@@ -325,6 +332,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -405,6 +413,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -509,6 +518,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -764,6 +774,7 @@
         AdSelectionServiceImpl adSelectionServiceNoCache =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         httpClientWithNoCaching,
                         mDevContextFilter,
@@ -869,6 +880,7 @@
         AdSelectionServiceImpl adSelectionServiceWithCache =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         httpClientWithCaching,
                         mDevContextFilter,
@@ -987,6 +999,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -2205,6 +2218,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -2445,6 +2459,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -2510,6 +2525,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -2626,6 +2642,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -2743,6 +2760,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -3131,6 +3149,7 @@
                         mSeller,
                         invalidPackageName,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -3213,6 +3232,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -3306,6 +3326,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -3314,6 +3335,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -3440,6 +3462,7 @@
         AdSelectionServiceImpl adSelectionServiceWithThrottling =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -3505,6 +3528,7 @@
                         mSeller,
                         CALLER_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -3567,6 +3591,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
index bf95dcd..f0dff64 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
@@ -58,8 +58,10 @@
 import com.android.adservices.data.DbTestUtil;
 import com.android.adservices.data.adselection.AdSelectionDatabase;
 import com.android.adservices.data.adselection.AdSelectionEntryDao;
+import com.android.adservices.data.adselection.AppInstallDao;
 import com.android.adservices.data.adselection.CustomAudienceSignals;
 import com.android.adservices.data.adselection.DBAdSelection;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
 import com.android.adservices.data.customaudience.CustomAudienceDao;
 import com.android.adservices.data.customaudience.CustomAudienceDatabase;
 import com.android.adservices.data.enrollment.EnrollmentDao;
@@ -171,6 +173,7 @@
     private ExecutorService mBackgroundExecutorService;
     private ScheduledThreadPoolExecutor mScheduledExecutor;
     private CustomAudienceDao mCustomAudienceDao;
+    private AppInstallDao mAppInstallDao;
     @Spy private AdSelectionEntryDao mAdSelectionEntryDaoSpy;
     private AdServicesHttpsClient mAdServicesHttpsClient;
     private AdSelectionServiceImpl mAdSelectionService;
@@ -206,6 +209,10 @@
                 Room.inMemoryDatabaseBuilder(mContext, CustomAudienceDatabase.class)
                         .build()
                         .customAudienceDao();
+        mAppInstallDao =
+                Room.inMemoryDatabaseBuilder(mContext, SharedStorageDatabase.class)
+                        .build()
+                        .appInstallDao();
         mAdServicesHttpsClient =
                 new AdServicesHttpsClient(
                         AdServicesExecutors.getBlockingExecutor(),
@@ -219,6 +226,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDaoSpy,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -260,6 +268,7 @@
                         SAMPLE_SELLER,
                         CALLER_PACKAGE_NAME,
                         false,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
index d06fbf9..197ab96 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
@@ -68,7 +68,6 @@
 import android.adservices.adselection.ReportInteractionCallback;
 import android.adservices.adselection.ReportInteractionInput;
 import android.adservices.adselection.SetAdCounterHistogramOverrideInput;
-import android.adservices.adselection.SetAppInstallAdvertisersCallback;
 import android.adservices.adselection.SetAppInstallAdvertisersInput;
 import android.adservices.adselection.UpdateAdCounterHistogramCallback;
 import android.adservices.adselection.UpdateAdCounterHistogramInput;
@@ -95,15 +94,18 @@
 import com.android.adservices.data.DbTestUtil;
 import com.android.adservices.data.adselection.AdSelectionDatabase;
 import com.android.adservices.data.adselection.AdSelectionEntryDao;
+import com.android.adservices.data.adselection.AppInstallDao;
 import com.android.adservices.data.adselection.CustomAudienceSignals;
 import com.android.adservices.data.adselection.DBAdSelection;
 import com.android.adservices.data.adselection.DBAdSelectionFromOutcomesOverride;
 import com.android.adservices.data.adselection.DBAdSelectionOverride;
 import com.android.adservices.data.adselection.DBBuyerDecisionLogic;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
 import com.android.adservices.data.customaudience.CustomAudienceDao;
 import com.android.adservices.data.customaudience.CustomAudienceDatabase;
 import com.android.adservices.data.enrollment.EnrollmentDao;
 import com.android.adservices.service.Flags;
+import com.android.adservices.service.adselection.AppInstallAdvertisersSetterTest.SetAppInstallAdvertisersTestCallback;
 import com.android.adservices.service.common.AppImportanceFilter;
 import com.android.adservices.service.common.AppImportanceFilter.WrongCallingApplicationStateException;
 import com.android.adservices.service.common.FledgeAuthorizationFilter;
@@ -245,6 +247,7 @@
     @Mock private ConsentManager mConsentManagerMock;
     private CustomAudienceDao mCustomAudienceDao;
     private AdSelectionEntryDao mAdSelectionEntryDao;
+    private AppInstallDao mAppInstallDao;
     private AdSelectionConfig.Builder mAdSelectionConfigBuilder;
 
     private Uri mBiddingLogicUri;
@@ -276,6 +279,13 @@
                         .build()
                         .adSelectionEntryDao();
 
+        mAppInstallDao =
+                Room.inMemoryDatabaseBuilder(
+                                ApplicationProvider.getApplicationContext(),
+                                SharedStorageDatabase.class)
+                        .build()
+                        .appInstallDao();
+
         mBiddingLogicUri = (mMockWebServerRule.uriForPath(mFetchJavaScriptPathBuyer));
 
         mCustomAudienceSignals =
@@ -313,6 +323,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -391,6 +402,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -505,6 +517,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -660,6 +673,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -808,6 +822,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -953,6 +968,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1090,6 +1106,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1229,6 +1246,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1305,6 +1323,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -1354,6 +1373,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1448,6 +1468,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1543,6 +1564,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1644,6 +1666,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1740,6 +1763,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1831,6 +1855,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -1921,6 +1946,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2012,6 +2038,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2123,6 +2150,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2253,6 +2281,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2334,6 +2363,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2382,6 +2412,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2425,6 +2456,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2473,6 +2505,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2533,6 +2566,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2589,6 +2623,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2649,6 +2684,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2710,6 +2746,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2812,6 +2849,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -2916,6 +2954,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3016,6 +3055,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3113,6 +3153,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3144,6 +3185,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -3151,6 +3193,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3205,6 +3248,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3259,6 +3303,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3304,6 +3349,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3352,6 +3398,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3394,6 +3441,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3440,6 +3488,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3472,6 +3521,7 @@
                         mSeller,
                         otherPackageName,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -3526,6 +3576,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3568,6 +3619,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -3626,6 +3678,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3672,6 +3725,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -3729,6 +3783,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3825,6 +3880,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -3835,6 +3891,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -3925,6 +3982,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4018,6 +4076,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4048,6 +4107,7 @@
                         mSeller,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION,
                         Throttler.ApiKey.FLEDGE_API_REPORT_IMPRESSIONS);
@@ -4138,6 +4198,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4238,6 +4299,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4340,6 +4402,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4389,6 +4452,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4441,6 +4505,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4487,6 +4552,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4539,6 +4605,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4603,6 +4670,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4661,6 +4729,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4723,6 +4792,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4784,6 +4854,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4894,6 +4965,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -4998,6 +5070,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -5107,6 +5180,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -5233,6 +5307,7 @@
         AdSelectionServiceImpl adSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mClient,
                         mDevContextFilter,
@@ -5291,7 +5366,6 @@
                         eq(AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS),
                         eq(STATUS_SUCCESS),
                         anyInt());
-        // TODO(b/265469079) Add tests to ensure adtechs were fetched and stored
     }
 
     @Test
@@ -5850,6 +5924,7 @@
     private AdSelectionServiceImpl generateAdSelectionServiceImpl() {
         return new AdSelectionServiceImpl(
                 mAdSelectionEntryDao,
+                mAppInstallDao,
                 mCustomAudienceDao,
                 mClient,
                 mDevContextFilter,
@@ -6086,13 +6161,16 @@
         return callback;
     }
 
-    private SetAppInstallAdvertisersTestCallback callSetAppInstallAdvertisers(
-            AdSelectionServiceImpl adSelectionService, SetAppInstallAdvertisersInput request)
-            throws Exception {
+    private AppInstallAdvertisersSetterTest.SetAppInstallAdvertisersTestCallback
+            callSetAppInstallAdvertisers(
+                    AdSelectionServiceImpl adSelectionService,
+                    SetAppInstallAdvertisersInput request)
+                    throws Exception {
         // Counted down in 1) callback and 2) logApiCall
         CountDownLatch resultLatch = new CountDownLatch(2);
-        SetAppInstallAdvertisersTestCallback callback =
-                new SetAppInstallAdvertisersTestCallback(resultLatch);
+        AppInstallAdvertisersSetterTest.SetAppInstallAdvertisersTestCallback callback =
+                new AppInstallAdvertisersSetterTest.SetAppInstallAdvertisersTestCallback(
+                        resultLatch);
 
         // Wait for the logging call, which happens after the callback
         Answer<Void> countDownAnswer =
@@ -6262,29 +6340,6 @@
         }
     }
 
-    public static class SetAppInstallAdvertisersTestCallback
-            extends SetAppInstallAdvertisersCallback.Stub {
-        private final CountDownLatch mCountDownLatch;
-        boolean mIsSuccess = false;
-        FledgeErrorResponse mFledgeErrorResponse;
-
-        public SetAppInstallAdvertisersTestCallback(CountDownLatch countDownLatch) {
-            mCountDownLatch = countDownLatch;
-        }
-
-        @Override
-        public void onSuccess() throws RemoteException {
-            mIsSuccess = true;
-            mCountDownLatch.countDown();
-        }
-
-        @Override
-        public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException {
-            mFledgeErrorResponse = fledgeErrorResponse;
-            mCountDownLatch.countDown();
-        }
-    }
-
     public static class UpdateAdCounterHistogramTestCallback
             extends UpdateAdCounterHistogramCallback.Stub {
         protected final CountDownLatch mCountDownLatch;
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdvertiserSetValidatorTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdvertiserSetValidatorTest.java
new file mode 100644
index 0000000..5081a89
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdvertiserSetValidatorTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.service.adselection;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.adservices.common.AdTechIdentifier;
+import android.adservices.common.CommonFixture;
+
+import com.android.adservices.service.common.AdTechIdentifierValidator;
+import com.android.adservices.service.common.ValidatorTestUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AdvertiserSetValidatorTest {
+    @Mock private AdTechIdentifierValidator mAdTechIdentifierValidator;
+
+    private AdvertiserSetValidator mValidator;
+
+    @Before
+    public void setup() {
+        mValidator = new AdvertiserSetValidator(mAdTechIdentifierValidator);
+    }
+
+    @Test
+    public void testFailureVerifyNullAdvertiserSet() {
+        assertThrows(NullPointerException.class, () -> mValidator.validate(null));
+        verifyZeroInteractions(mAdTechIdentifierValidator);
+    }
+
+    @Test
+    public void testFailureVerifyTooBigAdvertiserSet() {
+        HashSet<AdTechIdentifier> advertisers = new HashSet<>();
+        for (int host = 10, bytes = 0;
+                bytes <= AdvertiserSetValidator.MAX_TOTAL_SIZE_BYTES;
+                host++) {
+            AdTechIdentifier toAdd = AdTechIdentifier.fromString(host + ".com");
+            bytes += toAdd.toString().getBytes(StandardCharsets.UTF_8).length;
+            advertisers.add(toAdd);
+        }
+        IllegalArgumentException thrown =
+                assertThrows(
+                        IllegalArgumentException.class, () -> mValidator.validate(advertisers));
+        ValidatorTestUtil.assertValidationFailuresMatch(
+                thrown,
+                "",
+                Collections.singletonList(
+                        String.format(
+                                Locale.US,
+                                AdvertiserSetValidator.SET_SHOULD_NOT_EXCEED_MAX_SIZE,
+                                AdvertiserSetValidator.MAX_TOTAL_SIZE_BYTES)));
+    }
+
+    @Test
+    public void testSuccessValidSet() {
+        HashSet<AdTechIdentifier> advertisers = new HashSet<>();
+        advertisers.add(CommonFixture.VALID_BUYER_1);
+        advertisers.add(CommonFixture.VALID_BUYER_2);
+        mValidator.validate(advertisers);
+        verify(mAdTechIdentifierValidator)
+                .addValidation(eq(CommonFixture.VALID_BUYER_1.toString()), any());
+        verify(mAdTechIdentifierValidator)
+                .addValidation(eq(CommonFixture.VALID_BUYER_2.toString()), any());
+    }
+
+    @Test
+    public void testSuccessVerifyEmptyAdvertiserSet() {
+        mValidator.validate(Collections.emptySet());
+        verifyZeroInteractions(mAdTechIdentifierValidator);
+    }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AppInstallAdvertisersSetterTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AppInstallAdvertisersSetterTest.java
new file mode 100644
index 0000000..68ea265
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AppInstallAdvertisersSetterTest.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.service.adselection;
+
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.adservices.adselection.SetAppInstallAdvertisersCallback;
+import android.adservices.adselection.SetAppInstallAdvertisersInput;
+import android.adservices.common.AdServicesStatusUtils;
+import android.adservices.common.CommonFixture;
+import android.adservices.common.FledgeErrorResponse;
+import android.os.LimitExceededException;
+
+import com.android.adservices.concurrency.AdServicesExecutors;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.DBAppInstallPermissions;
+import com.android.adservices.service.Flags;
+import com.android.adservices.service.common.AppImportanceFilter;
+import com.android.adservices.service.common.FledgeAllowListsFilter;
+import com.android.adservices.service.common.FledgeAuthorizationFilter;
+import com.android.adservices.service.common.FledgeServiceFilter;
+import com.android.adservices.service.common.Throttler;
+import com.android.adservices.service.consent.ConsentManager;
+import com.android.adservices.service.stats.AdServicesLogger;
+import com.android.adservices.service.stats.AdServicesLoggerImpl;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AppInstallAdvertisersSetterTest {
+
+    private static final int UID = 42;
+
+    private static final SetAppInstallAdvertisersInput SAMPLE_INPUT =
+            getSampleSetAppInstallAdvertisersInputBuilder().build();
+    private static final List<DBAppInstallPermissions> DB_WRITE_FOR_SAMPLE_INPUT =
+            SAMPLE_INPUT.getAdvertisers().stream()
+                    .map(
+                            x ->
+                                    new DBAppInstallPermissions.Builder()
+                                            .setBuyer(x)
+                                            .setPackageName(SAMPLE_INPUT.getCallerPackageName())
+                                            .build())
+                    .collect(Collectors.toList());
+
+    private final AdServicesLogger mAdServicesLoggerMock =
+            ExtendedMockito.mock(AdServicesLoggerImpl.class);
+    private final ListeningExecutorService mExecutorService =
+            AdServicesExecutors.getBackgroundExecutor();
+    @Mock private AppInstallDao mAppInstallDao;
+    @Mock private AdServicesLogger mAdServicesLogger;
+    @Mock private Flags mFlags;
+    @Mock private FledgeServiceFilter mFledgeServiceFilter;
+
+    @Mock private ConsentManager mConsentManager;
+
+    private AppInstallAdvertisersSetter mAppInstallAdvertisersSetter;
+
+    @Before
+    public void setup() {
+        mAppInstallAdvertisersSetter =
+                new AppInstallAdvertisersSetter(
+                        mAppInstallDao,
+                        mExecutorService,
+                        mAdServicesLogger,
+                        mFlags,
+                        mFledgeServiceFilter,
+                        mConsentManager,
+                        UID);
+        when(mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()))
+                .thenReturn(false);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersSuccess() throws Exception {
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        verify(mFledgeServiceFilter)
+                .filterRequest(
+                        null,
+                        CommonFixture.TEST_PACKAGE_NAME_1,
+                        true,
+                        false,
+                        UID,
+                        AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS,
+                        Throttler.ApiKey.FLEDGE_API_SET_APP_INSTALL_ADVERTISERS);
+        assertTrue(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_SUCCESS);
+        verify(mAppInstallDao)
+                .setAdTechsForPackage(
+                        eq(CommonFixture.TEST_PACKAGE_NAME_1), eq(DB_WRITE_FOR_SAMPLE_INPUT));
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersFailure() throws Exception {
+        doThrow(new RuntimeException()).when(mAppInstallDao).setAdTechsForPackage(any(), any());
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_INTERNAL_ERROR);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersRevokedConsent() throws Exception {
+        when(mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()))
+                .thenReturn(true);
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        verify(mConsentManager)
+                .isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+                        SAMPLE_INPUT.getCallerPackageName());
+        assertTrue(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_USER_CONSENT_REVOKED);
+        verifyNoMoreInteractions(mAppInstallDao);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersBadInput() throws Exception {
+        SetAppInstallAdvertisersInput input =
+                getSampleSetAppInstallAdvertisersInputBuilder()
+                        .setAdvertisers(
+                                new HashSet<>(Arrays.asList(CommonFixture.INVALID_EMPTY_BUYER)))
+                        .build();
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(input);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_INVALID_ARGUMENT);
+        verifyNoMoreInteractions(mAppInstallDao);
+        // Consent should be checked after validations are run
+        verifyNoMoreInteractions(mConsentManager);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersBackgroundCaller() throws Exception {
+        doThrow(new AppImportanceFilter.WrongCallingApplicationStateException())
+                .when(mFledgeServiceFilter)
+                .filterRequest(any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_BACKGROUND_CALLER);
+        verifyNoMoreInteractions(mAppInstallDao);
+        // Consent should be checked after foreground check
+        verifyNoMoreInteractions(mConsentManager);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersAppNotAllowed() throws Exception {
+        doThrow(new FledgeAllowListsFilter.AppNotAllowedException())
+                .when(mFledgeServiceFilter)
+                .filterRequest(any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED);
+        verifyNoMoreInteractions(mAppInstallDao);
+        // Consent should be checked after app permissions check
+        verifyNoMoreInteractions(mConsentManager);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersUidMismatch() throws Exception {
+        doThrow(new FledgeAuthorizationFilter.CallerMismatchException())
+                .when(mFledgeServiceFilter)
+                .filterRequest(any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_UNAUTHORIZED);
+        verifyNoMoreInteractions(mAppInstallDao);
+        // Consent should be checked after package name check
+        verifyNoMoreInteractions(mConsentManager);
+    }
+
+    @Test
+    public void testSetAppInstallAdvertisersLimitExceeded() throws Exception {
+        doThrow(new LimitExceededException())
+                .when(mFledgeServiceFilter)
+                .filterRequest(any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
+        SetAppInstallAdvertisersTestCallback callback = callSetAppInstallAdvertisers(SAMPLE_INPUT);
+
+        assertFalse(callback.mIsSuccess);
+        verifyLog(AdServicesStatusUtils.STATUS_RATE_LIMIT_REACHED);
+        verifyNoMoreInteractions(mAppInstallDao);
+        // Consent should be checked after throttling
+        verifyNoMoreInteractions(mConsentManager);
+    }
+
+    private void verifyLog(int status) {
+        verify(mAdServicesLogger)
+                .logFledgeApiCallStats(
+                        AD_SERVICES_API_CALLED__API_NAME__SET_APP_INSTALL_ADVERTISERS, status, 0);
+    }
+
+    private SetAppInstallAdvertisersTestCallback callSetAppInstallAdvertisers(
+            SetAppInstallAdvertisersInput request) throws Exception {
+        CountDownLatch logLatch = new CountDownLatch(1);
+        CountDownLatch callbackLatch = new CountDownLatch(1);
+        SetAppInstallAdvertisersTestCallback callback =
+                new SetAppInstallAdvertisersTestCallback(callbackLatch);
+        callSetAppInstallAdvertisers(request, callback, callbackLatch, logLatch);
+        return callback;
+    }
+
+    private void callSetAppInstallAdvertisers(
+            SetAppInstallAdvertisersInput request,
+            SetAppInstallAdvertisersCallback.Stub callback,
+            CountDownLatch callbackLatch,
+            CountDownLatch logLatch)
+            throws Exception {
+
+        // Wait for the logging call, which happens after the callback
+        Answer<Void> countDownAnswer =
+                unused -> {
+                    logLatch.countDown();
+                    return null;
+                };
+        doAnswer(countDownAnswer)
+                .when(mAdServicesLoggerMock)
+                .logFledgeApiCallStats(anyInt(), anyInt(), anyInt());
+
+        mAppInstallAdvertisersSetter.setAppInstallAdvertisers(request, callback);
+        callbackLatch.await(5, TimeUnit.SECONDS);
+        logLatch.await(5, TimeUnit.SECONDS);
+    }
+
+    private static SetAppInstallAdvertisersInput.Builder
+            getSampleSetAppInstallAdvertisersInputBuilder() {
+        return new SetAppInstallAdvertisersInput.Builder()
+                .setAdvertisers(CommonFixture.BUYER_SET)
+                .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME_1);
+    }
+
+    public static class SetAppInstallAdvertisersTestCallback
+            extends SetAppInstallAdvertisersCallback.Stub {
+        private final CountDownLatch mCountDownLatch;
+        boolean mIsSuccess = false;
+        FledgeErrorResponse mFledgeErrorResponse;
+
+        public SetAppInstallAdvertisersTestCallback(CountDownLatch countDownLatch) {
+            mCountDownLatch = countDownLatch;
+        }
+
+        @Override
+        public void onSuccess() {
+            mIsSuccess = true;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onFailure(FledgeErrorResponse fledgeErrorResponse) {
+            mFledgeErrorResponse = fledgeErrorResponse;
+            mCountDownLatch.countDown();
+        }
+    }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/InteractionReporterTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/InteractionReporterTest.java
index b0bc75e..725be62 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/InteractionReporterTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/InteractionReporterTest.java
@@ -527,6 +527,7 @@
                         null,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         MY_UID,
                         AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
@@ -579,6 +580,7 @@
                         null,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         MY_UID,
                         AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
@@ -659,6 +661,7 @@
                         null,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         MY_UID,
                         AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
@@ -709,6 +712,7 @@
                         null,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         MY_UID,
                         AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
@@ -757,6 +761,7 @@
                         null,
                         TEST_PACKAGE_NAME,
                         true,
+                        true,
                         MY_UID,
                         AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_REPORT_INTERACTION);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
index 15f5db8..46fca83 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
@@ -307,6 +307,7 @@
                         SELLER_VALID,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -612,6 +613,7 @@
                         SELLER_VALID,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -858,6 +860,7 @@
                         SELLER_VALID,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -1831,6 +1834,7 @@
                         SELLER_VALID,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OutcomeSelectionRunnerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OutcomeSelectionRunnerTest.java
index 8d0562d..a10c0cd 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OutcomeSelectionRunnerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OutcomeSelectionRunnerTest.java
@@ -191,6 +191,7 @@
                         SAMPLE_SELLER,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
@@ -281,6 +282,7 @@
                         SAMPLE_SELLER,
                         MY_APP_PACKAGE_NAME,
                         true,
+                        true,
                         CALLER_UID,
                         AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__API_NAME_UNKNOWN,
                         Throttler.ApiKey.FLEDGE_API_SELECT_ADS);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/CustomAudienceServiceFilterTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/CustomAudienceServiceFilterTest.java
index fa3593f..61b1d7d 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/CustomAudienceServiceFilterTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/CustomAudienceServiceFilterTest.java
@@ -137,6 +137,7 @@
                                 SELLER_VALID,
                                 "invalidPackageName",
                                 false,
+                                false,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -154,6 +155,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                false,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -173,6 +175,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 true,
+                                false,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -188,6 +191,7 @@
                 SELLER_VALID,
                 CALLER_PACKAGE_NAME,
                 false,
+                false,
                 MY_UID,
                 API_NAME,
                 Throttler.ApiKey.UNKNOWN);
@@ -217,6 +221,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                false,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -225,7 +230,13 @@
     @Test
     public void testFilterRequestDoesNotDoEnrollmentCheckWhenAdTechParamIsNull() {
         mCustomAudienceServiceFilter.filterRequest(
-                null, CALLER_PACKAGE_NAME, false, MY_UID, API_NAME, Throttler.ApiKey.UNKNOWN);
+                null,
+                CALLER_PACKAGE_NAME,
+                false,
+                false,
+                MY_UID,
+                API_NAME,
+                Throttler.ApiKey.UNKNOWN);
 
         verify(mFledgeAuthorizationFilterSpy, never())
                 .assertAdTechAllowed(any(), anyString(), any(), anyInt());
@@ -244,6 +255,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                false,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
index 64cd362..6b91b76 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
@@ -78,6 +78,8 @@
 import com.android.adservices.concurrency.AdServicesExecutors;
 import com.android.adservices.data.adselection.AdSelectionDatabase;
 import com.android.adservices.data.adselection.AdSelectionEntryDao;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
 import com.android.adservices.data.customaudience.CustomAudienceDao;
 import com.android.adservices.data.customaudience.CustomAudienceDatabase;
 import com.android.adservices.service.Flags;
@@ -174,6 +176,7 @@
     private AdServicesHttpsClient mAdServicesHttpsClient;
     private CustomAudienceDao mCustomAudienceDao;
     private AdSelectionEntryDao mAdSelectionEntryDao;
+    private AppInstallDao mAppInstallDao;
     private ExecutorService mLightweightExecutorService;
     private ExecutorService mBackgroundExecutorService;
     private ScheduledThreadPoolExecutor mScheduledExecutor;
@@ -223,6 +226,10 @@
                 Room.inMemoryDatabaseBuilder(CONTEXT, AdSelectionDatabase.class)
                         .build()
                         .adSelectionEntryDao();
+        mAppInstallDao =
+                Room.inMemoryDatabaseBuilder(CONTEXT, SharedStorageDatabase.class)
+                        .build()
+                        .appInstallDao();
 
         mLightweightExecutorService = AdServicesExecutors.getLightWeightExecutor();
         mBackgroundExecutorService = AdServicesExecutors.getBackgroundExecutor();
@@ -250,7 +257,8 @@
         when(mMockDBAdSelectionFile.length()).thenReturn(DB_AD_SELECTION_FILE_SIZE);
         doNothing()
                 .when(mFledgeServiceFilter)
-                .filterRequest(any(), anyString(), anyBoolean(), anyInt(), anyInt(), any());
+                .filterRequest(
+                        any(), anyString(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
         when(ConsentManager.getInstance(CONTEXT)).thenReturn(mConsentManagerMock);
         when(AppImportanceFilter.create(any(), anyInt(), any()))
                 .thenReturn(mAppImportanceFilterMock);
@@ -926,6 +934,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
@@ -1711,7 +1720,8 @@
                 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any());
         doThrow(new ConsentManager.RevokedConsentException())
                 .when(mFledgeServiceFilter)
-                .filterRequest(any(), anyString(), anyBoolean(), anyInt(), anyInt(), any());
+                .filterRequest(
+                        any(), anyString(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any());
 
         mAdSelectionConfig =
                 AdSelectionConfigFixture.anAdSelectionConfigBuilder()
@@ -2102,6 +2112,7 @@
         mAdSelectionService =
                 new AdSelectionServiceImpl(
                         mAdSelectionEntryDao,
+                        mAppInstallDao,
                         mCustomAudienceDao,
                         mAdServicesHttpsClient,
                         mDevContextFilter,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeServiceFilterTests.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeServiceFilterTests.java
index 7885391..d15bace 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeServiceFilterTests.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeServiceFilterTests.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import android.adservices.common.AdTechIdentifier;
 import android.adservices.common.CommonFixture;
@@ -146,6 +147,7 @@
                 SELLER_VALID,
                 CALLER_PACKAGE_NAME,
                 false,
+                true,
                 MY_UID,
                 API_NAME,
                 Throttler.ApiKey.UNKNOWN);
@@ -169,6 +171,7 @@
                 SELLER_VALID,
                 CALLER_PACKAGE_NAME,
                 false,
+                true,
                 MY_UID,
                 API_NAME,
                 Throttler.ApiKey.UNKNOWN);
@@ -183,6 +186,7 @@
                                 SELLER_VALID,
                                 "invalidPackageName",
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -199,6 +203,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -217,6 +222,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 true,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -232,6 +238,7 @@
                 SELLER_VALID,
                 CALLER_PACKAGE_NAME,
                 false,
+                true,
                 MY_UID,
                 API_NAME,
                 Throttler.ApiKey.UNKNOWN);
@@ -261,6 +268,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -278,6 +286,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -293,12 +302,27 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
     }
 
     @Test
+    public void testFilterRequestSucceedsConsentRevokedEnforceConsentFalse() {
+        doReturn(AdServicesApiConsent.REVOKED).when(mConsentManagerMock).getConsent();
+        mFledgeServiceFilter.filterRequest(
+                SELLER_VALID,
+                CALLER_PACKAGE_NAME,
+                false,
+                false,
+                MY_UID,
+                API_NAME,
+                Throttler.ApiKey.UNKNOWN);
+        verifyNoMoreInteractions(mConsentManagerMock);
+    }
+
+    @Test
     public void testFilterRequestThrowsRevokedConsentExceptionAppDoesNotHaveConsentGaUxEnabled() {
         // Create new FledgeServiceFilter with new flags
         mFledgeServiceFilter =
@@ -320,6 +344,7 @@
                                 SELLER_VALID,
                                 CALLER_PACKAGE_NAME,
                                 false,
+                                true,
                                 MY_UID,
                                 API_NAME,
                                 Throttler.ApiKey.UNKNOWN));
@@ -330,7 +355,7 @@
         doReturn(AdServicesApiConsent.GIVEN).when(mConsentManagerMock).getConsent();
 
         mFledgeServiceFilter.filterRequest(
-                null, CALLER_PACKAGE_NAME, false, MY_UID, API_NAME, Throttler.ApiKey.UNKNOWN);
+                null, CALLER_PACKAGE_NAME, false, true, MY_UID, API_NAME, Throttler.ApiKey.UNKNOWN);
 
         verify(mFledgeAuthorizationFilterSpy, never())
                 .assertAdTechAllowed(any(), anyString(), any(), anyInt());