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

Commit 850d06e1 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

liblog: Add android_set_log_frontend

android_set_log_frontend allows one to select LOGGER_DEFAULT,
LOGGER_LOGD or LOGGER_NULL, the latter allows a runtime mechanism to
turn logging on or off.  LOGGER_DEFAULT is LOGGER_LOGD.

Test: gTest liblog-unit-tests notably liblog.android_set_log_frontend
      and liblog-benchmarks before and after.
Bug: 27405083
Change-Id: I365dbee9f7d83112da0ef8d1cace748d247773c8
parent ec5d6cb8
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -108,6 +108,11 @@ SYNOPSIS

       int android_log_destroy(android_log_context *ctx)

       #include <log/log_frontend.h>

       int android_set_log_frontend(int frontend_flag)
       int android_get_log_frontend()

       Link with -llog

DESCRIPTION
@@ -162,6 +167,12 @@ DESCRIPTION
       when  opening  the  sub-log.    It  is  recommended  to  open  the  log
       ANDROID_LOG_RDONLY in these cases.

       android_set_log_frontend() selects frontend filters. Argument is either
       LOGGER_DEFAULT,  LOGGER_LOGD  or  LOGGER_NULL.  The  latter  drops  all
       content   on   the   floor.     Both   android_set_log_frontend()   and
       android_get_log_frontend()  return  the  current frontend mask,   or  a
       negative errno for any problems.

ERRORS
       If messages fail, a negative error code will be returned to the caller.

@@ -194,4 +205,4 @@ SEE ALSO



                                  17 Oct 2016                        LIBLOG(3)
                                  08 Feb 2017                        LIBLOG(3)
+33 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2017, The Android Open Source Project
**
** This file is dual licensed.  It may be redistributed and/or modified
** under the terms of the Apache 2.0 License OR version 2 of the GNU
** General Public License.
*/

#ifndef _LIBS_LOG_FRONTEND_H
#define _LIBS_LOG_FRONTEND_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Logging frontends, bit mask to select features. Function returns selection.
 */
#define LOGGER_DEFAULT 0x0
#define LOGGER_LOGD    0x1
#define LOGGER_KERNEL  0x2 /* Reserved/Deprecated */
#define LOGGER_NULL    0x4 /* Does not release resources of other selections */

/* Both return the selected frontend flag mask, or negative errno */
int android_set_log_frontend(int frontend_flag);
int android_get_log_frontend();

#ifdef __cplusplus
}
#endif

#endif /* _LIBS_LOG_FRONTEND_H */
+65 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#endif

#include <log/event_tag_map.h>
#include <log/log_frontend.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>

@@ -618,3 +619,67 @@ LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,

    return write_to_log(LOG_ID_SECURITY, vec, 4);
}

static int __write_to_log_null(log_id_t log_id, struct iovec* vec, size_t nr)
{
    size_t len, i;

    if ((log_id < LOG_ID_MIN) || (log_id >= LOG_ID_MAX)) {
        return -EINVAL;
    }

    for (len = i = 0; i < nr; ++i) {
        len += vec[i].iov_len;
    }
    if (!len) {
        return -EINVAL;
    }
    return len;
}

/* Following functions need access to our internal write_to_log status */

LIBLOG_ABI_PUBLIC int android_set_log_frontend(int frontend_flag)
{
    if (frontend_flag < 0) {
        return -EINVAL;
    }

    __android_log_lock();

    if (frontend_flag & LOGGER_NULL) {
        write_to_log = __write_to_log_null;

        __android_log_unlock();

        return LOGGER_NULL;
    }

    /* Anything else, act as if LOGGER_DEFAULT */

    /* generically we only expect these two values for write_to_log */
    if ((write_to_log != __write_to_log_init) &&
        (write_to_log != __write_to_log_daemon)) {
        write_to_log = __write_to_log_init;
    }

    __android_log_unlock();

    return LOGGER_DEFAULT;
}

LIBLOG_ABI_PUBLIC int android_get_log_frontend()
{
    int ret = LOGGER_DEFAULT;

    __android_log_lock();
    if (write_to_log == __write_to_log_null) {
        ret = LOGGER_NULL;
    } else if ((write_to_log != __write_to_log_init) &&
               (write_to_log != __write_to_log_daemon)) {
        ret = -EINVAL;
    }
    __android_log_unlock();

    return ret;
}
+70 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <gtest/gtest.h>
#include <log/logprint.h>
#include <log/log_event_list.h>
#include <log/log_frontend.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>

@@ -225,6 +226,75 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) {
#endif
}

// This test makes little sense standalone, and requires the tests ahead
// and behind us, to make us whole.  We could incorporate a prefix and
// suffix test to make this standalone, but opted to not complicate this.
TEST(liblog, android_set_log_frontend) {
#ifdef __ANDROID__
    int logger = android_get_log_frontend();
    EXPECT_NE(LOGGER_NULL, logger);

    EXPECT_EQ(LOGGER_NULL, android_set_log_frontend(LOGGER_NULL));
    EXPECT_EQ(LOGGER_NULL, android_get_log_frontend());

    pid_t pid = getpid();

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

    log_time ts(CLOCK_MONOTONIC);
    ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));

    usleep(1000000);

    int count = 0;

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

        ASSERT_EQ(log_msg.entry.pid, pid);

        if ((log_msg.entry.len != sizeof(android_log_event_long_t))
         || (log_msg.id() != LOG_ID_EVENTS)) {
            continue;
        }

        android_log_event_long_t* eventData;
        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());

        if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
            continue;
        }

        log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
        if (ts == tx) {
            ++count;
        }
    }

    android_logger_list_close(logger_list);

    EXPECT_EQ(logger, android_set_log_frontend(logger));
    EXPECT_EQ(logger, android_get_log_frontend());

    // False negative if liblog.__android_log_btwrite__android_logger_list_read
    // fails above, so we will likely succeed. But we will have so many
    // failures elsewhere that it is probably not worthwhile for us to
    // highlight yet another disappointment.
    EXPECT_EQ(0, count);
    // We also expect failures in the following tests if the set does not
    // react in an appropriate manner internally, yet passes, so we depend
    // on this test being in the middle of a series of tests performed in
    // the same process.
#else
    GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}

#ifdef __ANDROID__
static inline int32_t get4LE(const char* src)
{