1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.privacysandbox.ads.adservices.java.measurement 18 19 import android.adservices.common.AdServicesPermissions 20 import android.content.Context 21 import android.net.Uri 22 import android.view.InputEvent 23 import androidx.annotation.DoNotInline 24 import androidx.annotation.RequiresPermission 25 import androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures 26 import androidx.privacysandbox.ads.adservices.java.internal.asListenableFuture 27 import androidx.privacysandbox.ads.adservices.measurement.DeletionRequest 28 import androidx.privacysandbox.ads.adservices.measurement.MeasurementManager 29 import androidx.privacysandbox.ads.adservices.measurement.MeasurementManager.Companion.obtain 30 import androidx.privacysandbox.ads.adservices.measurement.SourceRegistrationRequest 31 import androidx.privacysandbox.ads.adservices.measurement.WebSourceRegistrationRequest 32 import androidx.privacysandbox.ads.adservices.measurement.WebTriggerRegistrationRequest 33 import com.google.common.util.concurrent.ListenableFuture 34 import kotlinx.coroutines.CoroutineScope 35 import kotlinx.coroutines.Dispatchers 36 import kotlinx.coroutines.async 37 38 /** 39 * This provides APIs for App and Ad-Sdks to access Privacy Sandbox Measurement APIs in a privacy 40 * preserving way. This class can be used by Java clients. 41 */ 42 abstract class MeasurementManagerFutures internal constructor() { 43 /** 44 * Delete previous registrations. 45 * 46 * @param deletionRequest The request for deleting data. 47 * @return ListenableFuture. If the deletion is successful, result is null. 48 */ 49 @SuppressWarnings("MissingNullability") deleteRegistrationsAsyncnull50 abstract fun deleteRegistrationsAsync(deletionRequest: DeletionRequest): ListenableFuture<Unit> 51 52 /** 53 * Register an attribution source (click or view). 54 * 55 * @param attributionSource the platform issues a request to this URI in order to fetch metadata 56 * associated with the attribution source. 57 * @param inputEvent either an [InputEvent] object (for a click event) or null (for a view 58 * event). 59 */ 60 @SuppressWarnings("MissingNullability") 61 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 62 abstract fun registerSourceAsync( 63 attributionSource: Uri, 64 inputEvent: InputEvent? 65 ): ListenableFuture<Unit> 66 67 /** 68 * Register a trigger (conversion). 69 * 70 * @param trigger the API issues a request to this URI to fetch metadata associated with the 71 * trigger. 72 */ 73 @SuppressWarnings("MissingNullability") 74 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 75 abstract fun registerTriggerAsync(trigger: Uri): ListenableFuture<Unit> 76 77 /** 78 * Register attribution sources(click or view). This API will not process any redirects, all 79 * registration URLs should be supplied with the request. 80 * 81 * @param request source registration request 82 */ 83 @ExperimentalFeatures.RegisterSourceOptIn 84 @SuppressWarnings("MissingNullability") 85 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 86 abstract fun registerSourceAsync(request: SourceRegistrationRequest): ListenableFuture<Unit> 87 88 /** 89 * Register an attribution source(click or view) from web context. This API will not process any 90 * redirects, all registration URLs should be supplied with the request. At least one of 91 * appDestination or webDestination parameters are required to be provided. 92 * 93 * @param request source registration request 94 */ 95 @SuppressWarnings("MissingNullability") 96 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 97 abstract fun registerWebSourceAsync( 98 request: WebSourceRegistrationRequest 99 ): ListenableFuture<Unit> 100 101 /** 102 * Register an attribution trigger(click or view) from web context. This API will not process 103 * any redirects, all registration URLs should be supplied with the request. 104 * OutcomeReceiver#onError}. 105 * 106 * @param request trigger registration request 107 */ 108 @SuppressWarnings("MissingNullability") 109 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 110 abstract fun registerWebTriggerAsync( 111 request: WebTriggerRegistrationRequest, 112 ): ListenableFuture<Unit> 113 114 /** 115 * Get Measurement API status. 116 * 117 * The call returns an integer value (see [MeasurementManager.MEASUREMENT_API_STATE_DISABLED] 118 * and [MeasurementManager.MEASUREMENT_API_STATE_ENABLED] for possible values). 119 */ 120 @SuppressWarnings("MissingNullability") 121 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 122 abstract fun getMeasurementApiStatusAsync(): ListenableFuture<Int> 123 124 private class Api33Ext5JavaImpl(private val mMeasurementManager: MeasurementManager) : 125 MeasurementManagerFutures() { 126 @DoNotInline 127 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 128 override fun deleteRegistrationsAsync( 129 deletionRequest: DeletionRequest 130 ): ListenableFuture<Unit> { 131 return CoroutineScope(Dispatchers.Default) 132 .async { mMeasurementManager.deleteRegistrations(deletionRequest) } 133 .asListenableFuture() 134 } 135 136 @DoNotInline 137 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 138 override fun registerSourceAsync( 139 attributionSource: Uri, 140 inputEvent: InputEvent? 141 ): ListenableFuture<Unit> { 142 return CoroutineScope(Dispatchers.Default) 143 .async { mMeasurementManager.registerSource(attributionSource, inputEvent) } 144 .asListenableFuture() 145 } 146 147 @DoNotInline 148 @ExperimentalFeatures.RegisterSourceOptIn 149 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 150 override fun registerSourceAsync( 151 request: SourceRegistrationRequest 152 ): ListenableFuture<Unit> { 153 return CoroutineScope(Dispatchers.Default) 154 .async { mMeasurementManager.registerSource(request) } 155 .asListenableFuture() 156 } 157 158 @DoNotInline 159 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 160 override fun registerTriggerAsync(trigger: Uri): ListenableFuture<Unit> { 161 return CoroutineScope(Dispatchers.Default) 162 .async { mMeasurementManager.registerTrigger(trigger) } 163 .asListenableFuture() 164 } 165 166 @DoNotInline 167 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 168 override fun registerWebSourceAsync( 169 request: WebSourceRegistrationRequest 170 ): ListenableFuture<Unit> { 171 return CoroutineScope(Dispatchers.Default) 172 .async { mMeasurementManager.registerWebSource(request) } 173 .asListenableFuture() 174 } 175 176 @DoNotInline 177 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 178 override fun registerWebTriggerAsync( 179 request: WebTriggerRegistrationRequest, 180 ): ListenableFuture<Unit> { 181 return CoroutineScope(Dispatchers.Default) 182 .async { mMeasurementManager.registerWebTrigger(request) } 183 .asListenableFuture() 184 } 185 186 @DoNotInline 187 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION) 188 override fun getMeasurementApiStatusAsync(): ListenableFuture<Int> { 189 return CoroutineScope(Dispatchers.Default) 190 .async { mMeasurementManager.getMeasurementApiStatus() } 191 .asListenableFuture() 192 } 193 } 194 195 companion object { 196 /** 197 * Creates [MeasurementManagerFutures]. 198 * 199 * @return MeasurementManagerFutures object. If the device is running an incompatible build, 200 * the value returned is null. 201 */ 202 @JvmStatic fromnull203 fun from(context: Context): MeasurementManagerFutures? { 204 return obtain(context)?.let { Api33Ext5JavaImpl(it) } 205 } 206 } 207 } 208