• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 com.android.adservices.service.common.compat;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.PackageInfo;
23 import android.content.pm.PackageManager;
24 
25 import androidx.annotation.NonNull;
26 
27 import com.android.adservices.LogUtil;
28 import com.android.modules.utils.build.SdkLevel;
29 
30 import com.google.common.collect.ImmutableList;
31 
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Objects;
35 
36 /** Utility class for compatibility of PackageManager APIs with Android S and earlier. */
37 public final class PackageManagerCompatUtils {
38 
PackageManagerCompatUtils()39     private PackageManagerCompatUtils() {
40         // Prevent instantiation
41     }
42 
43     // This list is the same as the list declared in the AdExtServicesManifest, where the
44     // activities are disabled so that there are no dups on T+ devices.
45     // TODO(b/263904312): Remove after max_sdk_version is implemented.
46     // TODO(b/272737642) scan activities instead of hardcode
47     public static final ImmutableList<String> CONSENT_ACTIVITIES_CLASSES =
48             ImmutableList.copyOf(
49                     Arrays.asList(
50                             "com.android.adservices.ui.settings.activities."
51                                     + "AdServicesSettingsMainActivity",
52                             "com.android.adservices.ui.settings.activities.TopicsActivity",
53                             "com.android.adservices.ui.settings.activities.BlockedTopicsActivity",
54                             "com.android.adservices.ui.settings.activities.AppsActivity",
55                             "com.android.adservices.ui.settings.activities.BlockedAppsActivity",
56                             "com.android.adservices.ui.settings.activities.MeasurementActivity",
57                             "com.android.adservices.ui.notifications.ConsentNotificationActivity"));
58 
59     // This list is the same as the list declared in the AdExtServicesManifest, where the
60     // services with intent filters need to be disabled so that there are no dups on T+ devices.
61     // TODO(b/263904312): Remove after max_sdk_version is implemented.
62     // TODO(b/272737642) scan services instead of hardcode
63     public static final ImmutableList<String> SERVICE_CLASSES =
64             ImmutableList.copyOf(
65                     Arrays.asList(
66                             "com.android.adservices.adselection.AdSelectionService",
67                             "com.android.adservices.customaudience.CustomAudienceService",
68                             "com.android.adservices.topics.TopicsService",
69                             "com.android.adservices.adid.AdIdService",
70                             "com.android.adservices.appsetid.AppSetIdService",
71                             "com.android.adservices.measurement.MeasurementService",
72                             "com.android.adservices.common.AdServicesCommonService"));
73 
74     /**
75      * Invokes the appropriate overload of {@code getInstalledPackages} on {@link PackageManager}
76      * depending on the SDK version.
77      *
78      * <p>{@code PackageInfoFlags.of()} actually takes a {@code long} as input whereas the earlier
79      * overload takes an {@code int}. For backward-compatibility, we're limited to the {@code int}
80      * range, so using {@code int} as a parameter to this method.
81      *
82      * @param packageManager the package manager instance to query
83      * @param flags the flags to be used for querying package manager
84      * @return the list of installed packages returned from the query to {@link PackageManager}
85      */
86     @NonNull
getInstalledPackages( @onNull PackageManager packageManager, int flags)87     public static List<PackageInfo> getInstalledPackages(
88             @NonNull PackageManager packageManager, int flags) {
89         Objects.requireNonNull(packageManager);
90         return SdkLevel.isAtLeastT()
91                 ? packageManager.getInstalledPackages(PackageManager.PackageInfoFlags.of(flags))
92                 : packageManager.getInstalledPackages(flags);
93     }
94 
95     /**
96      * Invokes the appropriate overload of {@code getInstalledApplications} on {@link
97      * PackageManager} depending on the SDK version.
98      *
99      * <p>{@code ApplicationInfoFlags.of()} actually takes a {@code long} as input whereas the
100      * earlier overload takes an {@code int}. For backward-compatibility, we're limited to the
101      * {@code int} range, so using {@code int} as a parameter to this method.
102      *
103      * @param packageManager the package manager instance to query
104      * @param flags the flags to be used for querying package manager
105      * @return the list of installed applications returned from the query to {@link PackageManager}
106      */
107     @NonNull
getInstalledApplications( @onNull PackageManager packageManager, int flags)108     public static List<ApplicationInfo> getInstalledApplications(
109             @NonNull PackageManager packageManager, int flags) {
110         Objects.requireNonNull(packageManager);
111         return SdkLevel.isAtLeastT()
112                 ? packageManager.getInstalledApplications(
113                         PackageManager.ApplicationInfoFlags.of(flags))
114                 : packageManager.getInstalledApplications(flags);
115     }
116 
117     /**
118      * Invokes the appropriate overload of {@code getApplicationInfo} on {@link PackageManager}
119      * depending on the SDK version.
120      *
121      * <p>{@code ApplicationInfoFlags.of()} actually takes a {@code long} as input whereas the
122      * earlier overload takes an {@code int}. For backward-compatibility, we're limited to the
123      * {@code int} range, so using {@code int} as a parameter to this method.
124      *
125      * @param packageManager the package manager instance to query
126      * @param flags the flags to be used for querying package manager
127      * @param packageName the name of the package for which the ApplicationInfo should be retrieved
128      * @return the application info returned from the query to {@link PackageManager}
129      */
130     @NonNull
getApplicationInfo( @onNull PackageManager packageManager, @NonNull String packageName, int flags)131     public static ApplicationInfo getApplicationInfo(
132             @NonNull PackageManager packageManager, @NonNull String packageName, int flags)
133             throws PackageManager.NameNotFoundException {
134         Objects.requireNonNull(packageManager);
135         Objects.requireNonNull(packageName);
136         return SdkLevel.isAtLeastT()
137                 ? packageManager.getApplicationInfo(
138                         packageName, PackageManager.ApplicationInfoFlags.of(flags))
139                 : packageManager.getApplicationInfo(packageName, flags);
140     }
141 
142     /**
143      * Invokes the appropriate overload of {@code getPackageUid} on {@link PackageManager} depending
144      * on the SDK version.
145      *
146      * <p>{@code PackageInfoFlags.of()} actually takes a {@code long} as input whereas the earlier
147      * overload takes an {@code int}. For backward-compatibility, we're limited to the {@code int}
148      * range, so using {@code int} as a parameter to this method.
149      *
150      * @param packageManager the packageManager instance to query
151      * @param packageName the name of the package for which the uid needs to be returned
152      * @param flags the flags to be used for querying the packageManager
153      * @return the uid of the package with the specified name
154      * @throws PackageManager.NameNotFoundException if the package was not found
155      */
getPackageUid( @onNull PackageManager packageManager, @NonNull String packageName, int flags)156     public static int getPackageUid(
157             @NonNull PackageManager packageManager, @NonNull String packageName, int flags)
158             throws PackageManager.NameNotFoundException {
159         Objects.requireNonNull(packageManager);
160         Objects.requireNonNull(packageName);
161         return SdkLevel.isAtLeastT()
162                 ? packageManager.getPackageUid(
163                         packageName, PackageManager.PackageInfoFlags.of(flags))
164                 : packageManager.getPackageUid(packageName, flags);
165     }
166 
167     /**
168      * Activities for user consent and control are disabled by default. Check whether the activities
169      * are enabled
170      *
171      * @param context the context
172      * @return true if AdServices activities are enabled, otherwise false
173      */
174     @NonNull
isAdServicesActivityEnabled(@onNull Context context)175     public static boolean isAdServicesActivityEnabled(@NonNull Context context) {
176         Objects.requireNonNull(context);
177         PackageManager packageManager = context.getPackageManager();
178         try {
179             PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
180             for (String activity : CONSENT_ACTIVITIES_CLASSES) {
181                 int componentEnabledState =
182                         packageManager.getComponentEnabledSetting(
183                                 new ComponentName(packageInfo.packageName, activity));
184                 if (componentEnabledState != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
185                     return false;
186                 }
187             }
188         } catch (PackageManager.NameNotFoundException e) {
189             LogUtil.e("Error when checking if activities are enabled: " + e.getMessage());
190             return false;
191         }
192         return true;
193     }
194 }
195