/* * 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; } }