diff options
Diffstat (limited to 'adservices/service-core/java')
22 files changed, 409 insertions, 726 deletions
diff --git a/adservices/service-core/java/com/android/adservices/service/Flags.java b/adservices/service-core/java/com/android/adservices/service/Flags.java index 9b1a8de6f3..4fcbb820b6 100644 --- a/adservices/service-core/java/com/android/adservices/service/Flags.java +++ b/adservices/service-core/java/com/android/adservices/service/Flags.java @@ -709,7 +709,7 @@ public interface Flags extends CommonFlags { return MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_EVENT; } - float MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION = 11.46173F; + float MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION = 11.5F; /** Returns max information gain in Flexible Event API for Navigation sources */ default float getMeasurementFlexApiMaxInformationGainNavigation() { @@ -3522,14 +3522,6 @@ public interface Flags extends CommonFlags { return MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS; } - /** Disable early reporting windows configurability by default. */ - boolean MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS = false; - - /** Returns true if event reporting windows configurability is enabled, false otherwise. */ - default boolean getMeasurementEnableConfigurableEventReportingWindows() { - return MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS; - } - /** * Default early reporting windows for VTC type source. Derived from {@link * com.android.adservices.service.measurement.PrivacyParams#EVENT_EARLY_REPORTING_WINDOW_MILLISECONDS}. @@ -3589,18 +3581,8 @@ public interface Flags extends CommonFlags { return MEASUREMENT_AGGREGATE_REPORT_DELAY_CONFIG; } - /** Disable conversions configurability by default. */ - boolean DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS = false; - - /** - * Returns true, if event reports max conversions configurability is enabled, false otherwise. - */ - default boolean getMeasurementEnableVtcConfigurableMaxEventReports() { - return DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS; - } - - /** Disable conversions configurability by default. */ - int DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT = 2; + /** Default max allowed number of event reports. */ + int DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT = 1; /** Returns the default max allowed number of event reports. */ default int getMeasurementVtcConfigurableMaxEventReportsCount() { @@ -3983,11 +3965,11 @@ public interface Flags extends CommonFlags { } /** Default RVC NOTIFICATION feature flag.. */ - boolean DEFAULT_RVC_NOTIFICATION_ENABLED = false; + boolean DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED = false; /** RVC Notification feature flag.. */ - default boolean getEnableRvcNotification() { - return DEFAULT_RVC_NOTIFICATION_ENABLED; + default boolean getEnableRvcPostOtaNotification() { + return DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED; } /** Default enableAdServices system API feature flag.. */ @@ -4104,76 +4086,6 @@ public interface Flags extends CommonFlags { return MEASUREMENT_MIN_REPORTING_ORIGIN_UPDATE_WINDOW; } - float MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = 0.0000208f; - - /** - * {@link Source} Noise probability for 'Event' when both destinations (app and web) are - * available on the source and supports install attribution. - */ - default float getMeasurementInstallAttrDualDestinationEventNoiseProbability() { - return MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY; - } - - float MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY = 0.0170218f; - - /** - * {@link Source} Noise probability for 'Navigation' when both destinations (app and web) are - * available on the source. - */ - default float getMeasurementDualDestinationNavigationNoiseProbability() { - return MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY; - } - - float MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY = - MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY; - - /** - * {@link Source} Noise probability for 'Navigation' when both destinations (app and web) are - * available on the source and supports install attribution. - */ - default float getMeasurementInstallAttrDualDestinationNavigationNoiseProbability() { - return MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY; - } - - float MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = 0.0000042f; - - /** - * {@link Source} Noise probability for 'Event' when both destinations (app and web) are - * available on the source. - */ - default float getMeasurementDualDestinationEventNoiseProbability() { - return MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY; - } - - float MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY = 0.0000125f; - - /** {@link Source} Noise probability for 'Event' which supports install attribution. */ - default float getMeasurementInstallAttrEventNoiseProbability() { - return MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY; - } - - float MEASUREMENT_EVENT_NOISE_PROBABILITY = 0.0000025f; - - /** {@link Source} Noise probability for 'Event'. */ - default float getMeasurementEventNoiseProbability() { - return MEASUREMENT_EVENT_NOISE_PROBABILITY; - } - - float MEASUREMENT_NAVIGATION_NOISE_PROBABILITY = 0.0024263f; - - /** {@link Source} Noise probability for 'Navigation'. */ - default float getMeasurementNavigationNoiseProbability() { - return MEASUREMENT_NAVIGATION_NOISE_PROBABILITY; - } - - float MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY = - MEASUREMENT_NAVIGATION_NOISE_PROBABILITY; - - /** {@link Source} Noise probability for 'Navigation' which supports install attribution. */ - default float getMeasurementInstallAttrNavigationNoiseProbability() { - return MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY; - } - boolean MEASUREMENT_ENABLE_PREINSTALL_CHECK = false; /** Returns true when pre-install check is enabled. */ diff --git a/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java b/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java index 0f7570492b..2d4e6cb4ca 100644 --- a/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java +++ b/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java @@ -286,9 +286,6 @@ public final class FlagsConstants { public static final String KEY_MEASUREMENT_ENABLE_COARSE_EVENT_REPORT_DESTINATIONS = "measurement_enable_coarse_event_report_destinations"; - public static final String KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS = - "measurement_enable_vtc_configurable_max_event_reports_count"; - public static final String KEY_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT = "measurement_vtc_configurable_max_event_reports_count"; @@ -1071,9 +1068,6 @@ public final class FlagsConstants { public static final String KEY_MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS = "measurement_min_event_report_delay_millis"; - public static final String KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS = - "measurement_enable_configurable_event_reporting_windows"; - public static final String KEY_MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS = "measurement_event_reports_vtc_early_reporting_windows"; @@ -1139,32 +1133,6 @@ public final class FlagsConstants { public static final String KEY_MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH = "measurement_enable_redirect_to_well_known_path"; - public static final String - KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = - "measurement_install_attr_dual_destination_event_noise_probability"; - - public static final String KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY = - "measurement_dual_destination_navigation_noise_probability"; - - public static final String - KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY = - "measurement_install_attr_dual_destination_navigation_noise_probability"; - - public static final String KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = - "measurement_dual_destination_event_noise_probability"; - - public static final String KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY = - "measurement_install_attr_event_noise_probability"; - - public static final String KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY = - "measurement_install_attr_navigation_noise_probability"; - - public static final String KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY = - "measurement_event_noise_probability"; - - public static final String KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY = - "measurement_navigation_noise_probability"; - // Database Schema Version Flags public static final String KEY_ENABLE_DATABASE_SCHEMA_VERSION_8 = "enable_database_schema_version_8"; @@ -1178,7 +1146,8 @@ public final class FlagsConstants { public static final String KEY_RVC_UX_ENABLED = "rvc_ux_enabled"; - public static final String KEY_RVC_NOTIFICATION_ENABLED = "rvc_notification_enabled"; + public static final String KEY_RVC_POST_OTA_NOTIFICATION_ENABLED = + "rvc_post_ota_notification_enabled"; public static final String KEY_ENABLE_AD_SERVICES_SYSTEM_API = "enable_ad_services_system_api"; diff --git a/adservices/service-core/java/com/android/adservices/service/PhFlags.java b/adservices/service-core/java/com/android/adservices/service/PhFlags.java index e1a8b26790..e221e027d7 100644 --- a/adservices/service-core/java/com/android/adservices/service/PhFlags.java +++ b/adservices/service-core/java/com/android/adservices/service/PhFlags.java @@ -3481,16 +3481,6 @@ public final class PhFlags extends CommonPhFlags implements Flags { } @Override - public boolean getMeasurementEnableConfigurableEventReportingWindows() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getBoolean( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS, - /* defaultValue */ MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS); - } - - @Override public String getMeasurementEventReportsVtcEarlyReportingWindows() { // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. return DeviceConfig.getString( @@ -4298,49 +4288,6 @@ public final class PhFlags extends CommonPhFlags implements Flags { + getMeasurementMinReportingOriginUpdateWindow()); writer.println( "\t" - + FlagsConstants - .KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY - + " = " - + getMeasurementDualDestinationNavigationNoiseProbability()); - writer.println( - "\t" - + FlagsConstants - .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY - + " = " - + getMeasurementInstallAttrDualDestinationEventNoiseProbability()); - writer.println( - "\t" - + FlagsConstants - .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY - + " = " - + getMeasurementInstallAttrDualDestinationNavigationNoiseProbability()); - writer.println( - "\t" - + FlagsConstants.KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY - + " = " - + getMeasurementDualDestinationEventNoiseProbability()); - writer.println( - "\t" - + FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY - + " = " - + getMeasurementInstallAttrEventNoiseProbability()); - writer.println( - "\t" - + FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY - + " = " - + getMeasurementInstallAttrNavigationNoiseProbability()); - writer.println( - "\t" - + FlagsConstants.KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY - + " = " - + getMeasurementEventNoiseProbability()); - writer.println( - "\t" - + FlagsConstants.KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY - + " = " - + getMeasurementNavigationNoiseProbability()); - writer.println( - "\t" + FlagsConstants.KEY_MEASUREMENT_REGISTRATION_JOB_QUEUE_KILL_SWITCH + " = " + getAsyncRegistrationJobQueueKillSwitch()); @@ -4386,11 +4333,6 @@ public final class PhFlags extends CommonPhFlags implements Flags { + getMeasurementMinEventReportDelayMillis()); writer.println( "\t" - + FlagsConstants.KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS - + " = " - + getMeasurementEnableConfigurableEventReportingWindows()); - writer.println( - "\t" + FlagsConstants.KEY_MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS + " = " + getMeasurementEventReportsVtcEarlyReportingWindows()); @@ -5705,12 +5647,12 @@ public final class PhFlags extends CommonPhFlags implements Flags { } @Override - public boolean getEnableRvcNotification() { + public boolean getEnableRvcPostOtaNotification() { return getEnableAdServicesSystemApi() && DeviceConfig.getBoolean( FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED, - /* defaultValue */ DEFAULT_RVC_NOTIFICATION_ENABLED); + /* flagName */ FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED, + /* defaultValue */ DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED); } @Override @@ -5733,7 +5675,9 @@ public final class PhFlags extends CommonPhFlags implements Flags { getRecordManualInteractionEnabled()); uxMap.put(FlagsConstants.KEY_GA_UX_FEATURE_ENABLED, getGaUxFeatureEnabled()); uxMap.put(FlagsConstants.KEY_RVC_UX_ENABLED, getEnableRvcUx()); - uxMap.put(FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED, getEnableRvcNotification()); + uxMap.put( + FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED, + getEnableRvcPostOtaNotification()); uxMap.put( FlagsConstants.KEY_UI_OTA_STRINGS_FEATURE_ENABLED, getUiOtaStringsFeatureEnabled()); uxMap.put( @@ -5866,83 +5810,6 @@ public final class PhFlags extends CommonPhFlags implements Flags { } @Override - public float getMeasurementInstallAttrDualDestinationEventNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementDualDestinationNavigationNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementInstallAttrDualDestinationNavigationNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementDualDestinationEventNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementInstallAttrEventNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementInstallAttrNavigationNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementEventNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants.KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_EVENT_NOISE_PROBABILITY); - } - - @Override - public float getMeasurementNavigationNoiseProbability() { - // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. - return DeviceConfig.getFloat( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants.KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, - /* defaultValue */ MEASUREMENT_NAVIGATION_NOISE_PROBABILITY); - } - - @Override public boolean getMeasurementEnablePreinstallCheck() { // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value. return DeviceConfig.getBoolean( @@ -5952,16 +5819,6 @@ public final class PhFlags extends CommonPhFlags implements Flags { } @Override - public boolean getMeasurementEnableVtcConfigurableMaxEventReports() { - return DeviceConfig.getBoolean( - FlagsConstants.NAMESPACE_ADSERVICES, - /* flagName */ FlagsConstants - .KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS, - /* defaultValue */ - DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS); - } - - @Override public int getMeasurementVtcConfigurableMaxEventReportsCount() { return DeviceConfig.getInt( FlagsConstants.NAMESPACE_ADSERVICES, 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 63016c24d3..9bff5dea67 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 @@ -332,7 +332,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -370,7 +370,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -473,7 +473,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -762,7 +762,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -805,7 +805,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, requestParams.getCallerPackageName(), apiName); DevContext devContext = mDevContextFilter.createDevContext(); @@ -871,7 +871,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); int callerUid = getCallingUid(apiName); @@ -928,7 +928,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, request.getCallerPackageName(), apiName); AppInstallAdvertisersSetter setter = @@ -960,7 +960,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, inputParams.getCallerPackageName(), apiName); final int callingUid = getCallingUid(apiName); @@ -1033,7 +1033,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1100,7 +1100,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1150,7 +1150,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1205,7 +1205,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1256,7 +1256,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1305,7 +1305,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); int callingUid = getCallingUid(apiName); @@ -1355,7 +1355,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); // TODO(b/265204820): Implement service @@ -1393,7 +1393,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); // TODO(b/265204820): Implement service @@ -1428,7 +1428,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); // TODO(b/265204820): Implement service diff --git a/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java b/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java index c99b0b9a39..7809ecd409 100644 --- a/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java +++ b/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java @@ -123,47 +123,22 @@ public class FledgeAuthorizationFilter { * @param apiNameLoggingId the id of the api being called * @throws SecurityException if the package did not declare custom audience permission */ - public void assertAppDeclaredCustomAudiencePermission( + public void assertAppDeclaredPermission( @NonNull Context context, @NonNull String appPackageName, int apiNameLoggingId) throws SecurityException { Objects.requireNonNull(context); Objects.requireNonNull(appPackageName); if (!PermissionHelper.hasCustomAudiencesPermission(context, appPackageName)) { - logAndThrowPermissionFailure(apiNameLoggingId); - } - } - - /** - * Check if the app had declared the protected signals permission. - * - * @param context api service context - * @param apiNameLoggingId the id of the api being called - * @throws SecurityException if the package did not declare custom audience permission - */ - public void assertAppDeclaredProtectedSignalsPermission( - @NonNull Context context, @NonNull String appPackageName, int apiNameLoggingId) - throws SecurityException { - Objects.requireNonNull(context); - Objects.requireNonNull(appPackageName); - - if (!PermissionHelper.hasProtectedSignalsPermission(context, appPackageName)) { - /* - * Using the same message for both since getAdSelectionData can be called with either - * permission and we don't want the error message to depend on which is checked first. - */ - logAndThrowPermissionFailure(apiNameLoggingId); + sLogger.v("Permission not declared by caller in API %d", apiNameLoggingId); + mAdServicesLogger.logFledgeApiCallStats( + apiNameLoggingId, STATUS_PERMISSION_NOT_REQUESTED, 0); + throw new SecurityException( + AdServicesStatusUtils + .SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE); } } - private void logAndThrowPermissionFailure(int apiNameLoggingId) { - sLogger.v("Permission not declared by caller in API %d", apiNameLoggingId); - mAdServicesLogger.logFledgeApiCallStats( - apiNameLoggingId, STATUS_PERMISSION_NOT_REQUESTED, 0); - throw new SecurityException( - AdServicesStatusUtils.SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE); - } - /** * Check if a certain ad tech is enrolled and authorized to perform the operation for the * package. diff --git a/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java b/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java index e2afca1366..35d6ff658c 100644 --- a/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java +++ b/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java @@ -295,6 +295,10 @@ public class PackageChangedReceiver extends BroadcastReceiver { @VisibleForTesting void consentOnPackageFullyRemoved( @NonNull Context context, @NonNull Uri packageUri, int packageUid) { + if (!SdkLevel.isAtLeastS()) { + LogUtil.d("consentOnPackageFullyRemoved is not needed on Android R, returning..."); + return; + } Objects.requireNonNull(context); Objects.requireNonNull(packageUri); diff --git a/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java b/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java index 67142b6d3e..d02225e4ed 100644 --- a/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java +++ b/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java @@ -101,16 +101,6 @@ public final class PermissionHelper { } /** - * @return {@code true} if the caller has the permission to invoke Protected Signals APIs. - */ - public static boolean hasProtectedSignalsPermission( - @NonNull Context context, @NonNull String appPackageName) { - // TODO(b/236268316): Add check for SDK permission. - return hasPermission( - context, appPackageName, AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS); - } - - /** * @return {@code true} if the caller has the permission to invoke AdService's state * modification API. */ diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java index 900ffd58f3..1b2a3bcb85 100644 --- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java +++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java @@ -39,6 +39,7 @@ import android.app.job.JobScheduler; import android.content.Context; import android.content.SharedPreferences; import android.os.Build; +import android.os.Trace; import androidx.annotation.RequiresApi; @@ -206,6 +207,7 @@ public class ConsentManager { public static ConsentManager getInstance(@NonNull Context context) { Objects.requireNonNull(context); + Trace.beginSection("ConsentManager#Initialization"); if (sConsentManager == null) { synchronized (LOCK) { if (sConsentManager == null) { @@ -253,7 +255,8 @@ public class ConsentManager { context, datastore, appSearchConsentManager, - adServicesExtDataManager); + adServicesExtDataManager, + statsdAdServicesLogger); } } @@ -288,6 +291,7 @@ public class ConsentManager { } } } + Trace.endSection(); return sConsentManager; } @@ -2154,6 +2158,7 @@ public class ConsentManager { for back compat. */ ThrowableSetter ppapiAndAdExtDataServiceSetter, ErrorLogger errorLogger) { + Trace.beginSection("ConsentManager#WriteOperation"); mReadWriteLock.writeLock().lock(); try { switch (mConsentSourceOfTruth) { @@ -2188,8 +2193,8 @@ public class ConsentManager { throw new RuntimeException(getClass().getSimpleName() + " failed. " + e.getMessage()); } finally { mReadWriteLock.writeLock().unlock(); + Trace.endSection(); } - } @FunctionalInterface @@ -2218,6 +2223,7 @@ public class ConsentManager { for back compat. */ ThrowableGetter<T> ppapiAndAdExtDataServiceGetter, ErrorLogger errorLogger) { + Trace.beginSection("ConsentManager#ReadOperation"); mReadWriteLock.readLock().lock(); try { switch (mConsentSourceOfTruth) { @@ -2248,6 +2254,7 @@ public class ConsentManager { LogUtil.e(getClass().getSimpleName() + " failed. " + e.getMessage()); } finally { mReadWriteLock.readLock().unlock(); + Trace.endSection(); } return defaultReturn; @@ -2260,8 +2267,20 @@ public class ConsentManager { : AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW; } - /* Returns an object of ConsentMigrationStats */ - private static ConsentMigrationStats getConsentManagerStatsForLogging( + /*** + * Returns an object of ConsentMigrationStats for logging + * + * @param appConsents AppConsents consents per API (fledge, msmt, topics, default) + * @param migrationStatus Status of migration ( FAILURE, SUCCESS_WITH_SHARED_PREF_UPDATED, + * SUCCESS_WITH_SHARED_PREF_NOT_UPDATED) + * @param migrationType Type of migration ( PPAPI_TO_SYSTEM_SERVICE, + * APPSEARCH_TO_SYSTEM_SERVICE, + * ADEXT_SERVICE_TO_SYSTEM_SERVICE, + * ADEXT_SERVICE_TO_APPSEARCH) + * @param context Context of the application + * @return consentMigrationStats returns ConsentMigrationStats for logging + */ + public static ConsentMigrationStats getConsentManagerStatsForLogging( AppConsents appConsents, ConsentMigrationStats.MigrationStatus migrationStatus, ConsentMigrationStats.MigrationType migrationType, @@ -2269,7 +2288,6 @@ public class ConsentManager { ConsentMigrationStats consentMigrationStats = ConsentMigrationStats.builder() .setMigrationType(migrationType) - .setMigrationStatus(migrationStatus) // When appConsents is null we log it as a failure .setMigrationStatus( appConsents != null diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java index 2ea541bc53..9bd7afd617 100644 --- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java +++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java @@ -20,6 +20,8 @@ import static android.adservices.extdata.AdServicesExtDataParams.BOOLEAN_TRUE; import static android.adservices.extdata.AdServicesExtDataParams.BOOLEAN_UNKNOWN; import static android.adservices.extdata.AdServicesExtDataParams.STATE_MANUAL_INTERACTIONS_RECORDED; +import static com.android.adservices.service.consent.ConsentManager.getConsentManagerStatsForLogging; + import android.adservices.extdata.AdServicesExtDataParams; import android.annotation.NonNull; import android.annotation.TargetApi; @@ -35,6 +37,8 @@ import com.android.adservices.service.appsearch.AppSearchConsentManager; import com.android.adservices.service.appsearch.AppSearchConsentStorageManager; import com.android.adservices.service.common.compat.FileCompatUtils; import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager; +import com.android.adservices.service.stats.ConsentMigrationStats; +import com.android.adservices.service.stats.StatsdAdServicesLogger; import com.android.modules.utils.build.SdkLevel; import java.util.Objects; @@ -51,16 +55,18 @@ public final class ConsentMigrationUtils { * as it's the new consent source of truth. If any new data is written for consent, we need to * make sure it is migrated correctly post-OTA in this method. */ + @TargetApi(Build.VERSION_CODES.S) public static void handleConsentMigrationToAppSearchIfNeeded( @NonNull Context context, @NonNull BooleanFileDatastore datastore, @Nullable AppSearchConsentManager appSearchConsentManager, - @Nullable AdServicesExtDataStorageServiceManager adExtDataManager) { + @Nullable AdServicesExtDataStorageServiceManager adExtDataManager, + @Nullable StatsdAdServicesLogger statsdAdServicesLogger) { Objects.requireNonNull(context); Objects.requireNonNull(datastore); + Objects.requireNonNull(statsdAdServicesLogger); LogUtil.d("Check if consent migration to AppSearch is needed."); - - // TODO (b/306753680): Add consent migration logging. + AppConsents appConsents = null; try { SharedPreferences sharedPreferences = FileCompatUtils.getSharedPreferencesHelper( @@ -79,20 +85,34 @@ public final class ConsentMigrationUtils { return; } - migrateDataToAppSearch(appSearchConsentManager, dataFromR, datastore); + appConsents = migrateDataToAppSearch(appSearchConsentManager, dataFromR, datastore); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED_TO_APP_SEARCH, true); if (editor.commit()) { LogUtil.d("Finished migrating consent to AppSearch."); + logMigrationToAppSearch( + statsdAdServicesLogger, + appConsents, + ConsentMigrationStats.MigrationStatus.SUCCESS_WITH_SHARED_PREF_UPDATED, + context); } else { LogUtil.e("Finished migrating consent to AppSearch. Shared prefs not updated."); + logMigrationToAppSearch( + statsdAdServicesLogger, + appConsents, + ConsentMigrationStats.MigrationStatus.SUCCESS_WITH_SHARED_PREF_NOT_UPDATED, + context); } - // No longer need access to Android R data. Safe to clear here. adExtDataManager.clearDataOnOtaAsync(); } catch (Exception e) { LogUtil.e("Consent migration to AppSearch failed: ", e); + logMigrationToAppSearch( + statsdAdServicesLogger, + appConsents, + ConsentMigrationStats.MigrationStatus.FAILURE, + context); } } @@ -244,7 +264,7 @@ public final class ConsentMigrationUtils { } @TargetApi(Build.VERSION_CODES.S) - private static void migrateDataToAppSearch( + private static AppConsents migrateDataToAppSearch( AppSearchConsentManager appSearchConsentManager, AdServicesExtDataParams dataFromR, BooleanFileDatastore datastore) { @@ -278,6 +298,34 @@ public final class ConsentMigrationUtils { if (dataFromR.getIsAdultAccount() != BOOLEAN_UNKNOWN) { appSearchConsentManager.setAdultAccount(dataFromR.getIsAdultAccount() == BOOLEAN_TRUE); } + + // Logging false for fledge and topics consent by default because only measurement is + // supported on R. + AppConsents appConsents = + AppConsents.builder() + .setDefaultConsent( + measurementDefaultConsent != null + ? measurementDefaultConsent + : false) + .setMsmtConsent(isMeasurementConsented) + .setFledgeConsent(false) + .setTopicsConsent(false) + .build(); + return appConsents; + } + + @TargetApi(Build.VERSION_CODES.S) + private static void logMigrationToAppSearch( + StatsdAdServicesLogger statsdAdServicesLogger, + AppConsents appConsents, + ConsentMigrationStats.MigrationStatus migrationStatus, + Context context) { + statsdAdServicesLogger.logConsentMigrationStats( + getConsentManagerStatsForLogging( + appConsents, + migrationStatus, + ConsentMigrationStats.MigrationType.ADEXT_SERVICE_TO_APPSEARCH, + context)); } @TargetApi(Build.VERSION_CODES.S) 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 8373bb5ebb..fcab6c9a88 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 @@ -203,8 +203,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( - mContext, ownerPackageName, apiName); + mFledgeAuthorizationFilter.assertAppDeclaredPermission(mContext, ownerPackageName, apiName); final int callerUid = getCallingUid(apiName); final DevContext devContext = mDevContextFilter.createDevContext(); @@ -301,7 +300,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, input.getCallerPackageName(), apiName); final int callerUid = getCallingUid(apiName); @@ -386,8 +385,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( - mContext, ownerPackageName, apiName); + mFledgeAuthorizationFilter.assertAppDeclaredPermission(mContext, ownerPackageName, apiName); final int callerUid = getCallingUid(apiName); final DevContext devContext = mDevContextFilter.createDevContext(); @@ -506,7 +504,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao(); @@ -567,7 +565,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao(); @@ -616,7 +614,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub { } // Caller permissions must be checked with a non-null callingAppPackageName - mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, devContext.getCallingAppPackageName(), apiName); CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao(); diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java b/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java index 00a945fa96..b62df02677 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java @@ -37,11 +37,6 @@ public final class PrivacyParams { public static final int EVENT_SOURCE_MAX_REPORTS = 1; /** - * Max reports for Install Attributed 'Navigation' {@link Source}. - */ - public static final int INSTALL_ATTR_NAVIGATION_SOURCE_MAX_REPORTS = 3; - - /** * Max reports for Install Attributed 'Event' {@link Source}. */ public static final int INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS = 2; diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/Source.java b/adservices/service-core/java/com/android/adservices/service/measurement/Source.java index 2fe5e16b0d..35da5c7058 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/Source.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/Source.java @@ -121,6 +121,7 @@ public class Source { if (mParsedEventReportWindows != null) { return mParsedEventReportWindows; } + if (mEventReportWindows == null) { return null; } @@ -140,7 +141,8 @@ public class Source { } /** - * Returns parsed or default value of event report windows. + * Returns parsed or default value of event report windows (can be used during {@code Source} + * construction since the method does not require a {@code Source} object). * * @param eventReportWindows string to be parsed * @param sourceType Source's Type @@ -149,13 +151,13 @@ public class Source { * @return parsed or default value */ @Nullable - public static List<Pair<Long, Long>> getOrDefaultEventReportWindows( + public static List<Pair<Long, Long>> getOrDefaultEventReportWindowsForFlex( @Nullable JSONObject eventReportWindows, @NonNull SourceType sourceType, long expiryDelta, @NonNull Flags flags) { if (eventReportWindows == null) { - return getDefaultEventReportWindows(expiryDelta, sourceType, flags); + return getDefaultEventReportWindowsForFlex(expiryDelta, sourceType, flags); } return parseEventReportWindows(eventReportWindows); } @@ -180,17 +182,17 @@ public class Source { @NonNull JSONObject jsonObject) { List<Pair<Long, Long>> result = new ArrayList<>(); try { - long startDuration = 0; + long startTime = 0L; if (!jsonObject.isNull("start_time")) { - startDuration = jsonObject.getLong("start_time"); + startTime = jsonObject.getLong("start_time"); } JSONArray endTimesJSON = jsonObject.getJSONArray("end_times"); for (int i = 0; i < endTimesJSON.length(); i++) { - long endDuration = endTimesJSON.getLong(i); - Pair<Long, Long> window = new Pair<>(startDuration, endDuration); + long endTime = endTimesJSON.getLong(i); + Pair<Long, Long> window = Pair.create(startTime, endTime); result.add(window); - startDuration = endDuration; + startTime = endTime; } } catch (JSONException e) { LoggerFactory.getMeasurementLogger() @@ -200,24 +202,25 @@ public class Source { return result; } - private static List<Pair<Long, Long>> getDefaultEventReportWindows( + private static List<Pair<Long, Long>> getDefaultEventReportWindowsForFlex( long expiryDelta, SourceType sourceType, Flags flags) { List<Pair<Long, Long>> result = new ArrayList<>(); - List<Long> defaultEarlyWindows = - EventReportWindowCalcDelegate.getDefaultEarlyReportingWindows(sourceType, false); - List<Long> earlyWindows = + // Obtain default early report windows without regard to install-related behaviour. + List<Long> defaultEarlyWindowEnds = + EventReportWindowCalcDelegate.getDefaultEarlyReportingWindowEnds(sourceType, false); + List<Long> earlyWindowEnds = new EventReportWindowCalcDelegate(flags) - .getConfiguredOrDefaultEarlyReportingWindows( - sourceType, defaultEarlyWindows, false); + .getConfiguredOrDefaultEarlyReportingWindowEnds( + sourceType, defaultEarlyWindowEnds); long windowStart = 0; - for (long earlyWindow : earlyWindows) { - if (earlyWindow >= expiryDelta) { - continue; + for (long earlyWindowEnd : earlyWindowEnds) { + if (earlyWindowEnd >= expiryDelta) { + break; } - result.add(new Pair<>(windowStart, earlyWindow)); - windowStart = earlyWindow; + result.add(Pair.create(windowStart, earlyWindowEnd)); + windowStart = earlyWindowEnd; } - result.add(new Pair<>(windowStart, expiryDelta)); + result.add(Pair.create(windowStart, expiryDelta)); return result; } @@ -234,8 +237,7 @@ public class Source { } private double getInformationGainThreshold(Flags flags) { - int destinationMultiplier = getDestinationTypeMultiplier(flags); - if (destinationMultiplier == 2) { + if (getDestinationTypeMultiplier(flags) == 2) { return mSourceType == SourceType.EVENT ? flags.getMeasurementFlexApiMaxInformationGainDualDestinationEvent() : flags.getMeasurementFlexApiMaxInformationGainDualDestinationNavigation(); @@ -262,32 +264,31 @@ public class Source { setFlipProbability(mTriggerSpecs.getFlipProbability(this, flags)); return; } - boolean installCase = SourceNoiseHandler.isInstallDetectionEnabled(this); EventReportWindowCalcDelegate eventReportWindowCalcDelegate = new EventReportWindowCalcDelegate(flags); int reportingWindowCountForNoising = - eventReportWindowCalcDelegate.getReportingWindowCountForNoising(this, installCase); - int maxReportCount = - eventReportWindowCalcDelegate.getMaxReportCount(this, installCase); - int destinationMultiplier = getDestinationTypeMultiplier(flags); + eventReportWindowCalcDelegate.getReportingWindowCountForNoising(this); long numberOfStates = Combinatorics.getNumberOfStarsAndBarsSequences( - /*numStars=*/ maxReportCount, + /*numStars=*/ eventReportWindowCalcDelegate.getMaxReportCount(this), /*numBars=*/ getTriggerDataCardinality() * reportingWindowCountForNoising - * destinationMultiplier); + * getDestinationTypeMultiplier(flags)); setNumStates(numberOfStates); setFlipProbability(Combinatorics.getFlipProbability(numberOfStates)); } + /** Should source report coarse destinations */ + public boolean shouldReportCoarseDestinations(Flags flags) { + return flags.getMeasurementEnableCoarseEventReportDestinations() + && hasCoarseEventReportDestinations(); + } + /** * Returns the number of destination types to use in privacy computations. */ public int getDestinationTypeMultiplier(Flags flags) { - boolean shouldReportCoarseDestinations = - flags.getMeasurementEnableCoarseEventReportDestinations() - && hasCoarseEventReportDestinations(); - return !shouldReportCoarseDestinations && hasAppDestinations() + return !shouldReportCoarseDestinations(flags) && hasAppDestinations() && hasWebDestinations() ? SourceNoiseHandler.DUAL_DESTINATION_IMPRESSION_NOISE_MULTIPLIER : SourceNoiseHandler.SINGLE_DESTINATION_IMPRESSION_NOISE_MULTIPLIER; @@ -650,9 +651,9 @@ public class Source { /** * Time when {@link Source} event report window will expire. (Appends the Event Time to window) */ - public Long getProcessedEventReportWindow() { + public long getEffectiveEventReportWindow() { if (mEventReportWindow == null) { - return null; + return getExpiryTime(); } // TODO(b/290098169): Cleanup after a few releases // Handling cases where ReportWindow is already stored as mEventTime + mEventReportWindow @@ -744,6 +745,11 @@ public class Source { return mInstallCooldownWindow; } + /** Check if install detection is enabled for the source. */ + public boolean isInstallDetectionEnabled() { + return getInstallCooldownWindow() > 0 && hasAppDestinations(); + } + /** * Is an App-install attributed to the {@link Source}. */ @@ -971,10 +977,9 @@ public class Source { @Nullable Integer maxEventLevelReports, @NonNull Flags flags) { if (maxEventLevelReports == null) { - maxEventLevelReports = - sourceType == Source.SourceType.NAVIGATION - ? PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS - : flags.getMeasurementVtcConfigurableMaxEventReportsCount(); + return sourceType == Source.SourceType.NAVIGATION + ? PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS + : flags.getMeasurementVtcConfigurableMaxEventReportsCount(); } return maxEventLevelReports; } diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java index 58251ca9a2..3d2eec8c2c 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java @@ -1329,16 +1329,10 @@ class AttributionJobHandler { private boolean isWithinReportLimit( Source source, int existingReportCount, @EventSurfaceType int destinationType) { - return mEventReportWindowCalcDelegate.getMaxReportCount( - source, hasAppInstallAttributionOccurred(source, destinationType)) + return mEventReportWindowCalcDelegate.getMaxReportCount(source, destinationType) > existingReportCount; } - private static boolean hasAppInstallAttributionOccurred( - Source source, @EventSurfaceType int destinationType) { - return destinationType == EventSurfaceType.APP && source.isInstallAttributed(); - } - private static boolean isWithinInstallCooldownWindow(Source source, Trigger trigger) { return trigger.getTriggerTime() < (source.getEventTime() + source.getInstallCooldownWindow()); diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java b/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java index 0a456919f9..c83f608b64 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java @@ -29,72 +29,6 @@ import java.util.concurrent.ThreadLocalRandom; */ public final class ImpressionNoiseUtil { - /** - * This is used in the scenario where both app and web destinations are available with the - * {@link com.android.adservices.service.measurement.Source} and the source is of {@link - * com.android.adservices.service.measurement.Source.SourceType#EVENT} type and post-install - * detection is enabled (cooldown window being available). It's a special case because in this - * condition an extra early window is added only if install detection is enabled (install - * cool-down window is available) and only app conversions are relevant in that window. - * - * <p>Reading guide - The outermost array signifies different states of reporting - one of them - * will be picked at a time. The middle array holds reports in 1st and 2nd window, so there will - * be either 0 elements (no conversions in either window), 1 element (a conversion report in one - * of the windows) and 2 elements (conversions in both windows). The innermost array represents - * a single report. 3 elements in the innermost array are trigger metadata (0 - trigger1 or 1 - - * trigger2), window index (0 - window1, 1 - window2) and destination type (0 - app or 1 - web). - * - * <p>E.g. The element at index 5 is {{0, 1, 0}, {0, 1, 0}}, it means 2 conversions with trigger - * metadata as 0 in window2 (1) of app destination type(0). - */ - public static final int[][][] DUAL_DESTINATION_POST_INSTALL_FAKE_REPORT_CONFIG = - new int[][][] { - // window1 - no conversion, window 2 - no conversion - {}, - // window1 - no conversion, window 2 - 1 conversion with metadata 0 - {{0, 1, 0}}, - {{0, 1, 1}}, - // window1 - no conversion, window 2 - 1 conversion with metadata 1 - {{1, 1, 0}}, - {{1, 1, 1}}, - // window1 - no conversion, window 2 - 2 conversions with metadata 0 and 0 - {{0, 1, 0}, {0, 1, 0}}, - {{0, 1, 0}, {0, 1, 1}}, - // window1 - no conversion, window 2 - 2 conversions with metadata 0 and 1 - {{0, 1, 0}, {1, 1, 0}}, - {{0, 1, 0}, {1, 1, 1}}, - {{0, 1, 1}, {1, 1, 0}}, - // window1 - no conversion, window 2 - 2 conversions with metadata 1 and 1 - {{1, 1, 0}, {1, 1, 0}}, - {{1, 1, 0}, {1, 1, 1}}, - // window1 - 1 app conversion with metadata 0, window 2 - no conversion - {{0, 0, 0}}, - // window1 - 1 app conversion with metadata 1, window 2 - no conversion - {{1, 0, 0}}, - // window1 - 2 conversions with metadata 0 and 0, window 2 - no conversion - {{0, 0, 0}, {0, 0, 0}}, - // window1 - 2 app conversions with metadata 0 and 1, window 2 - no conversion - {{0, 0, 0}, {1, 0, 0}}, - // window1 - 2 app conversions with metadata 1 and 1, window 2 - no conversion - {{1, 0, 0}, {1, 0, 0}}, - // window1 - 1 app conversion with metadata 0, window 2 - 1 conversion with - // metadata 0 - {{0, 0, 0}, {0, 1, 0}}, - {{0, 0, 0}, {0, 1, 1}}, - // window1 - 1 app conversion with metadata 0, window 2 - 1 conversion with - // metadata 1 - {{0, 0, 0}, {1, 1, 0}}, - {{0, 0, 0}, {1, 1, 1}}, - // window1 - 1 app conversion with metadata 1, window 2 - 1 conversions with - // metadata 0 - {{1, 0, 0}, {0, 1, 0}}, - {{1, 0, 0}, {0, 1, 1}}, - // window1 - 1 app conversion with metadata 1, window 2 - 1 conversions with - // metadata 1 - {{1, 0, 0}, {1, 1, 0}}, - {{1, 0, 0}, {1, 1, 1}} - }; - private ImpressionNoiseUtil() {} /** diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java index 2c28fa51e5..8897662a95 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java @@ -30,11 +30,9 @@ import com.google.common.collect.ImmutableList; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -85,33 +83,24 @@ public class SourceNoiseHandler { List<Source.FakeReport> fakeReports; TriggerSpecs triggerSpecs = source.getTriggerSpecs(); if (triggerSpecs == null) { - if (isVtcDualDestinationModeWithPostInstallEnabled(source)) { - // Source is 'EVENT' type, both app and web destination are set and install - // exclusivity - // window is provided. Pick one of the static reporting states randomly. - fakeReports = generateVtcDualDestinationPostInstallFakeReports(source); - } else { - // There will at least be one (app or web) destination available - ImpressionNoiseParams noiseParams = getImpressionNoiseParams(source); - fakeReports = - ImpressionNoiseUtil.selectRandomStateAndGenerateReportConfigs( - noiseParams, rand) - .stream() - .map( - reportConfig -> - new Source.FakeReport( - new UnsignedLong( - Long.valueOf(reportConfig[0])), - mEventReportWindowCalcDelegate - .getReportingTimeForNoising( - source, - reportConfig[1], - isInstallDetectionEnabled( - source)), - resolveFakeReportDestinations( - source, reportConfig[2]))) - .collect(Collectors.toList()); - } + // There will at least be one (app or web) destination available + ImpressionNoiseParams noiseParams = getImpressionNoiseParams(source); + fakeReports = + ImpressionNoiseUtil.selectRandomStateAndGenerateReportConfigs( + noiseParams, rand) + .stream() + .map( + reportConfig -> + new Source.FakeReport( + new UnsignedLong( + Long.valueOf(reportConfig[0])), + mEventReportWindowCalcDelegate + .getReportingTimeForNoising( + source, + reportConfig[1]), + resolveFakeReportDestinations( + source, reportConfig[2]))) + .collect(Collectors.toList()); } else { int destinationTypeMultiplier = source.getDestinationTypeMultiplier(mFlags); List<int[]> fakeReportConfigs = @@ -144,51 +133,11 @@ public class SourceNoiseHandler { /** @return Probability of selecting random state for attribution */ public double getRandomAttributionProbability(@NonNull Source source) { - if (source.getTriggerSpecs() != null - || mFlags.getMeasurementEnableConfigurableEventReportingWindows() - || mFlags.getMeasurementEnableVtcConfigurableMaxEventReports() - || (mFlags.getMeasurementFlexLiteApiEnabled() - && (source.getMaxEventLevelReports() != null - || source.hasManualEventReportWindows()))) { - return convertToDoubleAndLimitDecimal(source.getFlipProbability(mFlags)); - } - // TODO(b/290117352): Remove Hardcoded noise values - - // Both destinations are set and install attribution is supported - if (!shouldReportCoarseDestinations(source) - && source.hasWebDestinations() - && isInstallDetectionEnabled(source)) { - return source.getSourceType() == Source.SourceType.EVENT - ? convertToDoubleAndLimitDecimal( - mFlags.getMeasurementInstallAttrDualDestinationEventNoiseProbability()) - : convertToDoubleAndLimitDecimal( - mFlags.getMeasurementInstallAttrDualDestinationNavigationNoiseProbability()); - } - - // Both destinations are set but install attribution isn't supported - if (!shouldReportCoarseDestinations(source) - && source.hasAppDestinations() - && source.hasWebDestinations()) { - return source.getSourceType() == Source.SourceType.EVENT - ? convertToDoubleAndLimitDecimal( - mFlags.getMeasurementDualDestinationEventNoiseProbability()) - : convertToDoubleAndLimitDecimal( - mFlags.getMeasurementDualDestinationNavigationNoiseProbability()); - } - - // App destination is set and install attribution is supported - if (isInstallDetectionEnabled(source)) { - return source.getSourceType() == Source.SourceType.EVENT - ? convertToDoubleAndLimitDecimal( - mFlags.getMeasurementInstallAttrEventNoiseProbability()) - : convertToDoubleAndLimitDecimal( - mFlags.getMeasurementInstallAttrNavigationNoiseProbability()); - } - - // One of the destinations is available without install attribution support - return source.getSourceType() == Source.SourceType.EVENT - ? convertToDoubleAndLimitDecimal(mFlags.getMeasurementEventNoiseProbability()) - : convertToDoubleAndLimitDecimal(mFlags.getMeasurementNavigationNoiseProbability()); + // Methods on Source and EventReportWindowCalcDelegate that calculate flip probability for + // the source rely on reporting windows and max reports that are obtained with consideration + // to install-state and its interaction with configurable report windows and configurable + // max reports. + return convertToDoubleAndLimitDecimal(source.getFlipProbability(mFlags)); } private double convertToDoubleAndLimitDecimal(double probability) { @@ -197,15 +146,6 @@ public class SourceNoiseHandler { .doubleValue(); } - private boolean isVtcDualDestinationModeWithPostInstallEnabled(Source source) { - return !shouldReportCoarseDestinations(source) - && !source.hasManualEventReportWindows() - && source.getMaxEventLevelReports() == null - && source.getSourceType() == Source.SourceType.EVENT - && source.hasWebDestinations() - && isInstallDetectionEnabled(source); - } - /** * Either both app and web destinations can be available or one of them will be available. When * both destinations are available, we double the number of states at noise generation to be @@ -216,7 +156,7 @@ public class SourceNoiseHandler { * @return app or web destination {@link Uri} */ private List<Uri> resolveFakeReportDestinations(Source source, int destinationIdentifier) { - if (shouldReportCoarseDestinations(source)) { + if (source.shouldReportCoarseDestinations(mFlags)) { ImmutableList.Builder<Uri> destinations = new ImmutableList.Builder<>(); Optional.ofNullable(source.getAppDestinations()).ifPresent(destinations::addAll); Optional.ofNullable(source.getWebDestinations()).ifPresent(destinations::addAll); @@ -234,44 +174,13 @@ public class SourceNoiseHandler { : source.getWebDestinations(); } - /** Check if install detection is enabled for the source. */ - public static boolean isInstallDetectionEnabled(@NonNull Source source) { - return source.getInstallCooldownWindow() > 0 && source.hasAppDestinations(); - } - - private boolean shouldReportCoarseDestinations(Source source) { - return mFlags.getMeasurementEnableCoarseEventReportDestinations() - && source.hasCoarseEventReportDestinations(); - } - - private List<Source.FakeReport> generateVtcDualDestinationPostInstallFakeReports( - Source source) { - int[][][] fakeReportsConfig = - ImpressionNoiseUtil.DUAL_DESTINATION_POST_INSTALL_FAKE_REPORT_CONFIG; - int randomIndex = new Random().nextInt(fakeReportsConfig.length); - int[][] reportsConfig = fakeReportsConfig[randomIndex]; - return Arrays.stream(reportsConfig) - .map( - reportConfig -> - new Source.FakeReport( - new UnsignedLong(Long.valueOf(reportConfig[0])), - mEventReportWindowCalcDelegate.getReportingTimeForNoising( - source, - /* window index */ reportConfig[1], - isInstallDetectionEnabled(source)), - resolveFakeReportDestinations(source, reportConfig[2]))) - .collect(Collectors.toList()); - } - @VisibleForTesting ImpressionNoiseParams getImpressionNoiseParams(Source source) { int destinationTypeMultiplier = source.getDestinationTypeMultiplier(mFlags); return new ImpressionNoiseParams( - mEventReportWindowCalcDelegate.getMaxReportCount( - source, isInstallDetectionEnabled(source)), + mEventReportWindowCalcDelegate.getMaxReportCount(source), source.getTriggerDataCardinality(), - mEventReportWindowCalcDelegate.getReportingWindowCountForNoising( - source, isInstallDetectionEnabled(source)), + mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(source), destinationTypeMultiplier); } } diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java index 2140bcb626..26157a01b1 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java @@ -492,8 +492,9 @@ public class AsyncSourceFetcher { Source.SourceType sourceType, int maxEventLevelReports, Source.TriggerDataMatching triggerDataMatching) { - List<Pair<Long, Long>> parsedEventReportWindows = Source.getOrDefaultEventReportWindows( - eventReportWindows, sourceType, expiry, mFlags); + List<Pair<Long, Long>> parsedEventReportWindows = + Source.getOrDefaultEventReportWindowsForFlex( + eventReportWindows, sourceType, expiry, mFlags); long defaultStart = parsedEventReportWindows.get(0).first; List<Long> defaultEnds = parsedEventReportWindows.stream().map((x) -> x.second).collect(Collectors.toList()); diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java index 813fbd03c1..93f7913854 100644 --- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java +++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java @@ -54,36 +54,42 @@ public class EventReportWindowCalcDelegate { } /** - * Max reports count based on conversion destination type and installation state. + * Max reports count given the Source object. * - * @param isInstallCase is app installed + * @param source the Source object * @return maximum number of reports allowed */ - public int getMaxReportCount(@NonNull Source source, boolean isInstallCase) { + public int getMaxReportCount(Source source) { + return getMaxReportCount(source, source.isInstallDetectionEnabled()); + } + + /** + * Max reports count based on conversion destination type. + * + * @param source the Source object + * @param destinationType destination type + * @return maximum number of reports allowed + */ + public int getMaxReportCount(@NonNull Source source, @EventSurfaceType int destinationType) { + return getMaxReportCount(source, isInstallCase(source, destinationType)); + } + + private int getMaxReportCount(@NonNull Source source, boolean isInstallCase) { // TODO(b/290101531): Cleanup flags if (mFlags.getMeasurementFlexLiteApiEnabled() && source.getMaxEventLevelReports() != null) { return source.getMaxEventLevelReports(); } - if (source.getSourceType() == Source.SourceType.EVENT - && mFlags.getMeasurementEnableVtcConfigurableMaxEventReports()) { - // Max VTC event reports are configurable - int configuredMaxReports = mFlags.getMeasurementVtcConfigurableMaxEventReportsCount(); + + if (source.getSourceType() == Source.SourceType.EVENT) { // Additional report essentially for first open + 1 post install conversion. If there // is already more than 1 report allowed, no need to have that additional report. - if (isInstallCase && configuredMaxReports == PrivacyParams.EVENT_SOURCE_MAX_REPORTS) { + if (isInstallCase && !source.hasWebDestinations() && isDefaultConfiguredVtc()) { return PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS; } - return configuredMaxReports; + return mFlags.getMeasurementVtcConfigurableMaxEventReportsCount(); } - if (isInstallCase) { - return source.getSourceType() == Source.SourceType.EVENT - ? PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS - : PrivacyParams.INSTALL_ATTR_NAVIGATION_SOURCE_MAX_REPORTS; - } - return source.getSourceType() == Source.SourceType.EVENT - ? PrivacyParams.EVENT_SOURCE_MAX_REPORTS - : PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS; + return PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS; } /** @@ -100,18 +106,14 @@ public class EventReportWindowCalcDelegate { // Cases where source could have both web and app destinations, there if the trigger // destination is an app, and it was installed, then installState should be considered true. - boolean isAppInstalled = isAppInstalled(source, destinationType); - List<Pair<Long, Long>> earlyReportingWindows = - getEarlyReportingWindows(source, isAppInstalled); - for (Pair<Long, Long> window : earlyReportingWindows) { + List<Pair<Long, Long>> reportingWindows = + getEffectiveReportingWindows(source, isInstallCase(source, destinationType)); + for (Pair<Long, Long> window : reportingWindows) { if (isWithinWindow(triggerTime, window)) { return window.second + mFlags.getMeasurementMinEventReportDelayMillis(); } } - Pair<Long, Long> finalWindow = getFinalReportingWindow(source, earlyReportingWindows); - if (isWithinWindow(triggerTime, finalWindow)) { - return finalWindow.second + mFlags.getMeasurementMinEventReportDelayMillis(); - } + return -1; } @@ -137,20 +139,12 @@ public class EventReportWindowCalcDelegate { */ public MomentPlacement fallsWithinWindow( @NonNull Source source, long triggerTime, @EventSurfaceType int destinationType) { - boolean isAppInstalled = isAppInstalled(source, destinationType); - List<Pair<Long, Long>> earlyReportingWindows = - getEarlyReportingWindows(source, isAppInstalled); - if (earlyReportingWindows.size() > 0) { - Long firstWindowStartTime = earlyReportingWindows.get(0).first; - if (triggerTime < firstWindowStartTime) { - return MomentPlacement.BEFORE; - } - } - Pair<Long, Long> finalWindow = getFinalReportingWindow(source, earlyReportingWindows); - if (earlyReportingWindows.size() == 0 && triggerTime < finalWindow.first) { + List<Pair<Long, Long>> reportingWindows = + getEffectiveReportingWindows(source, isInstallCase(source, destinationType)); + if (triggerTime < reportingWindows.get(0).first) { return MomentPlacement.BEFORE; } - if (triggerTime >= finalWindow.second) { + if (triggerTime >= reportingWindows.get(reportingWindows.size() - 1).second) { return MomentPlacement.AFTER; } return MomentPlacement.WITHIN; @@ -163,39 +157,25 @@ public class EventReportWindowCalcDelegate { * @return reporting time in milliseconds */ public long getReportingTimeForNoising( - @NonNull Source source, int windowIndex, boolean isInstallCase) { - List<Pair<Long, Long>> earlyWindows = getEarlyReportingWindows(source, isInstallCase); - Pair<Long, Long> finalWindow = getFinalReportingWindow(source, earlyWindows); - return windowIndex < earlyWindows.size() - ? earlyWindows.get(windowIndex).second + @NonNull Source source, int windowIndex) { + List<Pair<Long, Long>> reportingWindows = getEffectiveReportingWindows( + source, source.isInstallDetectionEnabled()); + Pair<Long, Long> finalWindow = reportingWindows.get(reportingWindows.size() - 1); + // TODO: (b/288646239) remove this check, confirming noising indexing accuracy. + return windowIndex < reportingWindows.size() + ? reportingWindows.get(windowIndex).second + mFlags.getMeasurementMinEventReportDelayMillis() : finalWindow.second + mFlags.getMeasurementMinEventReportDelayMillis(); } - private Pair<Long, Long> getFinalReportingWindow( - Source source, List<Pair<Long, Long>> earlyWindows) { - if (mFlags.getMeasurementFlexLiteApiEnabled() && source.hasManualEventReportWindows()) { - List<Pair<Long, Long>> windowList = source.parsedProcessedEventReportWindows(); - return windowList.get(windowList.size() - 1); - } - long secondToLastWindowEnd = - !earlyWindows.isEmpty() ? earlyWindows.get(earlyWindows.size() - 1).second : 0; - if (source.getProcessedEventReportWindow() != null) { - return new Pair<>(secondToLastWindowEnd, source.getProcessedEventReportWindow()); - } - return new Pair<>(secondToLastWindowEnd, source.getExpiryTime()); - } - /** - * Returns effective, i.e. the ones that occur before {@link - * Source#getProcessedEventReportWindow()}, event reporting windows count for noising cases. + * Returns effective, that is, the ones that occur before {@link + * Source#getEffectiveEventReportWindow()}, event reporting windows count for noising cases. * * @param source source for which the count is requested - * @param isInstallCase true of cool down window was specified */ - public int getReportingWindowCountForNoising(@NonNull Source source, boolean isInstallCase) { - // Early Count + lastWindow - return getEarlyReportingWindows(source, isInstallCase).size() + 1; + public int getReportingWindowCountForNoising(@NonNull Source source) { + return getEffectiveReportingWindows(source, source.isInstallDetectionEnabled()).size(); } /** @@ -250,47 +230,53 @@ public class EventReportWindowCalcDelegate { return -1L; } - private boolean isAppInstalled(Source source, int destinationType) { + private static boolean isInstallCase(Source source, @EventSurfaceType int destinationType) { return destinationType == EventSurfaceType.APP && source.isInstallAttributed(); } /** * If the flag is enabled and the specified report windows are valid, picks from flag controlled - * configurable early reporting windows. Otherwise, falls back to the statical {@link - * com.android.adservices.service.measurement.PrivacyParams} values. It curtails the windows - * that occur after {@link Source#getProcessedEventReportWindow()} because they would - * effectively be unusable. + * configurable early reporting windows. Otherwise, falls back to the values provided in + * {@code getDefaultEarlyReportingWindowEnds}, which can have install-related custom behaviour. + * It curtails the windows that occur after {@link Source#getEffectiveEventReportWindow()} + * because they would effectively be unusable. */ - private List<Pair<Long, Long>> getEarlyReportingWindows(Source source, boolean installState) { + private List<Pair<Long, Long>> getEffectiveReportingWindows(Source source, + boolean installState) { // TODO(b/290221611) Remove early reporting windows from code, only use them for flags. if (mFlags.getMeasurementFlexLiteApiEnabled() && source.hasManualEventReportWindows()) { - List<Pair<Long, Long>> windows = source.parsedProcessedEventReportWindows(); - // Select early windows only i.e. skip the last element - return windows.subList(0, windows.size() - 1); + return source.parsedProcessedEventReportWindows(); } - List<Long> earlyWindows; - List<Long> defaultEarlyWindows = - getDefaultEarlyReportingWindows(source.getSourceType(), installState); - earlyWindows = - getConfiguredOrDefaultEarlyReportingWindows( - source.getSourceType(), defaultEarlyWindows, true); + List<Long> defaultEarlyWindowEnds = + getDefaultEarlyReportingWindowEnds( + source.getSourceType(), + installState && !source.hasWebDestinations()); + List<Long> earlyWindowEnds = + getConfiguredOrDefaultEarlyReportingWindowEnds( + source.getSourceType(), defaultEarlyWindowEnds); // Add source event time to windows - earlyWindows = - earlyWindows.stream() + earlyWindowEnds = + earlyWindowEnds.stream() .map((x) -> source.getEventTime() + x) .collect(Collectors.toList()); List<Pair<Long, Long>> windowList = new ArrayList<>(); - long windowStart = 0; + long windowStart = 0L; Pair<Long, Long> finalWindow = - getFinalReportingWindow(source, createStartEndWindow(earlyWindows)); - for (long windowEnd : earlyWindows) { - if (finalWindow.second <= windowEnd) { - continue; + getFinalReportingWindow(source, earlyWindowEnds); + + for (long windowEnd : earlyWindowEnds) { + // Start time of `finalWindow` is either 0 or one of `earlyWindowEnds` times; stop + // iterating if we see it, and add `finalWindow`. + if (windowStart == finalWindow.first) { + break; } - windowList.add(new Pair<>(windowStart, windowEnd)); + windowList.add(Pair.create(windowStart, windowEnd)); windowStart = windowEnd; } + + windowList.add(finalWindow); + return ImmutableList.copyOf(windowList); } @@ -298,13 +284,13 @@ public class EventReportWindowCalcDelegate { * Returns the default early reporting windows * * @param sourceType Source's Type - * @param installState Install State of the source + * @param installAttributionEnabled whether windows for install attribution should be provided * @return a list of windows */ - public static List<Long> getDefaultEarlyReportingWindows( - Source.SourceType sourceType, boolean installState) { + public static List<Long> getDefaultEarlyReportingWindowEnds( + Source.SourceType sourceType, boolean installAttributionEnabled) { long[] earlyWindows; - if (installState) { + if (installAttributionEnabled) { earlyWindows = sourceType == Source.SourceType.EVENT ? INSTALL_ATTR_EVENT_EARLY_REPORTING_WINDOW_MILLISECONDS @@ -318,53 +304,34 @@ public class EventReportWindowCalcDelegate { return asList(earlyWindows); } - private List<Pair<Long, Long>> createStartEndWindow(List<Long> windowEnds) { - List<Pair<Long, Long>> windows = new ArrayList<>(); - long start = 0; - for (Long end : windowEnds) { - windows.add(new Pair<>(start, end)); - start = end; - } - return windows; - } - /** * Returns default or configured (via flag) early reporting windows for the SourceType * * @param sourceType Source's Type * @param defaultEarlyWindows default value for early windows - * @param checkEnableFlag set true if configurable window flag should be checked * @return list of windows */ - public List<Long> getConfiguredOrDefaultEarlyReportingWindows( - Source.SourceType sourceType, List<Long> defaultEarlyWindows, boolean checkEnableFlag) { - // TODO(b/290101531): Cleanup flags - if (checkEnableFlag && !mFlags.getMeasurementEnableConfigurableEventReportingWindows()) { - return defaultEarlyWindows; + public List<Long> getConfiguredOrDefaultEarlyReportingWindowEnds( + Source.SourceType sourceType, List<Long> defaultEarlyWindowEnds) { + // `defaultEarlyWindowEnds` may contain custom install-related logic, which we only apply if + // the configurable report windows (and max reports) are in their default state. Without + // this check, we may construct default-value report windows without the custom + // install-related logic applied. + if ((sourceType == Source.SourceType.EVENT && isDefaultConfiguredVtc()) + || (sourceType == Source.SourceType.NAVIGATION && isDefaultConfiguredCtc())) { + return defaultEarlyWindowEnds; } String earlyReportingWindowsString = pickEarlyReportingWindowsConfig(mFlags, sourceType); - if (earlyReportingWindowsString == null) { - LoggerFactory.getMeasurementLogger() - .d("Invalid configurable early reporting windows; null"); - return defaultEarlyWindows; - } - if (earlyReportingWindowsString.isEmpty()) { // No early reporting windows specified. It needs to be handled separately because - // splitting an empty string results into an array containing a single element, - // i.e. "". We want to handle it as an array having no element. - - if (Source.SourceType.EVENT.equals(sourceType)) { - // We need to add a reporting window at 2d for post-install case. Non-install case - // has no early reporting window by default. - return defaultEarlyWindows; - } + // splitting an empty string results in an array containing a single empty string. We + // want to handle it as an empty array. return Collections.emptyList(); } - ImmutableList.Builder<Long> earlyWindows = new ImmutableList.Builder<>(); + ImmutableList.Builder<Long> earlyWindowEnds = new ImmutableList.Builder<>(); String[] split = earlyReportingWindowsString.split(EARLY_REPORTING_WINDOWS_CONFIG_DELIMITER); if (split.length > MAX_CONFIGURABLE_EVENT_REPORT_EARLY_REPORTING_WINDOWS) { @@ -372,22 +339,54 @@ public class EventReportWindowCalcDelegate { .d( "Invalid configurable early reporting window; more than allowed size: " + MAX_CONFIGURABLE_EVENT_REPORT_EARLY_REPORTING_WINDOWS); - return defaultEarlyWindows; + return defaultEarlyWindowEnds; } - for (String window : split) { + for (String windowEnd : split) { try { - earlyWindows.add(TimeUnit.SECONDS.toMillis(Long.parseLong(window))); + earlyWindowEnds.add(TimeUnit.SECONDS.toMillis(Long.parseLong(windowEnd))); } catch (NumberFormatException e) { LoggerFactory.getMeasurementLogger() .d(e, "Configurable early reporting window parsing failed."); - return defaultEarlyWindows; + return defaultEarlyWindowEnds; } } - return earlyWindows.build(); + return earlyWindowEnds.build(); + } + + private Pair<Long, Long> getFinalReportingWindow( + Source source, List<Long> earlyWindowEnds) { + // The latest end-time we can associate with a report for this source + long effectiveExpiry = Math.min( + source.getEffectiveEventReportWindow(), source.getExpiryTime()); + // Find the latest end-time that can start a window ending at effectiveExpiry + for (int i = earlyWindowEnds.size() - 1; i >= 0; i--) { + long windowEnd = earlyWindowEnds.get(i); + if (windowEnd < effectiveExpiry) { + return Pair.create(windowEnd, effectiveExpiry); + } + } + return Pair.create(0L, effectiveExpiry); + } + + /** Indicates whether VTC report windows and max reports are default configured, which can + * affect custom install-related attribution. + */ + public boolean isDefaultConfiguredVtc() { + return mFlags.getMeasurementEventReportsVtcEarlyReportingWindows().isEmpty() + && mFlags.getMeasurementVtcConfigurableMaxEventReportsCount() == 1; + } + + /** Indicates whether CTC report windows are default configured, which can affect custom + * install-related attribution. + */ + private boolean isDefaultConfiguredCtc() { + return mFlags.getMeasurementEventReportsCtcEarlyReportingWindows().equals( + Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS); } - private String pickEarlyReportingWindowsConfig(Flags flags, Source.SourceType sourceType) { + private static String pickEarlyReportingWindowsConfig(Flags flags, + Source.SourceType sourceType) { return sourceType == Source.SourceType.EVENT ? flags.getMeasurementEventReportsVtcEarlyReportingWindows() : flags.getMeasurementEventReportsCtcEarlyReportingWindows(); diff --git a/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java b/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java index 08efcc33d7..d93eba2db7 100644 --- a/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java +++ b/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java @@ -89,13 +89,20 @@ public final class AdServicesShellCommandHandler { private static final int RESULT_GENERIC_ERROR = -1; private final PrintWriter mOut; + private final PrintWriter mErr; private String[] mArgs; private int mArgPos; private String mCurArgData; + /** If PrintWriter {@code err} is not provided, we use {@code out} for the {@code err}. */ public AdServicesShellCommandHandler(PrintWriter out) { + this(out, /* err= */ out); + } + + public AdServicesShellCommandHandler(PrintWriter out, PrintWriter err) { mOut = Objects.requireNonNull(out, "out cannot be null"); + mErr = Objects.requireNonNull(err, "err cannot be null"); } /** Runs the given command ({@code args[0]}) and optional arguments */ @@ -117,13 +124,14 @@ public final class AdServicesShellCommandHandler { } } catch (Throwable e) { // TODO(b/308009734): need to test this - mOut.printf("Exception occurred while executing %s\n", Arrays.toString(mArgs)); + mErr.printf("Exception occurred while executing %s\n", Arrays.toString(mArgs)); e.printStackTrace(mOut); } finally { if (DEBUG) { Log.d(TAG, "Flushing output"); } mOut.flush(); + mErr.flush(); } if (DEBUG) { Log.d(TAG, "Sending command result: " + res); @@ -173,7 +181,7 @@ public final class AdServicesShellCommandHandler { } private int invalidArgsError(String syntax) { - mOut.println(String.format(ERROR_TEMPLATE_INVALID_ARGS, Arrays.toString(mArgs), syntax)); + mErr.println(String.format(ERROR_TEMPLATE_INVALID_ARGS, Arrays.toString(mArgs), syntax)); return RESULT_GENERIC_ERROR; } @@ -193,9 +201,9 @@ public final class AdServicesShellCommandHandler { case CMD_SHORT_HELP: case CMD_HELP: onHelp(); - return RESULT_GENERIC_ERROR; + return RESULT_OK; case "": - mOut.println(ERROR_EMPTY_COMMAND); + mErr.println(ERROR_EMPTY_COMMAND); return RESULT_GENERIC_ERROR; case CMD_ECHO: return runEcho(); @@ -204,7 +212,7 @@ public final class AdServicesShellCommandHandler { case CMD_IS_ALLOWED_TOPICS_ACCESS: return runIsAllowedApiAccess(cmd); default: - mOut.printf("Unknown command: %s\n", cmd); + mErr.printf("Unknown command: %s\n", cmd); return RESULT_GENERIC_ERROR; } } diff --git a/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java new file mode 100644 index 0000000000..285396c155 --- /dev/null +++ b/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java @@ -0,0 +1,59 @@ +/* + * 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.shell; + +import android.adservices.shell.IShellCommand; +import android.adservices.shell.IShellCommandCallback; +import android.adservices.shell.ShellCommandParam; +import android.adservices.shell.ShellCommandResult; +import android.os.RemoteException; + +import com.android.adservices.LogUtil; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Implements a service which runs shell command in the AdServices process. + * + * <p>This internally calls {@link AdServicesShellCommandHandler} which has main logic to execute + * the shell command. + * + * @hide + */ +public final class ShellCommandServiceImpl extends IShellCommand.Stub { + @Override + public void runShellCommand(ShellCommandParam param, IShellCommandCallback callback) { + StringWriter outStringWriter = new StringWriter(); + StringWriter ErrStringWriter = new StringWriter(); + + try (PrintWriter outPw = new PrintWriter(outStringWriter); + PrintWriter errPw = new PrintWriter(ErrStringWriter); ) { + AdServicesShellCommandHandler handler = new AdServicesShellCommandHandler(outPw, errPw); + int resultCode = handler.run(param.getCommandArgs()); + ShellCommandResult response = + new ShellCommandResult.Builder() + .setResultCode(resultCode) + .setOut(outStringWriter.toString()) + .setErr(ErrStringWriter.toString()) + .build(); + callback.onResult(response); + } catch (RemoteException e) { + LogUtil.e(e, "Unable to send result to the callback for request: %s", param); + } + } +} diff --git a/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java index 79dde44bdd..9cac9eef52 100644 --- a/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java +++ b/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java @@ -189,7 +189,7 @@ public class ProtectedSignalsServiceImpl extends IProtectedSignalsService.Stub { } // Caller permissions must be checked in the binder thread, before anything else - mFledgeAuthorizationFilter.assertAppDeclaredProtectedSignalsPermission( + mFledgeAuthorizationFilter.assertAppDeclaredPermission( mContext, updateSignalsInput.getCallerPackageName(), apiName); final int callerUid = getCallingUid(apiName); diff --git a/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java b/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java index b5437a8da2..d877f45dd6 100644 --- a/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java +++ b/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java @@ -19,6 +19,8 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__SUCCESS_WITH_SHARED_PREF_NOT_UPDATED; import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__SUCCESS_WITH_SHARED_PREF_UPDATED; import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__UNSPECIFIED_MIGRATION_STATUS; +import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_APPSEARCH; +import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_SYSTEM_SERVICE; import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE; import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__PPAPI_TO_SYSTEM_SERVICE; import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__UNSPECIFIED_MIGRATION_TYPE; @@ -75,7 +77,14 @@ public abstract class ConsentMigrationStats { AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__PPAPI_TO_SYSTEM_SERVICE), // Migrating consent from App Search to system service APPSEARCH_TO_SYSTEM_SERVICE( - AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE); + AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE), + // Migrating consent from AdServicesExtDataStorageService to System Server + ADEXT_SERVICE_TO_SYSTEM_SERVICE( + AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_SYSTEM_SERVICE), + // Migrating consent from AdServicesExtDataStorageService to App Search + ADEXT_SERVICE_TO_APPSEARCH( + AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_APPSEARCH); + private final int mMigrationType; MigrationType(int migrationType) { diff --git a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java index 6d6bc18d67..6d89bd4d3e 100644 --- a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java +++ b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java @@ -16,7 +16,7 @@ package com.android.adservices.service.ui.enrollment.impl; -import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED; +import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED; import android.content.Context; import android.os.Build; @@ -40,8 +40,7 @@ public class RvcPostOTAChannel implements PrivacySandboxEnrollmentChannel { ConsentManager consentManager, UxStatesManager uxStatesManager) { // Rvc user should be matched to RvcPostOTAChannel on S+ - // TODO: rename flag to KEY_RVC_POST_OTA_NOTIFICATION_ENABLED - return uxStatesManager.getFlag(KEY_RVC_NOTIFICATION_ENABLED) + return uxStatesManager.getFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED) && consentManager.isOtaAdultUserFromRvc(); } |