/*
* Copyright 2010 Kevin Gaudin
*
* 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 kidozen.client.crash.collector;
import android.content.Context;
import android.text.format.Time;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import kidozen.client.crash.Compatibility;
import kidozen.client.crash.CrashReporter;
/**
* Collects data from the DropBoxManager introduced with Android API Level 8. A
* set of DropBox tags have been identified in the Android source code. , we
* collect data associated to these tags with hope that some of them could help
* debugging applications. Application specific tags can be provided by the app
* dev to track his own usage of the DropBoxManager.
*
* @author Kevin Gaudin
*
*/
final class DropBoxCollector {
private static final String[] SYSTEM_TAGS = { "system_app_anr", "system_app_wtf", "system_app_crash",
"system_server_anr", "system_server_wtf", "system_server_crash", "BATTERY_DISCHARGE_INFO",
"SYSTEM_RECOVERY_LOG", "SYSTEM_BOOT", "SYSTEM_LAST_KMSG", "APANIC_CONSOLE", "APANIC_THREADS",
"SYSTEM_RESTART", "SYSTEM_TOMBSTONE", "data_app_strictmode" };
private static final String NO_RESULT = "N/A";
/**
* Read latest messages contained in the DropBox for system related tags and
* optional developer-set tags.
*
* @param context
* The application context.
* @param additionalTags
* An array of tags provided by the application developer.
* @return A readable formatted String listing messages retrieved.
*/
public static String read(Context context, String[] additionalTags) {
try {
// Use reflection API to allow compilation with API Level 5.
final String serviceName = Compatibility.getDropBoxServiceName();
if (serviceName == null) {
return NO_RESULT;
}
final Object dropbox = context.getSystemService(serviceName);
final Method getNextEntry = dropbox.getClass().getMethod("getNextEntry", String.class, long.class);
if (getNextEntry == null) {
return "";
}
final Time timer = new Time();
timer.setToNow();
timer.minute -= CrashReporter.getConfig().dropboxCollectionMinutes();
timer.normalize(false);
final long time = timer.toMillis(false);
final List<String> tags = new ArrayList<String>();
if (CrashReporter.getConfig().includeDropBoxSystemTags()) {
tags.addAll(Arrays.asList(SYSTEM_TAGS));
}
if (additionalTags != null && additionalTags.length > 0) {
tags.addAll(Arrays.asList(additionalTags));
}
if (tags.isEmpty()) {
return "No tag configured for collection.";
}
final StringBuilder dropboxContent = new StringBuilder();
for (String tag : tags) {
dropboxContent.append("Tag: ").append(tag).append('\n');
Object entry = getNextEntry.invoke(dropbox, tag, time);
if (entry == null) {
dropboxContent.append("Nothing.").append('\n');
continue;
}
final Method getText = entry.getClass().getMethod("getText", int.class);
final Method getTimeMillis = entry.getClass().getMethod("getTimeMillis", (Class[]) null);
final Method close = entry.getClass().getMethod("close", (Class[]) null);
while (entry != null) {
final long msec = (Long) getTimeMillis.invoke(entry, (Object[]) null);
timer.set(msec);
dropboxContent.append("@").append(timer.format2445()).append('\n');
final String text = (String) getText.invoke(entry, 500);
if (text != null) {
dropboxContent.append("Text: ").append(text).append('\n');
} else {
dropboxContent.append("Not Text!").append('\n');
}
close.invoke(entry, (Object[]) null);
entry = getNextEntry.invoke(dropbox, tag, msec);
}
}
return dropboxContent.toString();
} catch (SecurityException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
} catch (NoSuchMethodException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
} catch (IllegalArgumentException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
} catch (IllegalAccessException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
} catch (InvocationTargetException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
} catch (NoSuchFieldException e) {
Log.i(CrashReporter.LOG_TAG, "DropBoxManager not available.");
}
return NO_RESULT;
}
}