Skip to content

Commit 6c7c4b4

Browse files
muhomorrthestinger
authored andcommitted
add auto-reboot implementation
1 parent cbbe8d9 commit 6c7c4b4

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

init/property_service.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,82 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value,
539539
return PROP_SUCCESS;
540540
}
541541

542+
static timer_t auto_reboot_timer;
543+
static bool device_unlocked_at_least_once;
544+
static bool is_auto_reboot_timer_started;
545+
546+
static void auto_reboot_timer_callback(union sigval) {
547+
LOG(INFO) << "auto_reboot: received timer callback, rebooting";
548+
trigger_shutdown("reboot");
549+
}
550+
551+
// all of the auto_reboot_* functions, except for auto_reboot_timer_callback, are called on the
552+
// same thread
553+
554+
static void auto_reboot_timer_init() {
555+
struct sigevent sev = {};
556+
sev.sigev_notify = SIGEV_THREAD;
557+
sev.sigev_notify_function = auto_reboot_timer_callback;
558+
559+
if (int r = timer_create(CLOCK_BOOTTIME_ALARM, &sev, &auto_reboot_timer); r != 0) {
560+
LOG(FATAL) << "auto_reboot: timer_create failed: " << strerror(errno);
561+
}
562+
}
563+
564+
static void auto_reboot_timer_set(time_t duration_sec) {
565+
const time_t min_duration = 20;
566+
if (duration_sec != 0 && duration_sec < min_duration) {
567+
LOG(WARNING) << "auto_reboot: raised timer duration from " << duration_sec << " to " << min_duration << " seconds";
568+
duration_sec = min_duration;
569+
}
570+
struct itimerspec ts_dur = {};
571+
ts_dur.it_value.tv_sec = duration_sec;
572+
struct itimerspec ts_prev = {};
573+
int flags = 0;
574+
if (int r = timer_settime(auto_reboot_timer, flags, &ts_dur, &ts_prev); r != 0) {
575+
LOG(FATAL) << "auto_reboot: timer_settime failed: " << strerror(errno);
576+
}
577+
if (duration_sec > 0) {
578+
LOG(INFO) << "auto_reboot: started timer for " << duration_sec << " seconds";
579+
}
580+
LOG(DEBUG) << "auto_reboot: prev timer value: " << ts_prev.it_value.tv_sec << " seconds";
581+
}
582+
583+
static int auto_reboot_handle_property_set(const std::string& value) {
584+
LOG(DEBUG) << "auto_reboot: handle_property_set: " << value;
585+
if (value == "on_device_unlocked") {
586+
device_unlocked_at_least_once = true;
587+
if (is_auto_reboot_timer_started) {
588+
auto_reboot_timer_set(0);
589+
is_auto_reboot_timer_started = false;
590+
LOG(INFO) << "auto_reboot: on_device_unlocked: stopped timer";
591+
} else {
592+
LOG(INFO) << "auto_reboot: on_device_unlocked: no started timer";
593+
}
594+
return PROP_SUCCESS;
595+
}
596+
597+
int duration_sec = atoi(value.c_str()); // std::stoi can throw
598+
if (duration_sec <= 0 || (uint64_t) duration_sec > (uint64_t) std::numeric_limits<time_t>::max()) {
599+
LOG(WARNING) << "auto_reboot: invalid prop value: " << value;
600+
return PROP_ERROR_INVALID_VALUE;
601+
}
602+
603+
if (device_unlocked_at_least_once) {
604+
if (is_auto_reboot_timer_started) {
605+
LOG(INFO) << "auto_reboot: timer is already started, ignored request to restart it;"
606+
<< " requested timer duration: " << value << " seconds";
607+
} else {
608+
auto_reboot_timer_set((time_t) duration_sec);
609+
is_auto_reboot_timer_started = true;
610+
}
611+
} else {
612+
LOG(INFO) << "auto_reboot: device was never unlocked, skipped setting timer";
613+
}
614+
615+
return PROP_SUCCESS;
616+
}
617+
542618
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*, or std::nullopt
543619
// if asynchronous.
544620
std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::string& value,
@@ -581,6 +657,11 @@ std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::st
581657
return {PROP_SUCCESS};
582658
}
583659

660+
if (name == "sys.auto_reboot_ctl") {
661+
int res = auto_reboot_handle_property_set(value);
662+
return {res};
663+
}
664+
584665
return PropertySet(name, value, socket, error);
585666
}
586667

@@ -1462,6 +1543,8 @@ static void PropertyServiceThread(int fd, bool listen_init) {
14621543
}
14631544
}
14641545

1546+
auto_reboot_timer_init();
1547+
14651548
while (true) {
14661549
auto epoll_result = epoll.Wait(std::nullopt);
14671550
if (!epoll_result.ok()) {

0 commit comments

Comments
 (0)