1 /* 2 * Copyright (C) 2011 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.cts.verifier; 18 19 import android.app.AlertDialog; 20 import android.content.Context; 21 import android.os.AsyncTask; 22 import android.os.Build; 23 import android.os.Environment; 24 import android.os.FileUtils; 25 import android.os.ParcelFileDescriptor; 26 27 import com.android.compatibility.common.util.FileUtil; 28 import com.android.compatibility.common.util.IInvocationResult; 29 import com.android.compatibility.common.util.ResultHandler; 30 import com.android.compatibility.common.util.ZipUtil; 31 32 import org.xmlpull.v1.XmlPullParserException; 33 34 import java.io.File; 35 import java.io.FileOutputStream; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.text.SimpleDateFormat; 39 import java.util.Date; 40 import java.util.Locale; 41 import java.util.logging.Level; 42 import java.util.logging.Logger; 43 44 /** 45 * Background task to generate a report and save it to external storage. 46 */ 47 class ReportExporter extends AsyncTask<Void, Void, String> { 48 49 public static final String REPORT_DIRECTORY = "verifierReports"; 50 51 private static final Logger LOG = Logger.getLogger(ReportExporter.class.getName()); 52 private static final String COMMAND_LINE_ARGS = ""; 53 private static final String LOG_URL = null; 54 private static final String REFERENCE_URL = null; 55 private static final String SUITE_NAME_METADATA_KEY = "SuiteName"; 56 private static final String SUITE_PLAN = "verifier"; 57 private static final String SUITE_BUILD = "0"; 58 private static final String ZIP_EXTENSION = ".zip"; 59 private final long START_MS = System.currentTimeMillis(); 60 private final long END_MS = START_MS; 61 private final Context mContext; 62 private final TestListAdapter mAdapter; 63 ReportExporter(Context context, TestListAdapter adapter)64 ReportExporter(Context context, TestListAdapter adapter) { 65 this.mContext = context; 66 this.mAdapter = adapter; 67 } 68 69 @Override doInBackground(Void... params)70 protected String doInBackground(Void... params) { 71 if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { 72 LOG.log(Level.WARNING, "External storage is not writable."); 73 return mContext.getString(R.string.no_storage); 74 } 75 IInvocationResult result; 76 try { 77 TestResultsReport report = new TestResultsReport(mContext, mAdapter); 78 result = report.generateResult(); 79 } catch (Exception e) { 80 LOG.log(Level.WARNING, "Couldn't create test results report", e); 81 return mContext.getString(R.string.test_results_error); 82 } 83 // create a directory for CTS Verifier reports 84 File externalStorageDirectory = Environment.getExternalStorageDirectory(); 85 File verifierReportsDir = new File(externalStorageDirectory, REPORT_DIRECTORY); 86 verifierReportsDir.mkdirs(); 87 88 String suiteName = Version.getMetadata(mContext, SUITE_NAME_METADATA_KEY); 89 // create a temporary directory for this particular report 90 File tempDir = new File(verifierReportsDir, getReportName(suiteName)); 91 tempDir.mkdirs(); 92 93 // create a File object for a report ZIP file 94 File reportZipFile = new File( 95 verifierReportsDir, getReportName(suiteName) + ZIP_EXTENSION); 96 97 try { 98 // Serialize the report 99 String versionName = Version.getVersionName(mContext); 100 ResultHandler.writeResults(suiteName, versionName, SUITE_PLAN, SUITE_BUILD, 101 result, tempDir, START_MS, END_MS, REFERENCE_URL, LOG_URL, 102 COMMAND_LINE_ARGS, null); 103 104 // copy formatting files to the temporary report directory 105 copyFormattingFiles(tempDir); 106 107 // create a compressed ZIP file containing the temporary report directory 108 ZipUtil.createZip(tempDir, reportZipFile); 109 } catch (IOException | XmlPullParserException e) { 110 LOG.log(Level.WARNING, "I/O exception writing report to storage.", e); 111 return mContext.getString(R.string.no_storage); 112 } finally { 113 // delete the temporary directory and its files made for the report 114 FileUtil.recursiveDelete(tempDir); 115 } 116 saveReportOnInternalStorage(reportZipFile); 117 return mContext.getString(R.string.report_saved, reportZipFile.getPath()); 118 } 119 saveReportOnInternalStorage(File reportZipFile)120 private void saveReportOnInternalStorage(File reportZipFile) { 121 try { 122 ParcelFileDescriptor pfd = ParcelFileDescriptor.open( 123 reportZipFile, ParcelFileDescriptor.MODE_READ_ONLY); 124 InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 125 126 File verifierDir = mContext.getDir(REPORT_DIRECTORY, Context.MODE_PRIVATE); 127 File verifierReport = new File(verifierDir, reportZipFile.getName()); 128 FileOutputStream fos = new FileOutputStream(verifierReport); 129 130 FileUtils.copy(is, fos); 131 } catch (Exception e) { 132 LOG.log(Level.WARNING, "I/O exception writing report to internal storage.", e); 133 } 134 } 135 136 /** 137 * Copy the XML formatting files stored in the assets directory to the result output. 138 * 139 * @param resultsDir 140 */ copyFormattingFiles(File resultsDir)141 private void copyFormattingFiles(File resultsDir) { 142 for (String resultFileName : ResultHandler.RESULT_RESOURCES) { 143 InputStream rawStream = null; 144 try { 145 rawStream = mContext.getAssets().open( 146 String.format("report/%s", resultFileName)); 147 } catch (IOException e) { 148 LOG.log(Level.WARNING, "Failed to load " + resultFileName + " from assets."); 149 } 150 if (rawStream != null) { 151 File resultFile = new File(resultsDir, resultFileName); 152 try { 153 FileUtil.writeToFile(rawStream, resultFile); 154 } catch (IOException e) { 155 LOG.log(Level.WARNING, "Failed to write " + resultFileName + " to a file."); 156 } 157 } 158 } 159 } 160 getReportName(String suiteName)161 private String getReportName(String suiteName) { 162 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss", Locale.ENGLISH); 163 String date = dateFormat.format(new Date()); 164 return String.format("%s-%s-%s-%s-%s-%s", 165 date, suiteName, Build.MANUFACTURER, Build.PRODUCT, Build.DEVICE, Build.ID); 166 } 167 168 @Override onPostExecute(String result)169 protected void onPostExecute(String result) { 170 new AlertDialog.Builder(mContext) 171 .setMessage(result) 172 .setPositiveButton(android.R.string.ok, null) 173 .show(); 174 } 175 } 176