• 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 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