1 /*
2  * Copyright (C) 2016 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 com.android.performance.tests;
18 
19 import com.android.tradefed.config.Option;
20 import com.android.tradefed.device.DeviceNotAvailableException;
21 import com.android.tradefed.device.ITestDevice;
22 import com.android.tradefed.log.LogUtil.CLog;
23 import com.android.tradefed.result.ByteArrayInputStreamSource;
24 import com.android.tradefed.result.ITestInvocationListener;
25 import com.android.tradefed.result.LogDataType;
26 import com.android.tradefed.testtype.IDeviceTest;
27 import com.android.tradefed.testtype.IRemoteTest;
28 import com.android.tradefed.util.StreamUtil;
29 import com.android.tradefed.util.proto.TfMetricProtoUtil;
30 import java.util.HashMap;
31 import java.util.Map;
32 
33 /** Test to gather post boot System memory usage */
34 public class SystemMemoryTest implements IDeviceTest, IRemoteTest {
35 
36     private static final String PROC_MEMINFO = "cat /proc/meminfo";
37     private static final String MEMTOTAL = "MemTotal";
38     private static final String MEMFREE = "MemFree";
39     private static final String CACHED = "Cached";
40     private static final String SEPARATOR = "\\s+";
41     private static final String LINE_SEPARATOR = "\\n";
42 
43     @Option(
44             name = "reporting-key",
45             description =
46                     "Reporting key is the unique identifier"
47                             + "used to report data in the dashboard.")
48     private String mRuKey = "";
49 
50     private ITestDevice mTestDevice = null;
51     private ITestInvocationListener mlistener = null;
52     private Map<String, String> mMetrics = new HashMap<>();
53 
54     @Override
run(ITestInvocationListener listener)55     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
56         mlistener = listener;
57         String memInfo = mTestDevice.executeShellCommand(PROC_MEMINFO);
58         if (!memInfo.isEmpty()) {
59 
60             uploadLogFile(memInfo, "System MemInfo");
61             parseProcInfo(memInfo);
62         } else {
63             CLog.e("Not able to collect the /proc/meminfo before launching app");
64         }
65         reportMetrics(mlistener, mRuKey, mMetrics);
66     }
67 
68     /**
69      * Method to write the data to test logs.
70      *
71      * @param data
72      * @param fileName
73      */
uploadLogFile(String data, String fileName)74     private void uploadLogFile(String data, String fileName) {
75         ByteArrayInputStreamSource inputStreamSrc = null;
76         try {
77             inputStreamSrc = new ByteArrayInputStreamSource(data.getBytes());
78             mlistener.testLog(fileName, LogDataType.TEXT, inputStreamSrc);
79         } finally {
80             StreamUtil.cancel(inputStreamSrc);
81         }
82     }
83 
84     /**
85      * Method to parse the system memory details
86      *
87      * @param memInfo string dump of cat /proc/meminfo
88      */
parseProcInfo(String memInfo)89     private void parseProcInfo(String memInfo) {
90         for (String line : memInfo.split(LINE_SEPARATOR)) {
91             line = line.replace(":", "").trim();
92             String dataSplit[] = line.split(SEPARATOR);
93             switch (dataSplit[0].toLowerCase()) {
94                 case "memtotal":
95                     mMetrics.put("System_MEMTOTAL", dataSplit[1]);
96                     break;
97                 case "memfree":
98                     mMetrics.put("System_MEMFREE", dataSplit[1]);
99                     break;
100                 case "cached":
101                     mMetrics.put("System_CACHED", dataSplit[1]);
102                     break;
103             }
104         }
105     }
106 
107     /**
108      * Report run metrics by creating an empty test run to stick them in
109      *
110      * @param listener the {@link ITestInvocationListener} of test results
111      * @param runName the test name
112      * @param metrics the {@link Map} that contains metrics for the given test
113      */
reportMetrics( ITestInvocationListener listener, String runName, Map<String, String> metrics)114     void reportMetrics(
115             ITestInvocationListener listener, String runName, Map<String, String> metrics) {
116         // Create an empty testRun to report the parsed runMetrics
117         CLog.d("About to report metrics: %s", metrics);
118         listener.testRunStarted(runName, 0);
119         listener.testRunEnded(0, TfMetricProtoUtil.upgradeConvert(metrics));
120     }
121 
122     @Override
setDevice(ITestDevice device)123     public void setDevice(ITestDevice device) {
124         mTestDevice = device;
125     }
126 
127     @Override
getDevice()128     public ITestDevice getDevice() {
129         return mTestDevice;
130     }
131 }
132