~aleteoryx/muditaos

ref: 65d67e2690ffc1d619b9b7ef4f8adc842f456f23 muditaos/module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp -rw-r--r-- 7.8 KiB
65d67e26 — Alek Rudnik [EGD-7948] Extend log dumping 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <functional>
#include <stdexcept>
#include "thread.hpp"
#include "condition_variable.hpp"
#include "mutex.hpp"
#include "Service/Mailbox.hpp"
#include "Service/Service.hpp"
#include "Service/ServiceCreator.hpp"
#include "Timers/TimerHandle.hpp"
#include "PowerManager.hpp"
#include <hal/key_input/RawKey.hpp>
#include <system/Constants.hpp>
#include "CpuStatistics.hpp"
#include "DeviceManager.hpp"
#include <chrono>
#include <vector>

namespace app
{
    class ApplicationCommon;
}

namespace sys
{
    namespace constants
    {
        using namespace std::chrono_literals;
        inline constexpr std::chrono::milliseconds timerInitInterval{30s};
        inline constexpr std::chrono::milliseconds timerPeriodInterval{100ms};
        inline constexpr std::chrono::milliseconds powerManagerLogsTimerInterval{1h};
        inline constexpr auto restoreTimeout{5000};
    } // namespace constants

    enum class Code
    {
        CloseSystem,
        Update,
        Restore,
        Reboot,
        RebootToUpdate,
        FactoryReset,
        None,
    };

    class SystemInitialisationError : public std::runtime_error
    {
      public:
        using std::runtime_error::runtime_error;
    };

    class SystemManagerCmd : public DataMessage
    {
      public:
        explicit SystemManagerCmd(Code type                 = Code::None,
                                  CloseReason closeReason   = CloseReason::RegularPowerDown,
                                  UpdateReason updateReason = UpdateReason::Update)
            : DataMessage(BusChannel::SystemManagerRequests), type(type), closeReason(closeReason),
              updateReason(updateReason)
        {}

        Code type;
        CloseReason closeReason;
        UpdateReason updateReason;
    };

    class SystemManagerCommon : public Service
    {
      public:
        using InitFunction   = std::function<bool()>;
        using DeinitFunction = std::function<bool()>;
        enum class State
        {
            Running,
            Suspend,
            Shutdown,
            ShutdownReady,
            Reboot,
            RebootToUpdate
        } state = State::Running;

        explicit SystemManagerCommon(std::vector<std::unique_ptr<BaseServiceCreator>> &&creators);
        ~SystemManagerCommon() override;

        void set(enum State state);

        void initialize();

        virtual void StartSystem(InitFunction sysInit, InitFunction appSpaceInit, DeinitFunction sysDeinit);

        static bool Restore(Service *s);

        static bool FactoryReset(Service *s);

        static bool Reboot(Service *s);

        static bool RebootToUpdate(Service *s, UpdateReason updateReason);

        static bool SuspendService(const std::string &name, Service *caller);

        static bool ResumeService(const std::string &name, Service *caller);

        /// Runs a service
        static bool RunSystemService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
        /// Runs an application
        static bool RunApplication(std::shared_ptr<app::ApplicationCommon> app,
                                   Service *caller,
                                   TickType_t timeout = 5000);

        /// Destroy existing service
        /// @note there is no fallback
        static bool DestroySystemService(const std::string &name, Service *caller);
        /// Destroy existing application
        static bool DestroyApplication(const std::string &name, Service *caller);

        /// Kill service
        /// @note - this is final, it straight takes service, calls it's close callback and it's gone
        /// please mind that services & apps not registered in SystemManager cant be killed - these should be handled by
        /// parents (as above in Destroy) ApplicationManager somehow propagates this, but I would call how it's done
        /// `imperfect`
        ///
        /// @note there is no timeout on deinit handler, might be worth to consider blocking `message` DeinitHandler
        /// instead
        void kill(std::shared_ptr<Service> const &toKill);

      protected:
        ReturnCodes InitHandler() override;
        virtual void batteryNormalLevelAction();
        virtual void batteryCriticalLevelAction(bool charging);
        virtual void batteryShutdownLevelAction();

      private:
        MessagePointer DataReceivedHandler(DataMessage *msg, ResponseMessage *resp) override;

        ReturnCodes DeinitHandler() override
        {
            return ReturnCodes::Success;
        }

        ReturnCodes SwitchPowerModeHandler(const ServicePowerMode mode) final
        {
            return ReturnCodes::Success;
        }

        void Run() override;

        void LogPowerOffReason();

        void PowerOff();

        void StartSystemServices();

        static bool RunService(std::shared_ptr<Service> service, Service *caller, TickType_t timeout = 5000);
        static bool RequestServiceClose(const std::string &name, Service *caller, TickType_t timeout = 5000);

        template <typename T> void DestroyServices(const T &whitelist);
        /// Sysmgr stores list of all active services but some of them are under control of parent services.
        /// Parent services ought to manage lifetime of child services hence we are sending DestroyRequests only to
        /// parents.
        /// It closes all workers except EventManager -as it needs information from Eventmanager that it's safe to
        /// shutdown
        void CloseSystemHandler(CloseReason closeReason = CloseReason::RegularPowerDown);

        void CloseServices();

        void preCloseRoutine(CloseReason closeReason);

        void postStartRoutine();

        void readyToCloseHandler(Message *msg);

        void UpdateSystemHandler();

        void RestoreSystemHandler();

        void RebootHandler(State state, std::optional<UpdateReason> updateReason = std::nullopt);

        /// periodic update of cpu statistics
        void CpuStatisticsTimerHandler();

        /// used for power management control for the filesystem
        void UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency);

        bool cpuStatisticsTimerInit{false};

        UpdateReason updateReason{UpdateReason::Update};
        std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
        sys::TimerHandle cpuStatisticsTimer;
        sys::TimerHandle servicesPreShutdownRoutineTimeout;
        sys::TimerHandle lowBatteryShutdownDelay;
        sys::TimerHandle powerManagerEfficiencyTimer;
        InitFunction userInit;
        InitFunction systemInit;
        DeinitFunction systemDeinit;
        std::vector<std::string> readyForCloseRegister;

        std::shared_ptr<sys::CpuSentinel> cpuSentinel;

        static std::vector<std::shared_ptr<Service>> servicesList;
        static std::vector<std::shared_ptr<app::ApplicationCommon>> applicationsList;
        static cpp_freertos::MutexStandard serviceDestroyMutex;
        static cpp_freertos::MutexStandard appDestroyMutex;
        static std::unique_ptr<PowerManager> powerManager;
        static std::unique_ptr<CpuStatistics> cpuStatistics;
        static std::unique_ptr<DeviceManager> deviceManager;
    };
} // namespace sys

inline const char *c_str(sys::SystemManagerCommon::State state)
{
    switch (state) {
    case sys::SystemManagerCommon::State::Running:
        return "Running";
    case sys::SystemManagerCommon::State::Suspend:
        return "Suspend";
    case sys::SystemManagerCommon::State::Shutdown:
        return "Shutdown";
    case sys::SystemManagerCommon::State::Reboot:
        return "Reboot";
    case sys::SystemManagerCommon::State::RebootToUpdate:
        return "RebootToUpdate";
    case sys::SystemManagerCommon::State::ShutdownReady:
        return "ShutdownReady";
    }
    return "";
}