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

Commit 270dd6a1 authored by Pawin Vongmasa's avatar Pawin Vongmasa
Browse files

Make mediaserver listen to Codec2 services' deaths

Test: Kill media.extractor or mediaswcodec and observe logcat

Bug: 130071409

Change-Id: Ie785642da99dfe4ff13e78d878817dae3de9f34a
parent 8263e351
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ cc_library {
    export_shared_lib_headers: [
        "android.hardware.media.c2@1.0",
        "libcodec2",
        "libcodec2_vndk",
        "libhidlbase",
        "libstagefright_bufferpool@2.0",
        "libui",
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ cc_library {
    export_shared_lib_headers: [
        "libcodec2",
        "libcodec2_hidl_client@1.0",
        "libcodec2_vndk",
    ],

}
+97 −91
Original line number Diff line number Diff line
@@ -75,82 +75,11 @@ namespace /* unnamed */ {
// c2_status_t value that corresponds to hwbinder transaction failure.
constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;

// Returns the list of IComponentStore service names that are available on the
// device. This list is specified at the build time in manifest files.
// Note: A software service will have "_software" as a suffix.
std::vector<std::string> const& getServiceNames() {
    static std::vector<std::string> sServiceNames{[]() {
        using ::android::hardware::media::c2::V1_0::IComponentStore;
        using ::android::hidl::manager::V1_2::IServiceManager;

        while (true) {
            sp<IServiceManager> serviceManager = IServiceManager::getService();
            CHECK(serviceManager) << "Hardware service manager is not running.";

            // There are three categories of services based on names.
            std::vector<std::string> defaultNames; // Prefixed with "default"
            std::vector<std::string> vendorNames;  // Prefixed with "vendor"
            std::vector<std::string> otherNames;   // Others
            Return<void> transResult;
            transResult = serviceManager->listManifestByInterface(
                    IComponentStore::descriptor,
                    [&defaultNames, &vendorNames, &otherNames](
                            hidl_vec<hidl_string> const& instanceNames) {
                        for (hidl_string const& instanceName : instanceNames) {
                            char const* name = instanceName.c_str();
                            if (strncmp(name, "default", 7) == 0) {
                                defaultNames.emplace_back(name);
                            } else if (strncmp(name, "vendor", 6) == 0) {
                                vendorNames.emplace_back(name);
                            } else {
                                otherNames.emplace_back(name);
                            }
                        }
                    });
            if (transResult.isOk()) {
                // Sort service names in each category.
                std::sort(defaultNames.begin(), defaultNames.end());
                std::sort(vendorNames.begin(), vendorNames.end());
                std::sort(otherNames.begin(), otherNames.end());

                // Concatenate the three lists in this order: default, vendor,
                // other.
                std::vector<std::string>& names = defaultNames;
                names.reserve(names.size() + vendorNames.size() + otherNames.size());
                names.insert(names.end(),
                             std::make_move_iterator(vendorNames.begin()),
                             std::make_move_iterator(vendorNames.end()));
                names.insert(names.end(),
                             std::make_move_iterator(otherNames.begin()),
                             std::make_move_iterator(otherNames.end()));

                // Summarize to logcat.
                if (names.empty()) {
                    LOG(INFO) << "No Codec2 services declared in the manifest.";
                } else {
                    std::stringstream stringOutput;
                    stringOutput << "Available Codec2 services:";
                    for (std::string const& name : names) {
                        stringOutput << " \"" << name << "\"";
                    }
                    LOG(INFO) << stringOutput.str();
                }

                return names;
            }
            LOG(ERROR) << "Could not retrieve the list of service instances of "
                       << IComponentStore::descriptor
                       << ". Retrying...";
        }
    }()};
    return sServiceNames;
}

// Searches for a name in getServiceNames() and returns the index found. If the
// Searches for a name in GetServiceNames() and returns the index found. If the
// name is not found, the returned index will be equal to
// getServiceNames().size().
// GetServiceNames().size().
size_t getServiceIndex(char const* name) {
    std::vector<std::string> const& names = getServiceNames();
    std::vector<std::string> const& names = Codec2Client::GetServiceNames();
    size_t i = 0;
    for (; i < names.size(); ++i) {
        if (name == names[i]) {
@@ -175,17 +104,14 @@ class Codec2Client::Cache {
    std::vector<C2Component::Traits> mTraits;
    std::once_flag mTraitsInitializationFlag;

    // The index of the service. This is based on getServiceNames().
    // The index of the service. This is based on GetServiceNames().
    size_t mIndex;
    // A "valid" cache object must have its mIndex set with init().
    bool mValid{false};
    // Called by s() exactly once to initialize the cache. The index must be a
    // valid index into the vector returned by getServiceNames(). Calling
    // valid index into the vector returned by GetServiceNames(). Calling
    // init(index) will associate the cache to the service with name
    // getServiceNames()[index].
    // GetServiceNames()[index].
    void init(size_t index) {
        mIndex = index;
        mValid = true;
    }

public:
@@ -195,7 +121,6 @@ public:
    // If the service is unavailable but listed in the manifest, this function
    // will block indefinitely.
    std::shared_ptr<Codec2Client> getClient() {
        CHECK(mValid) << "Uninitialized cache";
        std::scoped_lock lock{mClientMutex};
        if (!mClient) {
            mClient = Codec2Client::_CreateFromIndex(mIndex);
@@ -208,7 +133,6 @@ public:
    //
    // Note: This function is called only by ForAllServices().
    void invalidate() {
        CHECK(mValid) << "Uninitialized cache";
        std::scoped_lock lock{mClientMutex};
        mClient = nullptr;
    }
@@ -216,7 +140,6 @@ public:
    // Returns a list of traits for components supported by the service. This
    // list is cached.
    std::vector<C2Component::Traits> const& getTraits() {
        CHECK(mValid) << "Uninitialized cache";
        std::call_once(mTraitsInitializationFlag, [this]() {
            bool success{false};
            // Spin until _listComponents() is successful.
@@ -229,7 +152,7 @@ public:
                using namespace std::chrono_literals;
                static constexpr auto kServiceRetryPeriod = 5s;
                LOG(INFO) << "Failed to retrieve component traits from service "
                             "\"" << getServiceNames()[mIndex] << "\". "
                             "\"" << GetServiceNames()[mIndex] << "\". "
                             "Retrying...";
                std::this_thread::sleep_for(kServiceRetryPeriod);
            }
@@ -240,7 +163,7 @@ public:
    // List() returns the list of all caches.
    static std::vector<Cache>& List() {
        static std::vector<Cache> sCaches{[]() {
            size_t numServices = getServiceNames().size();
            size_t numServices = GetServiceNames().size();
            std::vector<Cache> caches(numServices);
            for (size_t i = 0; i < numServices; ++i) {
                caches[i].init(i);
@@ -610,8 +533,12 @@ Codec2Client::Codec2Client(const sp<IComponentStore>& base,
    }
}

sp<Codec2Client::Base> const& Codec2Client::getBase() const {
    return mBase;
}

std::string const& Codec2Client::getServiceName() const {
    return getServiceNames()[mServiceIndex];
    return GetServiceNames()[mServiceIndex];
}

c2_status_t Codec2Client::createComponent(
@@ -807,15 +734,94 @@ std::shared_ptr<C2ParamReflector>
    return std::make_shared<SimpleParamReflector>(mBase);
};

std::vector<std::string> const& Codec2Client::GetServiceNames() {
    static std::vector<std::string> sServiceNames{[]() {
        using ::android::hardware::media::c2::V1_0::IComponentStore;
        using ::android::hidl::manager::V1_2::IServiceManager;

        while (true) {
            sp<IServiceManager> serviceManager = IServiceManager::getService();
            CHECK(serviceManager) << "Hardware service manager is not running.";

            // There are three categories of services based on names.
            std::vector<std::string> defaultNames; // Prefixed with "default"
            std::vector<std::string> vendorNames;  // Prefixed with "vendor"
            std::vector<std::string> otherNames;   // Others
            Return<void> transResult;
            transResult = serviceManager->listManifestByInterface(
                    IComponentStore::descriptor,
                    [&defaultNames, &vendorNames, &otherNames](
                            hidl_vec<hidl_string> const& instanceNames) {
                        for (hidl_string const& instanceName : instanceNames) {
                            char const* name = instanceName.c_str();
                            if (strncmp(name, "default", 7) == 0) {
                                defaultNames.emplace_back(name);
                            } else if (strncmp(name, "vendor", 6) == 0) {
                                vendorNames.emplace_back(name);
                            } else {
                                otherNames.emplace_back(name);
                            }
                        }
                    });
            if (transResult.isOk()) {
                // Sort service names in each category.
                std::sort(defaultNames.begin(), defaultNames.end());
                std::sort(vendorNames.begin(), vendorNames.end());
                std::sort(otherNames.begin(), otherNames.end());

                // Concatenate the three lists in this order: default, vendor,
                // other.
                std::vector<std::string>& names = defaultNames;
                names.reserve(names.size() + vendorNames.size() + otherNames.size());
                names.insert(names.end(),
                             std::make_move_iterator(vendorNames.begin()),
                             std::make_move_iterator(vendorNames.end()));
                names.insert(names.end(),
                             std::make_move_iterator(otherNames.begin()),
                             std::make_move_iterator(otherNames.end()));

                // Summarize to logcat.
                if (names.empty()) {
                    LOG(INFO) << "No Codec2 services declared in the manifest.";
                } else {
                    std::stringstream stringOutput;
                    stringOutput << "Available Codec2 services:";
                    for (std::string const& name : names) {
                        stringOutput << " \"" << name << "\"";
                    }
                    LOG(INFO) << stringOutput.str();
                }

                return names;
            }
            LOG(ERROR) << "Could not retrieve the list of service instances of "
                       << IComponentStore::descriptor
                       << ". Retrying...";
        }
    }()};
    return sServiceNames;
}

std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
        const char* name) {
    size_t index = getServiceIndex(name);
    return index == getServiceNames().size() ?
    return index == GetServiceNames().size() ?
            nullptr : _CreateFromIndex(index);
}

std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
        CreateFromAllServices() {
    std::vector<std::shared_ptr<Codec2Client>> clients(
            GetServiceNames().size());
    for (size_t i = GetServiceNames().size(); i > 0; ) {
        --i;
        clients[i] = _CreateFromIndex(i);
    }
    return clients;
}

std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
    std::string const& name = getServiceNames()[index];
    std::string const& name = GetServiceNames()[index];
    LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
    sp<Base> baseStore = Base::getService(name);
    CHECK(baseStore) << "Codec2 service \"" << name << "\""
@@ -958,17 +964,17 @@ std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
    if (inputSurfaceSetting == 0) {
        return nullptr;
    }
    size_t index = getServiceNames().size();
    size_t index = GetServiceNames().size();
    if (serviceName) {
        index = getServiceIndex(serviceName);
        if (index == getServiceNames().size()) {
        if (index == GetServiceNames().size()) {
            LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
                       << serviceName << "\"";
        }
    }

    std::shared_ptr<Codec2Client::InputSurface> inputSurface;
    if (index != getServiceNames().size()) {
    if (index != GetServiceNames().size()) {
        std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
        if (client->createInputSurface(&inputSurface) == C2_OK) {
            return inputSurface;
+11 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ struct Codec2Client : public Codec2ConfigurableClient {

    typedef Codec2Client Store;

    sp<Base> const& getBase() const;

    std::string const& getServiceName() const;

    c2_status_t createComponent(
@@ -165,8 +167,17 @@ struct Codec2Client : public Codec2ConfigurableClient {

    std::shared_ptr<C2ParamReflector> getParamReflector();

    // Returns the list of IComponentStore service names that are available on
    // the device. This list is specified at the build time in manifest files.
    // Note: A software service will have "_software" as a suffix.
    static std::vector<std::string> const& GetServiceNames();

    // Create a service with a given service name.
    static std::shared_ptr<Codec2Client> CreateFromService(char const* name);

    // Get clients to all services.
    static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();

    // Try to create a component with a given name from all known
    // IComponentStore services.
    static std::shared_ptr<Component> CreateComponentByName(
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ cc_library_shared {

    srcs: [
        "ActivityManager.cpp",
        "DeathNotifier.cpp",
        "MediaPlayerFactory.cpp",
        "MediaPlayerService.cpp",
        "MediaRecorderClient.cpp",
@@ -17,6 +18,7 @@ cc_library_shared {
        "libaudioclient",
        "libbinder",
        "libcamera_client",
        "libcodec2_client",
        "libcrypto",
        "libcutils",
        "libdl",
Loading