/* * Copyright (C) 2022 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 android.app.adservices; import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_MANAGER; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.adservices.consent.ConsentParcel; import android.app.adservices.topics.TopicParcel; import android.app.sdksandbox.SdkSandboxManager; import android.content.Context; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import androidx.annotation.RequiresApi; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Objects; /** * AdServices Manager to handle the internal communication between PPAPI process and AdServices * System Service. * * @hide */ // TODO(b/269798827): Enable for R. @RequiresApi(Build.VERSION_CODES.S) public final class AdServicesManager { public static final String AD_SERVICES_SYSTEM_SERVICE = "adservices_manager"; @GuardedBy("SINGLETON_LOCK") private static AdServicesManager sSingleton; private final IAdServicesManager mService; private static final Object SINGLETON_LOCK = new Object(); @IntDef(value = {MEASUREMENT_DELETION}) @Retention(RetentionPolicy.SOURCE) public @interface DeletionApiType {} public static final int MEASUREMENT_DELETION = 0; // TODO(b/267789077): Create bit for other APIs. @VisibleForTesting public AdServicesManager(@NonNull IAdServicesManager iAdServicesManager) { Objects.requireNonNull(iAdServicesManager, "AdServicesManager is NULL!"); mService = iAdServicesManager; } /** Get the singleton of AdServicesManager. Only used on T+ */ @Nullable public static AdServicesManager getInstance(@NonNull Context context) { synchronized (SINGLETON_LOCK) { if (sSingleton == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // TODO(b/262282035): Fix this work around in U+. // Get the AdServicesManagerService's Binder from the SdkSandboxManager. // This is a workaround for b/262282035. IBinder iBinder = context.getSystemService(SdkSandboxManager.class).getAdServicesManager(); sSingleton = new AdServicesManager(IAdServicesManager.Stub.asInterface(iBinder)); } } return sSingleton; } /** Return the User Consent */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public ConsentParcel getConsent(@ConsentParcel.ConsentApiType int consentApiType) { try { return mService.getConsent(consentApiType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Set the User Consent */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setConsent(@NonNull ConsentParcel consentParcel) { Objects.requireNonNull(consentParcel); try { mService.setConsent(consentParcel); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Saves information to the storage that notification was displayed for the first time to the * user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordNotificationDisplayed(boolean wasNotificationDisplayed) { try { mService.recordNotificationDisplayed(wasNotificationDisplayed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns information whether Consent Notification was displayed or not. * * @return true if Consent Notification was displayed, otherwise false. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean wasNotificationDisplayed() { try { return mService.wasNotificationDisplayed(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Saves information to the storage that notification was displayed for the first time to the * user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordGaUxNotificationDisplayed(boolean wasNotificationDisplayed) { try { mService.recordGaUxNotificationDisplayed(wasNotificationDisplayed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns information whether user interacted with consent manually. * * @return * */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public int getUserManualInteractionWithConsent() { try { return mService.getUserManualInteractionWithConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves information to the storage that user interacted with consent manually. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordUserManualInteractionWithConsent(int interaction) { try { mService.recordUserManualInteractionWithConsent(interaction); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns information whether Consent GA UX Notification was displayed or not. * * @return true if Consent GA UX Notification was displayed, otherwise false. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean wasGaUxNotificationDisplayed() { try { return mService.wasGaUxNotificationDisplayed(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns information whether Consent PAS Notification was displayed or not. * * @return true if PAS Notification was displayed, otherwise false. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean wasPasNotificationDisplayed() { try { return mService.wasPasNotificationDisplayed(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Saves information to the storage that PAS notification was displayed for the first time to * the user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordPasNotificationDisplayed(boolean wasNotificationDisplayed) { try { mService.recordPasNotificationDisplayed(wasNotificationDisplayed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns information whether Consent PAS Notification was opened or not. * * @return true if PAS Notification was opened, otherwise false. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean wasPasNotificationOpened() { try { return mService.wasPasNotificationOpened(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves information to the storage that PAS notification was opened. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordPasNotificationOpened(boolean wasNotificationOpened) { try { mService.recordPasNotificationOpened(wasNotificationOpened); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Record a blocked topic. * * @param blockedTopicParcels the blocked topic to record */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordBlockedTopic(@NonNull List blockedTopicParcels) { try { mService.recordBlockedTopic(blockedTopicParcels); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Remove a blocked topic. * * @param blockedTopicParcel the blocked topic to remove */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void removeBlockedTopic(@NonNull TopicParcel blockedTopicParcel) { try { mService.removeBlockedTopic(blockedTopicParcel); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Get all blocked topics. * * @return a {@code List} of all blocked topics. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public List retrieveAllBlockedTopics() { try { return mService.retrieveAllBlockedTopics(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Clear all Blocked Topics */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void clearAllBlockedTopics() { try { mService.clearAllBlockedTopics(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns the list of apps with consent. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public List getKnownAppsWithConsent(List installedPackages) { try { return mService.getKnownAppsWithConsent(installedPackages); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns the list of apps with revoked consent. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public List getAppsWithRevokedConsent(List installedPackages) { try { return mService.getAppsWithRevokedConsent(installedPackages); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Set user consent for an app */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setConsentForApp(String packageName, int packageUid, boolean isConsentRevoked) { try { mService.setConsentForApp(packageName, packageUid, isConsentRevoked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Reset all apps and blocked apps. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void clearKnownAppsWithConsent() { try { mService.clearKnownAppsWithConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Reset all apps consent. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void clearAllAppConsentData() { try { mService.clearAllAppConsentData(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Get if user consent is revoked for a given app. * * @return {@code true} if the user consent was revoked. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isConsentRevokedForApp(String packageName, int packageUid) { try { return mService.isConsentRevokedForApp(packageName, packageUid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Set user consent if the app first time request access and/or return consent value for the * app. * * @return {@code true} if user consent was given. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean setConsentForAppIfNew( String packageName, int packageUid, boolean isConsentRevoked) { try { return mService.setConsentForAppIfNew(packageName, packageUid, isConsentRevoked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Clear the app consent entry for uninstalled app. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void clearConsentForUninstalledApp(String packageName, int packageUid) { try { mService.clearConsentForUninstalledApp(packageName, packageUid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves information to the storage that a deletion of measurement data occurred. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordAdServicesDeletionOccurred(@DeletionApiType int deletionType) { try { mService.recordAdServicesDeletionOccurred(deletionType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the PP API default consent of a user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordDefaultConsent(boolean defaultConsent) { try { mService.recordDefaultConsent(defaultConsent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the topics default consent of a user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordTopicsDefaultConsent(boolean defaultConsent) { try { mService.recordTopicsDefaultConsent(defaultConsent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the FLEDGE default consent of a user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordFledgeDefaultConsent(boolean defaultConsent) { try { mService.recordFledgeDefaultConsent(defaultConsent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the measurement default consent of a user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordMeasurementDefaultConsent(boolean defaultConsent) { try { mService.recordMeasurementDefaultConsent(defaultConsent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the default AdId state of a user. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void recordDefaultAdIdState(boolean defaultAdIdState) { try { mService.recordDefaultAdIdState(defaultAdIdState); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Checks whether the AdServices module needs to handle data reconciliation after a rollback. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean needsToHandleRollbackReconciliation(@DeletionApiType int deletionType) { try { return mService.needsToHandleRollbackReconciliation(deletionType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the PP API default consent of a user. * * @return true if the PP API default consent is given, false otherwise. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean getDefaultConsent() { try { return mService.getDefaultConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the topics default consent of a user. * * @return true if the topics default consent is given, false otherwise. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean getTopicsDefaultConsent() { try { return mService.getTopicsDefaultConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the FLEDGE default consent of a user. * * @return true if the FLEDGE default consent is given, false otherwise. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean getFledgeDefaultConsent() { try { return mService.getFledgeDefaultConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the measurement default consent of a user. * * @return true if the measurement default consent is given, false otherwise. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean getMeasurementDefaultConsent() { try { return mService.getMeasurementDefaultConsent(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns the default AdId state of a user. * * @return true if the default AdId State is enabled, false otherwise. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean getDefaultAdIdState() { try { return mService.getDefaultAdIdState(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns the current privacy sandbox feature. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public String getCurrentPrivacySandboxFeature() { try { return mService.getCurrentPrivacySandboxFeature(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Set the current privacy sandbox feature. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setCurrentPrivacySandboxFeature(String featureType) { try { mService.setCurrentPrivacySandboxFeature(featureType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isAdIdEnabled bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isAdIdEnabled() { try { return mService.isAdIdEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isAdIdEnabled bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setAdIdEnabled(boolean isAdIdEnabled) { try { mService.setAdIdEnabled(isAdIdEnabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isU18Account bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isU18Account() { try { return mService.isU18Account(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isU18Account bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setU18Account(boolean isU18Account) { try { mService.setU18Account(isU18Account); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isEntryPointEnabled bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isEntryPointEnabled() { try { return mService.isEntryPointEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isEntryPointEnabled bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setEntryPointEnabled(boolean isEntryPointEnabled) { try { mService.setEntryPointEnabled(isEntryPointEnabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isAdultAccount bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isAdultAccount() { try { return mService.isAdultAccount(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isAdultAccount bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setAdultAccount(boolean isAdultAccount) { try { mService.setAdultAccount(isAdultAccount); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the wasU18NotificationDisplayed bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean wasU18NotificationDisplayed() { try { return mService.wasU18NotificationDisplayed(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the wasU18NotificationDisplayed bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed) { try { mService.setU18NotificationDisplayed(wasU18NotificationDisplayed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns the current UX. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public String getUx() { try { return mService.getUx(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Set the current UX. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setUx(String ux) { try { mService.setUx(ux); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns the current enrollment channel. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public String getEnrollmentChannel() { try { return mService.getEnrollmentChannel(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Set the current enrollment channel. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setEnrollmentChannel(String enrollmentChannel) { try { mService.setEnrollmentChannel(enrollmentChannel); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isMeasurementDataReset bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isMeasurementDataReset() { try { return mService.isMeasurementDataReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isMeasurementDataReset bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setMeasurementDataReset(boolean isMeasurementDataReset) { try { mService.setMeasurementDataReset(isMeasurementDataReset); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Returns whether the isPaDataReset bit is true. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public boolean isPaDataReset() { try { return mService.isPaDataReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Saves the isPaDataReset bit. */ @RequiresPermission(ACCESS_ADSERVICES_MANAGER) public void setPaDataReset(boolean isPaDataReset) { try { mService.setPaDataReset(isPaDataReset); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }