From 7ca0418c82173fa1cff9537eaf1f030b5a712e9a Mon Sep 17 00:00:00 2001
From: mark9064 <30447455+mark9064@users.noreply.github.com>
Date: Fri, 23 Aug 2024 00:15:24 +0100
Subject: [PATCH] Refactor doNotGoToSleep to a wakelock counter

---
 src/CMakeLists.txt                       |  3 +++
 src/displayapp/screens/Alarm.cpp         |  6 +++---
 src/displayapp/screens/Alarm.h           |  3 ++-
 src/displayapp/screens/FlashLight.cpp    |  5 ++---
 src/displayapp/screens/FlashLight.h      |  3 ++-
 src/displayapp/screens/HeartRate.cpp     |  9 ++++----
 src/displayapp/screens/HeartRate.h       |  3 ++-
 src/displayapp/screens/Metronome.cpp     |  7 +++---
 src/displayapp/screens/Metronome.h       |  3 ++-
 src/displayapp/screens/Notifications.cpp |  7 +++---
 src/displayapp/screens/Notifications.h   |  3 ++-
 src/displayapp/screens/StopWatch.cpp     |  7 +++---
 src/displayapp/screens/StopWatch.h       |  3 ++-
 src/systemtask/SystemTask.cpp            | 16 ++++++--------
 src/systemtask/SystemTask.h              |  4 ++--
 src/systemtask/WakeLock.cpp              | 27 ++++++++++++++++++++++++
 src/systemtask/WakeLock.h                | 19 +++++++++++++++++
 17 files changed, 87 insertions(+), 41 deletions(-)
 create mode 100644 src/systemtask/WakeLock.cpp
 create mode 100644 src/systemtask/WakeLock.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc3b6176..0a97a015 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -478,6 +478,7 @@ list(APPEND SOURCE_FILES
 
         systemtask/SystemTask.cpp
         systemtask/SystemMonitor.cpp
+        systemtask/WakeLock.cpp
         drivers/TwiMaster.cpp
 
         heartratetask/HeartRateTask.cpp
@@ -542,6 +543,7 @@ list(APPEND RECOVERY_SOURCE_FILES
 
         systemtask/SystemTask.cpp
         systemtask/SystemMonitor.cpp
+        systemtask/WakeLock.cpp
         drivers/TwiMaster.cpp
         components/rle/RleDecoder.cpp
         components/heartrate/HeartRateController.cpp
@@ -660,6 +662,7 @@ set(INCLUDE_FILES
         displayapp/InfiniTimeTheme.h
         systemtask/SystemTask.h
         systemtask/SystemMonitor.h
+        systemtask/WakeLock.h
         displayapp/screens/Symbols.h
         drivers/TwiMaster.h
         heartratetask/HeartRateTask.h
diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp
index cbc702f3..292fb075 100644
--- a/src/displayapp/screens/Alarm.cpp
+++ b/src/displayapp/screens/Alarm.cpp
@@ -48,7 +48,7 @@ Alarm::Alarm(Controllers::AlarmController& alarmController,
              Controllers::Settings::ClockType clockType,
              System::SystemTask& systemTask,
              Controllers::MotorController& motorController)
-  : alarmController {alarmController}, systemTask {systemTask}, motorController {motorController} {
+  : alarmController {alarmController}, wakeLock(systemTask), motorController {motorController} {
 
   hourCounter.Create();
   lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
@@ -205,7 +205,7 @@ void Alarm::SetAlerting() {
   lv_obj_set_hidden(btnStop, false);
   taskStopAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this);
   motorController.StartRinging();
-  systemTask.PushMessage(System::Messages::DisableSleeping);
+  wakeLock.Lock();
 }
 
 void Alarm::StopAlerting() {
@@ -216,7 +216,7 @@ void Alarm::StopAlerting() {
     lv_task_del(taskStopAlarm);
     taskStopAlarm = nullptr;
   }
-  systemTask.PushMessage(System::Messages::EnableSleeping);
+  wakeLock.Release();
   lv_obj_set_hidden(enableSwitch, false);
   lv_obj_set_hidden(btnStop, true);
 }
diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h
index 444102cb..a875b275 100644
--- a/src/displayapp/screens/Alarm.h
+++ b/src/displayapp/screens/Alarm.h
@@ -22,6 +22,7 @@
 #include "displayapp/screens/Screen.h"
 #include "displayapp/widgets/Counter.h"
 #include "displayapp/Controllers.h"
+#include "systemtask/WakeLock.h"
 #include "Symbols.h"
 
 namespace Pinetime {
@@ -43,7 +44,7 @@ namespace Pinetime {
 
       private:
         Controllers::AlarmController& alarmController;
-        System::SystemTask& systemTask;
+        System::WakeLock wakeLock;
         Controllers::MotorController& motorController;
 
         lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch;
diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp
index f169fac1..7e0caff1 100644
--- a/src/displayapp/screens/FlashLight.cpp
+++ b/src/displayapp/screens/FlashLight.cpp
@@ -15,7 +15,7 @@ namespace {
 }
 
 FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController)
-  : systemTask {systemTask}, brightnessController {brightnessController} {
+  : wakeLock(systemTask), brightnessController {brightnessController} {
 
   previousBrightnessLevel = brightnessController.Level();
   brightnessController.Set(Controllers::BrightnessController::Levels::Low);
@@ -47,14 +47,13 @@ FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessCo
   backgroundAction->user_data = this;
   lv_obj_set_event_cb(backgroundAction, EventHandler);
 
-  systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+  wakeLock.Lock();
 }
 
 FlashLight::~FlashLight() {
   lv_obj_clean(lv_scr_act());
   lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
   brightnessController.Set(previousBrightnessLevel);
-  systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
 }
 
 void FlashLight::SetColors() {
diff --git a/src/displayapp/screens/FlashLight.h b/src/displayapp/screens/FlashLight.h
index c5404e93..00ef4a7e 100644
--- a/src/displayapp/screens/FlashLight.h
+++ b/src/displayapp/screens/FlashLight.h
@@ -3,6 +3,7 @@
 #include "displayapp/screens/Screen.h"
 #include "components/brightness/BrightnessController.h"
 #include "systemtask/SystemTask.h"
+#include "systemtask/WakeLock.h"
 #include <cstdint>
 #include <lvgl/lvgl.h>
 
@@ -23,7 +24,7 @@ namespace Pinetime {
         void SetIndicators();
         void SetColors();
 
-        Pinetime::System::SystemTask& systemTask;
+        Pinetime::System::WakeLock wakeLock;
         Controllers::BrightnessController& brightnessController;
 
         Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High;
diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp
index 9677be3b..1a84d349 100644
--- a/src/displayapp/screens/HeartRate.cpp
+++ b/src/displayapp/screens/HeartRate.cpp
@@ -29,7 +29,7 @@ namespace {
 }
 
 HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, System::SystemTask& systemTask)
-  : heartRateController {heartRateController}, systemTask {systemTask} {
+  : heartRateController {heartRateController}, wakeLock(systemTask) {
   bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
   label_hr = lv_label_create(lv_scr_act(), nullptr);
 
@@ -63,7 +63,7 @@ HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, Syst
   label_startStop = lv_label_create(btn_startStop, nullptr);
   UpdateStartStopButton(isHrRunning);
   if (isHrRunning) {
-    systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+    wakeLock.Lock();
   }
 
   taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
@@ -72,7 +72,6 @@ HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, Syst
 HeartRate::~HeartRate() {
   lv_task_del(taskRefresh);
   lv_obj_clean(lv_scr_act());
-  systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
 }
 
 void HeartRate::Refresh() {
@@ -101,12 +100,12 @@ void HeartRate::OnStartStopEvent(lv_event_t event) {
     if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) {
       heartRateController.Start();
       UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
-      systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+      wakeLock.Lock();
       lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight);
     } else {
       heartRateController.Stop();
       UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
-      systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
+      wakeLock.Release();
       lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
     }
   }
diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h
index bf39209a..88b4918c 100644
--- a/src/displayapp/screens/HeartRate.h
+++ b/src/displayapp/screens/HeartRate.h
@@ -4,6 +4,7 @@
 #include <chrono>
 #include "displayapp/screens/Screen.h"
 #include "systemtask/SystemTask.h"
+#include "systemtask/WakeLock.h"
 #include "Symbols.h"
 #include <lvgl/src/lv_core/lv_style.h>
 #include <lvgl/src/lv_core/lv_obj.h>
@@ -27,7 +28,7 @@ namespace Pinetime {
 
       private:
         Controllers::HeartRateController& heartRateController;
-        Pinetime::System::SystemTask& systemTask;
+        Pinetime::System::WakeLock wakeLock;
         void UpdateStartStopButton(bool isRunning);
         lv_obj_t* label_hr;
         lv_obj_t* label_bpm;
diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp
index 314fde73..6b758470 100644
--- a/src/displayapp/screens/Metronome.cpp
+++ b/src/displayapp/screens/Metronome.cpp
@@ -22,7 +22,7 @@ namespace {
 }
 
 Metronome::Metronome(Controllers::MotorController& motorController, System::SystemTask& systemTask)
-  : motorController {motorController}, systemTask {systemTask} {
+  : motorController {motorController}, wakeLock(systemTask) {
 
   bpmArc = lv_arc_create(lv_scr_act(), nullptr);
   bpmArc->user_data = this;
@@ -72,7 +72,6 @@ Metronome::Metronome(Controllers::MotorController& motorController, System::Syst
 
 Metronome::~Metronome() {
   lv_task_del(taskRefresh);
-  systemTask.PushMessage(System::Messages::EnableSleeping);
   lv_obj_clean(lv_scr_act());
 }
 
@@ -128,12 +127,12 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
         metronomeStarted = !metronomeStarted;
         if (metronomeStarted) {
           lv_label_set_text_static(lblPlayPause, Symbols::pause);
-          systemTask.PushMessage(System::Messages::DisableSleeping);
+          wakeLock.Lock();
           startTime = xTaskGetTickCount();
           counter = 1;
         } else {
           lv_label_set_text_static(lblPlayPause, Symbols::play);
-          systemTask.PushMessage(System::Messages::EnableSleeping);
+          wakeLock.Release();
         }
       }
       break;
diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h
index c498048e..fab7ff87 100644
--- a/src/displayapp/screens/Metronome.h
+++ b/src/displayapp/screens/Metronome.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "systemtask/SystemTask.h"
+#include "systemtask/WakeLock.h"
 #include "components/motor/MotorController.h"
 #include "displayapp/screens/Screen.h"
 #include "Symbols.h"
@@ -21,7 +22,7 @@ namespace Pinetime {
         TickType_t startTime = 0;
         TickType_t tappedTime = 0;
         Controllers::MotorController& motorController;
-        System::SystemTask& systemTask;
+        System::WakeLock wakeLock;
         int16_t bpm = 120;
         uint8_t bpb = 4;
         uint8_t counter = 1;
diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp
index 3a3f5f2b..45f72f2e 100644
--- a/src/displayapp/screens/Notifications.cpp
+++ b/src/displayapp/screens/Notifications.cpp
@@ -20,7 +20,7 @@ Notifications::Notifications(DisplayApp* app,
     notificationManager {notificationManager},
     alertNotificationService {alertNotificationService},
     motorController {motorController},
-    systemTask {systemTask},
+    wakeLock(systemTask),
     mode {mode} {
 
   notificationManager.ClearNewNotificationFlag();
@@ -40,7 +40,7 @@ Notifications::Notifications(DisplayApp* app,
     validDisplay = false;
   }
   if (mode == Modes::Preview) {
-    systemTask.PushMessage(System::Messages::DisableSleeping);
+    wakeLock.Lock();
     if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
       motorController.StartRinging();
     } else {
@@ -65,7 +65,6 @@ Notifications::~Notifications() {
   lv_task_del(taskRefresh);
   // make sure we stop any vibrations before exiting
   motorController.StopRinging();
-  systemTask.PushMessage(System::Messages::EnableSleeping);
   lv_obj_clean(lv_scr_act());
 }
 
@@ -120,7 +119,7 @@ void Notifications::Refresh() {
 }
 
 void Notifications::OnPreviewInteraction() {
-  systemTask.PushMessage(System::Messages::EnableSleeping);
+  wakeLock.Release();
   motorController.StopRinging();
   if (timeoutLine != nullptr) {
     lv_obj_del(timeoutLine);
diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h
index 114316b3..8488dc5b 100644
--- a/src/displayapp/screens/Notifications.h
+++ b/src/displayapp/screens/Notifications.h
@@ -8,6 +8,7 @@
 #include "components/ble/NotificationManager.h"
 #include "components/motor/MotorController.h"
 #include "systemtask/SystemTask.h"
+#include "systemtask/WakeLock.h"
 
 namespace Pinetime {
   namespace Controllers {
@@ -73,7 +74,7 @@ namespace Pinetime {
         Pinetime::Controllers::NotificationManager& notificationManager;
         Pinetime::Controllers::AlertNotificationService& alertNotificationService;
         Pinetime::Controllers::MotorController& motorController;
-        System::SystemTask& systemTask;
+        System::WakeLock wakeLock;
         Modes mode = Modes::Normal;
         std::unique_ptr<NotificationItem> currentItem;
         Pinetime::Controllers::NotificationManager::Notification::Id currentId;
diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp
index f0359da4..ff852beb 100644
--- a/src/displayapp/screens/StopWatch.cpp
+++ b/src/displayapp/screens/StopWatch.cpp
@@ -34,7 +34,7 @@ namespace {
   constexpr TickType_t blinkInterval = pdMS_TO_TICKS(1000);
 }
 
-StopWatch::StopWatch(System::SystemTask& systemTask) : systemTask {systemTask} {
+StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) {
   static constexpr uint8_t btnWidth = 115;
   static constexpr uint8_t btnHeight = 80;
   btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
@@ -79,7 +79,6 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : systemTask {systemTask} {
 
 StopWatch::~StopWatch() {
   lv_task_del(taskRefresh);
-  systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
   lv_obj_clean(lv_scr_act());
 }
 
@@ -135,7 +134,7 @@ void StopWatch::Start() {
   SetInterfaceRunning();
   startTime = xTaskGetTickCount();
   currentState = States::Running;
-  systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+  wakeLock.Lock();
 }
 
 void StopWatch::Pause() {
@@ -145,7 +144,7 @@ void StopWatch::Pause() {
   oldTimeElapsed = laps[lapsDone];
   blinkTime = xTaskGetTickCount() + blinkInterval;
   currentState = States::Halted;
-  systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
+  wakeLock.Release();
 }
 
 void StopWatch::Refresh() {
diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h
index 3386d042..55a178dc 100644
--- a/src/displayapp/screens/StopWatch.h
+++ b/src/displayapp/screens/StopWatch.h
@@ -7,6 +7,7 @@
 #include "portmacro_cmsis.h"
 
 #include "systemtask/SystemTask.h"
+#include "systemtask/WakeLock.h"
 #include "displayapp/apps/Apps.h"
 #include "displayapp/Controllers.h"
 #include "Symbols.h"
@@ -43,7 +44,7 @@ namespace Pinetime {
         void Start();
         void Pause();
 
-        Pinetime::System::SystemTask& systemTask;
+        Pinetime::System::WakeLock wakeLock;
         States currentState = States::Init;
         TickType_t startTime;
         TickType_t oldTimeElapsed = 0;
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 4c623883..e55c9ad8 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -189,15 +189,11 @@ void SystemTask::Work() {
     if (xQueueReceive(systemTasksMsgQueue, &msg, 100) == pdTRUE) {
       switch (msg) {
         case Messages::EnableSleeping:
-          // Make sure that exiting an app doesn't enable sleeping,
-          // if the exiting was caused by a firmware update
-          if (!bleController.IsFirmwareUpdating()) {
-            doNotGoToSleep = false;
-          }
+          wakeLocksHeld--;
           break;
         case Messages::DisableSleeping:
           GoToRunning();
-          doNotGoToSleep = true;
+          wakeLocksHeld++;
           break;
         case Messages::GoToRunning:
           GoToRunning();
@@ -243,24 +239,24 @@ void SystemTask::Work() {
           break;
         case Messages::BleFirmwareUpdateStarted:
           GoToRunning();
-          doNotGoToSleep = true;
+          wakeLocksHeld++;
           displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
           break;
         case Messages::BleFirmwareUpdateFinished:
           if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
             NVIC_SystemReset();
           }
-          doNotGoToSleep = false;
+          wakeLocksHeld--;
           break;
         case Messages::StartFileTransfer:
           NRF_LOG_INFO("[systemtask] FS Started");
           GoToRunning();
-          doNotGoToSleep = true;
+          wakeLocksHeld++;
           // TODO add intent of fs access icon or something
           break;
         case Messages::StopFileTransfer:
           NRF_LOG_INFO("[systemtask] FS Stopped");
-          doNotGoToSleep = false;
+          wakeLocksHeld--;
           // TODO add intent of fs access icon or something
           break;
         case Messages::OnTouchEvent:
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index 339587c1..8a4e5954 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -80,7 +80,7 @@ namespace Pinetime {
       void OnTouchEvent();
 
       bool IsSleepDisabled() {
-        return doNotGoToSleep;
+        return wakeLocksHeld > 0;
       }
 
       Pinetime::Controllers::NimbleController& nimble() {
@@ -124,7 +124,7 @@ namespace Pinetime {
       bool isBleDiscoveryTimerRunning = false;
       uint8_t bleDiscoveryTimer = 0;
       TimerHandle_t measureBatteryTimer;
-      bool doNotGoToSleep = false;
+      uint8_t wakeLocksHeld = 0;
       SystemTaskState state = SystemTaskState::Running;
 
       void HandleButtonAction(Controllers::ButtonActions action);
diff --git a/src/systemtask/WakeLock.cpp b/src/systemtask/WakeLock.cpp
new file mode 100644
index 00000000..2953f7ee
--- /dev/null
+++ b/src/systemtask/WakeLock.cpp
@@ -0,0 +1,27 @@
+#include "systemtask/WakeLock.h"
+
+using namespace Pinetime::System;
+
+WakeLock::WakeLock(SystemTask& systemTask) : systemTask {systemTask} {
+  lockHeld = false;
+}
+
+WakeLock::~WakeLock() {
+  Release();
+}
+
+void WakeLock::Lock() {
+  if (lockHeld) {
+    return;
+  }
+  systemTask.PushMessage(Messages::DisableSleeping);
+  lockHeld = true;
+}
+
+void WakeLock::Release() {
+  if (!lockHeld) {
+    return;
+  }
+  systemTask.PushMessage(Messages::EnableSleeping);
+  lockHeld = false;
+}
diff --git a/src/systemtask/WakeLock.h b/src/systemtask/WakeLock.h
new file mode 100644
index 00000000..5424c009
--- /dev/null
+++ b/src/systemtask/WakeLock.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "systemtask/SystemTask.h"
+
+namespace Pinetime {
+  namespace System {
+    class WakeLock {
+    public:
+      WakeLock(SystemTask& systemTask);
+      ~WakeLock();
+      void Lock();
+      void Release();
+
+    private:
+      bool lockHeld;
+      SystemTask& systemTask;
+    };
+  }
+}