init: allow properties to be used for the keycodes option
Bug: 117828597
Test: bugreport launches with a test property set to appropriate keys
Test: bugreport doesn't launch with the test property unset
Test: no errors seen in build or boot in either of the above cases
Change-Id: Iea27032080a0a7863932b1c1b573857ac66b56b5
diff --git a/init/README.md b/init/README.md
index f938ccc..6c51b37 100644
--- a/init/README.md
+++ b/init/README.md
@@ -226,6 +226,15 @@
keycodes are pressed at once, the service will start. This is typically used to start the
bugreport service.
+> This option may take a property instead of a list of keycodes. In this case, only one option is
+ provided: the property name in the typical property expansion format. The property must contain
+ a comma separated list of keycode values or the text 'none' to indicate that
+ this service does not respond to keycodes.
+
+> For example, `keycodes ${some.property.name:-none}` where some.property.name expands
+ to "123,124,125". Since keycodes are handled very early in init,
+ only PRODUCT_DEFAULT_PROPERTY_OVERRIDES properties can be used.
+
`memcg.limit_in_bytes <value>`
> Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted),
which must be equal or greater than 0.
diff --git a/init/service.cpp b/init/service.cpp
index b7de45d..7f49423 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -60,6 +60,7 @@
using android::base::GetProperty;
using android::base::Join;
using android::base::ParseInt;
+using android::base::Split;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -543,15 +544,32 @@
}
Result<Success> Service::ParseKeycodes(std::vector<std::string>&& args) {
- for (std::size_t i = 1; i < args.size(); i++) {
+ auto it = args.begin() + 1;
+ if (args.size() == 2 && StartsWith(args[1], "$")) {
+ std::string expanded;
+ if (!expand_props(args[1], &expanded)) {
+ return Error() << "Could not expand property '" << args[1] << "'";
+ }
+
+ // If the property is not set, it defaults to none, in which case there are no keycodes
+ // for this service.
+ if (expanded == "none") {
+ return Success();
+ }
+
+ args = Split(expanded, ",");
+ it = args.begin();
+ }
+
+ for (; it != args.end(); ++it) {
int code;
- if (ParseInt(args[i], &code, 0, KEY_MAX)) {
+ if (ParseInt(*it, &code, 0, KEY_MAX)) {
for (auto& key : keycodes_) {
- if (key == code) return Error() << "duplicate keycode: " << args[i];
+ if (key == code) return Error() << "duplicate keycode: " << *it;
}
keycodes_.insert(std::upper_bound(keycodes_.begin(), keycodes_.end(), code), code);
} else {
- return Error() << "invalid keycode: " << args[i];
+ return Error() << "invalid keycode: " << *it;
}
}
return Success();