/**
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This part of the Wire sofware uses source code from the breakapp project
* (https://github.com/ashtom/breakapp) governed by the MIT license.
*
* The MIT License (MIT)
*
* Copyright (c) 2013 Thomas Dohmke, Bit Stadium GmbH.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package net.hockeyapp.android;
import android.content.Context;
import com.waz.api.HockeyCrashReporter;
import com.waz.threading.Threading;
import timber.log.Timber;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.util.Date;
import java.util.UUID;
public class NativeCrashManager {
public static boolean loggedDumpFiles(String identifier) {
String[] filenames = searchForDumpFiles();
if (filenames == null) {
return false;
}
for (String dumpFilename : filenames) {
String logFilename = createLogFile();
if (logFilename != null) {
uploadDumpAndLog(identifier, dumpFilename, logFilename);
}
}
return filenames.length > 0;
}
public static void deleteDumpFiles(final Context context) {
Threading.IO().execute(new Runnable() {
@Override
public void run() {
try {
String[] filenames = searchForDumpFiles();
if (filenames == null) {
return;
}
for (String dumpFilename : filenames) {
context.deleteFile(dumpFilename);
}
} catch (Throwable t) {
// ignore
}
}
});
}
public static String createLogFile() {
final Date now = new Date();
try {
// Create filename from a random uuid
String filename = UUID.randomUUID().toString();
String path = Constants.FILES_PATH + "/" + filename + ".faketrace";
Timber.i("Writing unhandled exception to: %s", path);
// Write the stacktrace to disk
BufferedWriter write = new BufferedWriter(new FileWriter(path));
write.write("Package: " + Constants.APP_PACKAGE + "\n");
write.write("Version: " + Constants.APP_VERSION + "\n");
write.write("Android: " + Constants.ANDROID_VERSION + "\n");
write.write("Manufacturer: " + Constants.PHONE_MANUFACTURER + "\n");
write.write("Model: " + Constants.PHONE_MODEL + "\n");
write.write("Date: " + now + "\n");
write.write("\n");
write.write("MinidumpContainer");
write.flush();
write.close();
return filename + ".faketrace";
} catch (Exception ignored) {
}
return null;
}
public static void uploadDumpAndLog(final String identifier,
final String dumpFilename,
final String logFilename) {
try {
HockeyCrashReporter.uploadCrashReport(identifier,
new File(Constants.FILES_PATH, dumpFilename),
new File(Constants.FILES_PATH, logFilename));
} catch (Throwable t) {
ExceptionHandler.saveException(t, null);
}
}
private static String[] searchForDumpFiles() {
if (Constants.FILES_PATH != null) {
// Try to create the files folder if it doesn't exist
File dir = new File(Constants.FILES_PATH + "/");
boolean created = dir.mkdir();
if (!created && !dir.exists()) {
return new String[0];
}
// Filter for ".dmp" files
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".dmp");
}
};
return dir.list(filter);
} else {
Timber.i("Can't search for exception as file path is null.");
return new String[0];
}
}
}