Alexander Kopachov 2 лет назад
Родитель
Сommit
44a094981c

+ 6 - 1
features_config.h

@@ -1,3 +1,8 @@
+// Application automatic lock timeout if user IDLE. (ticks)
+#ifndef TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC
+#define TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC (60)
+#endif
+
 // Include Bluetooth token input automation
 #ifndef TOTP_NO_BADBT_TYPE
 #define TOTP_BADBT_TYPE_ENABLED
@@ -46,4 +51,4 @@
 // Active font for TOTP codes
 #ifndef TOTP_FONT
 #define TOTP_FONT TOTP_FONT_MODENINE
-#endif
+#endif

+ 1 - 1
services/crypto/crypto.c

@@ -91,7 +91,7 @@ CryptoSeedIVResult
             max_i = uid_size;
         }
 
-        const uint8_t* uid = (const uint8_t*)UID64_BASE;
+        const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566
         for(uint8_t i = 0; i < max_i; i++) {
             plugin_state->iv[i] = plugin_state->iv[i] ^ uid[i];
         }

+ 62 - 0
services/idle_timeout/idle_timeout.c

@@ -0,0 +1,62 @@
+#include "idle_timeout.h"
+#include <stdlib.h>
+#include <furi/core/timer.h>
+
+#define IDLE_TIMER_CHECK_PERIODICITY_SEC (1)
+#define SEC_TO_TICKS(sec) ((sec) * 1000)
+
+struct IdleTimeoutContext {
+    FuriTimer* timer;
+    bool activity_reported;
+    void* on_idle_callback_context;
+    IDLE_TIMEOUT_CALLBACK on_idle_callback;
+    uint16_t timeout_sec;
+    uint16_t idle_period_sec;
+    bool idle_handled;
+};
+
+static void idle_timer_callback(void* context) {
+    IdleTimeoutContext* instance = context;
+    if (instance->activity_reported) {
+        instance->idle_period_sec = 0;
+        instance->idle_handled = false;
+        instance->activity_reported = false;
+    } else if (!instance->idle_handled) {
+        if (instance->idle_period_sec >= instance->timeout_sec) {
+            instance->idle_handled = instance->on_idle_callback(instance->on_idle_callback_context);
+        } else {
+            instance->idle_period_sec += IDLE_TIMER_CHECK_PERIODICITY_SEC;
+        }
+    }   
+}
+
+IdleTimeoutContext* idle_timeout_alloc(uint16_t timeout_sec, IDLE_TIMEOUT_CALLBACK on_idle_callback, void* on_idle_callback_context) {
+    IdleTimeoutContext* instance = malloc(sizeof(IdleTimeoutContext));
+    if (instance == NULL) return NULL;
+
+    instance->timer = furi_timer_alloc(&idle_timer_callback, FuriTimerTypePeriodic, instance);
+    if (instance->timer == NULL) return NULL;
+
+    instance->timeout_sec = timeout_sec;
+    instance->on_idle_callback = on_idle_callback;
+    instance->on_idle_callback_context = on_idle_callback_context;
+    return instance;
+}
+
+void idle_timeout_start(IdleTimeoutContext* context) {
+    furi_timer_start(context->timer, SEC_TO_TICKS(IDLE_TIMER_CHECK_PERIODICITY_SEC));
+}
+
+void idle_timeout_stop(IdleTimeoutContext* context) {
+    furi_timer_stop(context->timer);
+}
+
+void idle_timeout_report_activity(IdleTimeoutContext* context) {
+    context->activity_reported = true;
+}
+
+void idle_timeout_free(IdleTimeoutContext* context) {
+    furi_timer_stop(context->timer);
+    furi_timer_free(context->timer);
+    free(context);
+}

+ 41 - 0
services/idle_timeout/idle_timeout.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+typedef struct IdleTimeoutContext IdleTimeoutContext;
+
+typedef bool (*IDLE_TIMEOUT_CALLBACK)(void* context);
+
+/**
+ * @brief Initializes a new instance of IDLE timeout
+ * @param timeout_sec IDLE timeout in seconds
+ * @param on_idle_callback callback function to trigger when IDLE timeout happened
+ * @param on_idle_callback_context callback function context
+ * @return IDLE timeout context
+ */
+IdleTimeoutContext* idle_timeout_alloc(uint16_t timeout_sec, IDLE_TIMEOUT_CALLBACK on_idle_callback, void* on_idle_callback_context);
+
+/**
+ * @brief Starts IDLE timeout
+ * @param context IDLE timeout context
+ */
+void idle_timeout_start(IdleTimeoutContext* context);
+
+/**
+ * @brief Stops IDLE timeout
+ * @param context IDLE timeout context
+ */
+void idle_timeout_stop(IdleTimeoutContext* context);
+
+/**
+ * @brief Reports activity to IDLE timeout
+ * @param context IDLE timeout context
+ */
+void idle_timeout_report_activity(IdleTimeoutContext* context);
+
+/**
+ * @brief Disposes IDLE timeout and releases all the resources
+ * @param context IDLE timeout context
+ */
+void idle_timeout_free(IdleTimeoutContext* context);

