summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJooyung Han <jooyung@google.com>2024-02-05 21:02:15 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-02-05 21:02:15 +0000
commit94ae84ff54c68787517f449b79e1aedc7f2864a9 (patch)
tree19e9ad52bde9df7fdb89e84af3feb3336597e44e
parent77f3da22f3bf363c6dbc63c50c898a12f8f1df78 (diff)
parent205e282f43152ab2c73053f0ecc4b4d397663506 (diff)
downloadnative-94ae84ff54c68787517f449b79e1aedc7f2864a9.tar.gz
Merge "Query methods for VINTF native instances" into main
-rw-r--r--cmds/servicemanager/Android.bp10
-rw-r--r--cmds/servicemanager/NameUtil.h58
-rw-r--r--cmds/servicemanager/ServiceManager.cpp84
-rw-r--r--cmds/servicemanager/ServiceManagerUnittest.cpp39
-rw-r--r--cmds/servicemanager/test_sm.cpp18
5 files changed, 195 insertions, 14 deletions
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index e00c2a2b5a..3897197bd5 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -95,6 +95,16 @@ cc_test {
static_libs: ["libgmock"],
}
+cc_test_host {
+ name: "servicemanager_unittest",
+ test_suites: ["general-tests"],
+ defaults: ["servicemanager_defaults"],
+ srcs: [
+ "ServiceManagerUnittest.cpp",
+ ],
+ static_libs: ["libgmock"],
+}
+
cc_fuzz {
name: "servicemanager_fuzzer",
defaults: [
diff --git a/cmds/servicemanager/NameUtil.h b/cmds/servicemanager/NameUtil.h
new file mode 100644
index 0000000000..b08093960d
--- /dev/null
+++ b/cmds/servicemanager/NameUtil.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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 <string_view>
+
+#include <android-base/strings.h>
+
+namespace android {
+
+#ifndef VENDORSERVICEMANAGER
+
+struct NativeName {
+ std::string package;
+ std::string instance;
+
+ // Parse {package}/{instance}
+ static bool fill(std::string_view name, NativeName* nname) {
+ size_t slash = name.find('/');
+ if (slash == std::string_view::npos) {
+ return false;
+ }
+ // no extra slashes
+ if (name.find('/', slash + 1) != std::string_view::npos) {
+ return false;
+ }
+ // every part should be non-empty
+ if (slash == 0 || slash + 1 == name.size()) {
+ return false;
+ }
+ // no dots in package
+ if (name.rfind('.', slash) != std::string_view::npos) {
+ return false;
+ }
+ nname->package = name.substr(0, slash);
+ nname->instance = name.substr(slash + 1);
+ return true;
+ }
+};
+
+#endif
+
+} // namespace android
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index f2f0a0f037..bf85e61583 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -35,6 +35,8 @@
#include <vintf/constants.h>
#endif // !VENDORSERVICEMANAGER
+#include "NameUtil.h"
+
using ::android::binder::Status;
using ::android::internal::Stability;
@@ -84,6 +86,10 @@ static bool forEachManifest(const std::function<bool(const ManifestWithDescripti
return false;
}
+static std::string getNativeInstanceName(const vintf::ManifestInstance& instance) {
+ return instance.package() + "/" + instance.instance();
+}
+
struct AidlName {
std::string package;
std::string iface;
@@ -105,7 +111,26 @@ struct AidlName {
}
};
+static std::string getAidlInstanceName(const vintf::ManifestInstance& instance) {
+ return instance.package() + "." + instance.interface() + "/" + instance.instance();
+}
+
static bool isVintfDeclared(const std::string& name) {
+ NativeName nname;
+ if (NativeName::fill(name, &nname)) {
+ bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
+ if (mwd.manifest->hasNativeInstance(nname.package, nname.instance)) {
+ ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
+ return true; // break
+ }
+ return false; // continue
+ });
+ if (!found) {
+ ALOGI("Could not find %s in the VINTF manifest.", name.c_str());
+ }
+ return found;
+ }
+
AidlName aname;
if (!AidlName::fill(name, &aname)) return false;
@@ -144,6 +169,24 @@ static bool isVintfDeclared(const std::string& name) {
}
static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
+ NativeName nname;
+ if (NativeName::fill(name, &nname)) {
+ std::optional<std::string> updatableViaApex;
+
+ forEachManifest([&](const ManifestWithDescription& mwd) {
+ bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ if (manifestInstance.format() != vintf::HalFormat::NATIVE) return true;
+ if (manifestInstance.package() != nname.package) return true;
+ if (manifestInstance.instance() != nname.instance) return true;
+ updatableViaApex = manifestInstance.updatableViaApex();
+ return false; // break (libvintf uses opposite convention)
+ });
+ return !cont;
+ });
+
+ return updatableViaApex;
+ }
+
AidlName aname;
if (!AidlName::fill(name, &aname)) return std::nullopt;
@@ -164,24 +207,25 @@ 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;
+static std::vector<std::string> getVintfUpdatableNames(const std::string& apexName) {
+ std::vector<std::string> names;
forEachManifest([&](const ManifestWithDescription& mwd) {
mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
- if (manifestInstance.format() == vintf::HalFormat::AIDL &&
- manifestInstance.updatableViaApex().has_value() &&
+ if (manifestInstance.updatableViaApex().has_value() &&
manifestInstance.updatableViaApex().value() == apexName) {
- std::string aname = manifestInstance.package() + "." +
- manifestInstance.interface() + "/" + manifestInstance.instance();
- instances.push_back(aname);
+ if (manifestInstance.format() == vintf::HalFormat::NATIVE) {
+ names.push_back(getNativeInstanceName(manifestInstance));
+ } else if (manifestInstance.format() == vintf::HalFormat::AIDL) {
+ names.push_back(getAidlInstanceName(manifestInstance));
+ }
}
return true; // continue (libvintf uses opposite convention)
});
return false; // continue
});
- return instances;
+ return names;
}
static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
@@ -216,6 +260,18 @@ static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& n
static std::vector<std::string> getVintfInstances(const std::string& interface) {
size_t lastDot = interface.rfind('.');
if (lastDot == std::string::npos) {
+ // This might be a package for native instance.
+ std::vector<std::string> ret;
+ (void)forEachManifest([&](const ManifestWithDescription& mwd) {
+ auto instances = mwd.manifest->getNativeInstances(interface);
+ ret.insert(ret.end(), instances.begin(), instances.end());
+ return false; // continue
+ });
+ // If found, return it without error log.
+ if (!ret.empty()) {
+ return ret;
+ }
+
ALOGE("VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) "
"but got: %s",
interface.c_str());
@@ -593,20 +649,20 @@ Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& ape
std::vector<std::string>* outReturn) {
auto ctx = mAccess->getCallingContext();
- std::vector<std::string> apexUpdatableInstances;
+ std::vector<std::string> apexUpdatableNames;
#ifndef VENDORSERVICEMANAGER
- apexUpdatableInstances = getVintfUpdatableInstances(apexName);
+ apexUpdatableNames = getVintfUpdatableNames(apexName);
#endif
outReturn->clear();
- for (const std::string& instance : apexUpdatableInstances) {
- if (mAccess->canFind(ctx, instance)) {
- outReturn->push_back(instance);
+ for (const std::string& name : apexUpdatableNames) {
+ if (mAccess->canFind(ctx, name)) {
+ outReturn->push_back(name);
}
}
- if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
+ if (outReturn->size() == 0 && apexUpdatableNames.size() != 0) {
return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
diff --git a/cmds/servicemanager/ServiceManagerUnittest.cpp b/cmds/servicemanager/ServiceManagerUnittest.cpp
new file mode 100644
index 0000000000..39d20b0025
--- /dev/null
+++ b/cmds/servicemanager/ServiceManagerUnittest.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <gtest/gtest.h>
+
+#include "NameUtil.h"
+
+namespace android {
+
+TEST(ServiceManager, NativeName) {
+ NativeName nname;
+ EXPECT_TRUE(NativeName::fill("mapper/default", &nname));
+ EXPECT_EQ("mapper", nname.package);
+ EXPECT_EQ("default", nname.instance);
+}
+
+TEST(ServiceManager, NativeName_Malformed) {
+ NativeName nname;
+ EXPECT_FALSE(NativeName::fill("mapper", &nname));
+ EXPECT_FALSE(NativeName::fill("mapper/", &nname));
+ EXPECT_FALSE(NativeName::fill("/default", &nname));
+ EXPECT_FALSE(NativeName::fill("mapper/default/0", &nname));
+ EXPECT_FALSE(NativeName::fill("aidl.like.IType/default", &nname));
+}
+
+} // namespace android
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 97e500d0a7..b57505302c 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -361,6 +361,24 @@ TEST(Vintf, GetUpdatableNames_InvalidApexNameReturnsEmpty) {
EXPECT_EQ(std::vector<std::string>{}, names);
}
+TEST(Vintf, IsDeclared_native) {
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+ auto sm = getPermissiveServiceManager();
+ bool declared = false;
+ EXPECT_TRUE(sm->isDeclared("mapper/minigbm", &declared).isOk());
+ EXPECT_TRUE(declared);
+}
+
+TEST(Vintf, GetDeclaredInstances_native) {
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+ auto sm = getPermissiveServiceManager();
+ std::vector<std::string> instances;
+ EXPECT_TRUE(sm->getDeclaredInstances("mapper", &instances).isOk());
+ EXPECT_EQ(std::vector<std::string>{"minigbm"}, instances);
+}
+
class CallbackHistorian : public BnServiceCallback {
Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
registrations.push_back(name);