Skip to content

Commit 205e282

Browse files
author
Jooyung Han
committed
Query methods for VINTF native instances
isDeclared(name), getDeclaredInstances(interface), updatableViaApex(name), and getUpdatableNames(apexName) are extended to support native instances when - "name" is formatted as e.g. "mapper/minigbm", - "interface" is formatted as e.g. "mapper" Bug: 316051788 Test: atest servicemanager_test Test: atest --host servicemanager_unittest Change-Id: I0520888dbf5d30c66b97058f45cd6828731ca8bc
1 parent 9f1c687 commit 205e282

5 files changed

Lines changed: 195 additions & 14 deletions

File tree

cmds/servicemanager/Android.bp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ cc_test {
9595
static_libs: ["libgmock"],
9696
}
9797

98+
cc_test_host {
99+
name: "servicemanager_unittest",
100+
test_suites: ["general-tests"],
101+
defaults: ["servicemanager_defaults"],
102+
srcs: [
103+
"ServiceManagerUnittest.cpp",
104+
],
105+
static_libs: ["libgmock"],
106+
}
107+
98108
cc_fuzz {
99109
name: "servicemanager_fuzzer",
100110
defaults: [

cmds/servicemanager/NameUtil.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (C) 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <string>
20+
#include <string_view>
21+
22+
#include <android-base/strings.h>
23+
24+
namespace android {
25+
26+
#ifndef VENDORSERVICEMANAGER
27+
28+
struct NativeName {
29+
std::string package;
30+
std::string instance;
31+
32+
// Parse {package}/{instance}
33+
static bool fill(std::string_view name, NativeName* nname) {
34+
size_t slash = name.find('/');
35+
if (slash == std::string_view::npos) {
36+
return false;
37+
}
38+
// no extra slashes
39+
if (name.find('/', slash + 1) != std::string_view::npos) {
40+
return false;
41+
}
42+
// every part should be non-empty
43+
if (slash == 0 || slash + 1 == name.size()) {
44+
return false;
45+
}
46+
// no dots in package
47+
if (name.rfind('.', slash) != std::string_view::npos) {
48+
return false;
49+
}
50+
nname->package = name.substr(0, slash);
51+
nname->instance = name.substr(slash + 1);
52+
return true;
53+
}
54+
};
55+
56+
#endif
57+
58+
} // namespace android

cmds/servicemanager/ServiceManager.cpp

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include <vintf/constants.h>
3636
#endif // !VENDORSERVICEMANAGER
3737

38+
#include "NameUtil.h"
39+
3840
using ::android::binder::Status;
3941
using ::android::internal::Stability;
4042

@@ -84,6 +86,10 @@ static bool forEachManifest(const std::function<bool(const ManifestWithDescripti
8486
return false;
8587
}
8688

89+
static std::string getNativeInstanceName(const vintf::ManifestInstance& instance) {
90+
return instance.package() + "/" + instance.instance();
91+
}
92+
8793
struct AidlName {
8894
std::string package;
8995
std::string iface;
@@ -105,7 +111,26 @@ struct AidlName {
105111
}
106112
};
107113

114+
static std::string getAidlInstanceName(const vintf::ManifestInstance& instance) {
115+
return instance.package() + "." + instance.interface() + "/" + instance.instance();
116+
}
117+
108118
static bool isVintfDeclared(const std::string& name) {
119+
NativeName nname;
120+
if (NativeName::fill(name, &nname)) {
121+
bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
122+
if (mwd.manifest->hasNativeInstance(nname.package, nname.instance)) {
123+
ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
124+
return true; // break
125+
}
126+
return false; // continue
127+
});
128+
if (!found) {
129+
ALOGI("Could not find %s in the VINTF manifest.", name.c_str());
130+
}
131+
return found;
132+
}
133+
109134
AidlName aname;
110135
if (!AidlName::fill(name, &aname)) return false;
111136

@@ -144,6 +169,24 @@ static bool isVintfDeclared(const std::string& name) {
144169
}
145170

146171
static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
172+
NativeName nname;
173+
if (NativeName::fill(name, &nname)) {
174+
std::optional<std::string> updatableViaApex;
175+
176+
forEachManifest([&](const ManifestWithDescription& mwd) {
177+
bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
178+
if (manifestInstance.format() != vintf::HalFormat::NATIVE) return true;
179+
if (manifestInstance.package() != nname.package) return true;
180+
if (manifestInstance.instance() != nname.instance) return true;
181+
updatableViaApex = manifestInstance.updatableViaApex();
182+
return false; // break (libvintf uses opposite convention)
183+
});
184+
return !cont;
185+
});
186+
187+
return updatableViaApex;
188+
}
189+
147190
AidlName aname;
148191
if (!AidlName::fill(name, &aname)) return std::nullopt;
149192

@@ -164,24 +207,25 @@ static std::optional<std::string> getVintfUpdatableApex(const std::string& name)
164207
return updatableViaApex;
165208
}
166209

