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

Commit 76944fee authored by Jooyung Han's avatar Jooyung Han
Browse files

servicemanager: getUpdatableNames()

This new method is a reverse of updatableViaApex(). It returns the list
of declared instances which can be updated via the passed APEX.

Updatable vendor apexes are supposed to be used only to update HAL
services. APEXd can use this method to see if the target APEX is
actually to updating HALs.

It's not exposed to NDK/Java yet because there's no clients.

Bug: 254201177
Test: TBD
Change-Id: I7b5aa7d00a3ddeb13855816006a9561dfa601529
parent 4e841480
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ class ServiceManagerMock : public IServiceManager {
    MOCK_METHOD1(isDeclared, bool(const String16&));
    MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
    MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
    MOCK_METHOD1(getUpdatableNames, Vector<String16>(const String16&));
    MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&));
    MOCK_METHOD2(registerForNotifications, status_t(const String16&,
                                             const sp<LocalRegistrationCallback>&));
+44 −0
Original line number Diff line number Diff line
@@ -142,6 +142,26 @@ static std::optional<std::string> getVintfUpdatableApex(const std::string& name)
    return updatableViaApex;
}

static std::vector<std::string> getVintfUpdatableInstances(const std::string& apexName) {
    std::vector<std::string> instances;

    forEachManifest([&](const ManifestWithDescription& mwd) {
        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
            if (manifestInstance.format() == vintf::HalFormat::AIDL &&
                manifestInstance.updatableViaApex().has_value() &&
                manifestInstance.updatableViaApex().value() == apexName) {
                std::string aname = manifestInstance.package() + "." +
                        manifestInstance.interface() + "/" + manifestInstance.instance();
                instances.push_back(aname);
            }
            return false; // continue
        });
        return false; // continue
    });

    return instances;
}

static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
    AidlName aname;
    if (!AidlName::fill(name, &aname)) return std::nullopt;
@@ -512,6 +532,30 @@ Status ServiceManager::updatableViaApex(const std::string& name,
    return Status::ok();
}

Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& apexName,
                                         std::vector<std::string>* outReturn) {
    auto ctx = mAccess->getCallingContext();

    std::vector<std::string> apexUpdatableInstances;
#ifndef VENDORSERVICEMANAGER
    apexUpdatableInstances = getVintfUpdatableInstances(apexName);
#endif

    outReturn->clear();

    for (const std::string& instance : apexUpdatableInstances) {
        if (mAccess->canFind(ctx, instance)) {
            outReturn->push_back(instance);
        }
    }

    if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
    }

    return Status::ok();
}

Status ServiceManager::getConnectionInfo(const std::string& name,
                                         std::optional<ConnectionInfo>* outReturn) {
    auto ctx = mAccess->getCallingContext();
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ public:
    binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
    binder::Status updatableViaApex(const std::string& name,
                                    std::optional<std::string>* outReturn) override;
    binder::Status getUpdatableNames(const std::string& apexName,
                                     std::vector<std::string>* outReturn) override;
    binder::Status getConnectionInfo(const std::string& name,
                                     std::optional<ConnectionInfo>* outReturn) override;
    binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
+18 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ public:
    bool isDeclared(const String16& name) override;
    Vector<String16> getDeclaredInstances(const String16& interface) override;
    std::optional<String16> updatableViaApex(const String16& name) override;
    Vector<String16> getUpdatableNames(const String16& apexName) override;
    std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
    class RegistrationWaiter : public android::os::BnServiceCallback {
    public:
@@ -479,6 +480,23 @@ std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& nam
    return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
}

Vector<String16> ServiceManagerShim::getUpdatableNames(const String16& apexName) {
    std::vector<std::string> out;
    if (Status status = mTheRealServiceManager->getUpdatableNames(String8(apexName).c_str(), &out);
        !status.isOk()) {
        ALOGW("Failed to getUpdatableNames for %s: %s", String8(apexName).c_str(),
              status.toString8().c_str());
        return {};
    }

    Vector<String16> res;
    res.setCapacity(out.size());
    for (const std::string& instance : out) {
        res.push(String16(instance.c_str()));
    }
    return res;
}

std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnectionInfo(
        const String16& name) {
    std::optional<os::ConnectionInfo> connectionInfo;
+6 −0
Original line number Diff line number Diff line
@@ -113,6 +113,12 @@ interface IServiceManager {
     */
    @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name);

    /**
     * Returns all instances which are updatable via the APEX. Instance names are fully qualified
     * like `pack.age.IFoo/default`.
     */
    @utf8InCpp String[] getUpdatableNames(@utf8InCpp String apexName);

    /**
     * If connection info is available for the given instance, returns the ConnectionInfo
     */
Loading