Merge "adbd: Depend only on libminijail."
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 78db69d..4721e2f 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -124,12 +124,9 @@
AID_INET, AID_NET_BT, AID_NET_BT_ADMIN,
AID_SDCARD_R, AID_SDCARD_RW, AID_NET_BW_STATS,
AID_READPROC};
- if (minijail_set_supplementary_gids(
- jail.get(),
- sizeof(groups) / sizeof(groups[0]),
- groups) != 0) {
- LOG(FATAL) << "Could not configure supplementary groups";
- }
+ minijail_set_supplementary_gids(jail.get(),
+ sizeof(groups) / sizeof(groups[0]),
+ groups);
// Don't listen on a port (default 5037) if running in secure mode.
// Don't run as root if running in secure mode.
diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp
index e8fe6c9..4ec8979 100644
--- a/adb/line_printer.cpp
+++ b/adb/line_printer.cpp
@@ -67,7 +67,7 @@
void LinePrinter::Print(string to_print, LineType type) {
if (!smart_terminal_) {
- Out(to_print);
+ Out(to_print + "\n");
return;
}
diff --git a/debuggerd/test/selinux/android.h b/debuggerd/test/selinux/android.h
new file mode 100644
index 0000000..abed087
--- /dev/null
+++ b/debuggerd/test/selinux/android.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+extern "C" int selinux_android_restorecon(const char*, unsigned int);
diff --git a/init/Android.mk b/init/Android.mk
index d6cb4e5..66ce8a8 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -52,7 +52,7 @@
service.cpp \
util.cpp \
-LOCAL_STATIC_LIBRARIES := libbase
+LOCAL_STATIC_LIBRARIES := libbase libselinux
LOCAL_MODULE := libinit
LOCAL_SANITIZE := integer
LOCAL_CLANG := true
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 10f9d81..d2291bb 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -39,6 +39,7 @@
#include <selinux/label.h>
#include <fs_mgr.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <cutils/partition_utils.h>
#include <cutils/android_reboot.h>
@@ -53,6 +54,7 @@
#include "log.h"
#include "property_service.h"
#include "service.h"
+#include "signal_handler.h"
#include "util.h"
#define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
@@ -62,6 +64,8 @@
// System call provided by bionic but not in any header file.
extern "C" int init_module(void *, unsigned long, const char *);
+static const int kTerminateServiceDelayMicroSeconds = 50000;
+
static int insmod(const char *filename, const char *options) {
std::string module;
if (!read_file(filename, &module)) {
@@ -608,6 +612,42 @@
return -EINVAL;
}
+ std::string timeout = property_get("ro.build.shutdown_timeout");
+ unsigned int delay = 0;
+
+ if (android::base::ParseUint(timeout.c_str(), &delay) && delay > 0) {
+ Timer t;
+ // Ask all services to terminate.
+ ServiceManager::GetInstance().ForEachService(
+ [] (Service* s) { s->Terminate(); });
+
+ while (t.duration() < delay) {
+ ServiceManager::GetInstance().ReapAnyOutstandingChildren();
+
+ int service_count = 0;
+ ServiceManager::GetInstance().ForEachService(
+ [&service_count] (Service* s) {
+ // Count the number of services running.
+ // Exclude the console as it will ignore the SIGTERM signal
+ // and not exit.
+ // Note: SVC_CONSOLE actually means "requires console" but
+ // it is only used by the shell.
+ if (s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
+ service_count++;
+ }
+ });
+
+ if (service_count == 0) {
+ // All terminable services terminated. We can exit early.
+ break;
+ }
+
+ // Wait a bit before recounting the number or running services.
+ usleep(kTerminateServiceDelayMicroSeconds);
+ }
+ NOTICE("Terminating running services took %.02f seconds", t.duration());
+ }
+
return android_reboot_with_callback(cmd, 0, reboot_target,
callback_on_ro_remount);
}
diff --git a/init/service.cpp b/init/service.cpp
index 40a4bc7..0ddc484 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -19,6 +19,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
@@ -531,6 +532,17 @@
StopOrReset(SVC_DISABLED);
}
+void Service::Terminate() {
+ flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
+ flags_ |= SVC_DISABLED;
+ if (pid_) {
+ NOTICE("Sending SIGTERM to service '%s' (pid %d)...\n", name_.c_str(),
+ pid_);
+ kill(-pid_, SIGTERM);
+ NotifyStateChange("stopping");
+ }
+}
+
void Service::Restart() {
if (flags_ & SVC_RUNNING) {
/* Stop, wait, then start the service. */
@@ -724,9 +736,9 @@
return nullptr;
}
-void ServiceManager::ForEachService(void (*func)(Service* svc)) const {
+void ServiceManager::ForEachService(std::function<void(Service*)> callback) const {
for (const auto& s : services_) {
- func(s.get());
+ callback(s.get());
}
}
@@ -767,6 +779,53 @@
INFO("\n");
}
+bool ServiceManager::ReapOneProcess() {
+ int status;
+ pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
+ if (pid == 0) {
+ return false;
+ } else if (pid == -1) {
+ ERROR("waitpid failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ Service* svc = FindServiceByPid(pid);
+
+ std::string name;
+ if (svc) {
+ name = android::base::StringPrintf("Service '%s' (pid %d)",
+ svc->name().c_str(), pid);
+ } else {
+ name = android::base::StringPrintf("Untracked pid %d", pid);
+ }
+
+ if (WIFEXITED(status)) {
+ NOTICE("%s exited with status %d\n", name.c_str(), WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ NOTICE("%s killed by signal %d\n", name.c_str(), WTERMSIG(status));
+ } else if (WIFSTOPPED(status)) {
+ NOTICE("%s stopped by signal %d\n", name.c_str(), WSTOPSIG(status));
+ } else {
+ NOTICE("%s state changed", name.c_str());
+ }
+
+ if (!svc) {
+ return true;
+ }
+
+ if (svc->Reap()) {
+ waiting_for_exec = false;
+ RemoveService(*svc);
+ }
+
+ return true;
+}
+
+void ServiceManager::ReapAnyOutstandingChildren() {
+ while (ReapOneProcess()) {
+ }
+}
+
bool ServiceParser::ParseSection(const std::vector<std::string>& args,
std::string* err) {
if (args.size() < 3) {
diff --git a/init/service.h b/init/service.h
index 10eb736..35abde9 100644
--- a/init/service.h
+++ b/init/service.h
@@ -82,6 +82,7 @@
bool Enable();
void Reset();
void Stop();
+ void Terminate();
void Restart();
void RestartIfNeeded(time_t& process_needs_restart);
bool Reap();
@@ -167,17 +168,22 @@
Service* FindServiceByName(const std::string& name) const;
Service* FindServiceByPid(pid_t pid) const;
Service* FindServiceByKeychord(int keychord_id) const;
- void ForEachService(void (*func)(Service* svc)) const;
+ void ForEachService(std::function<void(Service*)> callback) const;
void ForEachServiceInClass(const std::string& classname,
void (*func)(Service* svc)) const;
void ForEachServiceWithFlags(unsigned matchflags,
void (*func)(Service* svc)) const;
+ void ReapAnyOutstandingChildren();
void RemoveService(const Service& svc);
void DumpState() const;
private:
ServiceManager();
+ // Cleans up a child process that exited.
+ // Returns true iff a children was cleaned up.
+ bool ReapOneProcess();
+
static int exec_count_; // Every service needs a unique name.
std::vector<std::unique_ptr<Service>> services_;
};
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index e7d42cb..ea483d4 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -37,62 +37,12 @@
static int signal_write_fd = -1;
static int signal_read_fd = -1;
-static std::string DescribeStatus(int status) {
- if (WIFEXITED(status)) {
- return android::base::StringPrintf("exited with status %d", WEXITSTATUS(status));
- } else if (WIFSIGNALED(status)) {
- return android::base::StringPrintf("killed by signal %d", WTERMSIG(status));
- } else if (WIFSTOPPED(status)) {
- return android::base::StringPrintf("stopped by signal %d", WSTOPSIG(status));
- } else {
- return "state changed";
- }
-}
-
-static bool wait_for_one_process() {
- int status;
- pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
- if (pid == 0) {
- return false;
- } else if (pid == -1) {
- ERROR("waitpid failed: %s\n", strerror(errno));
- return false;
- }
-
- Service* svc = ServiceManager::GetInstance().FindServiceByPid(pid);
-
- std::string name;
- if (svc) {
- name = android::base::StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid);
- } else {
- name = android::base::StringPrintf("Untracked pid %d", pid);
- }
-
- NOTICE("%s %s\n", name.c_str(), DescribeStatus(status).c_str());
-
- if (!svc) {
- return true;
- }
-
- if (svc->Reap()) {
- waiting_for_exec = false;
- ServiceManager::GetInstance().RemoveService(*svc);
- }
-
- return true;
-}
-
-static void reap_any_outstanding_children() {
- while (wait_for_one_process()) {
- }
-}
-
static void handle_signal() {
// Clear outstanding requests.
char buf[32];
read(signal_read_fd, buf, sizeof(buf));
- reap_any_outstanding_children();
+ ServiceManager::GetInstance().ReapAnyOutstandingChildren();
}
static void SIGCHLD_handler(int) {
@@ -119,7 +69,7 @@
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, 0);
- reap_any_outstanding_children();
+ ServiceManager::GetInstance().ReapAnyOutstandingChildren();
register_epoll_handler(signal_read_fd, handle_signal);
}
diff --git a/metricsd/metrics_collector.cc b/metricsd/metrics_collector.cc
index 97690dd..2cf2338 100644
--- a/metricsd/metrics_collector.cc
+++ b/metricsd/metrics_collector.cc
@@ -71,6 +71,7 @@
const char kVmStatFileName[] = "/proc/vmstat";
const char kWeaveComponent[] = "metrics";
+const char kWeaveTrait[] = "_metrics";
} // namespace
@@ -234,23 +235,15 @@
bus_->AssertOnDBusThread();
CHECK(bus_->SetUpAsyncOperations());
- device_ = weaved::Device::CreateInstance(
- bus_,
- base::Bind(&MetricsCollector::UpdateWeaveState, base::Unretained(this)));
- device_->AddComponent(kWeaveComponent, {"_metrics"});
- device_->AddCommandHandler(
- kWeaveComponent,
- "_metrics.enableAnalyticsReporting",
- base::Bind(&MetricsCollector::OnEnableMetrics, base::Unretained(this)));
- device_->AddCommandHandler(
- kWeaveComponent,
- "_metrics.disableAnalyticsReporting",
- base::Bind(&MetricsCollector::OnDisableMetrics, base::Unretained(this)));
+ weave_service_subscription_ = weaved::Service::Connect(
+ brillo::MessageLoop::current(),
+ base::Bind(&MetricsCollector::OnWeaveServiceConnected,
+ weak_ptr_factory_.GetWeakPtr()));
latest_cpu_use_microseconds_ = cpu_usage_collector_->GetCumulativeCpuUse();
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
- base::Unretained(this)),
+ weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
return EX_OK;
@@ -260,12 +253,28 @@
brillo::DBusDaemon::OnShutdown(return_code);
}
-void MetricsCollector::OnEnableMetrics(
- const std::weak_ptr<weaved::Command>& cmd) {
- auto command = cmd.lock();
- if (!command)
+void MetricsCollector::OnWeaveServiceConnected(
+ const std::weak_ptr<weaved::Service>& service) {
+ service_ = service;
+ auto weave_service = service_.lock();
+ if (!weave_service)
return;
+ weave_service->AddComponent(kWeaveComponent, {kWeaveTrait}, nullptr);
+ weave_service->AddCommandHandler(
+ kWeaveComponent, kWeaveTrait, "enableAnalyticsReporting",
+ base::Bind(&MetricsCollector::OnEnableMetrics,
+ weak_ptr_factory_.GetWeakPtr()));
+ weave_service->AddCommandHandler(
+ kWeaveComponent, kWeaveTrait, "disableAnalyticsReporting",
+ base::Bind(&MetricsCollector::OnDisableMetrics,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ UpdateWeaveState();
+}
+
+void MetricsCollector::OnEnableMetrics(
+ std::unique_ptr<weaved::Command> command) {
if (base::WriteFile(
shared_metrics_directory_.Append(metrics::kConsentFileName), "", 0) !=
0) {
@@ -280,11 +289,7 @@
}
void MetricsCollector::OnDisableMetrics(
- const std::weak_ptr<weaved::Command>& cmd) {
- auto command = cmd.lock();
- if (!command)
- return;
-
+ std::unique_ptr<weaved::Command> command) {
if (!base::DeleteFile(
shared_metrics_directory_.Append(metrics::kConsentFileName), false)) {
PLOG(ERROR) << "Could not delete the consent file.";
@@ -298,16 +303,16 @@
}
void MetricsCollector::UpdateWeaveState() {
- if (!device_)
+ auto weave_service = service_.lock();
+ if (!weave_service)
return;
std::string enabled =
metrics_lib_->AreMetricsEnabled() ? "enabled" : "disabled";
- if (!device_->SetStateProperty(kWeaveComponent,
- "_metrics.analyticsReportingState",
- enabled,
- nullptr)) {
+ if (!weave_service->SetStateProperty(kWeaveComponent, kWeaveTrait,
+ "analyticsReportingState", enabled,
+ nullptr)) {
LOG(ERROR) << "failed to update weave's state";
}
}
@@ -381,8 +386,8 @@
}
base::TimeDelta waitDelta = base::TimeDelta::FromSeconds(wait);
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MeminfoCallback, base::Unretained(this),
- waitDelta),
+ base::Bind(&MetricsCollector::MeminfoCallback,
+ weak_ptr_factory_.GetWeakPtr(), waitDelta),
waitDelta);
}
@@ -396,8 +401,8 @@
// Make both calls even if the first one fails.
if (ProcessMeminfo(meminfo_raw)) {
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MeminfoCallback, base::Unretained(this),
- wait),
+ base::Bind(&MetricsCollector::MeminfoCallback,
+ weak_ptr_factory_.GetWeakPtr(), wait),
wait);
}
}
@@ -564,7 +569,8 @@
return;
}
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MemuseCallback, base::Unretained(this)),
+ base::Bind(&MetricsCollector::MemuseCallback,
+ weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(interval));
}
@@ -750,6 +756,6 @@
UpdateStats(TimeTicks::Now(), Time::Now());
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
- base::Unretained(this)),
+ weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
}
diff --git a/metricsd/metrics_collector.h b/metricsd/metrics_collector.h
index 45ef63d..ca4ae52 100644
--- a/metricsd/metrics_collector.h
+++ b/metricsd/metrics_collector.h
@@ -25,10 +25,12 @@
#include <vector>
#include <base/files/file_path.h>
+#include <base/memory/weak_ptr.h>
#include <base/time/time.h>
+#include <brillo/binder_watcher.h>
#include <brillo/daemons/dbus_daemon.h>
#include <libweaved/command.h>
-#include <libweaved/device.h>
+#include <libweaved/service.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "collectors/averaged_statistics_collector.h"
@@ -114,10 +116,10 @@
};
// Enables metrics reporting.
- void OnEnableMetrics(const std::weak_ptr<weaved::Command>& cmd);
+ void OnEnableMetrics(std::unique_ptr<weaved::Command> command);
// Disables metrics reporting.
- void OnDisableMetrics(const std::weak_ptr<weaved::Command>& cmd);
+ void OnDisableMetrics(std::unique_ptr<weaved::Command> command);
// Updates the weave device state.
void UpdateWeaveState();
@@ -216,6 +218,10 @@
// Reads a string from a file and converts it to uint64_t.
static bool ReadFileToUint64(const base::FilePath& path, uint64_t* value);
+ // Callback invoked when a connection to weaved's service is established
+ // over Binder interface.
+ void OnWeaveServiceConnected(const std::weak_ptr<weaved::Service>& service);
+
// VARIABLES
// Test mode.
@@ -272,7 +278,10 @@
unique_ptr<DiskUsageCollector> disk_usage_collector_;
unique_ptr<AveragedStatisticsCollector> averaged_stats_collector_;
- std::unique_ptr<weaved::Device> device_;
+ unique_ptr<weaved::Service::Subscription> weave_service_subscription_;
+ std::weak_ptr<weaved::Service> service_;
+
+ base::WeakPtrFactory<MetricsCollector> weak_ptr_factory_{this};
};
#endif // METRICS_METRICS_COLLECTOR_H_
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a52d87d..d322402 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -332,6 +332,7 @@
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
mkdir /data/local 0751 root root
mkdir /data/misc/media 0700 media media
+ mkdir /data/misc/vold 0700 root root
mkdir /data/misc/boottrace 0771 system shell
mkdir /data/misc/update_engine 0700 root root
mkdir /data/misc/trace 0700 root root