1 /* 2 * Copyright 2024 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.signals 18 19 import android.adservices.common.AdServicesPermissions 20 import android.annotation.SuppressLint 21 import android.content.Context 22 import android.util.Log 23 import androidx.annotation.RequiresPermission 24 import androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures 25 import androidx.privacysandbox.ads.adservices.internal.AdServicesInfo 26 27 /** This class provides APIs for app and ad-SDKs to join / leave custom audiences. */ 28 abstract class ProtectedSignalsManager internal constructor() { 29 /** 30 * The updateSignals API will retrieve a JSON from the URI that describes which signals to add 31 * or remove. This API also allows registering the encoder endpoint. The endpoint is used to 32 * download an encoding logic, which enables encoding the signals. 33 * 34 * <p>The top level keys for the JSON must correspond to one of 5 commands: 35 * 36 * <p>"put" - Adds a new signal, overwriting any existing signals with the same key. The value 37 * for this is a JSON object where the keys are base 64 strings corresponding to the key to put 38 * for and the values are base 64 string corresponding to the value to put. 39 * 40 * <p>"append" - Appends a new signal/signals to a time series of signals, removing the oldest 41 * signals to make room for the new ones if the size of the series exceeds the given maximum. 42 * The value for this is a JSON object where the keys are base 64 strings corresponding to the 43 * key to append to and the values are objects with two fields: "values" and "maxSignals" . 44 * "values" is a list of base 64 strings corresponding to signal values to append to the time 45 * series. "maxSignals" is the maximum number of values that are allowed in this timeseries. If 46 * the current number of signals associated with the key exceeds maxSignals the oldest signals 47 * will be removed. Note that you can append to a key added by put. Not that appending more than 48 * the maximum number of values will cause a failure. 49 * 50 * <p>"put_if_not_present" - Adds a new signal only if there are no existing signals with the 51 * same key. The value for this is a JSON object where the keys are base 64 strings 52 * corresponding to the key to put for and the values are base 64 string corresponding to the 53 * value to put. 54 * 55 * <p>"remove" - Removes the signal for a key. The value of this is a list of base 64 strings 56 * corresponding to the keys of signals that should be deleted. 57 * 58 * <p>"update_encoder" - Provides an action to update the endpoint, and a URI which can be used 59 * to retrieve an encoding logic. The sub-key for providing an update action is "action" and the 60 * values currently supported are: 61 * <ol> 62 * <li>"REGISTER" : Registers the encoder endpoint if provided for the first time or overwrites 63 * the existing one with the newly provided endpoint. Providing the "endpoint" is required for 64 * the "REGISTER" action. 65 * </ol> 66 * 67 * <p>The sub-key for providing an encoder endpoint is "endpoint" and the value is the URI 68 * string for the endpoint. 69 * 70 * <p>Key may only be operated on by one command per JSON. If two command attempt to operate on 71 * the same key, this method will through an {@link IllegalArgumentException} 72 * 73 * <p>This call fails with an {@link SecurityException} if 74 * <ol> 75 * <li>the {@code ownerPackageName} is not calling app's package name and/or 76 * <li>the buyer is not authorized to use the API. 77 * </ol> 78 * 79 * <p>This call fails with an {@link IllegalArgumentException} if 80 * <ol> 81 * <li>The JSON retrieved from the server is not valid. 82 * <li>The provided URI is invalid. 83 * </ol> 84 * 85 * <p>This call fails with {@link LimitExceededException} if the calling package exceeds the 86 * allowed rate limits and is throttled. 87 * 88 * <p>This call fails with an {@link IllegalStateException} if an internal service error is 89 * encountered. 90 */ 91 @ExperimentalFeatures.Ext12OptIn 92 @RequiresPermission(AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS) updateSignalsnull93 abstract suspend fun updateSignals(request: UpdateSignalsRequest) 94 95 companion object { 96 private const val TAG = "ProtectedSignalsManager" 97 98 /** 99 * Creates [ProtectedSignalsManager]. 100 * 101 * @return ProtectedSignalsManager object. If the device is running an incompatible build, 102 * the value returned is null. 103 */ 104 @JvmStatic 105 @SuppressLint("NewApi") 106 @ExperimentalFeatures.Ext12OptIn 107 fun obtain(context: Context): ProtectedSignalsManager? { 108 return if (AdServicesInfo.adServicesVersion() >= 12) { 109 Log.d(TAG, "Adservices version 12 detected, obtaining ProtectedSignalsManagerImpl.") 110 ProtectedSignalsManagerImpl( 111 android.adservices.signals.ProtectedSignalsManager.get(context) 112 ) 113 } else { 114 Log.d( 115 TAG, 116 "Adservices less than 12, returning null for ProtectedSignalsManager.obtain." 117 ) 118 null 119 } 120 } 121 } 122 } 123