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

Commit 2e293aa8 authored by Steven Moreland's avatar Steven Moreland
Browse files

servicemanager: vintf declared API

servicemanager already has to parse VINTF configurations, so exposing
this functionality here (mirroring hwservicemanager).

Note, this API, like isDeclared is not branded as "VINTF" for future
compatibility with APEX or other interfaces.

Bug: 168715768
Test: manual
Change-Id: Ifbc44677605de757c46ef17f7f29fd83e66a8161
parent c68e32d3
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ class ServiceManagerMock : public IServiceManager {
    MOCK_METHOD1(listServices, Vector<String16>(int));
    MOCK_METHOD1(listServices, Vector<String16>(int));
    MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
    MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
    MOCK_METHOD1(isDeclared, bool(const String16&));
    MOCK_METHOD1(isDeclared, bool(const String16&));
    MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
  protected:
  protected:
    MOCK_METHOD0(onAsBinder, IBinder*());
    MOCK_METHOD0(onAsBinder, IBinder*());
};
};
+74 −19
Original line number Original line Diff line number Diff line
@@ -37,22 +37,12 @@ using ::android::internal::Stability;
namespace android {
namespace android {


#ifndef VENDORSERVICEMANAGER
#ifndef VENDORSERVICEMANAGER
static bool isVintfDeclared(const std::string& name) {
    size_t firstSlash = name.find('/');
    size_t lastDot = name.rfind('.', firstSlash);
    if (firstSlash == std::string::npos || lastDot == std::string::npos) {
        LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
                   << "some.package.foo.IFoo/default) but got: " << name;
        return false;
    }
    const std::string package = name.substr(0, lastDot);
    const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
    const std::string instance = name.substr(firstSlash+1);

struct ManifestWithDescription {
struct ManifestWithDescription {
    std::shared_ptr<const vintf::HalManifest> manifest;
    std::shared_ptr<const vintf::HalManifest> manifest;
    const char* description;
    const char* description;
};
};
// func true -> stop search and forEachManifest will return true
static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) {
    for (const ManifestWithDescription& mwd : {
    for (const ManifestWithDescription& mwd : {
            ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
            ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
            ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
            ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
@@ -63,17 +53,58 @@ static bool isVintfDeclared(const std::string& name) {
          // or other bugs (b/151696835)
          // or other bugs (b/151696835)
          continue;
          continue;
        }
        }
        if (func(mwd)) return true;
    }
    return false;
}

static bool isVintfDeclared(const std::string& name) {
    size_t firstSlash = name.find('/');
    size_t lastDot = name.rfind('.', firstSlash);
    if (firstSlash == std::string::npos || lastDot == std::string::npos) {
        LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
                   << "some.package.foo.IFoo/default) but got: " << name;
        return false;
    }
    const std::string package = name.substr(0, lastDot);
    const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
    const std::string instance = name.substr(firstSlash+1);

    bool found = forEachManifest([&] (const ManifestWithDescription& mwd) {
        if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
        if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
            LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
            LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
            return true;
            return true;
        }
        }
    }
        return false;  // continue
    });


    if (!found) {
        // Although it is tested, explicitly rebuilding qualified name, in case it
        // Although it is tested, explicitly rebuilding qualified name, in case it
        // becomes something unexpected.
        // becomes something unexpected.
        LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
        LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
                   << " in the VINTF manifest.";
                   << " in the VINTF manifest.";
    return false;
    }

    return found;
}

static std::vector<std::string> getVintfInstances(const std::string& interface) {
    size_t lastDot = interface.rfind('.');
    if (lastDot == std::string::npos) {
        LOG(ERROR) << "VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) but got: " << interface;
        return {};
    }
    const std::string package = interface.substr(0, lastDot);
    const std::string iface = interface.substr(lastDot+1);

    std::vector<std::string> ret;
    (void)forEachManifest([&](const ManifestWithDescription& mwd) {
        auto instances = mwd.manifest->getAidlInstances(package, iface);
        ret.insert(ret.end(), instances.begin(), instances.end());
        return false;  // continue
    });

    return ret;
}
}


static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
@@ -331,6 +362,30 @@ Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {
    return Status::ok();
    return Status::ok();
}
}


binder::Status ServiceManager::getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) {
    auto ctx = mAccess->getCallingContext();

    std::vector<std::string> allInstances;
#ifndef VENDORSERVICEMANAGER
    allInstances = getVintfInstances(interface);
#endif

    outReturn->clear();

    for (const std::string& instance : allInstances) {
        // TODO(b/169275998): allow checking policy only once for the interface
        if (mAccess->canFind(ctx, interface + "/" + instance)) {
            outReturn->push_back(instance);
        }
    }

    if (outReturn->size() == 0 && allInstances.size() != 0) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    return Status::ok();
}

void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
                                    ServiceCallbackMap::iterator* it,
                                    ServiceCallbackMap::iterator* it,
                                    bool* found) {
                                    bool* found) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ public:
                                              const sp<IServiceCallback>& callback) override;
                                              const sp<IServiceCallback>& callback) override;


    binder::Status isDeclared(const std::string& name, bool* outReturn) override;
    binder::Status isDeclared(const std::string& name, bool* outReturn) override;
    binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
    binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
    binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                          const sp<IClientCallback>& cb) override;
                                          const sp<IClientCallback>& cb) override;
    binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
    binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
+15 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ public:
    Vector<String16> listServices(int dumpsysPriority) override;
    Vector<String16> listServices(int dumpsysPriority) override;
    sp<IBinder> waitForService(const String16& name16) override;
    sp<IBinder> waitForService(const String16& name16) override;
    bool isDeclared(const String16& name) override;
    bool isDeclared(const String16& name) override;
    Vector<String16> getDeclaredInstances(const String16& interface) override;


    // for legacy ABI
    // for legacy ABI
    const String16& getInterfaceDescriptor() const override {
    const String16& getInterfaceDescriptor() const override {
@@ -373,4 +374,18 @@ bool ServiceManagerShim::isDeclared(const String16& name) {
    return declared;
    return declared;
}
}


Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) {
    std::vector<std::string> out;
    if (!mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out).isOk()) {
        return {};
    }

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

} // namespace android
} // namespace android
+8 −0
Original line number Original line Diff line number Diff line
@@ -98,6 +98,14 @@ interface IServiceManager {
     */
     */
    boolean isDeclared(@utf8InCpp String name);
    boolean isDeclared(@utf8InCpp String name);


    /**
     * Returns all declared instances for a particular interface.
     *
     * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is
     * passed here, then ["foo"] would be returned.
     */
    @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface);

    /**
    /**
     * Request a callback when the number of clients of the service changes.
     * Request a callback when the number of clients of the service changes.
     * Used by LazyServiceRegistrar to dynamically stop services that have no clients.
     * Used by LazyServiceRegistrar to dynamically stop services that have no clients.
Loading