/* * Copyright (C) 2011 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.result; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.util.FileUtil; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * A utility class that checks the device for files and sends them to * {@link ITestInvocationListener#testLog(String, LogDataType, InputStreamSource)} if found. */ public class DeviceFileReporter { private final Map<String, LogDataType> mFilePatterns = new LinkedHashMap<String, LogDataType>(); private final ITestInvocationListener mListener; private final ITestDevice mDevice; private LogDataType mDefaultFileType = LogDataType.UNKNOWN; /** * Initialize a new DeviceFileReporter with the provided {@link ITestDevice} */ public DeviceFileReporter(ITestDevice device, ITestInvocationListener listener) { // Do a null check here, since otherwise that error would be asynchronous if (device == null || listener == null) { throw new NullPointerException(); } mDevice = device; mListener = listener; } /** * Add patterns with the log data type set to the default. * * @param patterns a varargs array of {@link String} filename glob patterns. Should be absolute. * @see #setDefaultLogDataType */ public void addPatterns(String... patterns) { addPatterns(Arrays.asList(patterns)); } /** * Add patterns with the log data type set to the default. * * @param patterns a {@link List} of {@link String} filename glob patterns. Should be absolute. * @see #setDefaultLogDataType */ public void addPatterns(List<String> patterns) { for (String pat : patterns) { mFilePatterns.put(pat, mDefaultFileType); } } /** * Add patterns with the respective log data types * * @param patterns a {@link Map} of {@link String} filename glob patterns to their respective * {@link LogDataType}s. The globs should be absolute. * @see #setDefaultLogDataType */ public void addPatterns(Map<String, LogDataType> patterns) { mFilePatterns.putAll(patterns); } /** * Set the default log data type set for patterns that don't have an associated type. * * @param type the {@link LogDataType} * @see addPatterns(List<String>) */ public void setDefaultLogDataType(LogDataType type) { if (type == null) { throw new NullPointerException(); } mDefaultFileType = type; } /** * Actually search the filesystem for the specified patterns and send them to * {@link ITestInvocationListener#testLog} if found */ public List<String> run() throws DeviceNotAvailableException { List<String> filenames = new LinkedList<String>(); for (Map.Entry<String, LogDataType> pat : mFilePatterns.entrySet()) { final String searchCmd = String.format("ls '%s'", pat.getKey()); final String fileList = mDevice.executeShellCommand(searchCmd); for (String filename : fileList.split("\r\n")) { if (filename.isEmpty() || filename.endsWith(": No such file or directory")) { continue; } File file = null; InputStreamSource iss = null; try { CLog.v("Trying to pull file %s from device %s", filename, mDevice.getSerialNumber()); file = mDevice.pullFile(filename); CLog.v("Local file %s has size %d", file, file.length()); iss = createIssForFile(file); mListener.testLog(filename, pat.getValue(), iss); filenames.add(filename); } catch (IOException e) { CLog.w("Failed to log file %s: %s", filename, e.getMessage()); } finally { if (iss != null) { iss.cancel(); iss = null; } FileUtil.deleteFile(file); } } } return filenames; } /** * Create an {@link InputStreamSource} for a file * <p /> * Exposed for unit testing */ InputStreamSource createIssForFile(File file) throws IOException { InputStream bufStr = new BufferedInputStream(new FileInputStream(file)); return new SnapshotInputStreamSource(bufStr); } }