Merge changes I1f55c6e1,Ib2adcf0a
* changes:
Move fastboot over to ParseByteCount.
Add android::base::ParseByteCount.
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 4fbfafb..38c11b9 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1221,7 +1221,7 @@
std::string error;
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
if (!t) {
- return SendFail(reply_fd, error);
+ return -1;
}
int ret = handle_forward_request(service, t, reply_fd);
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 3bb433d..363002f 100644
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -21,9 +21,11 @@
"""
from __future__ import print_function
+import binascii
import contextlib
import os
import random
+import select
import socket
import struct
import subprocess
@@ -33,6 +35,52 @@
import adb
+@contextlib.contextmanager
+def fake_adb_server(protocol=socket.AF_INET, port=0):
+ """Creates a fake ADB server that just replies with a CNXN packet."""
+
+ serversock = socket.socket(protocol, socket.SOCK_STREAM)
+ if protocol == socket.AF_INET:
+ serversock.bind(('127.0.0.1', port))
+ else:
+ serversock.bind(('::1', port))
+ serversock.listen(1)
+
+ # A pipe that is used to signal the thread that it should terminate.
+ readpipe, writepipe = os.pipe()
+
+ def _handle():
+ rlist = [readpipe, serversock]
+ while True:
+ ready, _, _ = select.select(rlist, [], [])
+ for r in ready:
+ if r == readpipe:
+ # Closure pipe
+ os.close(r)
+ serversock.shutdown(socket.SHUT_RDWR)
+ serversock.close()
+ return
+ elif r == serversock:
+ # Server socket
+ conn, _ = r.accept()
+ rlist.append(conn)
+ else:
+ # Client socket
+ data = r.recv(1024)
+ if not data:
+ rlist.remove(r)
+
+ port = serversock.getsockname()[1]
+ server_thread = threading.Thread(target=_handle)
+ server_thread.start()
+
+ try:
+ yield port
+ finally:
+ os.close(writepipe)
+ server_thread.join()
+
+
class NonApiTest(unittest.TestCase):
"""Tests for ADB that aren't a part of the AndroidDevice API."""
@@ -211,45 +259,32 @@
Bug: http://b/30313466
"""
- ipv4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- ipv4.bind(('127.0.0.1', 0))
- ipv4.listen(1)
+ for protocol in (socket.AF_INET, socket.AF_INET6):
+ try:
+ with fake_adb_server(protocol=protocol) as port:
+ output = subprocess.check_output(
+ ['adb', 'connect', 'localhost:{}'.format(port)])
- ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- try:
- ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
- ipv6.listen(1)
- except socket.error:
- print("IPv6 not available, skipping")
- return
+ self.assertEqual(
+ output.strip(), 'connected to localhost:{}'.format(port))
+ except socket.error:
+ print("IPv6 not available, skipping")
+ continue
- for s in (ipv4, ipv6):
- port = s.getsockname()[1]
+ def test_already_connected(self):
+ with fake_adb_server() as port:
output = subprocess.check_output(
['adb', 'connect', 'localhost:{}'.format(port)])
self.assertEqual(
output.strip(), 'connected to localhost:{}'.format(port))
- s.close()
- def test_already_connected(self):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind(('127.0.0.1', 0))
- s.listen(2)
+ # b/31250450: this always returns 0 but probably shouldn't.
+ output = subprocess.check_output(
+ ['adb', 'connect', 'localhost:{}'.format(port)])
- port = s.getsockname()[1]
- output = subprocess.check_output(
- ['adb', 'connect', 'localhost:{}'.format(port)])
-
- self.assertEqual(
- output.strip(), 'connected to localhost:{}'.format(port))
-
- # b/31250450: this always returns 0 but probably shouldn't.
- output = subprocess.check_output(
- ['adb', 'connect', 'localhost:{}'.format(port)])
-
- self.assertEqual(
- output.strip(), 'already connected to localhost:{}'.format(port))
+ self.assertEqual(
+ output.strip(), 'already connected to localhost:{}'.format(port))
def main():
random.seed(0)
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 92c52e2..f5f6d26 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -974,7 +974,7 @@
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in pending_list and fails to register";
delete t;
- return -1;
+ return -EALREADY;
}
}
@@ -983,7 +983,7 @@
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in transport_list and fails to register";
delete t;
- return -1;
+ return -EALREADY;
}
}
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index c09fcb7..8032421 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -101,7 +101,11 @@
int ret = register_socket_transport(fd, serial.c_str(), port, 0);
if (ret < 0) {
adb_close(fd);
- *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+ if (ret == -EALREADY) {
+ *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+ } else {
+ *response = android::base::StringPrintf("failed to connect to %s", serial.c_str());
+ }
} else {
*response = android::base::StringPrintf("connected to %s", serial.c_str());
}
diff --git a/init/README.md b/init/README.md
index 59ddd77..b14521c 100644
--- a/init/README.md
+++ b/init/README.md
@@ -282,6 +282,10 @@
"shutdown critical" will be killed. When the service tagged with "shutdown critical"
is not running when shut down starts, it will be started.
+`sigstop`
+> Send SIGSTOP to the service immediately before exec is called. This is intended for debugging.
+ See the below section on debugging for how this can be used.
+
`socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]`
> Create a unix domain socket named /dev/socket/_name_ and pass its fd to the
launched process. _type_ must be "dgram", "stream" or "seqpacket". User and
@@ -708,23 +712,39 @@
Debugging init
--------------
-By default, programs executed by init will drop stdout and stderr into
-/dev/null. To help with debugging, you can execute your program via the
-Android program logwrapper. This will redirect stdout/stderr into the
-Android logging system (accessed via logcat).
+Launching init services without init is not recommended as init sets up a significant amount of
+environment (user, groups, security label, capabilities, etc) that is hard to replicate manually.
-For example
-service akmd /system/bin/logwrapper /sbin/akmd
+If it is required to debug a service from its very start, the `sigstop` service option is added.
+This option will send SIGSTOP to a service immediately before calling exec. This gives a window
+where developers can attach a debugger, strace, etc before continuing the service with SIGCONT.
-For quicker turnaround when working on init itself, use:
+This flag can also be dynamically controled via the ctl.sigstop_on and ctl.sigstop_off properties.
- mm -j &&
- m ramdisk-nodeps &&
- m bootimage-nodeps &&
- adb reboot bootloader &&
- fastboot boot $ANDROID_PRODUCT_OUT/boot.img
+Below is an example of dynamically debugging logd via the above:
-Alternatively, use the emulator:
+ stop logd
+ setprop ctl.sigstop_on logd
+ start logd
+ ps -e | grep logd
+ > logd 4343 1 18156 1684 do_signal_stop 538280 T init
+ gdbclient.py -p 4343
+ b main
+ c
+ c
+ c
+ > Breakpoint 1, main (argc=1, argv=0x7ff8c9a488) at system/core/logd/main.cpp:427
- emulator -partition-size 1024 \
- -verbose -show-kernel -no-window
+Below is an example of doing the same but with strace
+
+ stop logd
+ setprop ctl.sigstop_on logd
+ start logd
+ ps -e | grep logd
+ > logd 4343 1 18156 1684 do_signal_stop 538280 T init
+ strace -p 4343
+
+ (From a different shell)
+ kill -SIGCONT 4343
+
+ > strace runs
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 379b4fa..c2cf573 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -32,12 +32,14 @@
#include <mutex>
#include <thread>
+#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
using android::base::StringPrintf;
+using android::base::boot_clock;
using namespace std::chrono_literals;
namespace android {
@@ -50,9 +52,9 @@
static bool g_bootcharting_finished;
static long long get_uptime_jiffies() {
- std::string uptime;
- if (!android::base::ReadFileToString("/proc/uptime", &uptime)) return 0;
- return 100LL * strtod(uptime.c_str(), NULL);
+ constexpr int64_t kNanosecondsPerJiffy = 10000000;
+ boot_clock::time_point uptime = boot_clock::now();
+ return uptime.time_since_epoch().count() / kNanosecondsPerJiffy;
}
static std::unique_ptr<FILE, decltype(&fclose)> fopen_unique(const char* filename,
diff --git a/init/builtins.cpp b/init/builtins.cpp
index acbeca2..8bd92cc 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -519,6 +519,7 @@
if (e4crypt_install_keyring()) {
return Error() << "e4crypt_install_keyring() failed";
}
+ property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
// Although encrypted, vold has already set the device up, so we do not need to
diff --git a/init/init.cpp b/init/init.cpp
index 2f3b28a..0d5690b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -238,6 +238,10 @@
static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
// clang-format off
static const std::map<std::string, ControlMessageFunction> control_message_functions = {
+ {"sigstop_on", {ControlTarget::SERVICE,
+ [](auto* service) { service->set_sigstop(true); return Success(); }}},
+ {"sigstop_off", {ControlTarget::SERVICE,
+ [](auto* service) { service->set_sigstop(false); return Success(); }}},
{"start", {ControlTarget::SERVICE, DoControlStart}},
{"stop", {ControlTarget::SERVICE, DoControlStop}},
{"restart", {ControlTarget::SERVICE, DoControlRestart}},
@@ -624,6 +628,14 @@
mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
+ // Mount staging areas for devices managed by vold
+ // See storage config details at http://source.android.com/devices/storage/
+ mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+ "mode=0755,uid=0,gid=1000");
+ // /mnt/vendor is used to mount vendor-specific partitions that can not be
+ // part of the vendor partition, e.g. because they are mounted read-write.
+ mkdir("/mnt/vendor", 0755);
+
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
// talk to the outside world...
InitKernelLogging(argv);
diff --git a/init/service.cpp b/init/service.cpp
index f9986c5..03c2cee 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -155,7 +155,7 @@
}
}
-static bool ExpandArgsAndExecv(const std::vector<std::string>& args) {
+static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
std::vector<std::string> expanded_args;
std::vector<char*> c_strings;
@@ -169,6 +169,10 @@
}
c_strings.push_back(nullptr);
+ if (sigstop) {
+ kill(getpid(), SIGSTOP);
+ }
+
return execv(c_strings[0], c_strings.data()) == 0;
}
@@ -582,6 +586,11 @@
return Success();
}
+Result<Success> Service::ParseSigstop(const std::vector<std::string>& args) {
+ sigstop_ = true;
+ return Success();
+}
+
Result<Success> Service::ParseSetenv(const std::vector<std::string>& args) {
environment_vars_.emplace_back(args[1], args[2]);
return Success();
@@ -704,6 +713,7 @@
{"seclabel", {1, 1, &Service::ParseSeclabel}},
{"setenv", {2, 2, &Service::ParseSetenv}},
{"shutdown", {1, 1, &Service::ParseShutdown}},
+ {"sigstop", {0, 0, &Service::ParseSigstop}},
{"socket", {3, 6, &Service::ParseSocket}},
{"user", {1, 1, &Service::ParseUser}},
{"writepid", {1, kMax, &Service::ParseWritepid}},
@@ -862,7 +872,7 @@
// priority. Aborts on failure.
SetProcessAttributes();
- if (!ExpandArgsAndExecv(args_)) {
+ if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}
diff --git a/init/service.h b/init/service.h
index bcf1943..cf38f69 100644
--- a/init/service.h
+++ b/init/service.h
@@ -118,6 +118,7 @@
bool is_override() const { return override_; }
bool process_cgroup_empty() const { return process_cgroup_empty_; }
unsigned long start_order() const { return start_order_; }
+ void set_sigstop(bool value) { sigstop_ = value; }
const std::vector<std::string>& args() const { return args_; }
private:
@@ -153,6 +154,7 @@
Result<Success> ParseSeclabel(const std::vector<std::string>& args);
Result<Success> ParseSetenv(const std::vector<std::string>& args);
Result<Success> ParseShutdown(const std::vector<std::string>& args);
+ Result<Success> ParseSigstop(const std::vector<std::string>& args);
Result<Success> ParseSocket(const std::vector<std::string>& args);
Result<Success> ParseFile(const std::vector<std::string>& args);
Result<Success> ParseUser(const std::vector<std::string>& args);
@@ -213,6 +215,8 @@
std::vector<std::pair<int, rlimit>> rlimits_;
+ bool sigstop_ = false;
+
std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 0983676..7c40a77 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -119,6 +119,9 @@
70200 aggregation (aggregation time|2|3)
70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2)
+# gms refuses to register this log tag, b/30156345
+70220 gms_unknown
+
# libc failure logging
80100 bionic_event_memcpy_buffer_overflow (uid|1)
80105 bionic_event_strcat_buffer_overflow (uid|1)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4f008ac..d3504ad 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -21,9 +21,6 @@
# Set the security context of /adb_keys if present.
restorecon /adb_keys
- # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
- mkdir /mnt 0775 root system
-
# Set the security context of /postinstall if present.
restorecon /postinstall
@@ -83,9 +80,6 @@
chmod 0664 /dev/stune/top-app/tasks
chmod 0664 /dev/stune/rt/tasks
- # Mount staging areas for devices managed by vold
- # See storage config details at http://source.android.com/tech/storage/
- mount tmpfs tmpfs /mnt nodev noexec nosuid mode=0755,uid=0,gid=1000
restorecon_recursive /mnt
mount configfs none /config nodev noexec nosuid
@@ -512,6 +506,7 @@
mkdir /data/ss 0700 system system
mkdir /data/system 0775 system system
+ mkdir /data/system/dropbox 0700 system system
mkdir /data/system/heapdump 0700 system system
mkdir /data/system/users 0775 system system