~aleteoryx/muditaos

ref: 395e99e16239630263d5892e2462f1333236ae99 muditaos/module-sys/SystemManager/SystemManager.hpp -rw-r--r-- 8.8 KiB
395e99e1 — Marek Niepieklo [CP-583] Update failure due to version.json on the phone 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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*
 * Service.hpp
 *
 *  Created on: Mar 7, 2019
 *      Author: mati
 */

#ifndef SYSTEMMANAGER_SYSTEMMANAGER_HPP_
#define SYSTEMMANAGER_SYSTEMMANAGER_HPP_

#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 "PhoneModes/Subject.hpp"
#include <common_data/RawKey.hpp>
#include "Constants.hpp"
#include "CpuStatistics.hpp"
#include "DeviceManager.hpp"
#include <chrono>
#include <vector>
#include <apps-common/Application.hpp>

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

    class PhoneModeRequest;         // Forward declaration
    class TetheringStateRequest;    // Forward declaration
    class TetheringEnabledResponse; // Forward declaration

    enum class Code
    {
        CloseSystem,
        Update,
        Restore,
        Reboot,
        RebootToUpdate,
        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 SystemManager : public Service
    {
      private:
        UpdateReason updateReason{UpdateReason::Update};

      public:
        using InitFunction = std::function<bool()>;

        enum class State
        {
            Running,
            Suspend,
            Shutdown,
            ShutdownReady,
            Reboot,
            RebootToUpdate
        } state = State::Running;

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

        void set(enum State state);

        void initialize();

        void StartSystem(InitFunction sysInit, InitFunction appSpaceInit);

        // Invoke system close procedure
        static bool CloseSystem(Service *s);

        static bool Restore(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::Application> 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);

        /// Translates a slider state into a phone mode.
        /// \param key  Slider button state
        /// \return Phone mode.
        static phone_modes::PhoneMode translateSliderState(const RawKey &key);

        /// 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);

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

        ReturnCodes InitHandler() override;

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

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

        void Run() override;

        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);

        /// loop to handle prior to full system close
        /// for now for rt1051 we need to
        /// 1. check if we have power plug in
        /// 2. if power is in, if we didn't get request for poweron ( this triggers reboot)
        /// this is needed as we can't just shutdown phone with power in - it would end in phone unable to boot (as
        /// red key won't work to power it on. For more information follow up with schematics
        bool PreShutdownLoop();

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

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

        MessagePointer handlePhoneModeRequest(PhoneModeRequest *request);
        MessagePointer handleTetheringStateRequest(TetheringStateRequest *request);
        MessagePointer enableTethering(TetheringEnabledResponse *response);

        void batteryCriticalLevelAction(bool charging);
        void batteryNormalLevelAction();
        void batteryShutdownLevelAction();

        bool cpuStatisticsTimerInit{false};

        std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
        sys::TimerHandle cpuStatisticsTimer;
        sys::TimerHandle servicesPreShutdownRoutineTimeout;
        sys::TimerHandle lowBatteryShutdownDelay;
        sys::TimerHandle powerManagerEfficiencyTimer;
        std::unique_ptr<phone_modes::Subject> phoneModeSubject;
        InitFunction userInit;
        InitFunction systemInit;
        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::Application>> 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::SystemManager::State state)
{
    switch (state) {
    case sys::SystemManager::State::Running:
        return "Running";
    case sys::SystemManager::State::Suspend:
        return "Suspend";
    case sys::SystemManager::State::Shutdown:
        return "Shutdown";
    case sys::SystemManager::State::Reboot:
        return "Reboot";
    case sys::SystemManager::State::RebootToUpdate:
        return "RebootToUpdate";
    case sys::SystemManager::State::ShutdownReady:
        return "ShutdownReady";
    }
    return "";
}

#endif /* SYSTEMMANAGER_SYSTEMMANAGER_HPP_ */