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

Commit 238e9093 authored by Deyao Ren's avatar Deyao Ren
Browse files

Remove and add service and action during apex load and unload

Bug: 232114573
Test: atest CtsInitTestCases ApexTestCases
Change-Id: I1f91ada1d44ac2380e2faf8fc25e0a521cc1a826
parent 07595e19
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ init_common_sources = [
    "util.cpp",
]
init_device_sources = [
    "apex_init_util.cpp",
    "block_dev_initializer.cpp",
    "bootchart.cpp",
    "builtins.cpp",
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class ActionManager {
    bool HasMoreCommands() const;
    void DumpState() const;
    void ClearQueue();
    auto size() const { return actions_.size(); }

  private:
    ActionManager(ActionManager const&) = delete;
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 "apex_init_util.h"

#include <glob.h>

#include <map>
#include <vector>

#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/properties.h>
#include <android-base/strings.h>

#include "action_manager.h"
#include "init.h"
#include "parser.h"
#include "service_list.h"
#include "util.h"

namespace android {
namespace init {

static Result<std::vector<std::string>> CollectApexConfigs(const std::string& apex_name) {
    glob_t glob_result;
    std::string glob_pattern = apex_name.empty() ?
            "/apex/*/etc/*rc" : "/apex/" + apex_name + "/etc/*rc";

    const int ret = glob(glob_pattern.c_str(), GLOB_MARK, nullptr, &glob_result);
    if (ret != 0 && ret != GLOB_NOMATCH) {
        globfree(&glob_result);
        return Error() << "Glob pattern '" << glob_pattern << "' failed";
    }
    std::vector<std::string> configs;
    for (size_t i = 0; i < glob_result.gl_pathc; i++) {
        std::string path = glob_result.gl_pathv[i];
        // Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
        // /apex/<name> paths, so unless we filter them out, we will parse the
        // same file twice.
        std::vector<std::string> paths = android::base::Split(path, "/");
        if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) {
            continue;
        }
        // Filter directories
        if (path.back() == '/') {
            continue;
        }
        configs.push_back(path);
    }
    globfree(&glob_result);
    return configs;
}

static Result<void> ParseConfigs(const std::vector<std::string>& configs) {
    Parser parser = CreateApexConfigParser(ActionManager::GetInstance(),
                     ServiceList::GetInstance());
    bool success = true;
    for (const auto& c : configs) {
        success &= parser.ParseConfigFile(c);
    }

    if (success) {
        return {};
    } else {
        return Error() << "Unable to parse apex configs";
    }
}

Result<void> ParseApexConfigs(const std::string& apex_name) {
    Result<std::vector<std::string>> configs = CollectApexConfigs(apex_name);
    if (!configs.ok()) {
        return configs.error();
    }

    if (configs.value().empty()) {
        return {};
    }

    auto filtered_configs = FilterVersionedConfigs(configs.value(),
                                    android::base::GetIntProperty("ro.build.version.sdk", INT_MAX));
    return ParseConfigs(filtered_configs);
}

}  // namespace init
}  // namespace android

init/apex_init_util.h

0 → 100644
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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

#include <string>
#include <vector>

#include "result.h"

namespace android {
namespace init {

// Parse all config files for a given apex.
// If apex name is empty(""), config files for all apexes will be parsed.
Result<void> ParseApexConfigs(const std::string& apex_name);

}  // namespace init
}  // namespace android
+3 −43
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#include <system/thread_defs.h>

#include "action_manager.h"
#include "apex_init_util.h"
#include "bootchart.h"
#include "builtin_arguments.h"
#include "fscrypt_init_extensions.h"
@@ -1279,48 +1280,6 @@ static Result<void> do_update_linker_config(const BuiltinArguments&) {
    return GenerateLinkerConfiguration();
}

static Result<void> parse_apex_configs() {
    glob_t glob_result;
    static constexpr char glob_pattern[] = "/apex/*/etc/*rc";
    const int ret = glob(glob_pattern, GLOB_MARK, nullptr, &glob_result);
    if (ret != 0 && ret != GLOB_NOMATCH) {
        globfree(&glob_result);
        return Error() << "glob pattern '" << glob_pattern << "' failed";
    }
    std::vector<std::string> configs;
    Parser parser =
            CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
    for (size_t i = 0; i < glob_result.gl_pathc; i++) {
        std::string path = glob_result.gl_pathv[i];
        // Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
        // /apex/<name> paths, so unless we filter them out, we will parse the
        // same file twice.
        std::vector<std::string> paths = android::base::Split(path, "/");
        if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) {
            continue;
        }
        // Filter directories
        if (path.back() == '/') {
            continue;
        }
        configs.push_back(path);
    }
    globfree(&glob_result);

    int active_sdk = android::base::GetIntProperty("ro.build.version.sdk", INT_MAX);

    bool success = true;
    for (const auto& c : parser.FilterVersionedConfigs(configs, active_sdk)) {
        success &= parser.ParseConfigFile(c);
    }
    ServiceList::GetInstance().MarkServicesUpdate();
    if (success) {
        return {};
    } else {
        return Error() << "Could not parse apex configs";
    }
}

/*
 * Creates a directory under /data/misc/apexdata/ for each APEX.
 */
@@ -1351,7 +1310,8 @@ static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
    if (!create_dirs.ok()) {
        return create_dirs.error();
    }
    auto parse_configs = parse_apex_configs();
    auto parse_configs = ParseApexConfigs(/*apex_name=*/"");
    ServiceList::GetInstance().MarkServicesUpdate();
    if (!parse_configs.ok()) {
        return parse_configs.error();
    }
Loading