Loading core/proto/android/os/incident.proto +17 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/batterystats.proto"; import "frameworks/base/core/proto/android/service/diskstats.proto"; import "frameworks/base/core/proto/android/service/dropbox.proto"; import "frameworks/base/core/proto/android/service/graphicsstats.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; import "frameworks/base/core/proto/android/service/notification.proto"; Loading Loading @@ -329,6 +330,22 @@ message IncidentProto { (section).userdebug_and_eng_only = true ]; // Dropbox entries split by tags. optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_crashes = 3027 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_crash" ]; optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_anr = 3028 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_anr" ]; optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_native_crash = 3029 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_native_crash" ]; // Reserved for OEMs. extensions 50000 to 100000; } core/proto/android/service/dropbox.proto 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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. */ syntax = "proto2"; package android.service.dropbox; import "frameworks/base/core/proto/android/privacy.proto"; option java_multiple_files = true; // Dump from com.android.server.DropboxManagerService.java. message DropBoxManagerServiceDumpProto { option (android.msg_privacy).dest = DEST_EXPLICIT; message Entry { // Time when entry was originally created. optional int64 time_ms = 1 [ (.android.privacy).dest = DEST_AUTOMATIC ] ; optional bytes data = 2; } repeated Entry entries = 1; } services/core/java/com/android/server/DropBoxManagerService.java +68 −8 Original line number Diff line number Diff line Loading @@ -41,11 +41,13 @@ import android.os.StatFs; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.service.dropbox.DropBoxManagerServiceDumpProto; import android.text.TextUtils; import android.text.format.TimeMigrationUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading @@ -66,6 +68,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.SortedSet; import java.util.TreeSet; import java.util.zip.GZIPOutputStream; Loading @@ -86,6 +89,9 @@ public final class DropBoxManagerService extends SystemService { private static final boolean PROFILE_DUMP = false; // Max number of bytes of a dropbox entry to write into protobuf. private static final int PROTO_MAX_DATA_BYTES = 256 * 1024; // 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. Loading Loading @@ -556,18 +562,22 @@ public final class DropBoxManagerService extends SystemService { StringBuilder out = new StringBuilder(); boolean doPrint = false, doFile = false; boolean dumpProto = false; ArrayList<String> searchArgs = new ArrayList<String>(); for (int i = 0; args != null && i < args.length; i++) { if (args[i].equals("-p") || args[i].equals("--print")) { doPrint = true; } else if (args[i].equals("-f") || args[i].equals("--file")) { doFile = true; } else if (args[i].equals("--proto")) { dumpProto = true; } else if (args[i].equals("-h") || args[i].equals("--help")) { pw.println("Dropbox (dropbox) dump options:"); pw.println(" [-h|--help] [-p|--print] [-f|--file] [timestamp]"); pw.println(" -h|--help: print this help"); pw.println(" -p|--print: print full contents of each entry"); pw.println(" -f|--file: print path of each entry's file"); pw.println(" --proto: dump data to proto"); pw.println(" [timestamp] optionally filters to only those entries."); return; } else if (args[i].startsWith("-")) { Loading @@ -577,6 +587,11 @@ public final class DropBoxManagerService extends SystemService { } } if (dumpProto) { dumpProtoLocked(fd, searchArgs); return; } out.append("Drop box contents: ").append(mAllFiles.contents.size()).append(" entries\n"); out.append("Max entries: ").append(mMaxFiles).append("\n"); Loading @@ -590,19 +605,15 @@ public final class DropBoxManagerService extends SystemService { out.append("\n"); } int numFound = 0, numArgs = searchArgs.size(); int numFound = 0; out.append("\n"); for (EntryFile entry : mAllFiles.contents) { String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); boolean match = true; for (int i = 0; i < numArgs && match; i++) { String arg = searchArgs.get(i); match = (date.contains(arg) || arg.equals(entry.tag)); } if (!match) continue; if (!matchEntry(entry, searchArgs)) continue; numFound++; if (doPrint) out.append("========================================\n"); String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); out.append(date).append(" ").append(entry.tag == null ? "(no tag)" : entry.tag); final File file = entry.getFile(mDropBoxDir); Loading Loading @@ -688,6 +699,55 @@ public final class DropBoxManagerService extends SystemService { if (PROFILE_DUMP) Debug.stopMethodTracing(); } private boolean matchEntry(EntryFile entry, ArrayList<String> searchArgs) { String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); boolean match = true; int numArgs = searchArgs.size(); for (int i = 0; i < numArgs && match; i++) { String arg = searchArgs.get(i); match = (date.contains(arg) || arg.equals(entry.tag)); } return match; } private void dumpProtoLocked(FileDescriptor fd, ArrayList<String> searchArgs) { final ProtoOutputStream proto = new ProtoOutputStream(fd); for (EntryFile entry : mAllFiles.contents) { if (!matchEntry(entry, searchArgs)) continue; final File file = entry.getFile(mDropBoxDir); if ((file == null) || ((entry.flags & DropBoxManager.IS_EMPTY) != 0)) { continue; } final long bToken = proto.start(DropBoxManagerServiceDumpProto.ENTRIES); proto.write(DropBoxManagerServiceDumpProto.Entry.TIME_MS, entry.timestampMillis); try ( DropBoxManager.Entry dbe = new DropBoxManager.Entry( entry.tag, entry.timestampMillis, file, entry.flags); InputStream is = dbe.getInputStream(); ) { if (is != null) { byte[] buf = new byte[PROTO_MAX_DATA_BYTES]; int readBytes = 0; int n = 0; while (n >= 0 && (readBytes += n) < PROTO_MAX_DATA_BYTES) { n = is.read(buf, readBytes, PROTO_MAX_DATA_BYTES - readBytes); } proto.write(DropBoxManagerServiceDumpProto.Entry.DATA, Arrays.copyOf(buf, readBytes)); } } catch (IOException e) { Slog.e(TAG, "Can't read: " + file, e); } proto.end(bToken); } proto.flush(); } /////////////////////////////////////////////////////////////////////////// /** Chronologically sorted list of {@link EntryFile} */ Loading Loading
core/proto/android/os/incident.proto +17 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/batterystats.proto"; import "frameworks/base/core/proto/android/service/diskstats.proto"; import "frameworks/base/core/proto/android/service/dropbox.proto"; import "frameworks/base/core/proto/android/service/graphicsstats.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; import "frameworks/base/core/proto/android/service/notification.proto"; Loading Loading @@ -329,6 +330,22 @@ message IncidentProto { (section).userdebug_and_eng_only = true ]; // Dropbox entries split by tags. optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_crashes = 3027 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_crash" ]; optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_anr = 3028 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_anr" ]; optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_native_crash = 3029 [ (section).type = SECTION_DUMPSYS, (section).args = "dropbox --proto data_app_native_crash" ]; // Reserved for OEMs. extensions 50000 to 100000; }
core/proto/android/service/dropbox.proto 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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. */ syntax = "proto2"; package android.service.dropbox; import "frameworks/base/core/proto/android/privacy.proto"; option java_multiple_files = true; // Dump from com.android.server.DropboxManagerService.java. message DropBoxManagerServiceDumpProto { option (android.msg_privacy).dest = DEST_EXPLICIT; message Entry { // Time when entry was originally created. optional int64 time_ms = 1 [ (.android.privacy).dest = DEST_AUTOMATIC ] ; optional bytes data = 2; } repeated Entry entries = 1; }
services/core/java/com/android/server/DropBoxManagerService.java +68 −8 Original line number Diff line number Diff line Loading @@ -41,11 +41,13 @@ import android.os.StatFs; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.service.dropbox.DropBoxManagerServiceDumpProto; import android.text.TextUtils; import android.text.format.TimeMigrationUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading @@ -66,6 +68,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.SortedSet; import java.util.TreeSet; import java.util.zip.GZIPOutputStream; Loading @@ -86,6 +89,9 @@ public final class DropBoxManagerService extends SystemService { private static final boolean PROFILE_DUMP = false; // Max number of bytes of a dropbox entry to write into protobuf. private static final int PROTO_MAX_DATA_BYTES = 256 * 1024; // 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. Loading Loading @@ -556,18 +562,22 @@ public final class DropBoxManagerService extends SystemService { StringBuilder out = new StringBuilder(); boolean doPrint = false, doFile = false; boolean dumpProto = false; ArrayList<String> searchArgs = new ArrayList<String>(); for (int i = 0; args != null && i < args.length; i++) { if (args[i].equals("-p") || args[i].equals("--print")) { doPrint = true; } else if (args[i].equals("-f") || args[i].equals("--file")) { doFile = true; } else if (args[i].equals("--proto")) { dumpProto = true; } else if (args[i].equals("-h") || args[i].equals("--help")) { pw.println("Dropbox (dropbox) dump options:"); pw.println(" [-h|--help] [-p|--print] [-f|--file] [timestamp]"); pw.println(" -h|--help: print this help"); pw.println(" -p|--print: print full contents of each entry"); pw.println(" -f|--file: print path of each entry's file"); pw.println(" --proto: dump data to proto"); pw.println(" [timestamp] optionally filters to only those entries."); return; } else if (args[i].startsWith("-")) { Loading @@ -577,6 +587,11 @@ public final class DropBoxManagerService extends SystemService { } } if (dumpProto) { dumpProtoLocked(fd, searchArgs); return; } out.append("Drop box contents: ").append(mAllFiles.contents.size()).append(" entries\n"); out.append("Max entries: ").append(mMaxFiles).append("\n"); Loading @@ -590,19 +605,15 @@ public final class DropBoxManagerService extends SystemService { out.append("\n"); } int numFound = 0, numArgs = searchArgs.size(); int numFound = 0; out.append("\n"); for (EntryFile entry : mAllFiles.contents) { String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); boolean match = true; for (int i = 0; i < numArgs && match; i++) { String arg = searchArgs.get(i); match = (date.contains(arg) || arg.equals(entry.tag)); } if (!match) continue; if (!matchEntry(entry, searchArgs)) continue; numFound++; if (doPrint) out.append("========================================\n"); String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); out.append(date).append(" ").append(entry.tag == null ? "(no tag)" : entry.tag); final File file = entry.getFile(mDropBoxDir); Loading Loading @@ -688,6 +699,55 @@ public final class DropBoxManagerService extends SystemService { if (PROFILE_DUMP) Debug.stopMethodTracing(); } private boolean matchEntry(EntryFile entry, ArrayList<String> searchArgs) { String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); boolean match = true; int numArgs = searchArgs.size(); for (int i = 0; i < numArgs && match; i++) { String arg = searchArgs.get(i); match = (date.contains(arg) || arg.equals(entry.tag)); } return match; } private void dumpProtoLocked(FileDescriptor fd, ArrayList<String> searchArgs) { final ProtoOutputStream proto = new ProtoOutputStream(fd); for (EntryFile entry : mAllFiles.contents) { if (!matchEntry(entry, searchArgs)) continue; final File file = entry.getFile(mDropBoxDir); if ((file == null) || ((entry.flags & DropBoxManager.IS_EMPTY) != 0)) { continue; } final long bToken = proto.start(DropBoxManagerServiceDumpProto.ENTRIES); proto.write(DropBoxManagerServiceDumpProto.Entry.TIME_MS, entry.timestampMillis); try ( DropBoxManager.Entry dbe = new DropBoxManager.Entry( entry.tag, entry.timestampMillis, file, entry.flags); InputStream is = dbe.getInputStream(); ) { if (is != null) { byte[] buf = new byte[PROTO_MAX_DATA_BYTES]; int readBytes = 0; int n = 0; while (n >= 0 && (readBytes += n) < PROTO_MAX_DATA_BYTES) { n = is.read(buf, readBytes, PROTO_MAX_DATA_BYTES - readBytes); } proto.write(DropBoxManagerServiceDumpProto.Entry.DATA, Arrays.copyOf(buf, readBytes)); } } catch (IOException e) { Slog.e(TAG, "Can't read: " + file, e); } proto.end(bToken); } proto.flush(); } /////////////////////////////////////////////////////////////////////////// /** Chronologically sorted list of {@link EntryFile} */ Loading