1 /* 2 * Copyright (C) 2017 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.dumpsys.cts; 18 19 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 20 21 import java.io.BufferedReader; 22 import java.io.StringReader; 23 import java.util.Date; 24 import java.util.regex.Matcher; 25 import java.util.regex.Pattern; 26 import java.text.SimpleDateFormat; 27 28 /** 29 * Test to check the format of the dumps of the processstats test. 30 */ 31 public class StoragedDumpsysTest extends BaseDumpsysTest { 32 private static final String DEVICE_SIDE_TEST_APK = "CtsStoragedTestApp.apk"; 33 private static final String DEVICE_SIDE_TEST_PACKAGE = "com.android.server.cts.storaged"; 34 35 @Override tearDown()36 protected void tearDown() throws Exception { 37 super.tearDown(); 38 getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE); 39 } 40 getCgroupFromLog(String log)41 private String getCgroupFromLog(String log) { 42 Pattern pattern = Pattern.compile("cgroup:([^\\s]+)", Pattern.MULTILINE); 43 Matcher matcher = pattern.matcher(log); 44 if (matcher.find()) { 45 return matcher.group(1); 46 } 47 return null; 48 } 49 getCurrentLogcatDate()50 private String getCurrentLogcatDate() throws Exception { 51 long timestampMs = getDevice().getDeviceDate(); 52 return new SimpleDateFormat("MM-dd HH:mm:ss.SSS") 53 .format(new Date(timestampMs)); 54 } 55 56 /** 57 * Tests the output of "dumpsys storaged --force --hours 0.01". 58 * 59 * @throws Exception 60 */ testStoragedOutput()61 public void testStoragedOutput() throws Exception { 62 String result = mDevice.executeShellCommand("stat /proc/uid_io/stats"); 63 if(result.contains("No such file or directory")) { 64 return; 65 } 66 67 if (mDevice.getAppPackageInfo(DEVICE_SIDE_TEST_APK) != null) { 68 getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE); 69 } 70 71 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 72 mDevice.installPackage(buildHelper.getTestFile(DEVICE_SIDE_TEST_APK), true); 73 74 mDevice.executeShellCommand("dumpsys storaged --force"); 75 76 String logcatDate = getCurrentLogcatDate(); 77 78 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, 79 "com.android.server.cts.storaged.StoragedTest", 80 "testBackgroundIO"); 81 String log = mDevice.executeAdbCommand( 82 "logcat", "-v", "brief", "-d", "-t", logcatDate, 83 "SimpleIOService:I", "*:S"); 84 String serviceCgroup = getCgroupFromLog(log); 85 if (serviceCgroup != null && serviceCgroup.equals("/top")) { 86 System.out.println("WARNING: Service was not in the correct cgroup; ActivityManager may be unresponsive."); 87 } 88 89 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, 90 "com.android.server.cts.storaged.StoragedTest", 91 "testForegroundIO"); 92 93 String output = mDevice.executeShellCommand("dumpsys storaged --force --hours 0.01"); 94 assertNotNull(output); 95 assertTrue(output.length() > 0); 96 97 boolean hasTestIO = false; 98 try (BufferedReader reader = new BufferedReader( 99 new StringReader(output))) { 100 101 String line; 102 String[] parts; 103 while ((line = reader.readLine()) != null) { 104 if (line.isEmpty()) { 105 continue; 106 } 107 108 if (line.contains(",")) { 109 parts = line.split(","); 110 assertTrue(parts.length == 2); 111 if (!parts[0].isEmpty()) { 112 assertInteger(parts[0]); 113 } 114 assertInteger(parts[1]); 115 continue; 116 } 117 118 parts = line.split(" "); 119 assertTrue(parts.length == 9); 120 for (int i = 1; i < parts.length; i++) { 121 assertInteger(parts[i]); 122 } 123 124 if (parts[0].equals(DEVICE_SIDE_TEST_PACKAGE)) { 125 /* 126 * order of parts in StoragedService::dumpUidRecords 127 * [0] DEVICE_SIDE_TEST_PACKAGE 128 * [1] read foreground charger_off 129 * [2] write foreground charger_off 130 * [3] read background charger_off 131 * [4] write background charger_off 132 * [5] read foreground charger_on 133 * [6] write foreground charger_on 134 * [7] read background charger_on 135 * [8] write background charger_on 136 */ 137 if ((Integer.parseInt(parts[6]) >= 8192 && Integer.parseInt(parts[8]) == 0) || 138 (Integer.parseInt(parts[2]) >= 8192 && Integer.parseInt(parts[4]) == 0)) { 139 System.out.print("WARNING: Background I/O was attributed to the " 140 + "foreground. This could indicate a broken or malfunctioning " 141 + "ActivityManager or UsageStatsService.\n"); 142 } else if ((Integer.parseInt(parts[2]) >= 4096 && Integer.parseInt(parts[4]) >= 4096) || 143 Integer.parseInt(parts[4]) >= 8192) { 144 System.out.print("WARNING: charger on I/O was attributed to " 145 + "charger off. This could indicate a broken or malfunctioning " 146 + "ADB USB connection, or device that refuses to charge at the " 147 + "typical 500mA because it is less than 0.05C.\n"); 148 } else { 149 assertTrue((Integer.parseInt(parts[6]) >= 4096 && Integer.parseInt(parts[8]) >= 4096) || 150 Integer.parseInt(parts[8]) >= 8192); 151 } 152 hasTestIO = true; 153 } 154 } 155 156 assertTrue(hasTestIO); 157 } 158 } 159 } 160