• 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 android.healthconnect.cts;
18 
19 import android.cts.statsdatom.lib.AtomTestUtils;
20 import android.cts.statsdatom.lib.DeviceUtils;
21 
22 import com.android.tradefed.device.DeviceNotAvailableException;
23 import com.android.tradefed.device.ITestDevice;
24 import com.android.tradefed.util.CommandStatus;
25 import com.android.tradefed.util.RunUtil;
26 
27 import java.time.Duration;
28 import java.time.Instant;
29 import java.time.temporal.ChronoUnit;
30 import java.util.Date;
31 import java.util.List;
32 
33 public class HostSideTestUtil {
34 
35     public static final String TEST_APP_PKG_NAME = "android.healthconnect.cts.testhelper";
36     public static final String DAILY_LOG_TESTS_ACTIVITY = ".DailyLogsTests";
37     private static final int NUMBER_OF_RETRIES = 10;
38 
39     private static final String FEATURE_TV = "android.hardware.type.television";
40     private static final String FEATURE_EMBEDDED = "android.hardware.type.embedded";
41     private static final String FEATURE_WATCH = "android.hardware.type.watch";
42     private static final String FEATURE_LEANBACK = "android.software.leanback";
43     private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
44 
45     private static final String ENABLE_RATE_LIMITER_FLAG = "enable_rate_limiter";
46     private static final String NAMESPACE_HEALTH_FITNESS = "health_fitness";
47     private static String sRateLimiterFlagDefaultValue;
48 
49     /** Clears all data on the device, including access logs. */
clearData(ITestDevice device)50     public static void clearData(ITestDevice device) throws Exception {
51         triggerTestInTestApp(device, DAILY_LOG_TESTS_ACTIVITY, "deleteAllStagedRemoteData");
52         // Next two lines will delete newly added Access Logs as all access logs over 7 days are
53         // deleted by the AutoDeleteService which is run by the daily job.
54         increaseDeviceTimeByDays(device, 10);
55         triggerDailyJob(device);
56     }
57 
58     /** Triggers a test on the device with the given className and testName. */
triggerTestInTestApp(ITestDevice device, String className, String testName)59     public static void triggerTestInTestApp(ITestDevice device, String className, String testName)
60             throws Exception {
61 
62         if (testName != null) {
63             DeviceUtils.runDeviceTests(device, TEST_APP_PKG_NAME, className, testName);
64         }
65     }
66 
67     /** Increases the device clock by the given numberOfDays. */
increaseDeviceTimeByDays(ITestDevice device, int numberOfDays)68     public static void increaseDeviceTimeByDays(ITestDevice device, int numberOfDays)
69             throws DeviceNotAvailableException {
70         Instant deviceDate = Instant.ofEpochMilli(device.getDeviceDate());
71 
72         device.setDate(Date.from(deviceDate.plus(numberOfDays, ChronoUnit.DAYS)));
73         device.executeShellCommand(
74                 "cmd time_detector set_time_state_for_tests --unix_epoch_time "
75                         + deviceDate.plus(numberOfDays, ChronoUnit.DAYS).toEpochMilli()
76                         + " --user_should_confirm_time false --elapsed_realtime 0");
77 
78         device.executeShellCommand("am broadcast -a android.intent.action.TIME_SET");
79     }
80 
81     /** Reset device time to revert all changes made during the test. */
resetTime(ITestDevice device, Instant testStartTime, Instant deviceStartTime)82     public static void resetTime(ITestDevice device, Instant testStartTime, Instant deviceStartTime)
83             throws DeviceNotAvailableException {
84         long timeDiff = Duration.between(testStartTime, Instant.now()).toMillis();
85 
86         device.executeShellCommand(
87                 "cmd time_detector set_time_state_for_tests --unix_epoch_time "
88                         + deviceStartTime.plusMillis(timeDiff).toEpochMilli()
89                         + " --user_should_confirm_time false --elapsed_realtime 0");
90         device.executeShellCommand("am broadcast -a android.intent.action.TIME_SET");
91     }
92 
93     /** Triggers the Health Connect daily job. */
triggerDailyJob(ITestDevice device)94     public static void triggerDailyJob(ITestDevice device) throws Exception {
95 
96         // There are multiple instances of HealthConnectDailyService. This command finds the one
97         // that needs to be triggered for this test using the job param 'hc_daily_job'.
98         String output =
99                 device.executeShellCommand(
100                         "dumpsys jobscheduler | grep -m1 -A0 -B10 \"hc_daily_job\"");
101         int indexOfStart = output.indexOf("/") + 1;
102         String jobId = output.substring(indexOfStart, output.indexOf(":", indexOfStart));
103         String jobExecutionCommand =
104                 "cmd jobscheduler run --namespace HEALTH_CONNECT_DAILY_JOB -f android " + jobId;
105 
106         executeJob(device, jobExecutionCommand, NUMBER_OF_RETRIES);
107         RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG);
108     }
109 
executeJob(ITestDevice device, String jobExecutionCommand, int retry)110     private static void executeJob(ITestDevice device, String jobExecutionCommand, int retry)
111             throws DeviceNotAvailableException, RuntimeException {
112         if (retry == 0) {
113             throw new RuntimeException("Could not execute job");
114         }
115         if (device.executeShellV2Command(jobExecutionCommand).getStatus()
116                 != CommandStatus.SUCCESS) {
117             executeJob(device, jobExecutionCommand, retry - 1);
118         }
119     }
120 
121     /** Checks if the hardware supports Health Connect. */
isHardwareSupported(ITestDevice device)122     public static boolean isHardwareSupported(ITestDevice device) {
123         // These UI tests are not optimised for Watches, TVs, Auto;
124         // IoT devices do not have a UI to run these UI tests
125         try {
126             return !DeviceUtils.hasFeature(device, FEATURE_TV)
127                     && !DeviceUtils.hasFeature(device, FEATURE_EMBEDDED)
128                     && !DeviceUtils.hasFeature(device, FEATURE_WATCH)
129                     && !DeviceUtils.hasFeature(device, FEATURE_LEANBACK)
130                     && !DeviceUtils.hasFeature(device, FEATURE_AUTOMOTIVE);
131         } catch (Exception e) {
132             return false;
133         }
134     }
135 
136     /** Grants {@code permissions} to {@code packageName} with ADB shell commands. */
grantPermissionsWithAdb( ITestDevice device, String packageName, List<String> permissions)137     public static void grantPermissionsWithAdb(
138             ITestDevice device, String packageName, List<String> permissions)
139             throws DeviceNotAvailableException {
140         for (String perm : permissions) {
141             device.executeShellCommand("pm grant " + packageName + " " + perm);
142         }
143     }
144 
145     /** Temporarily disables the rate limiter feature flag. */
setupRateLimitingFeatureFlag(ITestDevice device)146     public static void setupRateLimitingFeatureFlag(ITestDevice device) throws Exception {
147         // Store default value of the flag on device for teardown.
148         sRateLimiterFlagDefaultValue =
149                 DeviceUtils.getDeviceConfigFeature(
150                         device, NAMESPACE_HEALTH_FITNESS, ENABLE_RATE_LIMITER_FLAG);
151 
152         DeviceUtils.putDeviceConfigFeature(
153                 device, NAMESPACE_HEALTH_FITNESS, ENABLE_RATE_LIMITER_FLAG, "false");
154     }
155 
156     /** Restores the rate limiter feature flag. */
restoreRateLimitingFeatureFlag(ITestDevice device)157     public static void restoreRateLimitingFeatureFlag(ITestDevice device) throws Exception {
158         if (sRateLimiterFlagDefaultValue == null || sRateLimiterFlagDefaultValue.equals("null")) {
159             DeviceUtils.deleteDeviceConfigFeature(
160                     device, NAMESPACE_HEALTH_FITNESS, ENABLE_RATE_LIMITER_FLAG);
161         } else {
162             DeviceUtils.putDeviceConfigFeature(
163                     device,
164                     NAMESPACE_HEALTH_FITNESS,
165                     ENABLE_RATE_LIMITER_FLAG,
166                     sRateLimiterFlagDefaultValue);
167         }
168     }
169 }
170