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

Commit 001c87c3 authored by William Luh's avatar William Luh Committed by Gerrit Code Review
Browse files

Merge "Add macro to call event logger for errors."

parents 96ac40af 964428c0
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -563,6 +563,12 @@ typedef enum {
#define android_btWriteLog(tag, type, payload, len) \
    __android_log_btwrite(tag, type, payload, len)

#define android_errorWriteLog(tag, subTag) \
    __android_log_error_write(tag, subTag, -1, NULL, 0)

#define android_errorWriteWithInfoLog(tag, subTag, uid, data, dataLen) \
    __android_log_error_write(tag, subTag, uid, data, dataLen)

/*
 *    IF_ALOG uses android_testLog, but IF_ALOG can be overridden.
 *    android_testLog will remain constant in its purpose as a wrapper
@@ -612,6 +618,9 @@ typedef enum log_id {
 */
int __android_log_is_loggable(int prio, const char *tag, int def);

int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
                              uint32_t dataLen);

/*
 * Send a simple string to the log.
 */
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ include $(CLEAR_VARS)
# so make sure we do not regret hard-coding it as follows:
liblog_cflags := -DLIBLOG_LOG_TAG=1005

liblog_sources := logd_write.c
liblog_sources := logd_write.c log_event_write.c

# some files must not be compiled when building against Mingw
# they correspond to features not used by our host development tools
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

#include <errno.h>
#include <string.h>

#include <log/log.h>
#include <log/logger.h>

#define MAX_EVENT_PAYLOAD 512
#define MAX_SUBTAG_LEN 32

static inline void copy4LE(uint8_t *buf, size_t pos, int val)
{
    buf[pos] = val & 0xFF;
    buf[pos+1] = (val >> 8) & 0xFF;
    buf[pos+2] = (val >> 16) & 0xFF;
    buf[pos+3] = (val >> 24) & 0xFF;
}

int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
                              uint32_t dataLen)
{
    uint8_t buf[MAX_EVENT_PAYLOAD];
    size_t pos = 0;
    uint32_t subTagLen = 0;
    uint32_t roomLeftForData = 0;

    if ((subTag == NULL) || ((data == NULL) && (dataLen != 0))) return -EINVAL;

    subTagLen = strlen(subTag);

    // Truncate subtags that are too long.
    subTagLen = subTagLen > MAX_SUBTAG_LEN ? MAX_SUBTAG_LEN : subTagLen;

    // Truncate dataLen if it is too long.
    roomLeftForData = MAX_EVENT_PAYLOAD -
            (1 + // EVENT_TYPE_LIST
             1 + // Number of elements in list
             1 + // EVENT_TYPE_STRING
             sizeof(subTagLen) +
             subTagLen +
             1 + // EVENT_TYPE_INT
             sizeof(uid) +
             1 + // EVENT_TYPE_STRING
             sizeof(dataLen));
    dataLen = dataLen > roomLeftForData ? roomLeftForData : dataLen;

    buf[pos++] = EVENT_TYPE_LIST;
    buf[pos++] = 3; // Number of elements in the list (subTag, uid, data)

    // Write sub tag.
    buf[pos++] = EVENT_TYPE_STRING;
    copy4LE(buf, pos, subTagLen);
    pos += 4;
    memcpy(&buf[pos], subTag, subTagLen);
    pos += subTagLen;

    // Write UID.
    buf[pos++] = EVENT_TYPE_INT;
    copy4LE(buf, pos, uid);
    pos += 4;

    // Write data.
    buf[pos++] = EVENT_TYPE_STRING;
    copy4LE(buf, pos, dataLen);
    pos += 4;
    if (dataLen != 0)
    {
        memcpy(&buf[pos], data, dataLen);
        pos += dataLen;
    }

    return __android_log_bwrite(tag, buf, pos);
}
+396 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <string.h>

#include <cutils/properties.h>
#include <gtest/gtest.h>
@@ -876,3 +877,398 @@ TEST(liblog, is_loggable) {
    property_set(key, hold[2]);
    property_set(key + base_offset, hold[3]);
}

static inline int32_t get4LE(const char* src)
{
    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}

TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
    const int TAG = 123456781;
    const char SUBTAG[] = "test-subtag";
    const int UID = -1;
    const int DATA_LEN = 200;
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_LT(0, android_errorWriteWithInfoLog(
            TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag != TAG) {
            continue;
        }

        // List type
        ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
        eventData++;

        // Number of elements in list
        ASSERT_EQ(3, eventData[0]);
        eventData++;

        // Element #1: string type for subtag
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        ASSERT_EQ((int) strlen(SUBTAG), get4LE(eventData));
        eventData +=4;

        if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
            continue;
        }
        eventData += strlen(SUBTAG);

        // Element #2: int type for uid
        ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
        eventData++;

        ASSERT_EQ(UID, get4LE(eventData));
        eventData += 4;

        // Element #3: string type for data
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        ASSERT_EQ(DATA_LEN, get4LE(eventData));
        eventData += 4;

        if (memcmp(max_payload_buf, eventData, DATA_LEN)) {
            continue;
        }

        ++count;
    }

    EXPECT_EQ(1, count);

    android_logger_list_close(logger_list);
}

TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
    const int TAG = 123456782;
    const char SUBTAG[] = "test-subtag";
    const int UID = -1;
    const int DATA_LEN = sizeof(max_payload_buf);
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_LT(0, android_errorWriteWithInfoLog(
            TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();
        char *original = eventData;

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag != TAG) {
            continue;
        }

        // List type
        ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
        eventData++;

        // Number of elements in list
        ASSERT_EQ(3, eventData[0]);
        eventData++;

        // Element #1: string type for subtag
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        ASSERT_EQ((int) strlen(SUBTAG), get4LE(eventData));
        eventData +=4;

        if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
            continue;
        }
        eventData += strlen(SUBTAG);

        // Element #2: int type for uid
        ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
        eventData++;

        ASSERT_EQ(UID, get4LE(eventData));
        eventData += 4;

        // Element #3: string type for data
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        size_t dataLen = get4LE(eventData);
        eventData += 4;

        if (memcmp(max_payload_buf, eventData, dataLen)) {
            continue;
        }
        eventData += dataLen;

        // 4 bytes for the tag, and 512 bytes for the log since the max_payload_buf should be
        // truncated.
        ASSERT_EQ(4 + 512, eventData - original);

        ++count;
    }

    EXPECT_EQ(1, count);

    android_logger_list_close(logger_list);
}

TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
    const int TAG = 123456783;
    const char SUBTAG[] = "test-subtag";
    const int UID = -1;
    const int DATA_LEN = 200;
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_GT(0, android_errorWriteWithInfoLog(
            TAG, SUBTAG, UID, NULL, DATA_LEN));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag == TAG) {
            // This tag should not have been written because the data was null
            count++;
            break;
        }
    }

    EXPECT_EQ(0, count);

    android_logger_list_close(logger_list);
}

TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
    const int TAG = 123456784;
    const char SUBTAG[] = "abcdefghijklmnopqrstuvwxyz now i know my abc";
    const int UID = -1;
    const int DATA_LEN = 200;
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_LT(0, android_errorWriteWithInfoLog(
            TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag != TAG) {
            continue;
        }

        // List type
        ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
        eventData++;

        // Number of elements in list
        ASSERT_EQ(3, eventData[0]);
        eventData++;

        // Element #1: string type for subtag
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        // The subtag is longer than 32 and should be truncated to that.
        ASSERT_EQ(32, get4LE(eventData));
        eventData +=4;

        if (memcmp(SUBTAG, eventData, 32)) {
            continue;
        }
        eventData += 32;

        // Element #2: int type for uid
        ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
        eventData++;

        ASSERT_EQ(UID, get4LE(eventData));
        eventData += 4;

        // Element #3: string type for data
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        ASSERT_EQ(DATA_LEN, get4LE(eventData));
        eventData += 4;

        if (memcmp(max_payload_buf, eventData, DATA_LEN)) {
            continue;
        }

        ++count;
    }

    EXPECT_EQ(1, count);

    android_logger_list_close(logger_list);
}

TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
    const int TAG = 123456785;
    const char SUBTAG[] = "test-subtag";
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_LT(0, android_errorWriteLog(TAG, SUBTAG));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag != TAG) {
            continue;
        }

        // List type
        ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
        eventData++;

        // Number of elements in list
        ASSERT_EQ(3, eventData[0]);
        eventData++;

        // Element #1: string type for subtag
        ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
        eventData++;

        ASSERT_EQ((int) strlen(SUBTAG), get4LE(eventData));
        eventData +=4;

        if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
            continue;
        }
        ++count;
    }

    EXPECT_EQ(1, count);

    android_logger_list_close(logger_list);
}

TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
    const int TAG = 123456786;
    struct logger_list *logger_list;

    pid_t pid = getpid();

    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));

    ASSERT_GT(0, android_errorWriteLog(TAG, NULL));

    sleep(2);

    int count = 0;

    for (;;) {
        log_msg log_msg;
        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
            break;
        }

        char *eventData = log_msg.msg();

        // Tag
        int tag = get4LE(eventData);
        eventData += 4;

        if (tag == TAG) {
            // This tag should not have been written because the data was null
            count++;
            break;
        }
    }

    EXPECT_EQ(0, count);

    android_logger_list_close(logger_list);
}