1 /*
2  * Copyright (C) 2018 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.tradefed.targetprep;
18 
19 import com.android.annotations.VisibleForTesting;
20 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
21 import com.android.tradefed.build.IBuildInfo;
22 import com.android.tradefed.config.Option;
23 import com.android.tradefed.config.OptionClass;
24 import com.android.tradefed.device.DeviceNotAvailableException;
25 import com.android.tradefed.device.ITestDevice;
26 import com.android.tradefed.log.LogUtil.CLog;
27 import com.android.tradefed.targetprep.TargetSetupError;
28 
29 import java.io.File;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.util.NoSuchElementException;
33 
34 /**
35  * Preparer class for collect HAL traces during the test run.
36  *
37  * Currently used for collecting HAL traces for CTS tests. In test setup, pushes
38  * the profiler libs to device, sets up the permissions, and calls
39  * vts_profiling_configure to enable profiling for HAL services. In test
40  * tear down, pulls the traces to the host, resets permissions and cleans up the
41  * trace files and profiler libs on the device.
42  */
43 @OptionClass(alias = "vts-trace-collect-preparer")
44 public class VtsTraceCollectPreparer implements ITargetPreparer, ITargetCleaner {
45     static final String SELINUX_DISABLED = "Disabled"; // selinux disabled
46     static final String SELINUX_PERMISSIVE = "Permissive"; // selinux permissive mode
47 
48     // Relative path to vts 32 bit lib directory.
49     static final String VTS_LIB_DIR_32 = "DATA/lib/";
50     // Relative path to vts 64 bit lib directory.
51     static final String VTS_LIB_DIR_64 = "DATA/lib64/";
52     // Relative path to vts binary directory.
53     static final String VTS_BINARY_DIR = "DATA/bin/";
54     // Path of 32 bit test libs on target device.
55     static final String VTS_TMP_LIB_DIR_32 = "/data/local/tmp/32/";
56     // Path of 64 bit test libs on target device.
57     static final String VTS_TMP_LIB_DIR_64 = "/data/local/tmp/64/";
58     // Path of vts test directory on target device.
59     static final String VTS_TMP_DIR = "/data/local/tmp/";
60     // Default path to store trace files locally.
61     static final String LOCAL_TRACE_DIR = "vts-profiling";
62 
63     static final String VTS_PROFILER_SUFFIX = "vts.profiler.so";
64     static final String VTS_LIB_PREFIX = "libvts";
65     static final String PROFILING_CONFIGURE_BINARY = "vts_profiling_configure";
66     static final String TRACE_PATH = "trace_path";
67 
68     private String mEnforcingState = null; // start state for selinux enforcement
69 
70     @Option(name = "local-trace-dir", description = "Local directory to store trace.")
71     private String mLocalTraceDir = LOCAL_TRACE_DIR;
72 
73     /** {@inheritDoc} */
74     @Override
setUp(ITestDevice device, IBuildInfo buildInfo)75     public void setUp(ITestDevice device, IBuildInfo buildInfo)
76             throws DeviceNotAvailableException, TargetSetupError {
77         CompatibilityBuildHelper buildHelper = createBuildHelper(buildInfo);
78         try {
79             // adb root.
80             device.enableAdbRoot();
81             // Push 32 bit profiler libs.
82             pushProfilerLib(device, new File(buildHelper.getTestsDir(), VTS_LIB_DIR_32),
83                     VTS_TMP_LIB_DIR_32);
84             // Push 64 bit profiler libs.
85             pushProfilerLib(device, new File(buildHelper.getTestsDir(), VTS_LIB_DIR_64),
86                     VTS_TMP_LIB_DIR_64);
87             // Push vts_profiling_configure
88             device.pushFile(new File(buildHelper.getTestsDir(),
89                                     VTS_BINARY_DIR + PROFILING_CONFIGURE_BINARY),
90                     VTS_TMP_DIR + PROFILING_CONFIGURE_BINARY);
91         } catch (IOException | NoSuchElementException e) {
92             // Cleanup profiler libs.
93             removeProfilerLib(device);
94             throw new TargetSetupError("Could not push profiler.");
95         }
96         // Create directory to store the trace files.
97         try {
98             File resultDir = buildHelper.getResultDir();
99             File traceDir = new File(resultDir, mLocalTraceDir);
100             buildInfo.addBuildAttribute(TRACE_PATH, traceDir.getAbsolutePath());
101         } catch (FileNotFoundException e) {
102             CLog.e("Failed to get traceDir: " + e.getMessage());
103             // Cleanup profiler libs.
104             removeProfilerLib(device);
105             throw new TargetSetupError("Failed to get traceDir.");
106         }
107         // Set selinux permissive mode.
108         mEnforcingState = device.executeShellCommand("getenforce");
109         if (mEnforcingState == null
110                 || (!mEnforcingState.equals(SELINUX_DISABLED)
111                            && !mEnforcingState.equals(SELINUX_PERMISSIVE))) {
112             device.executeShellCommand("setenforce " + SELINUX_PERMISSIVE);
113         }
114     }
115 
116     /** {@inheritDoc} */
117     @Override
tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)118     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
119             throws DeviceNotAvailableException {
120         // Reset selinux permission mode.
121         if (mEnforcingState != null && !mEnforcingState.equals(SELINUX_DISABLED)) {
122             device.executeShellCommand("setenforce " + mEnforcingState);
123         }
124         // Cleanup profiler libs.
125         removeProfilerLib(device);
126     }
127 
128     /**
129      * Create and return a {@link CompatibilityBuildHelper} to use during the preparer.
130      */
131     @VisibleForTesting
createBuildHelper(IBuildInfo buildInfo)132     CompatibilityBuildHelper createBuildHelper(IBuildInfo buildInfo) {
133         return new CompatibilityBuildHelper(buildInfo);
134     }
135 
136     /**
137      * Push all the profiler libraries (with pattern *.vts-profiler.so) and VTS
138      * profiling related libraries (with pattern libvts*.so) to device.
139      *
140      * @param device device object
141      * @param profilerLibDir directory to lookup for profiler libraries.
142      * @param destDirName target directory on device to push to.
143      * @throws DeviceNotAvailableException
144      */
pushProfilerLib(ITestDevice device, File profilerLibDir, String destDirName)145     private void pushProfilerLib(ITestDevice device, File profilerLibDir, String destDirName)
146             throws DeviceNotAvailableException {
147         File[] files = profilerLibDir.listFiles();
148         if (files == null) {
149             CLog.d("No files found in %s", profilerLibDir.getAbsolutePath());
150             return;
151         }
152         for (File f : files) {
153             String fileName = f.getName();
154             if (f.isFile()
155                     && (fileName.endsWith(VTS_PROFILER_SUFFIX)
156                                || fileName.startsWith(VTS_LIB_PREFIX))) {
157                 CLog.d("Pushing %s", fileName);
158                 device.pushFile(f, destDirName + fileName);
159             }
160         }
161     }
162 
163     /**
164      * Remove all profiler and VTS profiling libraries from device.
165      *
166      * @param device device object
167      * @throws DeviceNotAvailableException
168      */
removeProfilerLib(ITestDevice device)169     private void removeProfilerLib(ITestDevice device) throws DeviceNotAvailableException {
170         device.executeShellCommand(String.format("rm -rf %s/*vts.profiler.so", VTS_TMP_LIB_DIR_32));
171         device.executeShellCommand(String.format("rm -rf %s/*vts.profiler.so", VTS_TMP_LIB_DIR_64));
172         device.executeShellCommand(String.format("rm -rf %s/libvts_*.so", VTS_TMP_LIB_DIR_32));
173         device.executeShellCommand(String.format("rm -rf %s/libvts_*.so", VTS_TMP_LIB_DIR_64));
174         device.executeShellCommand(String.format("rm %s/vts_profiling_configure", VTS_TMP_DIR));
175     }
176 }
177