• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 android.adservices.common;
18 
19 import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_STATE;
20 import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_STATE_COMPAT;
21 import static android.adservices.common.AdServicesPermissions.MODIFY_ADSERVICES_STATE;
22 import static android.adservices.common.AdServicesPermissions.MODIFY_ADSERVICES_STATE_COMPAT;
23 import static android.adservices.common.AdServicesPermissions.UPDATE_PRIVILEGED_AD_ID;
24 import static android.adservices.common.AdServicesPermissions.UPDATE_PRIVILEGED_AD_ID_COMPAT;
25 import static android.adservices.common.AndroidRCommonUtil.invokeCallbackOnErrorOnRvc;
26 
27 import android.adservices.adid.AdId;
28 import android.annotation.CallbackExecutor;
29 import android.annotation.FlaggedApi;
30 import android.annotation.IntDef;
31 import android.annotation.NonNull;
32 import android.annotation.RequiresPermission;
33 import android.annotation.SdkConstant;
34 import android.annotation.SdkConstant.SdkConstantType;
35 import android.annotation.SystemApi;
36 import android.app.sdksandbox.SandboxedSdkContext;
37 import android.content.Context;
38 import android.os.Build;
39 import android.os.OutcomeReceiver;
40 import android.os.RemoteException;
41 import android.os.SystemClock;
42 
43 import androidx.annotation.RequiresApi;
44 
45 import com.android.adservices.AdServicesCommon;
46 import com.android.adservices.LogUtil;
47 import com.android.adservices.ServiceBinder;
48 import com.android.adservices.flags.Flags;
49 
50 import java.lang.annotation.Retention;
51 import java.lang.annotation.RetentionPolicy;
52 import java.util.Objects;
53 import java.util.concurrent.Executor;
54 
55 /**
56  * AdServicesCommonManager contains APIs common across the various AdServices. It provides two
57  * SystemApis:
58  *
59  * <ul>
60  *   <li>isAdServicesEnabled - allows to get AdServices state.
61  *   <li>setAdServicesEntryPointEnabled - allows to control AdServices state.
62  * </ul>
63  *
64  * <p>The instance of the {@link AdServicesCommonManager} can be obtained using {@link
65  * Context#getSystemService} and {@link AdServicesCommonManager} class.
66  *
67  * @hide
68  */
69 @SystemApi
70 public class AdServicesCommonManager {
71     /** @hide */
72     public static final String AD_SERVICES_COMMON_SERVICE = "ad_services_common_service";
73 
74     private final Context mContext;
75     private final ServiceBinder<IAdServicesCommonService> mAdServicesCommonServiceBinder;
76 
77     // TODO(b/378923974): refactor all usages to reference these constants directly instead of
78     //  derived ones in other classes.
79 
80     /** Don't show any notification during the enrollment. */
81     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
82     public static final int NOTIFICATION_NONE = 0;
83 
84     /** Shows ongoing notification during the enrollment, which user can not dismiss. */
85     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
86     public static final int NOTIFICATION_ONGOING = 1;
87 
88     /** Shows regular notification during the enrollment, which user can dismiss. */
89     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
90     public static final int NOTIFICATION_REGULAR = 2;
91 
92     /**
93      * Result codes that are common across various APIs.
94      *
95      * @hide
96      */
97     @IntDef(value = {NOTIFICATION_NONE, NOTIFICATION_ONGOING, NOTIFICATION_REGULAR})
98     @Retention(RetentionPolicy.SOURCE)
99     public @interface NotificationType {}
100 
101     /** Default user choice state */
102     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
103     public static final int USER_CHOICE_UNKNOWN = 0;
104 
105     /** User opted in state */
106     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
107     public static final int USER_CHOICE_OPTED_IN = 1;
108 
109     /** User opted out state */
110     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
111     public static final int USER_CHOICE_OPTED_OUT = 2;
112 
113     /**
114      * Result codes that are common across various modules.
115      *
116      * @hide
117      */
118     @IntDef(
119             prefix = {""},
120             value = {USER_CHOICE_UNKNOWN, USER_CHOICE_OPTED_IN, USER_CHOICE_OPTED_OUT})
121     @Retention(RetentionPolicy.SOURCE)
122     public @interface ModuleUserChoice {}
123 
124     /** Default module state */
125     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
126     public static final int MODULE_STATE_UNKNOWN = 0;
127 
128     /** Module is available on the device */
129     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
130     public static final int MODULE_STATE_ENABLED = 1;
131 
132     /** Module is not available on the device */
133     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
134     public static final int MODULE_STATE_DISABLED = 2;
135 
136     /**
137      * Result codes that are common across various modules.
138      *
139      * @hide
140      */
141     @IntDef(
142             prefix = {""},
143             value = {MODULE_STATE_UNKNOWN, MODULE_STATE_ENABLED, MODULE_STATE_DISABLED})
144     @Retention(RetentionPolicy.SOURCE)
145     public @interface ModuleState {}
146 
147     /** Measurement module. */
148     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
149     public static final int MODULE_MEASUREMENT = 0;
150 
151     /** Privacy Sandbox module. */
152     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
153     public static final int MODULE_PROTECTED_AUDIENCE = 1;
154 
155     /** Privacy Sandbox Attribution module. */
156     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
157     public static final int MODULE_PROTECTED_APP_SIGNALS = 2;
158 
159     /** Topics module. */
160     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
161     public static final int MODULE_TOPICS = 3;
162 
163     /** On-device Personalization(ODP) module. */
164     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
165     public static final int MODULE_ON_DEVICE_PERSONALIZATION = 4;
166 
167     /** ADID module. */
168     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
169     public static final int MODULE_ADID = 5;
170 
171     /**
172      * ModuleCode IntDef.
173      *
174      * @hide
175      */
176     @IntDef(
177             value = {
178                 MODULE_MEASUREMENT,
179                 MODULE_PROTECTED_AUDIENCE,
180                 MODULE_PROTECTED_APP_SIGNALS,
181                 MODULE_TOPICS,
182                 MODULE_ON_DEVICE_PERSONALIZATION,
183                 MODULE_ADID
184             })
185     @Retention(RetentionPolicy.SOURCE)
186     public @interface Module {}
187 
188     /**
189      * Returns {@code module} or throws an {@link IllegalArgumentException} if it's invalid.
190      *
191      * @param module module to validate
192      * @hide
193      */
194     @Module
validateModule(@odule int module)195     public static int validateModule(@Module int module) {
196         return switch (module) {
197             case MODULE_ADID,
198                             MODULE_MEASUREMENT,
199                             MODULE_ON_DEVICE_PERSONALIZATION,
200                             MODULE_PROTECTED_APP_SIGNALS,
201                             MODULE_PROTECTED_AUDIENCE,
202                             MODULE_TOPICS ->
203                     module;
204             default -> throw new IllegalArgumentException("Invalid Module:" + module);
205         };
206     }
207 
208     /**
209      * Returns {@code moduleState} or throws an {@link IllegalArgumentException} if it's invalid.
210      *
211      * @param moduleState module state to validate
212      * @hide
213      */
214     @ModuleState
validateModuleState(@oduleState int moduleState)215     public static int validateModuleState(@ModuleState int moduleState) {
216         return switch (moduleState) {
217             case MODULE_STATE_UNKNOWN, MODULE_STATE_ENABLED, MODULE_STATE_DISABLED -> moduleState;
218             default -> throw new IllegalArgumentException("Invalid Module State:" + moduleState);
219         };
220     }
221 
222     /**
223      * Create AdServicesCommonManager.
224      *
225      * @hide
226      */
227     public AdServicesCommonManager(@NonNull Context context) {
228         mContext = context;
229         mAdServicesCommonServiceBinder =
230                 ServiceBinder.getServiceBinder(
231                         context,
232                         AdServicesCommon.ACTION_AD_SERVICES_COMMON_SERVICE,
233                         IAdServicesCommonService.Stub::asInterface);
234     }
235 
236     /**
237      * Factory method for creating an instance of AdServicesCommonManager.
238      *
239      * @param context The {@link Context} to use
240      * @return A {@link AdServicesCommonManager} instance
241      */
242     @NonNull
243     public static AdServicesCommonManager get(@NonNull Context context) {
244         // On T+, context.getSystemService() does more than just call constructor.
245         return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
246                 ? context.getSystemService(AdServicesCommonManager.class)
247                 : new AdServicesCommonManager(context);
248     }
249 
250     @NonNull
251     private IAdServicesCommonService getService() {
252         IAdServicesCommonService service = mAdServicesCommonServiceBinder.getService();
253         if (service == null) {
254             throw new IllegalStateException("Unable to find the service");
255         }
256         return service;
257     }
258 
259     /**
260      * Get the AdService's enablement state which represents whether AdServices feature is enabled
261      * or not. This API is for Android S+, which has the OutcomeReceiver class available.
262      *
263      * @hide
264      */
265     @SystemApi
266     @RequiresPermission(anyOf = {ACCESS_ADSERVICES_STATE, ACCESS_ADSERVICES_STATE_COMPAT})
267     @RequiresApi(Build.VERSION_CODES.S)
268     public void isAdServicesEnabled(
269             @NonNull @CallbackExecutor Executor executor,
270             @NonNull OutcomeReceiver<Boolean, Exception> callback) {
271         final IAdServicesCommonService service = getService();
272         try {
273             service.isAdServicesEnabled(
274                     new IAdServicesCommonCallback.Stub() {
275                         @Override
276                         public void onResult(IsAdServicesEnabledResult result) {
277                             executor.execute(
278                                     () -> {
279                                         callback.onResult(result.getAdServicesEnabled());
280                                     });
281                         }
282 
283                         @Override
284                         public void onFailure(int statusCode) {
285                             executor.execute(
286                                     () ->
287                                             callback.onError(
288                                                     AdServicesStatusUtils.asException(statusCode)));
289                         }
290                     });
291         } catch (RemoteException e) {
292             LogUtil.e(e, "RemoteException");
293             executor.execute(
294                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
295         }
296     }
297 
298     /**
299      * Get the AdService's enablement state which represents whether AdServices feature is enabled
300      * or not. This API is for Android R, and uses the AdServicesOutcomeReceiver class because
301      * OutcomeReceiver is not available.
302      *
303      * @deprecated use {@link #isAdServicesEnabled(Executor, OutcomeReceiver)} instead. Android R is
304      *     no longer supported.
305      * @hide
306      */
307     @SystemApi
308     @RequiresPermission(anyOf = {ACCESS_ADSERVICES_STATE, ACCESS_ADSERVICES_STATE_COMPAT})
309     @Deprecated
310     @FlaggedApi(Flags.FLAG_ADSERVICES_OUTCOMERECEIVER_R_API_DEPRECATED)
311     @SuppressWarnings("NewApi")
312     public void isAdServicesEnabled(
313             @NonNull @CallbackExecutor Executor executor,
314             @NonNull AdServicesOutcomeReceiver<Boolean, Exception> callback) {
315 
316         if (invokeCallbackOnErrorOnRvc(callback)) {
317             return;
318         }
319 
320         isAdServicesEnabled(executor, OutcomeReceiverConverter.toOutcomeReceiver(callback));
321     }
322 
323     /**
324      * Sets the AdService's enablement state based on the provided parameters.
325      *
326      * <p>As a result of the AdServices state, {@code adServicesEntryPointEnabled}, {@code
327      * adIdEnabled}, appropriate notification may be displayed to the user. It's displayed only once
328      * when all the following conditions are met:
329      *
330      * <ul>
331      *   <li>AdServices state - enabled.
332      *   <li>adServicesEntryPointEnabled - true.
333      * </ul>
334      *
335      * @param adServicesEntryPointEnabled indicate entry point enabled or not
336      * @param adIdEnabled indicate user opt-out of adid or not
337      * @hide
338      */
339     @SystemApi
340     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
341     public void setAdServicesEnabled(boolean adServicesEntryPointEnabled, boolean adIdEnabled) {
342         final IAdServicesCommonService service = getService();
343         try {
344             service.setAdServicesEnabled(adServicesEntryPointEnabled, adIdEnabled);
345         } catch (RemoteException e) {
346             LogUtil.e(e, "RemoteException");
347         }
348     }
349 
350     /**
351      * Enable AdServices based on the AdServicesStates input parameter. This API is for Android S+,
352      * which has the OutcomeReceiver class available.
353      *
354      * <p>Based on the provided {@code AdServicesStates}, AdServices may be enabled. Specifically,
355      * users will be provided with an enrollment channel (such as notification) to become privacy
356      * sandbox users when:
357      *
358      * <ul>
359      *   <li>isAdServicesUiEnabled - true.
360      *   <li>isU18Account | isAdultAccount - true.
361      * </ul>
362      *
363      * @param {@code AdServicesStates} parcel containing relevant AdServices state variables.
364      * @return false if API is disabled, true if the API call completed successfully. Otherwise, it
365      *     would return one of the following exceptions to the user:
366      *     <ul>
367      *       <li>IllegalStateException - the default exception thrown when service crashes
368      *           unexpectedly.
369      *       <li>SecurityException - when the caller is not authorized to call this API.
370      *       <li>TimeoutException - when the services takes too long to respond.
371      *     </ul>
372      *
373      * @hide
374      */
375     @SystemApi
376     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
377     @RequiresApi(Build.VERSION_CODES.S)
378     public void enableAdServices(
379             @NonNull AdServicesStates adServicesStates,
380             @NonNull @CallbackExecutor Executor executor,
381             @NonNull OutcomeReceiver<Boolean, Exception> callback) {
382         Objects.requireNonNull(adServicesStates);
383         Objects.requireNonNull(executor);
384         Objects.requireNonNull(callback);
385 
386         final IAdServicesCommonService service = getService();
387         try {
388             service.enableAdServices(
389                     adServicesStates,
390                     new IEnableAdServicesCallback.Stub() {
391                         @Override
392                         public void onResult(EnableAdServicesResponse response) {
393                             executor.execute(
394                                     () -> {
395                                         if (!response.isApiEnabled()) {
396                                             callback.onResult(false);
397                                             return;
398                                         }
399 
400                                         if (response.isSuccess()) {
401                                             callback.onResult(true);
402                                         } else {
403                                             callback.onError(
404                                                     AdServicesStatusUtils.asException(
405                                                             response.getStatusCode()));
406                                         }
407                                     });
408                         }
409 
410                         @Override
411                         public void onFailure(int statusCode) {
412                             executor.execute(
413                                     () ->
414                                             callback.onError(
415                                                     AdServicesStatusUtils.asException(statusCode)));
416                         }
417                     });
418         } catch (RemoteException e) {
419             LogUtil.e(e, "RemoteException");
420             executor.execute(
421                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
422         }
423     }
424 
425     /**
426      * Broadcast action: notify that a consent notification has been displayed to the user, and the
427      * user consent choices can be set by calling {@link #requestAdServicesModuleUserChoices()}.
428      *
429      * <p>The action must be defined as an intent-filter in AndroidManifest.xml in order to receive
430      * Intents from the platform.
431      *
432      * @hide
433      */
434     @SystemApi
435     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
436     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
437     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
438     public static final String ACTION_ADSERVICES_NOTIFICATION_DISPLAYED =
439             "android.adservices.common.action.ADSERVICES_NOTIFICATION_DISPLAYED";
440 
441     /**
442      * Activity Action: Open the consent landing page activity. In the activity, user consent
443      * choices can be set, depending on user action, by calling {@link
444      * #requestAdServicesModuleUserChoices()}. The action must be defined as an intent-filter in
445      * AndroidManifest.xml in order to receive Intents from the platform.
446      *
447      * <p>Input: nothing
448      *
449      * <p>Output: nothing
450      *
451      * @hide
452      */
453     @SystemApi
454     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
455     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
456     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
457     public static final String ACTION_VIEW_ADSERVICES_CONSENT_PAGE =
458             "android.adservices.common.action.VIEW_ADSERVICES_CONSENT_PAGE";
459 
460     /**
461      * Sets overrides for the AdServices Module(s).
462      *
463      * <p>This API can enable/disable AdServices modules. Setting a module to off will hide the
464      * settings controls for any PPAPIs (Privacy Preserving APIs) associated with it. In addition,
465      * those PPAPIs will not operate for that user.
466      *
467      * <p>A notification type is also required to determine what type of notification should be
468      * shown to the user to notify them of these changes. The NotificationType can be Ongoing,
469      * Regular, or None.
470      *
471      * @param updateParams object containing state information for modules and notification type.
472      * @param executor the executor for the callback.
473      * @param callback callback function to confirm modules overrides is set up correctly.
474      * @hide
475      */
476     @SystemApi
477     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
478     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
479     public void requestAdServicesModuleOverrides(
480             @NonNull UpdateAdServicesModuleStatesParams updateParams,
481             @NonNull @CallbackExecutor Executor executor,
482             @NonNull AdServicesOutcomeReceiver<Void, Exception> callback) {
483         Objects.requireNonNull(updateParams, "updateParams cannot be null");
484         Objects.requireNonNull(executor, "executor cannot be null");
485         Objects.requireNonNull(callback, "callback cannot be null");
486 
487         if (invokeCallbackOnErrorOnRvc(callback)) {
488             return;
489         }
490 
491         final IAdServicesCommonService service = getService();
492         try {
493             service.requestAdServicesModuleOverrides(
494                     updateParams,
495                     new IRequestAdServicesModuleOverridesCallback.Stub() {
496                         @Override
497                         public void onSuccess() throws RemoteException {
498                             callback.onResult(null);
499                         }
500 
501                         @Override
502                         public void onFailure(int statusCode) throws RemoteException {
503                             callback.onError(
504                                     new IllegalStateException(
505                                             "Internal Error! status code: " + statusCode));
506                         }
507                     });
508         } catch (RemoteException e) {
509             LogUtil.e(e, "RemoteException");
510             executor.execute(
511                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
512         }
513     }
514 
515     /**
516      * Sets the user choices for AdServices Module(s).
517      *
518      * <p>This API sets the user consent value for each AdServices module (PAS, Measurement, Topic,
519      * etc). The user consent controls whether the PPAPI associated with that module can operate or
520      * not. If a module already has a user choice opt-in or opt-out, then only user choice unknown
521      * will be accepted as a hard reset option, after which the user choice should be set to the
522      * desired value as soon as possible.
523      *
524      * @param updateParams object containing user choices for modules.
525      * @param executor the executor for the callback.
526      * @param callback callback function to confirm module user choice is set up correctly.
527      * @hide
528      */
529     @SystemApi
530     @FlaggedApi(Flags.FLAG_ADSERVICES_ENABLE_PER_MODULE_OVERRIDES_API)
531     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
532     public void requestAdServicesModuleUserChoices(
533             @NonNull UpdateAdServicesUserChoicesParams updateParams,
534             @NonNull @CallbackExecutor Executor executor,
535             @NonNull AdServicesOutcomeReceiver<Void, Exception> callback) {
536         Objects.requireNonNull(updateParams, "updateParams cannot be null");
537         Objects.requireNonNull(executor, "executor cannot be null");
538         Objects.requireNonNull(callback, "callback cannot be null");
539 
540         if (invokeCallbackOnErrorOnRvc(callback)) {
541             return;
542         }
543 
544         final IAdServicesCommonService service = getService();
545         try {
546             service.requestAdServicesModuleUserChoices(
547                     updateParams,
548                     new IRequestAdServicesModuleUserChoicesCallback.Stub() {
549                         @Override
550                         public void onSuccess() throws RemoteException {
551                             callback.onResult(null);
552                         }
553 
554                         @Override
555                         public void onFailure(int statusCode) throws RemoteException {
556                             callback.onError(
557                                     new IllegalStateException(
558                                             "Internal Error! status code: " + statusCode));
559                         }
560                     });
561         } catch (RemoteException e) {
562             LogUtil.e(e, "RemoteException");
563             executor.execute(
564                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
565         }
566     }
567 
568     /**
569      * Enable AdServices based on the AdServicesStates input parameter. This API is for Android R,
570      * and uses the AdServicesOutcomeReceiver class because OutcomeReceiver is not available.
571      *
572      * <p>Based on the provided {@code AdServicesStates}, AdServices may be enabled. Specifically,
573      * users will be provided with an enrollment channel (such as notification) to become privacy
574      * sandbox users when:
575      *
576      * <ul>
577      *   <li>isAdServicesUiEnabled - true.
578      *   <li>isU18Account | isAdultAccount - true.
579      * </ul>
580      *
581      * @param adServicesStates parcel containing relevant AdServices state variables.
582      * @deprecated use {@link #enableAdServices(AdServicesStates, Executor, OutcomeReceiver)}
583      *     instead. Android R is no longer supported.
584      * @hide
585      */
586     @SystemApi
587     @RequiresPermission(anyOf = {MODIFY_ADSERVICES_STATE, MODIFY_ADSERVICES_STATE_COMPAT})
588     @Deprecated
589     @FlaggedApi(Flags.FLAG_ADSERVICES_OUTCOMERECEIVER_R_API_DEPRECATED)
590     @SuppressWarnings("NewApi")
591     public void enableAdServices(
592             @NonNull AdServicesStates adServicesStates,
593             @NonNull @CallbackExecutor Executor executor,
594             @NonNull AdServicesOutcomeReceiver<Boolean, Exception> callback) {
595 
596         if (invokeCallbackOnErrorOnRvc(callback)) {
597             return;
598         }
599 
600         enableAdServices(
601                 adServicesStates, executor, OutcomeReceiverConverter.toOutcomeReceiver(callback));
602     }
603 
604     /**
605      * Updates {@link AdId} in Adservices when the device changes {@link AdId}. This API is used by
606      * AdIdProvider.
607      *
608      * @param updateAdIdRequest the request that contains {@link AdId} information to update.
609      * @param executor the executor for the callback.
610      * @param callback the callback in type {@link AdServicesOutcomeReceiver}, available on Android
611      *     R and above.
612      * @throws IllegalStateException when service is not available or the feature is not enabled, or
613      *     if there is any {@code Binder} invocation error.
614      * @throws SecurityException when the caller is not authorized to call this API.
615      * @deprecated use {@link #updateAdId(UpdateAdIdRequest, Executor, OutcomeReceiver)} instead.
616      *     Android R is no longer supported.
617      * @hide
618      */
619     // TODO(b/295205476): Move exceptions into the callback.
620     @SystemApi
621     @RequiresPermission(anyOf = {UPDATE_PRIVILEGED_AD_ID, UPDATE_PRIVILEGED_AD_ID_COMPAT})
622     @Deprecated
623     @FlaggedApi(Flags.FLAG_ADSERVICES_OUTCOMERECEIVER_R_API_DEPRECATED)
624     @SuppressWarnings("NewApi")
625     public void updateAdId(
626             @NonNull UpdateAdIdRequest updateAdIdRequest,
627             @NonNull @CallbackExecutor Executor executor,
628             @NonNull AdServicesOutcomeReceiver<Boolean, Exception> callback) {
629 
630         if (invokeCallbackOnErrorOnRvc(callback)) {
631             return;
632         }
633 
634         updateAdId(
635                 updateAdIdRequest, executor, OutcomeReceiverConverter.toOutcomeReceiver(callback));
636     }
637 
638     /**
639      * Updates {@link AdId} in Adservices when the device changes {@link AdId}. This API is used by
640      * AdIdProvider.
641      *
642      * @param updateAdIdRequest the request that contains {@link AdId} information to update.
643      * @param executor the executor for the callback.
644      * @param callback the callback in type {@link OutcomeReceiver}, available on Android S and
645      *     above.
646      * @throws IllegalStateException when service is not available or the feature is not enabled, or
647      *     if there is any {@code Binder} invocation error.
648      * @throws SecurityException when the caller is not authorized to call this API.
649      * @hide
650      */
651     @SystemApi
652     @RequiresPermission(anyOf = {UPDATE_PRIVILEGED_AD_ID, UPDATE_PRIVILEGED_AD_ID_COMPAT})
653     @RequiresApi(Build.VERSION_CODES.S)
654     public void updateAdId(
655             @NonNull UpdateAdIdRequest updateAdIdRequest,
656             @NonNull @CallbackExecutor Executor executor,
657             @NonNull OutcomeReceiver<Boolean, Exception> callback) {
658         Objects.requireNonNull(updateAdIdRequest);
659         Objects.requireNonNull(executor);
660         Objects.requireNonNull(callback);
661 
662         IAdServicesCommonService service = getService();
663         try {
664             service.updateAdIdCache(
665                     updateAdIdRequest,
666                     new IUpdateAdIdCallback.Stub() {
667                         @Override
668                         public void onResult(String message) {
669                             executor.execute(() -> callback.onResult(true));
670                         }
671 
672                         @Override
673                         public void onFailure(int statusCode) {
674                             executor.execute(
675                                     () ->
676                                             callback.onError(
677                                                     AdServicesStatusUtils.asException(statusCode)));
678                         }
679                     });
680         } catch (RemoteException e) {
681             LogUtil.e(e, "RemoteException calling updateAdIdCache with %s", updateAdIdRequest);
682             executor.execute(
683                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
684         }
685     }
686 
687     /**
688      * Get the AdService's common states.
689      *
690      * @param executor the executor for the callback.
691      * @param callback the callback in type {@link AdServicesOutcomeReceiver}, available on Android
692      *     R and above.
693      * @throws IllegalStateException if there is any {@code Binder} invocation error.
694      * @hide
695      */
696     @SystemApi
697     @FlaggedApi(Flags.FLAG_GET_ADSERVICES_COMMON_STATES_API_ENABLED)
698     @RequiresPermission(anyOf = {ACCESS_ADSERVICES_STATE, ACCESS_ADSERVICES_STATE_COMPAT})
699     public void getAdservicesCommonStates(
700             @NonNull @CallbackExecutor Executor executor,
701             @NonNull
702                     AdServicesOutcomeReceiver<AdServicesCommonStatesResponse, Exception> callback) {
703 
704         if (invokeCallbackOnErrorOnRvc(callback)) {
705             return;
706         }
707 
708         final IAdServicesCommonService service = getService();
709         CallerMetadata callerMetadata =
710                 new CallerMetadata.Builder()
711                         .setBinderElapsedTimestamp(SystemClock.elapsedRealtime())
712                         .build();
713         String appPackageName = "";
714         String sdkPackageName = "";
715         // First check if context is SandboxedSdkContext or not
716         SandboxedSdkContext sandboxedSdkContext =
717                 SandboxedSdkContextUtils.getAsSandboxedSdkContext(mContext);
718         if (sandboxedSdkContext != null) {
719             // This is the case with the Sandbox.
720             sdkPackageName = sandboxedSdkContext.getSdkPackageName();
721             appPackageName = sandboxedSdkContext.getClientPackageName();
722         } else {
723             // This is the case without the Sandbox.
724             appPackageName = mContext.getPackageName();
725         }
726         try {
727             service.getAdServicesCommonStates(
728                     new GetAdServicesCommonStatesParams.Builder(appPackageName, sdkPackageName)
729                             .build(),
730                     callerMetadata,
731                     new IAdServicesCommonStatesCallback.Stub() {
732                         @Override
733                         public void onResult(AdServicesCommonStatesResponse result) {
734                             executor.execute(
735                                     () -> {
736                                         callback.onResult(result);
737                                     });
738                         }
739 
740                         @Override
741                         public void onFailure(int statusCode) {
742                             executor.execute(
743                                     () ->
744                                             callback.onError(
745                                                     AdServicesStatusUtils.asException(statusCode)));
746                         }
747                     });
748         } catch (RemoteException e) {
749             LogUtil.e(e, "RemoteException");
750             executor.execute(
751                     () -> callback.onError(new IllegalStateException("Internal Error!", e)));
752         }
753     }
754 }
755