@@ -524,6 +524,82 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value,
524
524
return PROP_SUCCESS;
525
525
}
526
526
527
+ static timer_t auto_reboot_timer;
528
+ static bool device_unlocked_at_least_once;
529
+ static bool is_auto_reboot_timer_started;
530
+
531
+ static void auto_reboot_timer_callback (union sigval) {
532
+ LOG (INFO) << " auto_reboot: received timer callback, rebooting" ;
533
+ trigger_shutdown (" reboot" );
534
+ }
535
+
536
+ // all of the auto_reboot_* functions, except for auto_reboot_timer_callback, are called on the
537
+ // same thread
538
+
539
+ static void auto_reboot_timer_init () {
540
+ struct sigevent sev = {};
541
+ sev.sigev_notify = SIGEV_THREAD;
542
+ sev.sigev_notify_function = auto_reboot_timer_callback;
543
+
544
+ if (int r = timer_create (CLOCK_BOOTTIME_ALARM, &sev, &auto_reboot_timer); r != 0 ) {
545
+ LOG (FATAL) << " auto_reboot: timer_create failed: " << strerror (errno);
546
+ }
547
+ }
548
+
549
+ static void auto_reboot_timer_set (time_t duration_sec) {
550
+ const time_t min_duration = 20 ;
551
+ if (duration_sec != 0 && duration_sec < min_duration) {
552
+ LOG (WARNING) << " auto_reboot: raised timer duration from " << duration_sec << " to " << min_duration << " seconds" ;
553
+ duration_sec = min_duration;
554
+ }
555
+ struct itimerspec ts_dur = {};
556
+ ts_dur.it_value .tv_sec = duration_sec;
557
+ struct itimerspec ts_prev = {};
558
+ int flags = 0 ;
559
+ if (int r = timer_settime (auto_reboot_timer, flags, &ts_dur, &ts_prev); r != 0 ) {
560
+ LOG (FATAL) << " auto_reboot: timer_settime failed: " << strerror (errno);
561
+ }
562
+ if (duration_sec > 0 ) {
563
+ LOG (INFO) << " auto_reboot: started timer for " << duration_sec << " seconds" ;
564
+ }
565
+ LOG (DEBUG) << " auto_reboot: prev timer value: " << ts_prev.it_value .tv_sec << " seconds" ;
566
+ }
567
+
568
+ static int auto_reboot_handle_property_set (const std::string& value) {
569
+ LOG (DEBUG) << " auto_reboot: handle_property_set: " << value;
570
+ if (value == " on_device_unlocked" ) {
571
+ device_unlocked_at_least_once = true ;
572
+ if (is_auto_reboot_timer_started) {
573
+ auto_reboot_timer_set (0 );
574
+ is_auto_reboot_timer_started = false ;
575
+ LOG (INFO) << " auto_reboot: on_device_unlocked: stopped timer" ;
576
+ } else {
577
+ LOG (INFO) << " auto_reboot: on_device_unlocked: no started timer" ;
578
+ }
579
+ return PROP_SUCCESS;
580
+ }
581
+
582
+ int duration_sec = atoi (value.c_str ()); // std::stoi can throw
583
+ if (duration_sec <= 0 || (uint64_t ) duration_sec > (uint64_t ) std::numeric_limits<time_t >::max ()) {
584
+ LOG (WARNING) << " auto_reboot: invalid prop value: " << value;
585
+ return PROP_ERROR_INVALID_VALUE;
586
+ }
587
+
588
+ if (device_unlocked_at_least_once) {
589
+ if (is_auto_reboot_timer_started) {
590
+ LOG (INFO) << " auto_reboot: timer is already started, ignored request to restart it;"
591
+ << " requested timer duration: " << value << " seconds" ;
592
+ } else {
593
+ auto_reboot_timer_set ((time_t ) duration_sec);
594
+ is_auto_reboot_timer_started = true ;
595
+ }
596
+ } else {
597
+ LOG (INFO) << " auto_reboot: device was never unlocked, skipped setting timer" ;
598
+ }
599
+
600
+ return PROP_SUCCESS;
601
+ }
602
+
527
603
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*, or std::nullopt
528
604
// if asynchronous.
529
605
std::optional<uint32_t > HandlePropertySet (const std::string& name, const std::string& value,
@@ -566,6 +642,11 @@ std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::st
566
642
return {PROP_SUCCESS};
567
643
}
568
644
645
+ if (name == " sys.auto_reboot_ctl" ) {
646
+ int res = auto_reboot_handle_property_set (value);
647
+ return {res};
648
+ }
649
+
569
650
return PropertySet (name, value, socket, error);
570
651
}
571
652
@@ -1438,6 +1519,8 @@ static void PropertyServiceThread() {
1438
1519
LOG (FATAL) << result.error ();
1439
1520
}
1440
1521
1522
+ auto_reboot_timer_init ();
1523
+
1441
1524
while (true ) {
1442
1525
auto epoll_result = epoll.Wait (std::nullopt);
1443
1526
if (!epoll_result.ok ()) {
0 commit comments