Files
pebble/src/fw/services/prf/idle_watchdog.c
2025-01-27 11:38:16 -08:00

106 lines
3.2 KiB
C

/*
* Copyright 2024 Google LLC
*
* 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 "idle_watchdog.h"
#include "applib/event_service_client.h"
#include "comm/ble/gap_le_connection.h"
#include "services/common/battery/battery_monitor.h"
#include "services/common/regular_timer.h"
#include "services/common/system_task.h"
#include "system/reboot_reason.h"
#include "kernel/util/standby.h"
#include <bluetooth/classic_connect.h>
#define PRF_IDLE_TIMEOUT_MINUTES 10
static RegularTimerInfo s_is_idle_timer;
static void prv_handle_watchdog_timeout_cb(void *not_used) {
GAPLEConnection *le_connection = gap_le_connection_any();
if (le_connection || bt_driver_classic_is_connected()) {
// We are still connected, don't shut down
return;
}
BatteryChargeState current_state = battery_get_charge_state();
if (current_state.is_plugged) {
// We are plugged in, don't shut down
return;
}
enter_standby(RebootReasonCode_PrfIdle);
}
static void prv_handle_watchdog_timeout(void *not_used) {
system_task_add_callback(prv_handle_watchdog_timeout_cb, NULL);
}
static void prv_start_watchdog(void) {
s_is_idle_timer = (const RegularTimerInfo) {
.cb = prv_handle_watchdog_timeout,
};
regular_timer_add_multiminute_callback(&s_is_idle_timer,
PRF_IDLE_TIMEOUT_MINUTES);
}
void prv_watchdog_feed(PebbleEvent *e, void *context) {
if (regular_timer_is_scheduled(&s_is_idle_timer)) {
prv_start_watchdog();
}
}
void prf_idle_watchdog_start(void) {
// Possible scenario: connect -> 9.9 minutes elapse -> disconnect
// Feeding the watchdog on bt events ensures we don't shutdown after being
// idle for only 0.1 minutes
static EventServiceInfo bt_event_info;
bt_event_info = (EventServiceInfo) {
.type = PEBBLE_BT_CONNECTION_EVENT,
.handler = prv_watchdog_feed,
};
event_service_client_subscribe(&bt_event_info);
// Possible scenario: plug in watch to charge -> 9.9 minutes elapse -> remove watch from charger
// Feeding the watchdog on usb events ensures we don't shutdown as the watch is about to be used
static EventServiceInfo battery_event_info;
battery_event_info = (EventServiceInfo) {
.type = PEBBLE_BATTERY_CONNECTION_EVENT,
.handler = prv_watchdog_feed,
};
event_service_client_subscribe(&battery_event_info);
// The watch is clearly being used if a button was pressed
static EventServiceInfo button_event_info;
button_event_info = (EventServiceInfo) {
.type = PEBBLE_BUTTON_DOWN_EVENT,
.handler = prv_watchdog_feed,
};
event_service_client_subscribe(&button_event_info);
prv_start_watchdog();
}
void prf_idle_watchdog_stop(void) {
if (regular_timer_is_scheduled(&s_is_idle_timer)) {
regular_timer_remove_callback(&s_is_idle_timer);
}
}