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 package com.android.adservices;
17 
18 import android.adservices.adid.AdIdProviderService;
19 import android.adservices.appsetid.AppSetIdProviderService;
20 import android.adservices.cobalt.AdServicesCobaltUploadService;
21 import android.adservices.extdata.AdServicesExtDataStorageService;
22 import android.annotation.Nullable;
23 import android.content.pm.ResolveInfo;
24 import android.content.pm.ServiceInfo;
25 
26 import java.util.List;
27 import java.util.stream.Collectors;
28 
29 // TODO(b/295321663): need to split constants into AdServicesCommonConstants so they can be used by
30 // host-side test artifacts.
31 
32 /**
33  * Common constants for AdServices
34  *
35  * @hide
36  */
37 public final class AdServicesCommon {
AdServicesCommon()38     private AdServicesCommon() {}
39 
40     /** Intent action to discover the Topics service in the APK. */
41     public static final String ACTION_TOPICS_SERVICE = "android.adservices.TOPICS_SERVICE";
42 
43     /** Intent action to discover the Custom Audience service in the APK. */
44     public static final String ACTION_CUSTOM_AUDIENCE_SERVICE =
45             "android.adservices.customaudience.CUSTOM_AUDIENCE_SERVICE";
46 
47     /** Intent action to discover the AdSelection service in the APK. */
48     public static final String ACTION_AD_SELECTION_SERVICE =
49             "android.adservices.adselection.AD_SELECTION_SERVICE";
50 
51     /** Intent action to discover the protected signals service in the APK. */
52     public static final String ACTION_PROTECTED_SIGNALS_SERVICE =
53             "android.adservices.signals.PROTECTED_SIGNALS_SERVICE";
54 
55     /** Intent action to discover the Measurement service in the APK. */
56     public static final String ACTION_MEASUREMENT_SERVICE =
57             "android.adservices.MEASUREMENT_SERVICE";
58 
59     /** Intent action to discover the AdId service in the APK. */
60     public static final String ACTION_ADID_SERVICE = "android.adservices.ADID_SERVICE";
61 
62     /** Intent action to discover the AdId Provider service. */
63     public static final String ACTION_ADID_PROVIDER_SERVICE = AdIdProviderService.SERVICE_INTERFACE;
64 
65     /** Intent action to discover the AppSetId service in the APK. */
66     public static final String ACTION_APPSETID_SERVICE = "android.adservices.APPSETID_SERVICE";
67 
68     /** Intent action to discover the AppSetId Provider service. */
69     public static final String ACTION_APPSETID_PROVIDER_SERVICE =
70             AppSetIdProviderService.SERVICE_INTERFACE;
71 
72     /** Intent action to discover the AdServicesExtDataStorageService. */
73     public static final String ACTION_AD_EXT_DATA_STORAGE_SERVICE =
74             AdServicesExtDataStorageService.SERVICE_INTERFACE;
75 
76     /** Intent action to discover the AdServicesCommon service in the APK. */
77     public static final String ACTION_AD_SERVICES_COMMON_SERVICE =
78             "android.adservices.AD_SERVICES_COMMON_SERVICE";
79 
80     /** Intent action to discover the AdServices Cobalt upload service. */
81     public static final String ACTION_AD_SERVICES_COBALT_UPLOAD_SERVICE =
82             AdServicesCobaltUploadService.SERVICE_INTERFACE;
83 
84     /** Intent action to discover the Shell Command service in the APK. */
85     public static final String ACTION_SHELL_COMMAND_SERVICE =
86             "android.adservices.SHELL_COMMAND_SERVICE";
87 
88     // Used to differentiate between AdServices APK package name and AdExtServices APK package name.
89     // The AdExtServices APK package name suffix is android.ext.services.
90     public static final String ADSERVICES_APK_PACKAGE_NAME_SUFFIX = "android.adservices.api";
91 
92     /** The package name suffix of the ExtServices APK on R/S */
93     public static final String ADEXTSERVICES_PACKAGE_NAME_SUFFIX = "android.ext.services";
94 
95     /** Suffix for the AdServices APEX package name. */
96     public static final String ADSERVICES_APEX_NAME_SUFFIX = "android.adservices";
97 
98     /**
99      * Suffix for the ExtServices APEX Package name. Used to figure out the installed apex version.
100      */
101     public static final String EXTSERVICES_APEX_NAME_SUFFIX = "android.extservices";
102 
103     /**
104      * Prefix for system properties used for debugging purposes (like simulating unsupported devices
105      * or change some behavior without changing a flag).
106      */
107     public static final String SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX = "debug.adservices.";
108 
109     /** System property used to simulate AdServices behavior on devices with low memory. */
110     public static final String SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_RAM_LOW =
111             SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX + "low_ram_device";
112 
113     /** The name of System Property for the binder timeout */
114     public static final String BINDER_TIMEOUT_SYSTEM_PROPERTY_NAME = "binder_timeout";
115 
116     /** System property used to allow test to override the binder's timeout. */
117     public static final String SYSTEM_PROPERTY_FOR_DEBUGGING_BINDER_TIMEOUT =
118             SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX + BINDER_TIMEOUT_SYSTEM_PROPERTY_NAME;
119 
120     /** Path name for Adservice class names */
121     public static final String ADSERVICES_CLASS_PATH_PREFIX = "com.android.adservices.";
122 
123     /** The package name of the active AdServices APK on this device. */
resolveAdServicesService( @ullable List<ResolveInfo> intentResolveInfos, String intentAction)124     public static ServiceInfo resolveAdServicesService(
125             @Nullable List<ResolveInfo> intentResolveInfos, String intentAction) {
126         int size = intentResolveInfos == null ? 0 : intentResolveInfos.size();
127 
128         enforceSingleServiceForAdIdAndAppSetId(intentAction, size);
129 
130         switch (size) {
131             case 0:
132                 LogUtil.e(
133                         "Failed to find resolveInfo for adServices service. Intent action: %s",
134                         intentAction);
135                 return null;
136 
137             case 1:
138                 return intentResolveInfos.get(0).serviceInfo;
139 
140             case 2:
141                 // On T+ devices, we may have two versions of the services present due to
142                 // b/263904312. Only use the service that comes from AdServices APK. The package
143                 // name of AdService is com.[google.]android.adservices.api while the package name
144                 // of ExtServices APK is com.[google.]android.ext.services.
145                 ServiceInfo serviceInfo = getServiceInfoIfAdServices(intentResolveInfos.get(0));
146                 return serviceInfo == null
147                         ? getServiceInfoIfAdServices(intentResolveInfos.get(1))
148                         : serviceInfo;
149 
150             default:
151                 List<String> intents =
152                         intentResolveInfos.stream()
153                                 .filter(s -> s != null && s.serviceInfo != null)
154                                 .map(s -> s.serviceInfo.packageName)
155                                 .collect(Collectors.toList());
156                 LogUtil.e("Found multiple services %s for %s", intents, intentAction);
157                 return null;
158         }
159     }
160 
getServiceInfoIfAdServices(@ullable ResolveInfo resolveInfo)161     private static ServiceInfo getServiceInfoIfAdServices(@Nullable ResolveInfo resolveInfo) {
162         if (resolveInfo == null) {
163             return null;
164         }
165 
166         ServiceInfo serviceInfo = resolveInfo.serviceInfo;
167         if (serviceInfo == null || serviceInfo.packageName == null) {
168             return null;
169         }
170 
171         return serviceInfo.packageName.endsWith(ADSERVICES_APK_PACKAGE_NAME_SUFFIX)
172                 ? serviceInfo
173                 : null;
174     }
175 
176     // It was designed to allow OEM to override the AdId/AppSetId Provider Service in GMS Core.
177     // However, this is never available because if the device has both GMS Core and an
178     // overriding Provider, it falls into this case and returns null. Therefore, let it
179     // explicitly throw in case any OEM wants to actually override it, and we can apply
180     // a change to allow it if needed.
enforceSingleServiceForAdIdAndAppSetId( String intentAction, int numberOfResolvedServices)181     private static void enforceSingleServiceForAdIdAndAppSetId(
182             String intentAction, int numberOfResolvedServices) {
183         if ((ACTION_ADID_PROVIDER_SERVICE.equals(intentAction)
184                         || ACTION_APPSETID_PROVIDER_SERVICE.equals(intentAction))
185                 && numberOfResolvedServices > 1) {
186             throw new IllegalStateException("Found multiple services for " + intentAction);
187         }
188     }
189 }
190