Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d2a6896 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve error message for ProtoLog decoding failures." into main

parents 924ff30a dfe8541e
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -180,16 +180,20 @@ public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
        }

        try {
            if (!mViewerConfigReader.messageHashIsAvailableInFile(message.getMessageHash())) {
            ProtoLogViewerConfigReader.MessageData messageData =
                    mViewerConfigReader.getMessageDataForHashFromFile(message.getMessageHash());
            if (messageData == null) {
                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.";
                        + "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. Message: '" + messageData.message
                        + "', group: '" + messageData.group + "'.";
            }
        } catch (IOException e) {
            return "Failed to get string message to log but could not identify the root cause due "
+118 −38
Original line number Diff line number Diff line
@@ -34,6 +34,21 @@ public class ProtoLogViewerConfigReader {
        this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
    }

    /**
     * Data class for a log message from the viewer config.
     */
    public static class MessageData {
        @NonNull
        public final String message;
        @NonNull
        public final String group;

        public MessageData(@NonNull String message, @NonNull String group) {
            this.message = message;
            this.group = group;
        }
    }

    /**
     * Returns message format string for its hash or null if unavailable
     * or the viewer config is not loaded into memory.
@@ -130,6 +145,56 @@ public class ProtoLogViewerConfigReader {
        return false;
    }

    /**
     * Returns the message data for a given message hash from the viewer config file.
     *
     * @param messageHash The hash of the message we are looking for in the viewer config file.
     * @return The {@link MessageData} if the message is found, null otherwise.
     * @throws IOException if there was an issue reading the viewer config file.
     */
    @Nullable
    public MessageData getMessageDataForHashFromFile(long messageHash)
            throws IOException {
        try (var pisWrapper = mViewerConfigInputStreamProvider.getInputStream()) {
            final var pis = pisWrapper.get();

            String foundMessage = null;
            long foundGroupId = -1;
            final LongSparseArray<String> groupMap = new LongSparseArray<>();

            while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                if (pis.getFieldNumber() == (int) MESSAGES) {
                    final long inMessageToken = pis.start(MESSAGES);
                    ParsedMessage parsedMessage = readMessage(pis);
                    if (parsedMessage.messageId == messageHash) {
                        foundMessage = parsedMessage.message;
                        foundGroupId = parsedMessage.groupId;
                    }

                    pis.end(inMessageToken);
                } else if (pis.getFieldNumber() == (int) GROUPS) {
                    final long inMessageToken = pis.start(GROUPS);

                    long groupId = 0;
                    ParsedGroup parsedGroup = readGroup(pis);
                    if (parsedGroup.groupName != null) {
                        groupMap.put(parsedGroup.groupId, parsedGroup.groupName);
                    }
                    pis.end(inMessageToken);
                }
            }

            if (foundMessage != null) {
                String groupName = groupMap.get(foundGroupId);
                if (groupName != null) {
                    return new MessageData(foundMessage, groupName);
                }
            }
        }

        return null;
    }

    @NonNull
    private Map<Long, String> loadViewerConfigMappingForGroup(@NonNull String group)
            throws IOException {
@@ -141,38 +206,22 @@ public class ProtoLogViewerConfigReader {
            while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                if (pis.getFieldNumber() == (int) MESSAGES) {
                    final long inMessageToken = pis.start(MESSAGES);
                    ParsedMessage parsedMessage = readMessage(pis);

                    long messageId = 0;
                    String message = null;
                    int groupId = 0;
                    while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                        switch (pis.getFieldNumber()) {
                            case (int) MESSAGE_ID:
                                messageId = pis.readLong(MESSAGE_ID);
                                break;
                            case (int) MESSAGE:
                                message = pis.readString(MESSAGE);
                                break;
                            case (int) GROUP_ID:
                                groupId = pis.readInt(GROUP_ID);
                                break;
                        }
                    }

                    if (groupId == 0) {
                    if (parsedMessage.groupId == 0) {
                        throw new IOException("Failed to get group id");
                    }

                    if (messageId == 0) {
                    if (parsedMessage.messageId == 0) {
                        throw new IOException("Failed to get message id");
                    }

                    if (message == null) {
                    if (parsedMessage.message == null) {
                        throw new IOException("Failed to get message string");
                    }

                    if (groupId == targetGroupId) {
                        hashesForGroup.put(messageId, message);
                    if (parsedMessage.groupId == targetGroupId) {
                        hashesForGroup.put(parsedMessage.messageId, parsedMessage.message);
                    }

                    pis.end(inMessageToken);
@@ -190,29 +239,60 @@ public class ProtoLogViewerConfigReader {
            while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                if (pis.getFieldNumber() == (int) GROUPS) {
                    final long inMessageToken = pis.start(GROUPS);
                    ParsedGroup parsedGroup = readGroup(pis);
                    if (Objects.equals(parsedGroup.groupName, group)) {
                        return parsedGroup.groupId;
                    }

                    long groupId = 0;
                    String groupName = null;
                    pis.end(inMessageToken);
                }
            }
        }

        throw new RuntimeException("Group " + group + " not found in viewer config");
    }

    private static class ParsedMessage {
        long messageId = 0;
        String message = null;
        int groupId = 0;
    }

    private static ParsedMessage readMessage(ProtoInputStream pis) throws IOException {
        final ParsedMessage result = new ParsedMessage();
        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (pis.getFieldNumber()) {
                            case (int) ID:
                                groupId = pis.readInt(ID);
                case (int) MESSAGE_ID:
                    result.messageId = pis.readLong(MESSAGE_ID);
                    break;
                            case (int) NAME:
                                groupName = pis.readString(NAME);
                case (int) MESSAGE:
                    result.message = pis.readString(MESSAGE);
                    break;
                case (int) GROUP_ID:
                    result.groupId = pis.readInt(GROUP_ID);
                    break;
            }
        }

                    if (Objects.equals(groupName, group)) {
                        return groupId;
        return result;
    }

                    pis.end(inMessageToken);
    private static class ParsedGroup {
        long groupId = 0;
        String groupName = null;
    }

    private static ParsedGroup readGroup(ProtoInputStream pis) throws IOException {
        final ParsedGroup result = new ParsedGroup();
        while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (pis.getFieldNumber()) {
                case (int) ID:
                    result.groupId = pis.readInt(ID);
                    break;
                case (int) NAME:
                    result.groupName = pis.readString(NAME);
                    break;
            }
        }

        throw new RuntimeException("Group " + group + " not found in viewer config");
        return result;
    }
}
+17 −0
Original line number Diff line number Diff line
@@ -163,4 +163,21 @@ public class ProtoLogViewerConfigReaderTest {
        Truth.assertThat(mConfig.messageHashIsAvailableInFile(5)).isTrue();
        Truth.assertThat(mConfig.messageHashIsAvailableInFile(6)).isFalse();
    }

    @Test
    public void testGetMessageDataForHashFromFile() throws IOException {
        ProtoLogViewerConfigReader.MessageData data1 =
                mConfig.getMessageDataForHashFromFile(1);
        Truth.assertThat(data1).isNotNull();
        Truth.assertThat(data1.message).isEqualTo("My Test Log Message 1 %b");
        Truth.assertThat(data1.group).isEqualTo(TEST_GROUP_NAME);

        ProtoLogViewerConfigReader.MessageData data4 =
                mConfig.getMessageDataForHashFromFile(4);
        Truth.assertThat(data4).isNotNull();
        Truth.assertThat(data4.message).isEqualTo("My Test Log Message 4 %b");
        Truth.assertThat(data4.group).isEqualTo(OTHER_TEST_GROUP_NAME);

        Truth.assertThat(mConfig.getMessageDataForHashFromFile(6)).isNull();
    }
}