+ 26 - 11
totp_app.c

@@ -18,8 +18,6 @@
 #include "services/crypto/crypto.h"
 #include "cli/cli.h"
 
-#define IDLE_TIMEOUT (60000)
-
 static void render_callback(Canvas* const canvas, void* ctx) {
     furi_assert(ctx);
     PluginState* plugin_state = ctx;
@@ -106,6 +104,17 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) {
     return true;
 }
 
+static bool on_user_idle(void* context) {
+    PluginState* plugin_state = context;
+    if(plugin_state->current_scene != TotpSceneAuthentication &&
+        plugin_state->current_scene != TotpSceneStandby) {
+        totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication);
+        return true;
+    }
+
+    return false;
+}
+
 static bool totp_plugin_state_init(PluginState* const plugin_state) {
     plugin_state->gui = furi_record_open(RECORD_GUI);
     plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION);
@@ -127,10 +136,22 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
     }
 #endif
 
+    if (plugin_state->pin_set) {
+        plugin_state->idle_timeout_context = idle_timeout_alloc(TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC, &on_user_idle, plugin_state);
+        idle_timeout_start(plugin_state->idle_timeout_context);
+    } else {
+        plugin_state->idle_timeout_context = NULL;
+    }
+
     return true;
 }
 
 static void totp_plugin_state_free(PluginState* plugin_state) {
+    if (plugin_state->idle_timeout_context != NULL) {
+        idle_timeout_stop(plugin_state->idle_timeout_context);
+        idle_timeout_free(plugin_state->idle_timeout_context);
+    }
+
     furi_record_close(RECORD_GUI);
     furi_record_close(RECORD_NOTIFICATION);
     furi_record_close(RECORD_DIALOGS);
@@ -184,14 +205,13 @@ int32_t totp_app() {
 
     PluginEvent event;
     bool processing = true;
-    uint32_t last_user_interaction_time = furi_get_tick();
     while(processing) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
+        FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever);
 
         if(furi_mutex_acquire(plugin_state->mutex, FuriWaitForever) == FuriStatusOk) {
             if(event_status == FuriStatusOk) {
-                if(event.type == EventTypeKey) {
-                    last_user_interaction_time = furi_get_tick();
+                if(event.type == EventTypeKey && plugin_state->idle_timeout_context != NULL) {
+                    idle_timeout_report_activity(plugin_state->idle_timeout_context);
                 }
 
                 if(event.type == EventForceCloseApp) {
@@ -199,11 +219,6 @@ int32_t totp_app() {
                 } else {
                     processing = totp_scene_director_handle_event(&event, plugin_state);
                 }
-            } else if(
-                plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication &&
-                plugin_state->current_scene != TotpSceneStandby &&
-                furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) {
-                totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication);
             }
 
             view_port_update(view_port);

+ 9 - 0
types/plugin_state.h

@@ -6,6 +6,7 @@
 #include "../features_config.h"
 #include "../ui/totp_scenes_enum.h"
 #include "../services/config/config_file_context.h"
+#include "../services/idle_timeout/idle_timeout.h"
 #include "notification_method.h"
 #include "automation_method.h"
 #ifdef TOTP_BADBT_TYPE_ENABLED
@@ -48,6 +49,9 @@ typedef struct {
      */
     float timezone_offset;
 
+    /**
+     * @brief Config file context
+     */
     ConfigFileContext* config_file_context;
 
     /**
@@ -96,4 +100,9 @@ typedef struct {
      */
     TotpBtTypeCodeWorkerContext* bt_type_code_worker_context;
 #endif
+
+    /**
+     * @brief IDLE timeout context
+     */
+    IdleTimeoutContext* idle_timeout_context;
 } PluginState;

+ 1 - 1
workers/bt_type_code/bt_type_code.c

@@ -49,7 +49,7 @@ static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) {
         max_i = TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN;
     }
 
-    const uint8_t* uid = (const uint8_t*)UID64_BASE;
+    const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566
     memcpy(mac, uid, max_i);
     for(uint8_t i = max_i; i < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; i++) {
         mac[i] = 0;