summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pablo Gamito <pablogamito@google.com> 2025-01-22 13:46:27 -0800
committer Pablo Gamito <pablogamito@google.com> 2025-01-23 00:15:23 +0000
commit8623733336a2a73d98f5107d0942d3db40c612dc (patch)
treecc96d51bf056e3d20005230280cca69ae0e4c394
parent1dd200f972b74346d6794ede34344c730a8977a2 (diff)
Distinguish the reason why decoding failed.
We were throwing a RuntimeException that the message hash wasn't in the viewer config file, but this can also happen when the viewer config file wasn't loaded into memory from disk, which is more likely a bug. Update the exception to clarify what's happening. Test: atest com.android.internal.protolog.ProtoLogViewerConfigReaderTest Bug: 388235335 Flag: EXEMPT updating error message clarity Change-Id: I484c918ec196d57bb910900e3a7a7870923d64a5
-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();
+ }
}