diff options
Diffstat (limited to 'src/com/android/tradefed/targetprep')
3 files changed, 225 insertions, 3 deletions
diff --git a/src/com/android/tradefed/targetprep/CrashCollector.java b/src/com/android/tradefed/targetprep/CrashCollector.java new file mode 100644 index 000000000..3c17023e1 --- /dev/null +++ b/src/com/android/tradefed/targetprep/CrashCollector.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2016 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.tradefed.targetprep; + +import com.android.tradefed.build.IBuildInfo; +import com.android.tradefed.build.IDeviceBuildInfo; +import com.android.tradefed.config.Option; +import com.android.tradefed.config.OptionClass; +import com.android.tradefed.device.BackgroundDeviceAction; +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.device.LargeOutputReceiver; +import com.android.tradefed.log.ITestLogger; +import com.android.tradefed.log.LogUtil.CLog; +import com.android.tradefed.result.ITestLoggerReceiver; +import com.android.tradefed.result.InputStreamSource; +import com.android.tradefed.result.LogDataType; +import com.android.tradefed.util.StreamUtil; + +/** + * A {@link ITargetPreparer} that runs crash collector on device which suppresses and logs crashes + * during test execution. + * <p> + * Note: this preparer requires N platform or newer. + */ +@OptionClass(alias = "crash-collector") +public class CrashCollector extends TestFilePushSetup + implements ITestLoggerReceiver, ITargetCleaner { + + private static String LOG_NAME = "crash-collector-log"; + private ITestLogger mTestLogger; + private BackgroundDeviceAction mCrashCollector; + private LargeOutputReceiver mCrashReceiver; + + @Option(name = "crash-collector-path", + description = "Path to crashcollector binary in test artifact bundle.") + private String mCrashCollectorPath = "local/tmp/crashcollector"; + + @Option(name = "disable", description = "If this preparer should be disabled.") + private boolean mDisable = false; + + @Option(name = "max-crash-log-size", description = "Max size to retain for crash logs.") + private long mMaxCrashLogSize = 10 * 1024 * 1024; + + boolean shouldDisable(ITestDevice device, IBuildInfo buildInfo) + throws DeviceNotAvailableException { + if (mDisable) { + return true; + } + // first get pseudo API level to check for platform support + String codeName = device.getProperty("ro.build.version.codename").trim(); + int apiLevel = device.getApiLevel(); + if ("!REL".equals(codeName)) { + apiLevel++; + } + if (apiLevel < 24) { + return true; + } + if (!(buildInfo instanceof IDeviceBuildInfo)) { + CLog.w("Unsupported build info type: %s, cannot install crashcollector binary", + buildInfo.getClass().getSimpleName()); + return true; + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void setUp(ITestDevice device, IBuildInfo buildInfo) + throws TargetSetupError, BuildError, DeviceNotAvailableException { + mDisable = shouldDisable(device, buildInfo); + if (mDisable) { + return; + } + // clear all existing test file names, since we may receive that from the parameter defined + // in parent class TestFilePushSetup when this class is used together with TestFilePushSetup + // in a same config + clearTestFileName(); + addTestFileName(mCrashCollectorPath); + super.setUp(device, buildInfo); + mCrashReceiver = new LargeOutputReceiver("crash-collector", + device.getSerialNumber(), mMaxCrashLogSize); + mCrashCollector = new BackgroundDeviceAction( + "/data/local/tmp/crashcollector/crashcollector", "crash-collector", + device, mCrashReceiver, 0); + mCrashCollector.start(); + } + + /** + * {@inheritDoc} + */ + @Override + public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e) + throws DeviceNotAvailableException { + if (mCrashCollector != null) { + mCrashCollector.cancel(); + } + if (mCrashReceiver != null) { + mCrashReceiver.cancel(); + InputStreamSource iss = mCrashReceiver.getData(); + try { + mTestLogger.testLog(LOG_NAME, LogDataType.TEXT, iss); + } finally { + StreamUtil.cancel(iss); + } + mCrashReceiver.delete(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setTestLogger(ITestLogger testLogger) { + mTestLogger = testLogger; + } +} diff --git a/src/com/android/tradefed/targetprep/NativeLeakCollector.java b/src/com/android/tradefed/targetprep/NativeLeakCollector.java new file mode 100644 index 000000000..1659181ad --- /dev/null +++ b/src/com/android/tradefed/targetprep/NativeLeakCollector.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 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.tradefed.targetprep; + +import com.android.tradefed.build.IBuildInfo; +import com.android.tradefed.build.IDeviceBuildInfo; +import com.android.tradefed.config.Option; +import com.android.tradefed.config.OptionClass; +import com.android.tradefed.device.BackgroundDeviceAction; +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.device.LargeOutputReceiver; +import com.android.tradefed.log.ITestLogger; +import com.android.tradefed.log.LogUtil.CLog; +import com.android.tradefed.result.ByteArrayInputStreamSource; +import com.android.tradefed.result.ITestLoggerReceiver; +import com.android.tradefed.result.InputStreamSource; +import com.android.tradefed.result.LogDataType; +import com.android.tradefed.util.StreamUtil; + +/** + * A {@link ITargetCleaner} that runs 'dumpsys meminfo --unreachable -a' to identify the unreachable + * native memory currently held by each process. + * <p> + * Note: this preparer requires N platform or newer. + */ +@OptionClass(alias = "native-leak-collector") +public class NativeLeakCollector implements ITestLoggerReceiver, ITargetCleaner { + private static final String UNREACHABLE_MEMINFO_CMD = + "dumpsys -t 60 meminfo --unreachable -a"; + + private ITestLogger mTestLogger; + + @Option(name = "disable", description = "If this preparer should be disabled.") + private boolean mDisable = false; + + @Option(name = "log-filename", description = "The filename to give this log.") + private String mLogFilename = "unreachable-meminfo"; + + /** + * {@inheritDoc} + */ + @Override + public void setUp(ITestDevice device, IBuildInfo buildInfo) + throws TargetSetupError, BuildError, DeviceNotAvailableException { + // No-op + } + + /** + * {@inheritDoc} + */ + @Override + public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e) + throws DeviceNotAvailableException { + if (mDisable || (e instanceof DeviceNotAvailableException)) { + return; + } + + String output = device.executeShellCommand(UNREACHABLE_MEMINFO_CMD); + if (output != null && !output.isEmpty()) { + ByteArrayInputStreamSource byteOutput = + new ByteArrayInputStreamSource(output.getBytes()); + mTestLogger.testLog(mLogFilename, LogDataType.TEXT, byteOutput); + StreamUtil.cancel(byteOutput); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setTestLogger(ITestLogger testLogger) { + mTestLogger = testLogger; + } +} diff --git a/src/com/android/tradefed/targetprep/TestFilePushSetup.java b/src/com/android/tradefed/targetprep/TestFilePushSetup.java index cbf59ed9c..b3c8dc8e0 100644 --- a/src/com/android/tradefed/targetprep/TestFilePushSetup.java +++ b/src/com/android/tradefed/targetprep/TestFilePushSetup.java @@ -67,14 +67,16 @@ public class TestFilePushSetup implements ITargetPreparer { /** * Adds a file to the list of items to push * - * Used for unit testing - * * @param fileName */ - void addTestFileName(String fileName) { + protected void addTestFileName(String fileName) { mTestPaths.add(fileName); } + protected void clearTestFileName() { + mTestPaths.clear(); + } + /** * Resolve the host side path based on testing artifact information inside build info. * |