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 package com.android.adservices.common; 17 18 import com.android.adservices.shared.testing.Logger; 19 import com.android.adservices.shared.testing.Logger.RealLogger; 20 import com.android.adservices.shared.testing.Nullable; 21 import com.android.adservices.shared.testing.SystemPropertiesHelper; 22 23 import java.util.Objects; 24 25 // TODO(b/295321663): add unit tests 26 27 /** Helper to check if AdServices is supported / enabled in a device. */ 28 abstract class AbstractDeviceSupportHelper { 29 30 private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive"; 31 private static final String FEATURE_LEANBACK = "android.software.leanback"; 32 private static final String FEATURE_WATCH = "android.hardware.type.watch"; 33 34 // TODO(b/295321663): 3 constants below should be static imported from AdServicesCommonConstants 35 private static final String SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX = "debug.adservices."; 36 private static final String SYSTEM_PROPERTY_FOR_DEBUGGING_SUPPORTED_DEVICE = 37 SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX + "supported"; 38 // TODO(b/297408848): rename to AdServicesLite something 39 private static final String SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_RAM_LOW = 40 SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX + "low_ram_device"; 41 private static final String SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_LARGE_SCREEN = 42 SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX + "large_screen_device"; 43 44 // Used only for Go device checks, which rely on checking GMS Core and Play Store. 45 public static final String GMS_CORE_PACKAGE = "com.google.android.gms"; 46 public static final String PLAY_STORE_PACKAGE = "com.android.vending"; 47 48 protected final Logger mLog; 49 private final SystemPropertiesHelper.Interface mSystemProperties; 50 AbstractDeviceSupportHelper( RealLogger logger, SystemPropertiesHelper.Interface systemProperties)51 protected AbstractDeviceSupportHelper( 52 RealLogger logger, SystemPropertiesHelper.Interface systemProperties) { 53 mLog = new Logger(Objects.requireNonNull(logger), getClass()); 54 mSystemProperties = Objects.requireNonNull(systemProperties); 55 } 56 57 /** Checks whether AdServices is supported by the device / form factor. */ isDeviceSupported()58 public final boolean isDeviceSupported() { 59 if (isDebuggable()) { 60 String overriddenValue = 61 mSystemProperties.get(SYSTEM_PROPERTY_FOR_DEBUGGING_SUPPORTED_DEVICE); 62 if (isNotEmpty(overriddenValue)) { 63 boolean supported = Boolean.valueOf(overriddenValue); 64 mLog.i( 65 "isDeviceSupported(): returning %b as defined by system property %s (%s)", 66 supported, SYSTEM_PROPERTY_FOR_DEBUGGING_SUPPORTED_DEVICE, overriddenValue); 67 return supported; 68 } 69 } 70 71 boolean supported = isDeviceSupportedByDefault(); 72 mLog.v("isDeviceSupported(): returning hardcoded value (%b)", supported); 73 return supported; 74 } 75 isGoDevice()76 public final boolean isGoDevice() { 77 return isLowRamDevice() && isPhone() && hasGmsCore() && hasPlayStore(); 78 } 79 80 // TODO(b/297408848): rename to isAdservicesLiteDevice() or something like that 81 /** Checks whether the device has low ram. */ isLowRamDevice()82 public final boolean isLowRamDevice() { 83 if (isDebuggable()) { 84 String overriddenValue = 85 mSystemProperties.get(SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_RAM_LOW); 86 if (isNotEmpty(overriddenValue)) { 87 boolean isLowRamDevice = Boolean.valueOf(overriddenValue); 88 mLog.i( 89 "isLowRamDevice(): returning %b as defined by system property %s (%s)", 90 isLowRamDevice, 91 SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_RAM_LOW, 92 overriddenValue); 93 return isLowRamDevice; 94 } 95 } 96 97 boolean isLowRamDevice = isLowRamDeviceByDefault(); 98 boolean isPhone = isPhone(); 99 boolean isIt = isPhone && isLowRamDevice; 100 mLog.v( 101 "isLowRamDevice(): returning non-simulated value %b when isPhone=%b and" 102 + " isLowRamDevice=%b", 103 isIt, isPhone, isLowRamDevice); 104 return isIt; 105 } 106 isLargeScreenDevice()107 public final boolean isLargeScreenDevice() { 108 if (isDebuggable()) { 109 String overriddenValue = 110 mSystemProperties.get(SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_LARGE_SCREEN); 111 if (isNotEmpty(overriddenValue)) { 112 boolean isLargeScreenDevice = Boolean.valueOf(overriddenValue); 113 mLog.i( 114 "isLargeScreenDevice(): returning %b as defined by system property %s (%s)", 115 isLargeScreenDevice, 116 SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_LARGE_SCREEN, 117 overriddenValue); 118 return isLargeScreenDevice; 119 } 120 } 121 122 boolean isLargeScreenDevice = isLargeScreenDeviceByDefault(); 123 boolean isPhone = isPhone(); 124 boolean isIt = isPhone && isLargeScreenDevice; 125 mLog.v( 126 "isLargeScreenDevice(): returning non-simulated value %b when isPhone=%b and" 127 + " isLargeScreenDevice=%b", 128 isIt, isPhone, isLargeScreenDevice); 129 return isIt; 130 } 131 hasGmsCore()132 protected abstract boolean hasGmsCore(); 133 hasPlayStore()134 protected abstract boolean hasPlayStore(); 135 hasPackageManagerFeature(String feature)136 protected abstract boolean hasPackageManagerFeature(String feature); 137 isLowRamDeviceByDefault()138 protected abstract boolean isLowRamDeviceByDefault(); 139 isLargeScreenDeviceByDefault()140 protected abstract boolean isLargeScreenDeviceByDefault(); 141 isDebuggable()142 protected abstract boolean isDebuggable(); 143 144 /** 145 * Check whether the device has a specific android service. 146 * 147 * @param intentAction the intent action. 148 * @return {@code true} when there is one and only one corresponding android service on the 149 * device. 150 */ isAndroidServiceAvailable(String intentAction)151 protected abstract boolean isAndroidServiceAvailable(String intentAction); 152 153 @Nullable getAdServicesPackageName()154 protected abstract String getAdServicesPackageName(); 155 isDeviceSupportedByDefault()156 private boolean isDeviceSupportedByDefault() { 157 return isPhone() && !isGoDevice(); 158 } 159 isPhone()160 private boolean isPhone() { 161 // TODO(b/284744130): need to figure out how to filter out tablets 162 boolean isIt = 163 !hasPackageManagerFeature(FEATURE_WATCH) 164 && !hasPackageManagerFeature(FEATURE_AUTOMOTIVE) 165 && !hasPackageManagerFeature(FEATURE_LEANBACK); 166 mLog.v("isPhone(): returning %b", isIt); 167 return isIt; 168 } 169 isNotEmpty(String string)170 private static boolean isNotEmpty(String string) { 171 return string != null && !string.isEmpty(); 172 } 173 } 174