Home | History | Annotate | Download | only in aupt
      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 android.support.test.aupt;
     18 
     19 import android.app.ActivityManager;
     20 import android.app.Instrumentation;
     21 import android.os.Environment;
     22 import android.os.ParcelFileDescriptor;
     23 import android.os.RemoteException;
     24 import android.util.Log;
     25 
     26 import java.io.ByteArrayOutputStream;
     27 import java.io.File;
     28 import java.io.FileNotFoundException;
     29 import java.io.FileOutputStream;
     30 import java.io.IOException;
     31 import java.io.InputStream;
     32 import java.io.OutputStream;
     33 import java.text.SimpleDateFormat;
     34 import java.util.Date;
     35 import java.util.Locale;
     36 
     37 public class FilesystemUtil {
     38     private static final String TAG = FilesystemUtil.class.getSimpleName();
     39 
     40     /** Save the output of a process to a file */
     41     public static void saveProcessOutput(Instrumentation instr, String command, File file)
     42             throws IOException {
     43         Log.d(TAG, String.format("Saving command \"%s\" output into file %s",
     44                 command, file.getAbsolutePath()));
     45 
     46         OutputStream out = new FileOutputStream(file);
     47         saveProcessOutput(instr, command, out);
     48         out.close();
     49     }
     50 
     51     /** Send the output of a process to an OutputStream. */
     52     public static void saveProcessOutput(Instrumentation instr, String command, OutputStream out)
     53             throws IOException {
     54         try {
     55             // First, try to execute via our UiAutomation
     56             ParcelFileDescriptor pfd = instr.getUiAutomation().executeShellCommand(command);
     57             pipe(new ParcelFileDescriptor.AutoCloseInputStream(pfd), out);
     58         } catch (IllegalStateException ise) {
     59             // If we don't have a UiAutomation, we'll get an IllegalStatException;
     60             // so try to do it via an exec()
     61             Process process = Runtime.getRuntime().exec(command);
     62             pipe(process.getInputStream(), out);
     63 
     64             // Wait for our process to finish
     65             try {
     66                 process.waitFor();
     67             } catch (InterruptedException ie) {
     68                 throw new IOException("Thread interrupted waiting for command: " + command);
     69             }
     70 
     71             // Make sure it succeeded.
     72             if (process.exitValue() != 0) {
     73                 throw new IOException("Failed to save output of command: " + command);
     74             }
     75         }
     76     }
     77 
     78     /** Save a bugreport to the given file */
     79     public static void saveBugreport(Instrumentation instr, String filename)
     80             throws IOException, InterruptedException {
     81         ByteArrayOutputStream baos = new ByteArrayOutputStream();
     82         String cmdline = String.format("/system/bin/sh -c /system/bin/bugreport>%s",
     83                 templateToFilename(filename));
     84         saveProcessOutput(instr, cmdline, baos);
     85         baos.close();
     86     }
     87 
     88     /** Save a bugreport to the given file */
     89     public static void saveBugreportz(Instrumentation instr) throws IOException {
     90         try {
     91             ActivityManager.getService().requestBugReport(ActivityManager.BUGREPORT_OPTION_FULL);
     92         } catch (RemoteException e) {
     93             throw new IOException("Could not capture bugreportz", e);
     94         }
     95     }
     96 
     97     /** Save annotated Meminfo to our default logging directory */
     98     public static void dumpMeminfo(Instrumentation instr, String notes) {
     99         long epochSeconds = System.currentTimeMillis() / 1000;
    100         File outputDir = new File(Environment.getExternalStorageDirectory(), "meminfo");
    101         Log.i(TAG, outputDir.toString());
    102         if (!outputDir.exists()) {
    103             boolean yes  = outputDir.mkdirs();
    104             Log.i(TAG, yes ? "created" : "not created");
    105         }
    106         File outputFile = new File(outputDir, String.format("%d.txt", epochSeconds));
    107         Log.i(TAG, outputFile.toString());
    108         FileOutputStream fos = null;
    109 
    110         try {
    111             fos = new FileOutputStream(outputFile);
    112             fos.write(String.format("notes: %s\n\n", notes).getBytes());
    113 
    114             saveProcessOutput(instr, "dumpsys meminfo -c", fos);
    115             fos.close();
    116         } catch (FileNotFoundException e) {
    117             Log.e(TAG, "exception while dumping meminfo", e);
    118         } catch (IOException e) {
    119             Log.e(TAG, "exception while dumping meminfo", e);
    120         }
    121     }
    122 
    123     /** Splice the date into the "%s" in a file name */
    124     public static String templateToFilename(String filenameTemplate) {
    125         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
    126         return String.format(filenameTemplate, sdf.format(new Date()));
    127     }
    128 
    129     /** Pipe an inputstream to an outputstream. This matches Apache's IOUtils::copy */
    130     private static void pipe(InputStream in, OutputStream out) throws IOException {
    131         byte[] buffer = new byte[4096];
    132         int bytesRead = 0;
    133 
    134         try {
    135             while (bytesRead >= 0) {
    136                 out.write(buffer, 0, bytesRead);
    137                 bytesRead = in.read(buffer);
    138             }
    139         } finally {
    140             in.close();
    141             out.flush();
    142         }
    143     }
    144 }
    145