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