diff --git a/device.mk b/device.mk index 7defec0..c0f39f6 100644 --- a/device.mk +++ b/device.mk @@ -20,3 +20,10 @@ PRODUCT_SOONG_NAMESPACES += \ # Disable OMX PRODUCT_PROPERTY_OVERRIDES += \ vendor.media.omx=0 + +# Platform watchdogd +PRODUCT_PACKAGES += gs_watchdogd +PRODUCT_SOONG_NAMESPACES += \ + device/google/gs-common/gs_watchdogd +SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += \ + hardware/google/pixel-sepolicy/gs_watchdogd diff --git a/gs_watchdogd/Android.bp b/gs_watchdogd/Android.bp new file mode 100644 index 0000000..708f2d9 --- /dev/null +++ b/gs_watchdogd/Android.bp @@ -0,0 +1,20 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_binary { + name: "gs_watchdogd", + recovery_available: true, + system_ext_specific: true, + init_rc: ["init.gs_watchdogd.rc"], + srcs: ["gs_watchdogd.cpp"], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + shared_libs: ["libbase"], + sanitize: { + misc_undefined: ["signed-integer-overflow"], + }, +} diff --git a/gs_watchdogd/gs_watchdogd.cpp b/gs_watchdogd/gs_watchdogd.cpp new file mode 100644 index 0000000..59b089c --- /dev/null +++ b/gs_watchdogd/gs_watchdogd.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DEV_GLOB "/sys/devices/platform/*.watchdog_cl0/watchdog/watchdog*" + +using android::base::Basename; +using android::base::StringPrintf; + +int main(int argc, char** argv) { + android::base::InitLogging(argv, &android::base::KernelLogger); + + int interval = 10; + if (argc >= 2) interval = atoi(argv[1]); + + int margin = 10; + if (argc >= 3) margin = atoi(argv[2]); + + LOG(INFO) << "gs_watchdogd started (interval " << interval << ", margin " << margin << ")!"; + + glob_t globbuf; + int ret = glob(DEV_GLOB, GLOB_MARK, nullptr, &globbuf); + if (ret) { + PLOG(ERROR) << "Failed to lookup glob " << DEV_GLOB << ": " << ret; + return 1; + } + + if (globbuf.gl_pathc > 1) { + PLOG(WARNING) << "Multiple watchdog dev path found by " << DEV_GLOB; + } + + std::string dev_path = StringPrintf("/dev/%s", Basename(globbuf.gl_pathv[0]).c_str()); + globfree(&globbuf); + + int fd = open(dev_path.c_str(), O_RDWR | O_CLOEXEC); + if (fd == -1) { + PLOG(ERROR) << "Failed to open " << dev_path; + return 1; + } + + int timeout = interval + margin; + ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeout); + if (ret) { + PLOG(ERROR) << "Failed to set timeout to " << timeout; + ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout); + if (ret) { + PLOG(ERROR) << "Failed to get timeout"; + } else { + if (timeout > margin) { + interval = timeout - margin; + } else { + interval = 1; + } + LOG(WARNING) << "Adjusted interval to timeout returned by driver: " + << "timeout " << timeout << ", interval " << interval << ", margin " + << margin; + } + } + + while (true) { + write(fd, "", 1); + sleep(interval); + } +} diff --git a/gs_watchdogd/init.gs_watchdogd.rc b/gs_watchdogd/init.gs_watchdogd.rc new file mode 100644 index 0000000..7a65945 --- /dev/null +++ b/gs_watchdogd/init.gs_watchdogd.rc @@ -0,0 +1,8 @@ +# Set watchdog timer to 30 seconds and pet it every 10 seconds to get a 20 second margin +service gs_watchdogd /system_ext/bin/gs_watchdogd 10 20 + class core + oneshot + seclabel u:r:gs_watchdogd:s0 + +on init && property:vendor.all.devices.ready=1 + start gs_watchdogd