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 androidx.annotation.NonNull; 19 20 import java.nio.charset.StandardCharsets; 21 import java.util.Arrays; 22 23 /** An abstraction for running shell commands. */ 24 public abstract class DeviceShellCommandExecutor { 25 26 /** Executes a command, logs and returns a string from stdout. */ 27 @NonNull executeToString(@onNull String command)28 public final String executeToString(@NonNull String command) throws Exception { 29 byte[] bytes = executeToBytesInternal(command); 30 String result = parseBytesAsString(bytes); 31 log("Executed '" + command + "': Result='" + result + "'"); 32 return result; 33 } 34 35 /** Executes a command, logs and returns a trimmed string from stdout. */ 36 @NonNull executeToTrimmedString(@onNull String command)37 public final String executeToTrimmedString(@NonNull String command) throws Exception { 38 byte[] bytes = executeToBytesInternal(command); 39 String result = parseBytesAsString(bytes).trim(); 40 log("Executed '" + command + "': Result='" + result + "'"); 41 return result; 42 } 43 44 /** 45 * Executes a command, logs and returns a boolean based on whether "true" or "false" was 46 * printed to from stdout. 47 */ 48 @NonNull executeToBoolean(@onNull String command)49 public final boolean executeToBoolean(@NonNull String command) throws Exception { 50 byte[] bytes = executeToBytesInternal(command); 51 boolean result = parseBytesAsBoolean(bytes); 52 log("Executed '" + command + "': Result='" + result + "'"); 53 return result; 54 } 55 56 /** Executes a command, logs and returns a byte array from stdout. */ 57 @NonNull executeToBytes(@onNull String command)58 public final byte[] executeToBytes(@NonNull String command) throws Exception { 59 byte[] bytes = executeToBytesInternal(command); 60 log("Executed '" + command + "': Result='" + Arrays.toString(bytes) + "'"); 61 return bytes; 62 } 63 64 /** The raw execution method for subclasses to implement. */ 65 @NonNull executeToBytesInternal(@onNull String command)66 protected abstract byte[] executeToBytesInternal(@NonNull String command) throws Exception; 67 68 /** The logging method for subclasses to implement. */ log(@onNull String msg)69 protected abstract void log(@NonNull String msg); 70 71 /** 72 * Ignoring leading/trainling whitespace, matches "true" or "false" or throws an exception. 73 */ parseBytesAsBoolean(@onNull byte[] result)74 public static boolean parseBytesAsBoolean(@NonNull byte[] result) { 75 String resultString = parseBytesAsString(result).trim(); 76 if (resultString.equals("true")) { 77 return true; 78 } else if (resultString.equals("false")) { 79 return false; 80 } else { 81 throw new AssertionError("Command returned unexpected result: " + resultString); 82 } 83 } 84 85 /** 86 * Converts command line bytes to a String. 87 */ parseBytesAsString(byte[] result)88 protected static String parseBytesAsString(byte[] result) { 89 return new String(result, 0, result.length, StandardCharsets.ISO_8859_1); 90 } 91 } 92