| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.compatibility.common.util; |
| |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import android.app.ActivityManager; |
| import android.app.ActivityManager.MemoryInfo; |
| import android.app.Instrumentation; |
| import android.app.UiAutomation; |
| import android.content.Context; |
| import android.os.ParcelFileDescriptor; |
| import android.os.StatFs; |
| import android.util.Log; |
| |
| import androidx.annotation.NonNull; |
| import androidx.test.InstrumentationRegistry; |
| |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.util.concurrent.Callable; |
| import java.util.function.Predicate; |
| |
| public class SystemUtil { |
| private static final String TAG = "CtsSystemUtil"; |
| |
| public static long getFreeDiskSize(Context context) { |
| final StatFs statFs = new StatFs(context.getFilesDir().getAbsolutePath()); |
| return (long)statFs.getAvailableBlocks() * statFs.getBlockSize(); |
| } |
| |
| public static long getFreeMemory(Context context) { |
| final MemoryInfo info = new MemoryInfo(); |
| ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(info); |
| return info.availMem; |
| } |
| |
| public static long getTotalMemory(Context context) { |
| final MemoryInfo info = new MemoryInfo(); |
| ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(info); |
| return info.totalMem; |
| } |
| |
| /** |
| * Executes a shell command using shell user identity, and return the standard output in string |
| * <p>Note: calling this function requires API level 21 or above |
| * @param instrumentation {@link Instrumentation} instance, obtained from a test running in |
| * instrumentation framework |
| * @param cmd the command to run |
| * @return the standard output of the command |
| * @throws Exception |
| */ |
| public static String runShellCommand(Instrumentation instrumentation, String cmd) |
| throws IOException { |
| return runShellCommand(instrumentation.getUiAutomation(), cmd); |
| } |
| |
| /** |
| * Executes a shell command using shell user identity, and return the standard output in string |
| * <p>Note: calling this function requires API level 21 or above |
| * @param automation {@link UiAutomation} instance, obtained from a test running in |
| * instrumentation framework |
| * @param cmd the command to run |
| * @return the standard output of the command |
| * @throws Exception |
| */ |
| public static String runShellCommand(UiAutomation automation, String cmd) |
| throws IOException { |
| Log.v(TAG, "Running command: " + cmd); |
| if (cmd.startsWith("pm grant ") || cmd.startsWith("pm revoke ")) { |
| throw new UnsupportedOperationException("Use UiAutomation.grantRuntimePermission() " |
| + "or revokeRuntimePermission() directly, which are more robust."); |
| } |
| ParcelFileDescriptor pfd = automation.executeShellCommand(cmd); |
| byte[] buf = new byte[512]; |
| int bytesRead; |
| FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); |
| StringBuffer stdout = new StringBuffer(); |
| while ((bytesRead = fis.read(buf)) != -1) { |
| stdout.append(new String(buf, 0, bytesRead)); |
| } |
| fis.close(); |
| return stdout.toString(); |
| } |
| |
| /** |
| * Simpler version of {@link #runShellCommand(Instrumentation, String)}. |
| */ |
| public static String runShellCommand(String cmd) { |
| try { |
| return runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd); |
| } catch (IOException e) { |
| fail("Failed reading command output: " + e); |
| return ""; |
| } |
| } |
| |
| /** |
| * Same as {@link #runShellCommand(String)}, with optionally |
| * check the result using {@code resultChecker}. |
| */ |
| public static String runShellCommand(String cmd, Predicate<String> resultChecker) { |
| final String result = runShellCommand(cmd); |
| if (resultChecker != null) { |
| assertTrue("Assertion failed. Command was: " + cmd + "\n" |
| + "Output was:\n" + result, |
| resultChecker.test(result)); |
| } |
| return result; |
| } |
| |
| /** |
| * Same as {@link #runShellCommand(String)}, but fails if the output is not empty. |
| */ |
| public static String runShellCommandForNoOutput(String cmd) { |
| final String result = runShellCommand(cmd); |
| assertTrue("Command failed. Command was: " + cmd + "\n" |
| + "Didn't expect any output, but the output was:\n" + result, |
| result.length() == 0); |
| return result; |
| } |
| |
| /** |
| * Runs a command and print the result on logcat. |
| */ |
| public static void runCommandAndPrintOnLogcat(String logtag, String cmd) { |
| Log.i(logtag, "Executing: " + cmd); |
| final String output = runShellCommand(cmd); |
| for (String line : output.split("\\n", -1)) { |
| Log.i(logtag, line); |
| } |
| } |
| |
| /** |
| * Runs a command and return the section matching the patterns. |
| * |
| * @see TextUtils#extractSection |
| */ |
| public static String runCommandAndExtractSection(String cmd, |
| String extractionStartRegex, boolean startInclusive, |
| String extractionEndRegex, boolean endInclusive) { |
| return TextUtils.extractSection(runShellCommand(cmd), extractionStartRegex, startInclusive, |
| extractionEndRegex, endInclusive); |
| } |
| |
| /** |
| * Runs a {@link ThrowingRunnable} adopting Shell's permissions. |
| */ |
| public static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable runnable) { |
| final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation(); |
| runWithShellPermissionIdentity(automan, runnable); |
| } |
| |
| /** |
| * Runs a {@link ThrowingRunnable} adopting a subset of Shell's permissions. |
| */ |
| public static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable runnable, |
| String... permissions) { |
| final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation(); |
| runWithShellPermissionIdentity(automan, runnable, permissions); |
| } |
| |
| /** |
| * Runs a {@link ThrowingRunnable} adopting Shell's permissions, where you can specify the |
| * uiAutomation used. |
| */ |
| public static void runWithShellPermissionIdentity( |
| @NonNull UiAutomation automan, @NonNull ThrowingRunnable runnable) { |
| runWithShellPermissionIdentity(automan, runnable, null /* permissions */); |
| } |
| |
| /** |
| * Runs a {@link ThrowingRunnable} adopting Shell's permissions, where you can specify the |
| * uiAutomation used. |
| * @param automan UIAutomation to use. |
| * @param runnable The code to run with Shell's identity. |
| * @param permissions A subset of Shell's permissions. Passing {@code null} will use all |
| * available permissions. |
| */ |
| public static void runWithShellPermissionIdentity(@NonNull UiAutomation automan, |
| @NonNull ThrowingRunnable runnable, String... permissions) { |
| automan.adoptShellPermissionIdentity(permissions); |
| try { |
| runnable.run(); |
| } catch (Exception e) { |
| throw new RuntimeException("Caught exception", e); |
| } finally { |
| automan.dropShellPermissionIdentity(); |
| } |
| } |
| |
| /** |
| * Calls a {@link Callable} adopting Shell's permissions. |
| */ |
| public static <T> T callWithShellPermissionIdentity(@NonNull Callable<T> callable) |
| throws Exception { |
| final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation(); |
| automan.adoptShellPermissionIdentity(); |
| try { |
| return callable.call(); |
| } finally { |
| automan.dropShellPermissionIdentity(); |
| } |
| } |
| } |