133 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2020 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 <signal.h>
 | |
| #include <sys/time.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <mutex>
 | |
| #include <thread>
 | |
| 
 | |
| #include <android-base/logging.h>
 | |
| #include <android-base/parsebool.h>
 | |
| #include <android-base/parseint.h>
 | |
| #include <android-base/properties.h>
 | |
| #include <android-base/thread_annotations.h>
 | |
| 
 | |
| #include "property_monitor.h"
 | |
| 
 | |
| static constexpr char kAdbWatchdogProperty[] = "persist.adb.watchdog";
 | |
| static constexpr char kTestHarnessProperty[] = "persist.sys.test_harness";
 | |
| 
 | |
| static constexpr unsigned int kDefaultAdbWatchdogTimeoutSeconds = 600;
 | |
| static unsigned int g_watchdog_timeout_seconds;
 | |
| 
 | |
| static std::mutex g_watchdog_mutex [[clang::no_destroy]];
 | |
| 
 | |
| // The watchdog is "running" when it's enabled via property and there are no connected clients.
 | |
| static bool g_watchdog_running GUARDED_BY(g_watchdog_mutex) = false;
 | |
| 
 | |
| static PropertyMonitor g_property_monitor [[clang::no_destroy]];
 | |
| 
 | |
| static void UpdateWatchdog() REQUIRES(g_watchdog_mutex) {
 | |
|     static std::once_flag once;
 | |
|     std::call_once(once, []() {
 | |
|         signal(SIGALRM, [](int) {
 | |
|             execl("/system/bin/reboot", "/system/bin/reboot", "bootloader", nullptr);
 | |
|         });
 | |
|     });
 | |
| 
 | |
|     static bool alarm_set = false;
 | |
| 
 | |
|     static auto Arm = []() {
 | |
|         LOG(INFO) << "adb watchdog armed, triggering in " << g_watchdog_timeout_seconds
 | |
|                   << " seconds";
 | |
|         alarm(g_watchdog_timeout_seconds);
 | |
|         alarm_set = true;
 | |
|     };
 | |
| 
 | |
|     static auto Disarm = []() {
 | |
|         unsigned int previous = alarm(0);
 | |
|         if (previous != 0) {
 | |
|             LOG(INFO) << "adb watchdog disarmed with " << previous << " seconds left";
 | |
|         }
 | |
|         alarm_set = false;
 | |
|     };
 | |
| 
 | |
|     bool watchdog_enabled = android::base::GetBoolProperty(
 | |
|             kAdbWatchdogProperty, android::base::GetBoolProperty(kTestHarnessProperty, false));
 | |
|     if (!watchdog_enabled) {
 | |
|         if (alarm_set) {
 | |
|             Disarm();
 | |
|         }
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (g_watchdog_running) {
 | |
|         if (!alarm_set) {
 | |
|             Arm();
 | |
|         }
 | |
|     } else {
 | |
|         Disarm();
 | |
|     }
 | |
| }
 | |
| 
 | |
| namespace watchdog {
 | |
| 
 | |
| void Start() {
 | |
|     std::lock_guard<std::mutex> lock(g_watchdog_mutex);
 | |
|     g_watchdog_running = true;
 | |
|     UpdateWatchdog();
 | |
| }
 | |
| 
 | |
| void Stop() {
 | |
|     std::lock_guard<std::mutex> lock(g_watchdog_mutex);
 | |
|     g_watchdog_running = false;
 | |
|     UpdateWatchdog();
 | |
| }
 | |
| 
 | |
| void Initialize() {
 | |
|     for (auto& property : {kAdbWatchdogProperty, kTestHarnessProperty}) {
 | |
|         g_property_monitor.Add(property, [property](std::string value) {
 | |
|             LOG(INFO) << property << " set to '" << value << "'";
 | |
| 
 | |
|             std::lock_guard<std::mutex> lock(g_watchdog_mutex);
 | |
|             UpdateWatchdog();
 | |
|             return true;
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     g_property_monitor.Add("persist.adb.watchdog.timeout_secs", [](std::string value) {
 | |
|         // This presumably isn't going to change while the watchdog is armed,
 | |
|         // so we don't need to recalculate a timer.
 | |
|         {
 | |
|             std::lock_guard<std::mutex> lock(g_watchdog_mutex);
 | |
|             if (!android::base::ParseUint(value, &g_watchdog_timeout_seconds)) {
 | |
|                 g_watchdog_timeout_seconds = kDefaultAdbWatchdogTimeoutSeconds;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         LOG(INFO) << "adb watchdog timeout set to " << g_watchdog_timeout_seconds << " seconds";
 | |
|         return true;
 | |
|     });
 | |
| 
 | |
|     Start();
 | |
|     std::thread([]() { g_property_monitor.Run(); }).detach();
 | |
| }
 | |
| 
 | |
| }  // namespace watchdog
 |