Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,7 @@ java_library { "apex_aidl_interface-java", "packagemanager_aidl-java", "framework-protos", "libtombstone_proto_java", "updatable-driver-protos", "ota_metadata_proto_java", "android.hidl.base-V1.0-java", Loading ProtoLibraries.bp +0 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ gensrcs { ":ipconnectivity-proto-src", ":libstats_atom_enum_protos", ":libstats_atom_message_protos", ":libtombstone_proto-src", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], Loading STABILITY_OWNERS 0 → 100644 +2 −0 Original line number Diff line number Diff line gaillard@google.com services/core/java/com/android/server/BootReceiver.java +57 −26 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.am.DropboxRateLimiter; import com.android.server.os.TombstoneProtos; import com.android.server.os.TombstoneProtos.Tombstone; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading @@ -60,11 +62,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; import java.util.AbstractMap; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Performs a number of miscellaneous, non-system-critical actions Loading Loading @@ -327,12 +332,12 @@ public class BootReceiver extends BroadcastReceiver { * * @param ctx Context * @param tombstone path to the tombstone * @param proto whether the tombstone is stored as proto * @param tombstoneProto the parsed proto tombstone * @param processName the name of the process corresponding to the tombstone * @param tmpFileLock the lock for reading/writing tmp files */ public static void addTombstoneToDropBox( Context ctx, File tombstone, boolean proto, String processName, Context ctx, File tombstone, Tombstone tombstoneProto, String processName, ReentrantLock tmpFileLock) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); if (db == null) { Loading @@ -342,32 +347,34 @@ public class BootReceiver extends BroadcastReceiver { // Check if we should rate limit and abort early if needed. DropboxRateLimiter.RateLimitResult rateLimitResult = sDropboxRateLimiter.shouldRateLimit( proto ? TAG_TOMBSTONE_PROTO_WITH_HEADERS : TAG_TOMBSTONE, processName); sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE_PROTO_WITH_HEADERS, processName); if (rateLimitResult.shouldRateLimit()) return; HashMap<String, Long> timestamps = readTimestamps(); try { if (proto) { // Remove the memory data from the proto. Tombstone tombstoneProtoWithoutMemory = removeMemoryFromTombstone(tombstoneProto); final byte[] tombstoneBytes = tombstoneProtoWithoutMemory.toByteArray(); // Use JNI to call the c++ proto to text converter and add the headers to the tombstone. String tombstoneWithoutMemory = new StringBuilder(getBootHeadersToLogAndUpdate()) .append(rateLimitResult.createHeader()) .append(getTombstoneText(tombstoneBytes)) .toString(); // Add the tombstone without memory data to dropbox. db.addText(TAG_TOMBSTONE, tombstoneWithoutMemory); // Add the tombstone proto to dropbox. if (recordFileTimestamp(tombstone, timestamps)) { // We need to attach the count indicating the number of dropped dropbox entries // due to rate limiting. Do this by enclosing the proto tombsstone in a // container proto that has the dropped entry count and the proto tombstone as // bytes (to avoid the complexity of reading and writing nested protos). tmpFileLock.lock(); try { addAugmentedProtoToDropbox(tombstone, db, rateLimitResult); addAugmentedProtoToDropbox(tombstone, tombstoneBytes, db, rateLimitResult); } finally { tmpFileLock.unlock(); } } } else { // Add the header indicating how many events have been dropped due to rate limiting. final String headers = getBootHeadersToLogAndUpdate() + rateLimitResult.createHeader(); addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, TAG_TOMBSTONE); } } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); } Loading @@ -375,11 +382,8 @@ public class BootReceiver extends BroadcastReceiver { } private static void addAugmentedProtoToDropbox( File tombstone, DropBoxManager db, File tombstone, byte[] tombstoneBytes, DropBoxManager db, DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException { // Read the proto tombstone file as bytes. final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); final File tombstoneProtoWithHeaders = File.createTempFile( tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); Files.setPosixFilePermissions( Loading Loading @@ -412,6 +416,8 @@ public class BootReceiver extends BroadcastReceiver { } } private static native String getTombstoneText(byte[] tombstoneBytes); private static void addLastkToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String footers, String filename, int maxSize, Loading @@ -429,6 +435,31 @@ public class BootReceiver extends BroadcastReceiver { addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag); } /** Removes memory information from the Tombstone proto. */ @VisibleForTesting public static Tombstone removeMemoryFromTombstone(Tombstone tombstoneProto) { Tombstone.Builder tombstoneBuilder = tombstoneProto.toBuilder() .clearMemoryMappings() .clearThreads() .putAllThreads(tombstoneProto.getThreadsMap().entrySet() .stream() .map(BootReceiver::clearMemoryDump) .collect(Collectors.toMap(e->e.getKey(), e->e.getValue()))); if (tombstoneProto.hasSignalInfo()) { tombstoneBuilder.setSignalInfo( tombstoneProto.getSignalInfo().toBuilder().clearFaultAdjacentMetadata()); } return tombstoneBuilder.build(); } private static AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread> clearMemoryDump( Map.Entry<Integer, TombstoneProtos.Thread> e) { return new AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread>( e.getKey(), e.getValue().toBuilder().clearMemoryDump().build()); } private static void addFileToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String filename, int maxSize, String tag) throws IOException { Loading services/core/java/com/android/server/os/NativeTombstoneManager.java +66 −69 Original line number Diff line number Diff line Loading @@ -41,14 +41,13 @@ import android.system.Os; import android.system.StructStat; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoParseException; import com.android.internal.annotations.GuardedBy; import com.android.server.BootReceiver; import com.android.server.ServiceThread; import com.android.server.os.TombstoneProtos.Cause; import com.android.server.os.TombstoneProtos.Tombstone; import com.android.server.os.protobuf.CodedInputStream; import libcore.io.IoUtils; Loading Loading @@ -128,18 +127,21 @@ public final class NativeTombstoneManager { return; } String processName = "UNKNOWN"; final boolean isProtoFile = filename.endsWith(".pb"); File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb"); if (!isProtoFile) { return; } Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile); Optional<ParsedTombstone> parsedTombstone = handleProtoTombstone(path, true); if (parsedTombstone.isPresent()) { processName = parsedTombstone.get().getProcessName(); BootReceiver.addTombstoneToDropBox( mContext, path, parsedTombstone.get().getTombstone(), parsedTombstone.get().getProcessName(), mTmpFileLock); } BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock); } private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) { private Optional<ParsedTombstone> handleProtoTombstone( File path, boolean addToList) { final String filename = path.getName(); if (!filename.endsWith(".pb")) { Slog.w(TAG, "unexpected tombstone name: " + path); Loading Loading @@ -169,7 +171,7 @@ public final class NativeTombstoneManager { return Optional.empty(); } final Optional<TombstoneFile> parsedTombstone = TombstoneFile.parse(pfd); final Optional<ParsedTombstone> parsedTombstone = TombstoneFile.parse(pfd); if (!parsedTombstone.isPresent()) { IoUtils.closeQuietly(pfd); return Optional.empty(); Loading @@ -182,7 +184,7 @@ public final class NativeTombstoneManager { previous.dispose(); } mTombstones.put(number, parsedTombstone.get()); mTombstones.put(number, parsedTombstone.get().getTombstoneFile()); } } Loading Loading @@ -330,6 +332,27 @@ public final class NativeTombstoneManager { } } static class ParsedTombstone { TombstoneFile mTombstoneFile; Tombstone mTombstone; ParsedTombstone(TombstoneFile tombstoneFile, Tombstone tombstone) { mTombstoneFile = tombstoneFile; mTombstone = tombstone; } public String getProcessName() { return mTombstoneFile.getProcessName(); } public TombstoneFile getTombstoneFile() { return mTombstoneFile; } public Tombstone getTombstone() { return mTombstone; } } static class TombstoneFile { final ParcelFileDescriptor mPfd; Loading Loading @@ -412,67 +435,21 @@ public final class NativeTombstoneManager { } } static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) { final FileInputStream is = new FileInputStream(pfd.getFileDescriptor()); final ProtoInputStream stream = new ProtoInputStream(is); int pid = 0; int uid = 0; String processName = null; String crashReason = ""; String selinuxLabel = ""; try { while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { case (int) Tombstone.PID: pid = stream.readInt(Tombstone.PID); break; case (int) Tombstone.UID: uid = stream.readInt(Tombstone.UID); break; case (int) Tombstone.COMMAND_LINE: if (processName == null) { processName = stream.readString(Tombstone.COMMAND_LINE); } break; static Optional<ParsedTombstone> parse(ParcelFileDescriptor pfd) { Tombstone tombstoneProto; try (FileInputStream is = new FileInputStream(pfd.getFileDescriptor())) { final byte[] tombstoneBytes = is.readAllBytes(); case (int) Tombstone.CAUSES: if (!crashReason.equals("")) { // Causes appear in decreasing order of likelihood. For now we only // want the most likely crash reason here, so ignore all others. break; } long token = stream.start(Tombstone.CAUSES); cause: while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { case (int) Cause.HUMAN_READABLE: crashReason = stream.readString(Cause.HUMAN_READABLE); break cause; default: break; } } stream.end(token); break; case (int) Tombstone.SELINUX_LABEL: selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL); break; default: break; } } } catch (IOException | ProtoParseException ex) { tombstoneProto = Tombstone.parseFrom( CodedInputStream.newInstance(tombstoneBytes)); } catch (IOException ex) { Slog.e(TAG, "Failed to parse tombstone", ex); return Optional.empty(); } int pid = tombstoneProto.getPid(); int uid = tombstoneProto.getUid(); if (!UserHandle.isApp(uid)) { Slog.e(TAG, "Tombstone's UID (" + uid + ") not an app, ignoring"); return Optional.empty(); Loading @@ -489,6 +466,7 @@ public final class NativeTombstoneManager { final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); String selinuxLabel = tombstoneProto.getSelinuxLabel(); if (!selinuxLabel.startsWith("u:r:untrusted_app")) { Slog.e(TAG, "Tombstone has invalid selinux label (" + selinuxLabel + "), ignoring"); return Optional.empty(); Loading @@ -500,11 +478,30 @@ public final class NativeTombstoneManager { result.mAppId = appId; result.mPid = pid; result.mUid = uid; result.mProcessName = processName == null ? "" : processName; result.mProcessName = getCmdLineProcessName(tombstoneProto); result.mTimestampMs = timestampMs; result.mCrashReason = crashReason; result.mCrashReason = getCrashReason(tombstoneProto); return Optional.of(result); return Optional.of(new ParsedTombstone(result, tombstoneProto)); } private static String getCmdLineProcessName(Tombstone tombstoneProto) { for (String cmdline : tombstoneProto.getCommandLineList()) { if (cmdline != null) { return cmdline; } } return ""; } private static String getCrashReason(Tombstone tombstoneProto) { for (Cause cause : tombstoneProto.getCausesList()) { if (cause.getHumanReadable() != null && !cause.getHumanReadable().equals("")) { return cause.getHumanReadable(); } } return ""; } public IParcelFileDescriptorRetriever getPfdRetriever() { Loading Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,7 @@ java_library { "apex_aidl_interface-java", "packagemanager_aidl-java", "framework-protos", "libtombstone_proto_java", "updatable-driver-protos", "ota_metadata_proto_java", "android.hidl.base-V1.0-java", Loading
ProtoLibraries.bp +0 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ gensrcs { ":ipconnectivity-proto-src", ":libstats_atom_enum_protos", ":libstats_atom_message_protos", ":libtombstone_proto-src", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], Loading
STABILITY_OWNERS 0 → 100644 +2 −0 Original line number Diff line number Diff line gaillard@google.com
services/core/java/com/android/server/BootReceiver.java +57 −26 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.am.DropboxRateLimiter; import com.android.server.os.TombstoneProtos; import com.android.server.os.TombstoneProtos.Tombstone; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading @@ -60,11 +62,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; import java.util.AbstractMap; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Performs a number of miscellaneous, non-system-critical actions Loading Loading @@ -327,12 +332,12 @@ public class BootReceiver extends BroadcastReceiver { * * @param ctx Context * @param tombstone path to the tombstone * @param proto whether the tombstone is stored as proto * @param tombstoneProto the parsed proto tombstone * @param processName the name of the process corresponding to the tombstone * @param tmpFileLock the lock for reading/writing tmp files */ public static void addTombstoneToDropBox( Context ctx, File tombstone, boolean proto, String processName, Context ctx, File tombstone, Tombstone tombstoneProto, String processName, ReentrantLock tmpFileLock) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); if (db == null) { Loading @@ -342,32 +347,34 @@ public class BootReceiver extends BroadcastReceiver { // Check if we should rate limit and abort early if needed. DropboxRateLimiter.RateLimitResult rateLimitResult = sDropboxRateLimiter.shouldRateLimit( proto ? TAG_TOMBSTONE_PROTO_WITH_HEADERS : TAG_TOMBSTONE, processName); sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE_PROTO_WITH_HEADERS, processName); if (rateLimitResult.shouldRateLimit()) return; HashMap<String, Long> timestamps = readTimestamps(); try { if (proto) { // Remove the memory data from the proto. Tombstone tombstoneProtoWithoutMemory = removeMemoryFromTombstone(tombstoneProto); final byte[] tombstoneBytes = tombstoneProtoWithoutMemory.toByteArray(); // Use JNI to call the c++ proto to text converter and add the headers to the tombstone. String tombstoneWithoutMemory = new StringBuilder(getBootHeadersToLogAndUpdate()) .append(rateLimitResult.createHeader()) .append(getTombstoneText(tombstoneBytes)) .toString(); // Add the tombstone without memory data to dropbox. db.addText(TAG_TOMBSTONE, tombstoneWithoutMemory); // Add the tombstone proto to dropbox. if (recordFileTimestamp(tombstone, timestamps)) { // We need to attach the count indicating the number of dropped dropbox entries // due to rate limiting. Do this by enclosing the proto tombsstone in a // container proto that has the dropped entry count and the proto tombstone as // bytes (to avoid the complexity of reading and writing nested protos). tmpFileLock.lock(); try { addAugmentedProtoToDropbox(tombstone, db, rateLimitResult); addAugmentedProtoToDropbox(tombstone, tombstoneBytes, db, rateLimitResult); } finally { tmpFileLock.unlock(); } } } else { // Add the header indicating how many events have been dropped due to rate limiting. final String headers = getBootHeadersToLogAndUpdate() + rateLimitResult.createHeader(); addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE, TAG_TOMBSTONE); } } catch (IOException e) { Slog.e(TAG, "Can't log tombstone", e); } Loading @@ -375,11 +382,8 @@ public class BootReceiver extends BroadcastReceiver { } private static void addAugmentedProtoToDropbox( File tombstone, DropBoxManager db, File tombstone, byte[] tombstoneBytes, DropBoxManager db, DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException { // Read the proto tombstone file as bytes. final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); final File tombstoneProtoWithHeaders = File.createTempFile( tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); Files.setPosixFilePermissions( Loading Loading @@ -412,6 +416,8 @@ public class BootReceiver extends BroadcastReceiver { } } private static native String getTombstoneText(byte[] tombstoneBytes); private static void addLastkToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String footers, String filename, int maxSize, Loading @@ -429,6 +435,31 @@ public class BootReceiver extends BroadcastReceiver { addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag); } /** Removes memory information from the Tombstone proto. */ @VisibleForTesting public static Tombstone removeMemoryFromTombstone(Tombstone tombstoneProto) { Tombstone.Builder tombstoneBuilder = tombstoneProto.toBuilder() .clearMemoryMappings() .clearThreads() .putAllThreads(tombstoneProto.getThreadsMap().entrySet() .stream() .map(BootReceiver::clearMemoryDump) .collect(Collectors.toMap(e->e.getKey(), e->e.getValue()))); if (tombstoneProto.hasSignalInfo()) { tombstoneBuilder.setSignalInfo( tombstoneProto.getSignalInfo().toBuilder().clearFaultAdjacentMetadata()); } return tombstoneBuilder.build(); } private static AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread> clearMemoryDump( Map.Entry<Integer, TombstoneProtos.Thread> e) { return new AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread>( e.getKey(), e.getValue().toBuilder().clearMemoryDump().build()); } private static void addFileToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String filename, int maxSize, String tag) throws IOException { Loading
services/core/java/com/android/server/os/NativeTombstoneManager.java +66 −69 Original line number Diff line number Diff line Loading @@ -41,14 +41,13 @@ import android.system.Os; import android.system.StructStat; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoParseException; import com.android.internal.annotations.GuardedBy; import com.android.server.BootReceiver; import com.android.server.ServiceThread; import com.android.server.os.TombstoneProtos.Cause; import com.android.server.os.TombstoneProtos.Tombstone; import com.android.server.os.protobuf.CodedInputStream; import libcore.io.IoUtils; Loading Loading @@ -128,18 +127,21 @@ public final class NativeTombstoneManager { return; } String processName = "UNKNOWN"; final boolean isProtoFile = filename.endsWith(".pb"); File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb"); if (!isProtoFile) { return; } Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile); Optional<ParsedTombstone> parsedTombstone = handleProtoTombstone(path, true); if (parsedTombstone.isPresent()) { processName = parsedTombstone.get().getProcessName(); BootReceiver.addTombstoneToDropBox( mContext, path, parsedTombstone.get().getTombstone(), parsedTombstone.get().getProcessName(), mTmpFileLock); } BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock); } private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) { private Optional<ParsedTombstone> handleProtoTombstone( File path, boolean addToList) { final String filename = path.getName(); if (!filename.endsWith(".pb")) { Slog.w(TAG, "unexpected tombstone name: " + path); Loading Loading @@ -169,7 +171,7 @@ public final class NativeTombstoneManager { return Optional.empty(); } final Optional<TombstoneFile> parsedTombstone = TombstoneFile.parse(pfd); final Optional<ParsedTombstone> parsedTombstone = TombstoneFile.parse(pfd); if (!parsedTombstone.isPresent()) { IoUtils.closeQuietly(pfd); return Optional.empty(); Loading @@ -182,7 +184,7 @@ public final class NativeTombstoneManager { previous.dispose(); } mTombstones.put(number, parsedTombstone.get()); mTombstones.put(number, parsedTombstone.get().getTombstoneFile()); } } Loading Loading @@ -330,6 +332,27 @@ public final class NativeTombstoneManager { } } static class ParsedTombstone { TombstoneFile mTombstoneFile; Tombstone mTombstone; ParsedTombstone(TombstoneFile tombstoneFile, Tombstone tombstone) { mTombstoneFile = tombstoneFile; mTombstone = tombstone; } public String getProcessName() { return mTombstoneFile.getProcessName(); } public TombstoneFile getTombstoneFile() { return mTombstoneFile; } public Tombstone getTombstone() { return mTombstone; } } static class TombstoneFile { final ParcelFileDescriptor mPfd; Loading Loading @@ -412,67 +435,21 @@ public final class NativeTombstoneManager { } } static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) { final FileInputStream is = new FileInputStream(pfd.getFileDescriptor()); final ProtoInputStream stream = new ProtoInputStream(is); int pid = 0; int uid = 0; String processName = null; String crashReason = ""; String selinuxLabel = ""; try { while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { case (int) Tombstone.PID: pid = stream.readInt(Tombstone.PID); break; case (int) Tombstone.UID: uid = stream.readInt(Tombstone.UID); break; case (int) Tombstone.COMMAND_LINE: if (processName == null) { processName = stream.readString(Tombstone.COMMAND_LINE); } break; static Optional<ParsedTombstone> parse(ParcelFileDescriptor pfd) { Tombstone tombstoneProto; try (FileInputStream is = new FileInputStream(pfd.getFileDescriptor())) { final byte[] tombstoneBytes = is.readAllBytes(); case (int) Tombstone.CAUSES: if (!crashReason.equals("")) { // Causes appear in decreasing order of likelihood. For now we only // want the most likely crash reason here, so ignore all others. break; } long token = stream.start(Tombstone.CAUSES); cause: while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (stream.getFieldNumber()) { case (int) Cause.HUMAN_READABLE: crashReason = stream.readString(Cause.HUMAN_READABLE); break cause; default: break; } } stream.end(token); break; case (int) Tombstone.SELINUX_LABEL: selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL); break; default: break; } } } catch (IOException | ProtoParseException ex) { tombstoneProto = Tombstone.parseFrom( CodedInputStream.newInstance(tombstoneBytes)); } catch (IOException ex) { Slog.e(TAG, "Failed to parse tombstone", ex); return Optional.empty(); } int pid = tombstoneProto.getPid(); int uid = tombstoneProto.getUid(); if (!UserHandle.isApp(uid)) { Slog.e(TAG, "Tombstone's UID (" + uid + ") not an app, ignoring"); return Optional.empty(); Loading @@ -489,6 +466,7 @@ public final class NativeTombstoneManager { final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); String selinuxLabel = tombstoneProto.getSelinuxLabel(); if (!selinuxLabel.startsWith("u:r:untrusted_app")) { Slog.e(TAG, "Tombstone has invalid selinux label (" + selinuxLabel + "), ignoring"); return Optional.empty(); Loading @@ -500,11 +478,30 @@ public final class NativeTombstoneManager { result.mAppId = appId; result.mPid = pid; result.mUid = uid; result.mProcessName = processName == null ? "" : processName; result.mProcessName = getCmdLineProcessName(tombstoneProto); result.mTimestampMs = timestampMs; result.mCrashReason = crashReason; result.mCrashReason = getCrashReason(tombstoneProto); return Optional.of(result); return Optional.of(new ParsedTombstone(result, tombstoneProto)); } private static String getCmdLineProcessName(Tombstone tombstoneProto) { for (String cmdline : tombstoneProto.getCommandLineList()) { if (cmdline != null) { return cmdline; } } return ""; } private static String getCrashReason(Tombstone tombstoneProto) { for (Cause cause : tombstoneProto.getCausesList()) { if (cause.getHumanReadable() != null && !cause.getHumanReadable().equals("")) { return cause.getHumanReadable(); } } return ""; } public IParcelFileDescriptorRetriever getPfdRetriever() { Loading