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

Commit eb6a9ceb authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "tej_pull_lazy"

* changes:
  Create libstatspull_lazy
  Create libstatssocket_lazy
parents 102f7e4d c9c6cc04
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
joeo@google.com
jeffreyhuang@google.com
jtnguyen@google.com
muhammadq@google.com
ruchirr@google.com
sharaienko@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
+44 −0
Original line number Diff line number Diff line
// Lazy loading version of libstatspull that can be used by code
// that is running before the statsd APEX is mounted and
// libstatspull.so is available.
cc_library_static {
    name: "libstatspull_lazy",
    header_libs: [
        "libstatspull_headers",
        "libstatssocket_headers",
    ],
    export_header_lib_headers: [
        "libstatspull_headers",
    ],
    apex_available: ["//apex_available:platform"],
    srcs: ["libstatspull_lazy.cpp"],
}

cc_test {
    name: "libstatspull_lazy_test",
    srcs: [
        "tests/libstatspull_lazy_test.cpp",
    ],
    static_libs: [
        "libstatspull_lazy",
        "libstatssocket_lazy",
    ],
    shared_libs: ["liblog"],
    cflags: [
        "-Wall",
        "-Werror",
    ],
    test_suites: ["device-tests", "mts-statsd"],
    test_config: "libstatspull_lazy_test.xml",
    // TODO(b/153588990): Remove when the build system properly separates.
    // 32bit and 64bit architectures.
    compile_multilib: "both",
    multilib: {
        lib64: {
            suffix: "64",
        },
        lib32: {
            suffix: "32",
        },
    },
}
 No newline at end of file
+7 −0
Original line number Diff line number Diff line
{
  "presubmit" : [
    {
      "name" : "libstatspull_lazy_test"
    }
  ]
}
 No newline at end of file
+190 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 "libstatspull_lazy.h"

#include <mutex>

#include <dlfcn.h>
#include <stdatomic.h>

#include "log/log.h"

#include "stats_pull_atom_callback.h"

// This file provides a lazy interface to libstatspull.so to address early boot dependencies.
// Specifically bootanimation, surfaceflinger, and lmkd run before the statsd APEX is loaded and
// libstatspull.so is in the statsd APEX.

// Method pointers to libstatspull methods are held in an array which simplifies checking
// all pointers are initialized.
enum MethodIndex {
    // PullAtomMetadata APIs in stats_pull_atom_callback.h.
    k_AStatsManager_PullAtomMetadata_obtain,
    k_AStatsManager_PullAtomMetadata_release,
    k_AStatsManager_PullAtomMetadata_setCoolDownMillis,
    k_AStatsManager_PullAtomMetadata_getCoolDownMillis,
    k_AStatsManager_PullAtomMetadata_setTimeoutMillis,
    k_AStatsManager_PullAtomMetadata_getTimeoutMillis,
    k_AStatsManager_PullAtomMetadata_setAdditiveFields,
    k_AStatsManager_PullAtomMetadata_getNumAdditiveFields,
    k_AStatsManager_PullAtomMetadata_getAdditiveFields,

    // AStatsEventList APIs in stats_pull_atom_callback.h
    k_AStatsEventList_addStatsEvent,

    // PullAtomCallback APIs in stats_pull_atom_callback.h
    k_AStatsManager_setPullAtomCallback,
    k_AStatsManager_clearPullAtomCallback,

    // Marker for count of methods
    k_MethodCount
};

// Table of methods pointers in libstatspull APIs.
static void* g_Methods[k_MethodCount];

//
// Libstatspull lazy loading.
//

static atomic_bool gPreventLibstatspullLoading = false;  // Allows tests to block loading.

void PreventLibstatspullLazyLoadingForTests() {
    gPreventLibstatspullLoading.store(true);
}

static void* LoadLibstatspull(int dlopen_flags) {
    if (gPreventLibstatspullLoading.load()) {
        return nullptr;
    }
    return dlopen("libstatspull.so", dlopen_flags);
}

//
// Initialization and symbol binding.

static void BindSymbol(void* handle, const char* name, enum MethodIndex index) {
    void* symbol = dlsym(handle, name);
    LOG_ALWAYS_FATAL_IF(symbol == nullptr, "Failed to find symbol '%s' in libstatspull.so: %s",
                        name, dlerror());
    g_Methods[index] = symbol;
}

static void InitializeOnce() {
    void* handle = LoadLibstatspull(RTLD_NOW);
    LOG_ALWAYS_FATAL_IF(handle == nullptr, "Failed to load libstatspull.so: %s", dlerror());

#undef BIND_SYMBOL
#define BIND_SYMBOL(name) BindSymbol(handle, #name, k_##name);
    // PullAtomMetadata APIs in stats_pull_atom_callback.h.
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_obtain);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_release);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setCoolDownMillis);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getCoolDownMillis);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setTimeoutMillis);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getTimeoutMillis);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setAdditiveFields);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getNumAdditiveFields);
    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getAdditiveFields);

    // AStatsEventList APIs in stats_pull_atom_callback.h
    BIND_SYMBOL(AStatsEventList_addStatsEvent);

    // PullAtomCallback APIs in stats_pull_atom_callback.h
    BIND_SYMBOL(AStatsManager_setPullAtomCallback);
    BIND_SYMBOL(AStatsManager_clearPullAtomCallback);

#undef BIND_SYMBOL

    // Check every symbol is bound.
    for (int i = 0; i < k_MethodCount; ++i) {
        LOG_ALWAYS_FATAL_IF(g_Methods[i] == nullptr,
                            "Uninitialized method in libstatspull_lazy at index: %d", i);
    }
}

static void EnsureInitialized() {
    static std::once_flag initialize_flag;
    std::call_once(initialize_flag, InitializeOnce);
}

#define INVOKE_METHOD(name, args...)                            \
    do {                                                        \
        EnsureInitialized();                                    \
        void* method = g_Methods[k_##name];                     \
        return reinterpret_cast<decltype(&name)>(method)(args); \
    } while (0)

//
// Forwarding for methods in stats_pull_atom_callback.h.
//

AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain() {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_obtain);
}

void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_release, metadata);
}

void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
                                                      int64_t cool_down_millis) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setCoolDownMillis, metadata, cool_down_millis);
}

int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getCoolDownMillis, metadata);
}

void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
                                                     int64_t timeout_millis) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setTimeoutMillis, metadata, timeout_millis);
}

int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getTimeoutMillis, metadata);
}

void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
                                                      int32_t* additive_fields,
                                                      int32_t num_fields) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setAdditiveFields, metadata, additive_fields,
                  num_fields);
}

int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields(
        AStatsManager_PullAtomMetadata* metadata) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getNumAdditiveFields, metadata);
}

void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
                                                      int32_t* fields) {
    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getAdditiveFields, metadata, fields);
}

AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data) {
    INVOKE_METHOD(AStatsEventList_addStatsEvent, pull_data);
}

void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
                                       AStatsManager_PullAtomCallback callback, void* cookie) {
    INVOKE_METHOD(AStatsManager_setPullAtomCallback, atom_tag, metadata, callback, cookie);
}

void AStatsManager_clearPullAtomCallback(int32_t atom_tag) {
    INVOKE_METHOD(AStatsManager_clearPullAtomCallback, atom_tag);
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.
 */

#pragma once

extern "C" void PreventLibstatspullLazyLoadingForTests();
 No newline at end of file
Loading