167-
static std::vector<std::string> getVintfUpdatableInstances(const std::string& apexName) {
168-
std::vector<std::string> instances;
210+
static std::vector<std::string> getVintfUpdatableNames(const std::string& apexName) {
211+
std::vector<std::string> names;
169212

170213
forEachManifest([&](const ManifestWithDescription& mwd) {
171214
mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
172-
if (manifestInstance.format() == vintf::HalFormat::AIDL &&
173-
manifestInstance.updatableViaApex().has_value() &&
215+
if (manifestInstance.updatableViaApex().has_value() &&
174216
manifestInstance.updatableViaApex().value() == apexName) {
175-
std::string aname = manifestInstance.package() + "." +
176-
manifestInstance.interface() + "/" + manifestInstance.instance();
177-
instances.push_back(aname);
217+
if (manifestInstance.format() == vintf::HalFormat::NATIVE) {
218+
names.push_back(getNativeInstanceName(manifestInstance));
219+
} else if (manifestInstance.format() == vintf::HalFormat::AIDL) {
220+
names.push_back(getAidlInstanceName(manifestInstance));
221+
}
178222
}
179223
return true; // continue (libvintf uses opposite convention)
180224
});
181225
return false; // continue
182226
});
183227

184-
return instances;
228+
return names;
185229
}
186230

187231
static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
@@ -216,6 +260,18 @@ static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& n
216260
static std::vector<std::string> getVintfInstances(const std::string& interface) {
217261
size_t lastDot = interface.rfind('.');
218262
if (lastDot == std::string::npos) {
263+
// This might be a package for native instance.
264+
std::vector<std::string> ret;
265+
(void)forEachManifest([&](const ManifestWithDescription& mwd) {
266+
auto instances = mwd.manifest->getNativeInstances(interface);
267+
ret.insert(ret.end(), instances.begin(), instances.end());
268+
return false; // continue
269+
});
270+
// If found, return it without error log.
271+
if (!ret.empty()) {
272+
return ret;
273+
}
274+
219275
ALOGE("VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) "
220276
"but got: %s",
221277
interface.c_str());
@@ -593,20 +649,20 @@ Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& ape
593649
std::vector<std::string>* outReturn) {
594650
auto ctx = mAccess->getCallingContext();
595651

596-
std::vector<std::string> apexUpdatableInstances;
652+
std::vector<std::string> apexUpdatableNames;
597653
#ifndef VENDORSERVICEMANAGER
598-
apexUpdatableInstances = getVintfUpdatableInstances(apexName);
654+
apexUpdatableNames = getVintfUpdatableNames(apexName);
599655
#endif
600656

601657
outReturn->clear();
602658

603-
for (const std::string& instance : apexUpdatableInstances) {
604-
if (mAccess->canFind(ctx, instance)) {
605-
outReturn->push_back(instance);
659+
for (const std::string& name : apexUpdatableNames) {
660+
if (mAccess->canFind(ctx, name)) {
661+
outReturn->push_back(name);
606662
}
607663
}
608664

609-
if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
665+
if (outReturn->size() == 0 && apexUpdatableNames.size() != 0) {
610666
return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
611667
}
612668

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (C) 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <gtest/gtest.h>
18+
19+
#include "NameUtil.h"
20+
21+
namespace android {
22+
23+
TEST(ServiceManager, NativeName) {
24+
NativeName nname;
25+
EXPECT_TRUE(NativeName::fill("mapper/default", &nname));
26+
EXPECT_EQ("mapper", nname.package);
27+
EXPECT_EQ("default", nname.instance);
28+
}
29+
30+
TEST(ServiceManager, NativeName_Malformed) {
31+
NativeName nname;
32+
EXPECT_FALSE(NativeName::fill("mapper", &nname));
33+
EXPECT_FALSE(NativeName::fill("mapper/", &nname));
34+
EXPECT_FALSE(NativeName::fill("/default", &nname));
35+
EXPECT_FALSE(NativeName::fill("mapper/default/0", &nname));
36+
EXPECT_FALSE(NativeName::fill("aidl.like.IType/default", &nname));
37+
}
38+
39+
} // namespace android

cmds/servicemanager/test_sm.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,24 @@ TEST(Vintf, GetUpdatableNames_InvalidApexNameReturnsEmpty) {
361361
EXPECT_EQ(std::vector<std::string>{}, names);
362362
}
363363

364+
TEST(Vintf, IsDeclared_native) {
365+
if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
366+
367+
auto sm = getPermissiveServiceManager();
368+
bool declared = false;
369+
EXPECT_TRUE(sm->isDeclared("mapper/minigbm", &declared).isOk());
370+
EXPECT_TRUE(declared);
371+
}
372+
373+
TEST(Vintf, GetDeclaredInstances_native) {
374+
if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
375+
376+
auto sm = getPermissiveServiceManager();
377+
std::vector<std::string> instances;
378+
EXPECT_TRUE(sm->getDeclaredInstances("mapper", &instances).isOk());
379+
EXPECT_EQ(std::vector<std::string>{"minigbm"}, instances);
380+
}
381+
364382
class CallbackHistorian : public BnServiceCallback {
365383
Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
366384
registrations.push_back(name);

0 commit comments

Comments
 (0)