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

Commit b1848e00 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4531101 from 672fbe53 to pi-release

Change-Id: I63aadcc9923b1a03e6da331b1313241cf2e33e27
parents d4dabe9a 672fbe53
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@

using android::hardware::IPCThreadState;
using android::hardware::configureRpcThreadpool;
using android::hardware::handleTransportPoll;
using android::hardware::setupTransportPolling;
using android::hardware::health::V1_0::HealthInfo;
using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
using android::hardware::health::V2_0::IHealth;
@@ -35,21 +37,19 @@ using android::hardware::health::V2_0::implementation::Health;

extern int healthd_main(void);

static int gBinderFd = -1;

static void binder_event(uint32_t /*epevents*/) {
    IPCThreadState::self()->handlePolledCommands();
    if (gBinderFd >= 0) handleTransportPoll(gBinderFd);
}

void healthd_mode_service_2_0_init(struct healthd_config* config) {
    int binderFd;

    LOG(INFO) << LOG_TAG << " Hal is starting up...";

    configureRpcThreadpool(1, false /* callerWillJoin */);
    IPCThreadState::self()->disableBackgroundScheduling(true);
    IPCThreadState::self()->setupPolling(&binderFd);
    gBinderFd = setupTransportPolling();

    if (binderFd >= 0) {
        if (healthd_register_event(binderFd, binder_event))
    if (gBinderFd >= 0) {
        if (healthd_register_event(gBinderFd, binder_event))
            LOG(ERROR) << LOG_TAG << ": Register for binder events failed";
    }

+17 −37
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@

#include "init.h"
#include "persistent_properties.h"
#include "space_tokenizer.h"
#include "util.h"

using android::base::ReadFileToString;
@@ -69,6 +68,7 @@ using android::base::Timer;
using android::base::Trim;
using android::base::WriteStringToFile;
using android::properties::BuildTrie;
using android::properties::ParsePropertyInfoFile;
using android::properties::PropertyInfoAreaFile;
using android::properties::PropertyInfoEntry;

@@ -350,9 +350,11 @@ class SocketConnection {
    ufds[0].events = POLLIN;
    ufds[0].revents = 0;
    while (*timeout_ms > 0) {
      Timer timer;
        auto start_time = std::chrono::steady_clock::now();
        int nr = poll(ufds, 1, *timeout_ms);
      uint64_t millis = timer.duration().count();
        auto now = std::chrono::steady_clock::now();
        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
        uint64_t millis = time_elapsed.count();
        *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;

        if (nr > 0) {
@@ -726,22 +728,6 @@ static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf,
    return 0;
}

Result<PropertyInfoEntry> ParsePropertyInfoLine(const std::string& line) {
    auto tokenizer = SpaceTokenizer(line);

    auto property = tokenizer.GetNext();
    if (property.empty()) return Error() << "Did not find a property entry in '" << line << "'";

    auto context = tokenizer.GetNext();
    if (context.empty()) return Error() << "Did not find a context entry in '" << line << "'";

    // It is not an error to not find these, as older files will not contain them.
    auto exact_match = tokenizer.GetNext();
    auto schema = tokenizer.GetRemaining();

    return {property, context, schema, exact_match == "exact"};
}

bool LoadPropertyInfoFromFile(const std::string& filename,
                              std::vector<PropertyInfoEntry>* property_infos) {
    auto file_contents = std::string();
@@ -750,20 +736,14 @@ bool LoadPropertyInfoFromFile(const std::string& filename,
        return false;
    }

    for (const auto& line : Split(file_contents, "\n")) {
        auto trimmed_line = Trim(line);
        if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
            continue;
    auto errors = std::vector<std::string>{};
    ParsePropertyInfoFile(file_contents, property_infos, &errors);
    // Individual parsing errors are reported but do not cause a failed boot, which is what
    // returning false would do here.
    for (const auto& error : errors) {
        LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
    }

        auto property_info = ParsePropertyInfoLine(line);
        if (!property_info) {
            LOG(ERROR) << "Could not read line from '" << filename << "': " << property_info.error();
            continue;
        }

        property_infos->emplace_back(*property_info);
    }
    return true;
}

+4 −0
Original line number Diff line number Diff line
@@ -19,4 +19,8 @@ cc_library {
        "-fvisibility=hidden",
    ],
    export_include_dirs: ["include"],
    required: [
        "llndk.libraries.txt",
        "vndksp.libraries.txt",
    ],
}
+5 −0
Original line number Diff line number Diff line
@@ -257,6 +257,11 @@ struct android_smpte2086_metadata {
    float minLuminance;
};

struct android_cta861_3_metadata {
    float maxContentLightLevel;
    float maxFrameAverageLightLevel;
};

#ifdef __cplusplus
}
#endif
+84 −56
Original line number Diff line number Diff line
@@ -44,8 +44,6 @@
#define MEMCG_SYSFS_PATH "/dev/memcg/"
#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes"
#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
#define MEMPRESSURE_WATCH_MEDIUM_LEVEL "medium"
#define MEMPRESSURE_WATCH_CRITICAL_LEVEL "critical"
#define ZONEINFO_PATH "/proc/zoneinfo"
#define LINE_MAX 128

@@ -72,13 +70,22 @@ enum lmk_cmd {
static int use_inkernel_interface = 1;
static bool has_inkernel_module;

/* memory pressure level medium event */
static int mpevfd[2];
#define CRITICAL_INDEX 1
#define MEDIUM_INDEX 0
/* memory pressure levels */
enum vmpressure_level {
    VMPRESS_LEVEL_LOW = 0,
    VMPRESS_LEVEL_MEDIUM,
    VMPRESS_LEVEL_CRITICAL,
    VMPRESS_LEVEL_COUNT
};

static const char *level_name[] = {
    "low",
    "medium",
    "critical"
};

static int medium_oomadj;
static int critical_oomadj;
static int level_oomadj[VMPRESS_LEVEL_COUNT];
static int mpevfd[VMPRESS_LEVEL_COUNT];
static bool debug_process_killing;
static bool enable_pressure_upgrade;
static int64_t upgrade_pressure;
@@ -90,8 +97,8 @@ static int ctrl_lfd;
static int ctrl_dfd = -1;
static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */

/* 2 memory pressure levels, 1 ctrl listen socket, 1 ctrl data socket */
#define MAX_EPOLL_EVENTS 4
/* 3 memory pressure levels, 1 ctrl listen socket, 1 ctrl data socket */
#define MAX_EPOLL_EVENTS 5
static int epollfd;
static int maxevents;

@@ -226,7 +233,7 @@ static int pid_remove(int pid) {
    return 0;
}

static void writefilestring(char *path, char *s) {
static void writefilestring(const char *path, char *s) {
    int fd = open(path, O_WRONLY | O_CLOEXEC);
    int len = strlen(s);
    int ret;
@@ -587,7 +594,8 @@ static struct proc *proc_adj_lru(int oomadj) {
}

/* Kill one process specified by procp.  Returns the size of the process killed */
static int kill_one_process(struct proc* procp, int min_score_adj, bool is_critical) {
static int kill_one_process(struct proc* procp, int min_score_adj,
                            enum vmpressure_level level) {
    int pid = procp->pid;
    uid_t uid = procp->uid;
    char *taskname;
@@ -606,12 +614,12 @@ static int kill_one_process(struct proc* procp, int min_score_adj, bool is_criti
        return -1;
    }

    r = kill(pid, SIGKILL);
    ALOGI(
        "Killing '%s' (%d), uid %d, adj %d\n"
        "   to free %ldkB because system is under %s memory pressure oom_adj %d\n",
        taskname, pid, uid, procp->oomadj, tasksize * page_k, is_critical ? "critical" : "medium",
        min_score_adj);
    r = kill(pid, SIGKILL);
        taskname, pid, uid, procp->oomadj, tasksize * page_k,
        level_name[level], min_score_adj);
    pid_remove(pid);

    if (r) {
@@ -626,10 +634,10 @@ static int kill_one_process(struct proc* procp, int min_score_adj, bool is_criti
 * Find a process to kill based on the current (possibly estimated) free memory
 * and cached memory sizes.  Returns the size of the killed processes.
 */
static int find_and_kill_process(bool is_critical) {
static int find_and_kill_process(enum vmpressure_level level) {
    int i;
    int killed_size = 0;
    int min_score_adj = is_critical ? critical_oomadj : medium_oomadj;
    int min_score_adj = level_oomadj[level];

    for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
        struct proc *procp;
@@ -638,7 +646,7 @@ retry:
        procp = proc_adj_lru(i);

        if (procp) {
            killed_size = kill_one_process(procp, min_score_adj, is_critical);
            killed_size = kill_one_process(procp, min_score_adj, level);
            if (killed_size < 0) {
                goto retry;
            } else {
@@ -674,14 +682,23 @@ static int64_t get_memory_usage(const char* path) {
    return mem_usage;
}

static void mp_event_common(bool is_critical) {
enum vmpressure_level upgrade_level(enum vmpressure_level level) {
    return (enum vmpressure_level)((level < VMPRESS_LEVEL_CRITICAL) ?
        level + 1 : level);
}

enum vmpressure_level downgrade_level(enum vmpressure_level level) {
    return (enum vmpressure_level)((level > VMPRESS_LEVEL_LOW) ?
        level - 1 : level);
}

static void mp_event_common(enum vmpressure_level level) {
    int ret;
    unsigned long long evcount;
    int index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX;
    int64_t mem_usage, memsw_usage;
    int64_t mem_pressure;

    ret = read(mpevfd[index], &evcount, sizeof(evcount));
    ret = read(mpevfd[level], &evcount, sizeof(evcount));
    if (ret < 0)
        ALOGE("Error reading memory pressure event fd; errno=%d",
              errno);
@@ -689,18 +706,19 @@ static void mp_event_common(bool is_critical) {
    mem_usage = get_memory_usage(MEMCG_MEMORY_USAGE);
    memsw_usage = get_memory_usage(MEMCG_MEMORYSW_USAGE);
    if (memsw_usage < 0 || mem_usage < 0) {
        find_and_kill_process(is_critical);
        return;
        goto do_kill;
    }

    // Calculate percent for swappinness.
    mem_pressure = (mem_usage * 100) / memsw_usage;

    if (enable_pressure_upgrade && !is_critical) {
    if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {
        // We are swapping too much.
        if (mem_pressure < upgrade_pressure) {
            ALOGI("Event upgraded to critical.");
            is_critical = true;
            level = upgrade_level(level);
            if (debug_process_killing) {
                ALOGI("Event upgraded to %s", level_name[level]);
            }
        }
    }

@@ -708,41 +726,51 @@ static void mp_event_common(bool is_critical) {
    // kill any process, since enough memory is available.
    if (mem_pressure > downgrade_pressure) {
        if (debug_process_killing) {
            ALOGI("Ignore %s memory pressure", is_critical ? "critical" : "medium");
            ALOGI("Ignore %s memory pressure", level_name[level]);
        }
        return;
    } else if (is_critical && mem_pressure > upgrade_pressure) {
    } else if (level == VMPRESS_LEVEL_CRITICAL &&
               mem_pressure > upgrade_pressure) {
        if (debug_process_killing) {
            ALOGI("Downgrade critical memory pressure");
        }
        // Downgrade event to medium, since enough memory available.
        is_critical = false;
        // Downgrade event, since enough memory available.
        level = downgrade_level(level);
    }

    if (find_and_kill_process(is_critical) == 0) {
do_kill:
    if (find_and_kill_process(level) == 0) {
        if (debug_process_killing) {
            ALOGI("Nothing to kill");
        }
    }
}

static void mp_event(uint32_t events __unused) {
    mp_event_common(false);
static void mp_event_low(uint32_t events __unused) {
    mp_event_common(VMPRESS_LEVEL_LOW);
}

static void mp_event_medium(uint32_t events __unused) {
    mp_event_common(VMPRESS_LEVEL_MEDIUM);
}

static void mp_event_critical(uint32_t events __unused) {
    mp_event_common(true);
    mp_event_common(VMPRESS_LEVEL_CRITICAL);
}

static int init_mp_common(char *levelstr, void *event_handler, bool is_critical)
{
static bool init_mp_common(void *event_handler, enum vmpressure_level level) {
    int mpfd;
    int evfd;
    int evctlfd;
    char buf[256];
    struct epoll_event epev;
    int ret;
    int mpevfd_index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX;
    const char *levelstr = level_name[level];

    if (level_oomadj[level] > OOM_SCORE_ADJ_MAX) {
        ALOGI("%s pressure events are disabled", levelstr);
        return true;
    }

    mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
    if (mpfd < 0) {
@@ -783,8 +811,8 @@ static int init_mp_common(char *levelstr, void *event_handler, bool is_critical)
        goto err;
    }
    maxevents++;
    mpevfd[mpevfd_index] = evfd;
    return 0;
    mpevfd[level] = evfd;
    return true;

err:
    close(evfd);
@@ -793,17 +821,7 @@ err_eventfd:
err_open_evctlfd:
    close(mpfd);
err_open_mpfd:
    return -1;
}

static int init_mp_medium()
{
    return init_mp_common(MEMPRESSURE_WATCH_MEDIUM_LEVEL, (void *)&mp_event, false);
}

static int init_mp_critical()
{
    return init_mp_common(MEMPRESSURE_WATCH_CRITICAL_LEVEL, (void *)&mp_event_critical, true);
    return false;
}

static int init(void) {
@@ -848,10 +866,13 @@ static int init(void) {
    if (use_inkernel_interface) {
        ALOGI("Using in-kernel low memory killer interface");
    } else {
        ret = init_mp_medium();
        ret |= init_mp_critical();
        if (ret)
        if (!init_mp_common((void *)&mp_event_low, VMPRESS_LEVEL_LOW) ||
            !init_mp_common((void *)&mp_event_medium, VMPRESS_LEVEL_MEDIUM) ||
            !init_mp_common((void *)&mp_event_critical,
                            VMPRESS_LEVEL_CRITICAL)) {
            ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer");
            return -1;
        }
    }

    for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
@@ -892,15 +913,22 @@ int main(int argc __unused, char **argv __unused) {
            .sched_priority = 1,
    };

    medium_oomadj = property_get_int32("ro.lmk.medium", 800);
    critical_oomadj = property_get_int32("ro.lmk.critical", 0);
    /* By default disable low level vmpressure events */
    level_oomadj[VMPRESS_LEVEL_LOW] =
        property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);
    level_oomadj[VMPRESS_LEVEL_MEDIUM] =
        property_get_int32("ro.lmk.medium", 800);
    level_oomadj[VMPRESS_LEVEL_CRITICAL] =
        property_get_int32("ro.lmk.critical", 0);
    debug_process_killing = property_get_bool("ro.lmk.debug", false);
    enable_pressure_upgrade = property_get_bool("ro.lmk.critical_upgrade", false);
    upgrade_pressure = (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 50);
    downgrade_pressure = (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 60);
    is_go_device = property_get_bool("ro.config.low_ram", false);

    mlockall(MCL_FUTURE);
    if (mlockall(MCL_CURRENT | MCL_FUTURE))
        ALOGW("mlockall failed: errno=%d", errno);

    sched_setscheduler(0, SCHED_FIFO, &param);
    if (!init())
        mainloop();
Loading