Add a sample service for testing init.

I find myself using something like this every time I add functionality
to init. I cannot possibly be the only one doing this. On the other
hand, if this hasn't been added for so long, maybe there's a reason
for that.

The advantage of using a test service versus modifying an existing
service is that the test service doesn't *require* any permissions or
privileges, so you can add and/or remove whatever you need to test
without breaking the service.

I found it useful to have the service check its own /proc/<pid>/status
from command-line arguments, so that's what the service does.

This CL also adds a .clang-format file for init.

Bug: None
Test: Service runs and exits successfully.

Change-Id: I3e7841a7283158e10c0bf55e0103c03902afb1f0
This commit is contained in:
Jorge Lucangeli Obes 2016-12-20 16:54:04 -05:00
parent 23f4e6b0a5
commit 28e980b59c
6 changed files with 174 additions and 0 deletions

14
init/.clang-format Normal file
View file

@ -0,0 +1,14 @@
---
Language: Cpp
BasedOnStyle: Google
BinPackArguments: true
BinPackParameters: true
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: false
IndentWidth: 4
Standard: Auto
TabWidth: 8
UseTab: Never
DerivePointerAlignment: false
PointerAlignment: Left
...

View file

@ -134,3 +134,8 @@ LOCAL_SANITIZE := integer
LOCAL_CLANG := true
LOCAL_CPPFLAGS := -Wall -Wextra -Werror
include $(BUILD_NATIVE_TEST)
# Include targets in subdirs.
# =========================================================
include $(call all-makefiles-under,$(LOCAL_PATH))

View file

@ -0,0 +1,27 @@
# Copyright (C) 2016 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.
LOCAL_PATH := $(call my-dir)
# Sample service for testing.
# =========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := test_service
LOCAL_SRC_FILES := test_service.cpp
LOCAL_SHARED_LIBRARIES += libbase
LOCAL_INIT_RC := test_service.rc
include $(BUILD_EXECUTABLE)

View file

@ -0,0 +1,43 @@
# Sample service for testing
This is a sample service that can be used for testing init.
## Design
The service includes a `.rc` file that allows starting it from init.
service test_service /system/bin/test_service CapAmb 0000000000003000
class main
user system
group system
capabilities NET_ADMIN NET_RAW
disabled
oneshot
The service accepts any even number of arguments on the command line
(i.e. any number of pairs of arguments.)
It will attempt to find the first element of each pair of arguments in
`/proc/self/status`, and attempt to exactly match the second element of the pair
to the relevant line of `proc/self/status`.
### Example
In the above case, the service will look for lines containing `CapAmb`:
cat /proc/self/status
...
CapAmb: 0000000000003000
And then attempt to exactly match the token after `:`, `0000000000003000`,
with the command-line argument.
If they match, the service exits successfully. If not, the service will exit
with an error.
## Usage
mmma -j <jobs> system/core/init/testservice
adb root
adb remount
adb sync
adb reboot
adb root
adb shell start test_service
adb logcat -b all -d | grep test_service
Look for an exit status of 0.

View file

@ -0,0 +1,78 @@
// Copyright (C) 2016 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 <unistd.h>
#include <map>
#include <sstream>
#include <string>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
void Usage(char* argv[]) {
printf("Usage: %s <status field> <value> [<status field> <value>]*\n", argv[0]);
printf("E.g.: $ %s Uid \"1000 1000 1000 1000\"\n", argv[0]);
}
int main(int argc, char* argv[]) {
if (argc < 3) {
Usage(argv);
LOG(FATAL) << "no status field requested";
}
if (argc % 2 == 0) {
// Since |argc| counts argv[0], if |argc| is odd, then the number of
// command-line arguments is even.
Usage(argv);
LOG(FATAL) << "need even number of command-line arguments";
}
std::string status;
bool res = android::base::ReadFileToString("/proc/self/status", &status, true);
if (!res) {
PLOG(FATAL) << "could not read /proc/self/status";
}
std::map<std::string, std::string> fields;
std::vector<std::string> lines = android::base::Split(status, "\n");
for (const auto& line : lines) {
std::vector<std::string> tokens = android::base::Split(line, ":");
if (tokens.size() >= 2) {
std::string field = tokens[0];
std::string value = android::base::Trim(tokens[1]);
if (field.length() > 0) {
fields[field] = value;
}
}
}
bool test_fails = false;
size_t uargc = static_cast<size_t>(argc); // |argc| >= 3.
for (size_t i = 1; i < static_cast<size_t>(argc); i = i + 2) {
std::string expected_value = argv[i + 1];
auto f = fields.find(argv[i]);
if (f != fields.end()) {
if (f->second != expected_value) {
LOG(ERROR) << "field '" << argv[i] << "' expected '" << expected_value
<< "', actual '" << f->second << "'";
test_fails = true;
}
} else {
LOG(WARNING) << "could not find field '" << argv[i] << "'";
}
}
return test_fails ? 1 : 0;
}

View file

@ -0,0 +1,7 @@
service test_service /system/bin/test_service CapAmb 0000000000003000
class main
user system
group system
capabilities NET_ADMIN NET_RAW
disabled
oneshot