Add boot events (SYSTEM_LAST_KMSG and friends) to the dropbox.
Optimize DropBoxManagerService.dump() a bit.
This commit is contained in:
@@ -1,40 +1,108 @@
|
||||
/*
|
||||
**
|
||||
** Copyright 2007, The Android Open Source Project
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* 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.android.server;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.os.Build;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.FileUtils;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.os.RecoverySystem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Performs a number of miscellaneous, non-system-critical actions
|
||||
* after the system has finished booting.
|
||||
*/
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "BootReceiver";
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
Intent service = new Intent(context, com.android.server.LoadAverageService.class);
|
||||
ContentResolver res = context.getContentResolver();
|
||||
boolean shown = Settings.System.getInt(
|
||||
res, Settings.System.SHOW_PROCESSES, 0) != 0;
|
||||
if (shown) {
|
||||
context.startService(service);
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
try {
|
||||
logBootEvents(context);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't log boot events", e);
|
||||
}
|
||||
|
||||
try {
|
||||
RecoverySystem.handleAftermath();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't handle recovery aftermath", e);
|
||||
}
|
||||
|
||||
try {
|
||||
// Start the load average overlay, if activated
|
||||
ContentResolver res = context.getContentResolver();
|
||||
if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
|
||||
Intent loadavg = new Intent(context, com.android.server.LoadAverageService.class);
|
||||
context.startService(loadavg);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't start load average service", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logBootEvents(Context context) throws IOException {
|
||||
DropBoxManager db = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE);
|
||||
|
||||
String build =
|
||||
"Build: " + Build.FINGERPRINT + "\nKernel: " +
|
||||
FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n");
|
||||
|
||||
if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
|
||||
String now = Long.toString(System.currentTimeMillis());
|
||||
SystemProperties.set("ro.runtime.firstboot", now);
|
||||
if (db != null) db.addText("SYSTEM_BOOT", build);
|
||||
} else {
|
||||
if (db != null) db.addText("SYSTEM_RESTART", build);
|
||||
return; // Subsequent boot, don't log kernel boot log
|
||||
}
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
logBootFile(cr, db, "/cache/recovery/log", "SYSTEM_RECOVERY_LOG");
|
||||
logBootFile(cr, db, "/data/dontpanic/last_kmsg", "SYSTEM_LAST_KMSG");
|
||||
logBootFile(cr, db, "/data/dontpanic/apanic_console", "APANIC_CONSOLE");
|
||||
logBootFile(cr, db, "/data/dontpanic/apanic_threads", "APANIC_THREADS");
|
||||
}
|
||||
|
||||
private void logBootFile(ContentResolver cr, DropBoxManager db, String filename, String tag)
|
||||
throws IOException {
|
||||
if (cr == null || db == null || !db.isTagEnabled(tag)) return; // Logging disabled
|
||||
|
||||
File file = new File(filename);
|
||||
long fileTime = file.lastModified();
|
||||
if (fileTime <= 0) return; // File does not exist
|
||||
|
||||
String setting = "logfile:" + filename;
|
||||
long lastTime = Settings.Secure.getLong(cr, setting, 0);
|
||||
if (lastTime == fileTime) return; // Already logged this particular file
|
||||
|
||||
db.addFile(tag,
|
||||
ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY),
|
||||
DropBoxManager.IS_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,13 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Debug;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.StatFs;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.format.Time;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.os.IDropBoxManagerService;
|
||||
@@ -56,8 +57,6 @@ import java.util.zip.GZIPOutputStream;
|
||||
/**
|
||||
* Implementation of {@link IDropBoxManagerService} using the filesystem.
|
||||
* Clients use {@link DropBoxManager} to access this service.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
|
||||
private static final String TAG = "DropBoxManagerService";
|
||||
@@ -67,6 +66,8 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
|
||||
private static final int DEFAULT_AGE_SECONDS = 3 * 86400;
|
||||
private static final int QUOTA_RESCAN_MILLIS = 5000;
|
||||
|
||||
private static final boolean PROFILE_DUMP = false;
|
||||
|
||||
// TODO: This implementation currently uses one file per entry, which is
|
||||
// inefficient for smallish entries -- consider using a single queue file
|
||||
// per tag (or even globally) instead.
|
||||
@@ -257,6 +258,9 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PROFILE_DUMP) Debug.startMethodTracing("/data/trace/dropbox.dump");
|
||||
|
||||
Formatter out = new Formatter();
|
||||
boolean doPrint = false, doFile = false;
|
||||
ArrayList<String> searchArgs = new ArrayList<String>();
|
||||
for (int i = 0; args != null && i < args.length; i++) {
|
||||
@@ -265,53 +269,51 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
|
||||
} else if (args[i].equals("-f") || args[i].equals("--file")) {
|
||||
doFile = true;
|
||||
} else if (args[i].startsWith("-")) {
|
||||
pw.print("Unknown argument: ");
|
||||
pw.println(args[i]);
|
||||
out.format("Unknown argument: %s\n", args[i]);
|
||||
} else {
|
||||
searchArgs.add(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pw.format("Drop box contents: %d entries", mAllFiles.contents.size());
|
||||
pw.println();
|
||||
out.format("Drop box contents: %d entries\n", mAllFiles.contents.size());
|
||||
|
||||
if (!searchArgs.isEmpty()) {
|
||||
pw.print("Searching for:");
|
||||
for (String a : searchArgs) pw.format(" %s", a);
|
||||
pw.println();
|
||||
out.format("Searching for:");
|
||||
for (String a : searchArgs) out.format(" %s", a);
|
||||
out.format("\n");
|
||||
}
|
||||
|
||||
int numFound = 0;
|
||||
pw.println();
|
||||
int numFound = 0, numArgs = searchArgs.size();
|
||||
Time time = new Time();
|
||||
out.format("\n");
|
||||
for (EntryFile entry : mAllFiles.contents) {
|
||||
String date = new Formatter().format("%s.%03d",
|
||||
DateFormat.format("yyyy-MM-dd kk:mm:ss", entry.timestampMillis),
|
||||
entry.timestampMillis % 1000).toString();
|
||||
|
||||
time.set(entry.timestampMillis);
|
||||
String date = time.format("%Y-%m-%d %H:%M:%S");
|
||||
boolean match = true;
|
||||
for (String a: searchArgs) match = match && (date.contains(a) || a.equals(entry.tag));
|
||||
for (int i = 0; i < numArgs && match; i++) {
|
||||
String arg = searchArgs.get(i);
|
||||
match = (date.contains(arg) || arg.equals(entry.tag));
|
||||
}
|
||||
if (!match) continue;
|
||||
|
||||
numFound++;
|
||||
pw.print(date);
|
||||
pw.print(" ");
|
||||
pw.print(entry.tag == null ? "(no tag)" : entry.tag);
|
||||
out.format("%s.%03d %s", date, entry.timestampMillis % 1000,
|
||||
entry.tag == null ? "(no tag)" : entry.tag);
|
||||
if (entry.file == null) {
|
||||
pw.println(" (no file)");
|
||||
out.format(" (no file)\n");
|
||||
continue;
|
||||
} else if ((entry.flags & DropBoxManager.IS_EMPTY) != 0) {
|
||||
pw.println(" (contents lost)");
|
||||
out.format(" (contents lost)\n");
|
||||
continue;
|
||||
} else {
|
||||
pw.print((entry.flags & DropBoxManager.IS_GZIPPED) != 0 ? " (comopressed " : " (");
|
||||
pw.print((entry.flags & DropBoxManager.IS_TEXT) != 0 ? "text" : "data");
|
||||
pw.format(", %d bytes)", entry.file.length());
|
||||
pw.println();
|
||||
out.format(" (%s%s, %d bytes)\n",
|
||||
(entry.flags & DropBoxManager.IS_GZIPPED) != 0 ? "compressed " : "",
|
||||
(entry.flags & DropBoxManager.IS_TEXT) != 0 ? "text" : "data",
|
||||
entry.file.length());
|
||||
}
|
||||
|
||||
if (doFile || (doPrint && (entry.flags & DropBoxManager.IS_TEXT) == 0)) {
|
||||
if (!doPrint) pw.print(" ");
|
||||
pw.println(entry.file.getPath());
|
||||
out.format("%s%s\n", (doPrint ? "" : " "), entry.file.getPath());
|
||||
}
|
||||
|
||||
if ((entry.flags & DropBoxManager.IS_TEXT) != 0 && (doPrint || !doFile)) {
|
||||
@@ -327,36 +329,36 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
|
||||
for (;;) {
|
||||
int n = r.read(buf);
|
||||
if (n <= 0) break;
|
||||
pw.write(buf, 0, n);
|
||||
out.format("%s", new String(buf, 0, n));
|
||||
newline = (buf[n - 1] == '\n');
|
||||
}
|
||||
if (!newline) pw.println();
|
||||
if (!newline) out.format("\n");
|
||||
} else {
|
||||
String text = dbe.getText(70);
|
||||
boolean truncated = (text.length() == 70);
|
||||
pw.print(" ");
|
||||
pw.print(text.trim().replace('\n', '/'));
|
||||
if (truncated) pw.print(" ...");
|
||||
pw.println();
|
||||
out.format(" %s%s\n", text.trim().replace('\n', '/'),
|
||||
truncated ? " ..." : "");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
pw.print("*** ");
|
||||
pw.println(e.toString());
|
||||
out.format("*** %s\n", e.toString());
|
||||
Log.e(TAG, "Can't read: " + entry.file, e);
|
||||
} finally {
|
||||
if (dbe != null) dbe.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (doPrint) pw.println();
|
||||
if (doPrint) out.format("\n");
|
||||
}
|
||||
|
||||
if (numFound == 0) pw.println("(No entries found.)");
|
||||
if (numFound == 0) out.format("(No entries found.)\n");
|
||||
|
||||
if (args == null || args.length == 0) {
|
||||
if (!doPrint) pw.println();
|
||||
pw.println("Usage: dumpsys dropbox [--print|--file] [YYYY-mm-dd] [HH:MM:SS.SSS] [tag]");
|
||||
if (!doPrint) out.format("\n");
|
||||
out.format("Usage: dumpsys dropbox [--print|--file] [YYYY-mm-dd] [HH:MM:SS] [tag]\n");
|
||||
}
|
||||
|
||||
pw.write(out.toString());
|
||||
if (PROFILE_DUMP) Debug.stopMethodTracing();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user