1 /*
2  * Copyright (C) 2021 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 android.app.time.cts.shell;
17 
18 import static org.junit.Assume.assumeTrue;
19 
20 import java.io.BufferedReader;
21 import java.io.StringReader;
22 import java.util.Objects;
23 
24 /**
25  * A class for interacting with the {@code location_time_zone_manager} service via the shell "cmd"
26  * command-line interface.
27  */
28 public class LocationTimeZoneManagerShellHelper {
29 
30     /**
31      * The name of the service for shell commands.
32      */
33     private static final String SERVICE_NAME = "location_time_zone_manager";
34 
35     /**
36      * A shell command that starts the service (after stop).
37      */
38     private static final String SHELL_COMMAND_START = "start";
39 
40     /**
41      * A shell command that stops the service.
42      */
43     private static final String SHELL_COMMAND_STOP = "stop";
44 
45     /**
46      * A shell command that clears recorded provider state information during tests.
47      */
48     private static final String SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES =
49             "clear_recorded_provider_states";
50 
51     /**
52      * A shell command that tells the service to dump its current state.
53      */
54     private static final String SHELL_COMMAND_DUMP_STATE = "dump_state";
55 
56     /**
57      * Option for {@link #SHELL_COMMAND_DUMP_STATE} that tells it to dump state as a binary proto.
58      */
59     private static final String DUMP_STATE_OPTION_PROTO = "proto";
60 
61     /** A shell command that starts the location_time_zone_manager with named test providers. */
62     public static final String SHELL_COMMAND_START_WITH_TEST_PROVIDERS =
63             "start_with_test_providers";
64 
65     /**
66      * The token that can be passed to {@link #SHELL_COMMAND_START_WITH_TEST_PROVIDERS} to indicate
67      * there is no provider.
68      */
69     public static final String NULL_PACKAGE_NAME_TOKEN = "@null";
70 
71     private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " ";
72 
73     private final DeviceShellCommandExecutor mShellCommandExecutor;
74 
LocationTimeZoneManagerShellHelper(DeviceShellCommandExecutor shellCommandExecutor)75     public LocationTimeZoneManagerShellHelper(DeviceShellCommandExecutor shellCommandExecutor) {
76         mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor);
77     }
78 
79     /**
80      * Throws an {@link org.junit.AssumptionViolatedException} if the location_time_zone_manager
81      * service is not found. The service can be turned off in config, so this can be used to prevent
82      * CTS tests that need it from running.
83      */
assumeLocationTimeZoneManagerIsPresent()84     public void assumeLocationTimeZoneManagerIsPresent() throws Exception {
85         assumeTrue(isLocationTimeZoneManagerPresent());
86     }
87 
88     /**
89      * Returns {@code false} if the location_time_zone_manager service is not found.
90      */
isLocationTimeZoneManagerPresent()91     public boolean isLocationTimeZoneManagerPresent() throws Exception {
92         // Look for the service name in "cmd -l".
93         String serviceList = mShellCommandExecutor.executeToString("cmd -l");
94         try (BufferedReader reader = new BufferedReader(new StringReader(serviceList))) {
95             String serviceName;
96             while ((serviceName = reader.readLine()) != null) {
97                 serviceName = serviceName.trim();
98                 if (SERVICE_NAME.equals(serviceName)) {
99                     return true;
100                 }
101             }
102             return false;
103         }
104     }
105 
106     /** Executes "start". Starts the service. */
start()107     public void start() throws Exception {
108         mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_START);
109     }
110 
111     /** Executes "stop". Stops the service. */
stop()112     public void stop() throws Exception {
113         mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_STOP);
114     }
115 
116     /** Executes "clear_recorded_provider_states". */
clearRecordedProviderStates()117     public void clearRecordedProviderStates() throws Exception {
118         String cmd = SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES;
119         mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd);
120     }
121 
122     /**
123      * Executes "dump_state". Raw proto bytes are returned as host protos tend to use "full" proto,
124      * device protos use "lite".
125      **/
dumpState()126     public byte[] dumpState() throws Exception {
127         String cmd = String.format("%s --%s", SHELL_COMMAND_DUMP_STATE, DUMP_STATE_OPTION_PROTO);
128         return mShellCommandExecutor.executeToBytes(SHELL_CMD_PREFIX + cmd);
129     }
130 
131     /** Executes "start_with_test_providers". */
startWithTestProviders(String testPrimaryLocationTimeZoneProviderPackageName, String testSecondaryLocationTimeZoneProviderPackageName, boolean recordProviderStates)132     public void startWithTestProviders(String testPrimaryLocationTimeZoneProviderPackageName,
133             String testSecondaryLocationTimeZoneProviderPackageName, boolean recordProviderStates)
134             throws Exception {
135         testPrimaryLocationTimeZoneProviderPackageName =
136                 replaceNullPackageNameWithToken(testPrimaryLocationTimeZoneProviderPackageName);
137         testSecondaryLocationTimeZoneProviderPackageName =
138                 replaceNullPackageNameWithToken(testSecondaryLocationTimeZoneProviderPackageName);
139         String cmd = String.format("%s %s %s %s",
140                 SHELL_COMMAND_START_WITH_TEST_PROVIDERS,
141                 testPrimaryLocationTimeZoneProviderPackageName,
142                 testSecondaryLocationTimeZoneProviderPackageName,
143                 recordProviderStates);
144         mShellCommandExecutor.executeToBytes(SHELL_CMD_PREFIX + cmd);
145     }
146 
replaceNullPackageNameWithToken(String packageName)147     private static String replaceNullPackageNameWithToken(String packageName) {
148         return packageName == null ? NULL_PACKAGE_NAME_TOKEN : packageName;
149     }
150 }
151