summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java33
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java30
-rw-r--r--tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java11
3 files changed, 70 insertions, 4 deletions
diff --git a/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
index e0a77d2be724..1f9df3cc842a 100644
--- a/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
@@ -28,6 +28,7 @@ import com.android.internal.protolog.common.IProtoLogGroup;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
@@ -161,15 +162,39 @@ public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
messageString = message.getMessage(mViewerConfigReader);
if (messageString == null) {
- throw new RuntimeException("Failed to decode message for logcat. "
- + "Message hash (" + message.getMessageHash() + ") either not available in "
- + "viewerConfig file (" + mViewerConfigFilePath + ") or "
- + "not loaded into memory from file before decoding.");
+ // Either we failed to load the config for this log message from the viewer config file
+ // into memory, or the message hash is simply not available in the viewer config file.
+ // We want to confirm that the message hash is not available in the viewer config file
+ // before throwing an exception.
+ throw new RuntimeException(getReasonForFailureToGetMessageString(message));
}
return messageString;
}
+ private String getReasonForFailureToGetMessageString(Message message) {
+ if (message.getMessageHash() == null) {
+ return "Trying to get message from null message hash";
+ }
+
+ try {
+ if (mViewerConfigReader.messageHashIsAvailableInFile(message.getMessageHash())) {
+ return "Failed to decode message for logcat logging. "
+ + "Message hash (" + message.getMessageHash() + ") is not available in "
+ + "viewerConfig file (" + mViewerConfigFilePath + "). This might be due "
+ + "to the viewer config file and the executing code being out of sync.";
+ } else {
+ return "Failed to decode message for logcat. "
+ + "Message hash (" + message.getMessageHash() + ") was available in the "
+ + "viewerConfig file (" + mViewerConfigFilePath + ") but wasn't loaded "
+ + "into memory from file before decoding! This is likely a bug.";
+ }
+ } catch (IOException e) {
+ return "Failed to get string message to log but could not identify the root cause due "
+ + "to an IO error in reading the viewer config file.";
+ }
+ }
+
private void loadLogcatGroupsViewerConfig(@NonNull IProtoLogGroup[] protoLogGroups) {
final var groupsLoggingToLogcat = new ArrayList<String>();
for (IProtoLogGroup protoLogGroup : protoLogGroups) {
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 524f64225084..f77179949fbf 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -100,6 +100,36 @@ public class ProtoLogViewerConfigReader {
}
}
+ /**
+ * Return whether or not the viewer config file contains a message with the specified hash.
+ * @param messageHash The hash message we are looking for in the viewer config file
+ * @return True iff the message with message hash is contained in the viewer config.
+ * @throws IOException if there was an issue reading the viewer config file.
+ */
+ public boolean messageHashIsAvailableInFile(long messageHash)
+ throws IOException {
+ try (var pisWrapper = mViewerConfigInputStreamProvider.getInputStream()) {
+ final var pis = pisWrapper.get();
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ if (pis.getFieldNumber() == (int) MESSAGES) {
+ final long inMessageToken = pis.start(MESSAGES);
+
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ if (pis.getFieldNumber() == (int) MESSAGE_ID) {
+ if (pis.readLong(MESSAGE_ID) == messageHash) {
+ return true;
+ }
+ }
+ }
+
+ pis.end(inMessageToken);
+ }
+ }
+ }
+
+ return false;
+ }
+
@NonNull
private Map<Long, String> loadViewerConfigMappingForGroup(@NonNull String group)
throws IOException {
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
index 9e029a8d5e57..72b1780ceb06 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
@@ -33,6 +33,7 @@ import org.junit.runners.JUnit4;
import perfetto.protos.ProtologCommon;
import java.io.File;
+import java.io.IOException;
@Presubmit
@RunWith(JUnit4.class)
@@ -159,4 +160,14 @@ public class ProtoLogViewerConfigReaderTest {
loadViewerConfig();
unloadViewerConfig();
}
+
+ @Test
+ public void testMessageHashIsAvailableInFile() throws IOException {
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(1)).isTrue();
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(2)).isTrue();
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(3)).isTrue();
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(4)).isTrue();
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(5)).isTrue();
+ Truth.assertThat(mConfig.messageHashIsAvailableInFile(6)).isFalse();
+ }
}