| /* |
| * Copyright (C) 2016 Fairphone B.V. |
| * |
| * 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.fairphone.hiccup.app; |
| |
| import android.content.Context; |
| import android.support.annotation.Nullable; |
| import android.system.ErrnoException; |
| import android.system.Os; |
| |
| import com.fairphone.hiccup.HiccupdService; |
| import com.fairphone.hiccup.LogFile; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.text.ParseException; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipOutputStream; |
| |
| public class LogfileArchive { |
| |
| private final static SimpleDateFormat dirNameDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss"); |
| static private final String logFileDirectory = "/crashreport_logfiles/"; |
| private Date date; |
| private String logfilePath; |
| |
| private LogfileArchive(String path) throws CrashReportFormatException { |
| File file = new File(path); |
| try { |
| date = dirNameDateFormat.parse(file.getName().replaceFirst("crashreport_", "").replaceAll(".zip", "")); |
| } catch (ParseException e) { |
| throw new CrashReportFormatException(); |
| } |
| logfilePath = path; |
| } |
| |
| /** |
| * This generates a new Crashreport. It will create a new directory i |
| */ |
| static public LogfileArchive fetchCrashReportLogfiles(Context ctx, HiccupSettings.IncludeLogFilesConfiguration conf) { |
| List<LogFile> logFiles = getLogFiles(conf); |
| if (logFiles.isEmpty()) return null; |
| return createLogfilesArchive(ctx, logFiles); |
| } |
| |
| @Nullable |
| private static LogfileArchive createLogfilesArchive(Context ctx, List<LogFile> logFiles) { |
| Date date = new Date(); |
| String basePath = ctx.getFilesDir().getAbsolutePath(); |
| new File(basePath + logFileDirectory).mkdirs(); |
| String tmpZipName = basePath + logFileDirectory + "/.INCOMPLETE_" + getCrashReportName(date) + ".zip"; |
| String zipName = basePath + logFileDirectory + '/' + getCrashReportName(date) + ".zip"; |
| writeZipFile(logFiles, tmpZipName); |
| try { |
| Os.rename(tmpZipName, zipName); |
| } catch (ErrnoException e) { |
| e.printStackTrace(); |
| } |
| try { |
| return new LogfileArchive(zipName); |
| } catch (CrashReportFormatException e) { |
| e.printStackTrace(); |
| return null; |
| } |
| } |
| |
| private static List<LogFile> getLogFiles(HiccupSettings.IncludeLogFilesConfiguration conf) { |
| List<LogFile> logFiles= null; |
| try { |
| switch (conf) { |
| case NONE: |
| break; |
| case LAST_KMSG: |
| logFiles = getLastKmesg(); |
| break; |
| case ALL: |
| logFiles = getAllLogFiles(); |
| break; |
| } |
| } catch (Exception e) { |
| HiccupUtil.LOG("error talking to Hiccupd\n" + e.toString()); |
| } |
| if (logFiles != null) { |
| HiccupUtil.LOG("Received " + String.valueOf(logFiles.size()) + " Logfiles"); |
| } else { |
| HiccupUtil.LOG("Empty list received..."); |
| } |
| return logFiles; |
| } |
| |
| private static List<LogFile> getAllLogFiles() { |
| List<LogFile> logFiles = new ArrayList<LogFile>(); |
| HiccupdService hiccupd = HiccupdService.getInstance(); |
| hiccupd.stopLogging(); |
| logFiles = hiccupd.getLogs(); |
| hiccupd.cleanLogs(); |
| hiccupd.startLogging(); |
| return logFiles; |
| } |
| |
| private static List<LogFile> getLastKmesg() { |
| List<LogFile> logFiles = new ArrayList<LogFile>(); |
| HiccupdService hiccupd = HiccupdService.getInstance(); |
| logFiles = hiccupd.getLastKmsg(); |
| return logFiles; |
| } |
| |
| static private void writeZipFile(List<LogFile> logFiles, String path) { |
| FileOutputStream dest; |
| try { |
| dest = new FileOutputStream(path); |
| ZipOutputStream out = new ZipOutputStream(new |
| BufferedOutputStream(dest)); |
| for (LogFile logFile : logFiles) { |
| try { |
| dumpLogfile(out, logFile); |
| } catch (IOException e) { |
| HiccupUtil.LOG("skipping " + logFile.getFileName() + ": " + e.toString()); |
| } |
| } |
| out.close(); |
| dest.close(); |
| } catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| static private void dumpLogfile(ZipOutputStream zipOutputStream, LogFile logFile) throws IOException { |
| FileInputStream inputStream = new FileInputStream(logFile.getFileDescriptor()); |
| final int BUFFER = 2048; |
| int count; |
| byte data[] = new byte[BUFFER]; |
| ZipEntry entry = new ZipEntry(logFile.getFileName()); |
| zipOutputStream.putNextEntry(entry); |
| while ((count = inputStream.read(data, 0, |
| BUFFER)) != -1) { |
| zipOutputStream.write(data, 0, count); |
| } |
| inputStream.close(); |
| } |
| |
| static private String getCrashReportName(Date date) { |
| SimpleDateFormat df = dirNameDateFormat; |
| return "crashreport_" + df.format(date); |
| } |
| |
| public void delete() { |
| File dir = new File(logfilePath); |
| if (dir.isDirectory()) { |
| String[] children = dir.list(); |
| for (String aChildren : children) { |
| new File(dir, aChildren).delete(); |
| } |
| } |
| dir.delete(); |
| } |
| |
| public File getCrashReportFile() { |
| return new File(logfilePath); |
| } |
| |
| private String getCrashReportName() { |
| SimpleDateFormat df = dirNameDateFormat; |
| return "crashreport_" + df.format(date); |
| } |
| |
| private class CrashReportFormatException extends Exception { |
| } |
| } |