1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <memory>
19 #include <mutex>
20 #include <vector>
21 
22 #include <android-base/unique_fd.h>
23 #include <healthd/healthd.h>
24 
25 namespace android {
26 namespace hardware {
27 namespace health {
28 
29 class HealthLoop {
30   public:
31     HealthLoop();
32 
33     // Client is responsible for holding this forever. Process will exit
34     // when this is destroyed.
35     virtual ~HealthLoop();
36 
37     // Initialize and start the main loop. This function does not exit unless
38     // the process is interrupted.
39     // Once the loop is started, event handlers are no longer allowed to be
40     // registered.
41     int StartLoop();
42 
43   protected:
44     // healthd_mode_ops overrides. Note that healthd_mode_ops->battery_update
45     // is missing because it is only used by BatteryMonitor.
46     // Init is called right after epollfd_ is initialized (so RegisterEvent
47     // is allowed) but before other things are initialized (so SetChargerOnline
48     // is not allowed.)
49     virtual void Init(healthd_config* config) = 0;
50     virtual void Heartbeat() = 0;
51     virtual int PrepareToWait() = 0;
52 
53     // Note that this is NOT healthd_mode_ops->battery_update(BatteryProperties*),
54     // which is called by BatteryMonitor after values are fetched. This is the
55     // implementation of healthd_battery_update(), which calls
56     // the correct IHealth::update(),
57     // which calls BatteryMonitor::update(), which calls
58     // healthd_mode_ops->battery_update(BatteryProperties*).
59     virtual void ScheduleBatteryUpdate() = 0;
60 
61     // Register an epoll event. When there is an event, |func| will be
62     // called with |this| as the first argument and |epevents| as the second.
63     // This may be called in a different thread from where StartLoop is called
64     // (for obvious reasons; StartLoop never ends).
65     // Once the loop is started, event handlers are no longer allowed to be
66     // registered.
67     using BoundFunction = std::function<void(HealthLoop*, uint32_t /* epevents */)>;
68     int RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup);
69 
70     // Helper for implementing ScheduleBatteryUpdate(). An implementation of
71     // ScheduleBatteryUpdate should get charger_online from BatteryMonitor::update(),
72     // then reset wake alarm interval by calling AdjustWakealarmPeriods.
73     void AdjustWakealarmPeriods(bool charger_online);
74 
75   private:
76     struct EventHandler {
77         HealthLoop* object = nullptr;
78         int fd;
79         BoundFunction func;
80     };
81 
82     int InitInternal();
83     void MainLoop();
84     void WakeAlarmInit();
85     void WakeAlarmEvent(uint32_t);
86     void UeventInit();
87     void UeventEvent(uint32_t);
88     void WakeAlarmSetInterval(int interval);
89     void PeriodicChores();
90 
91     // These are fixed after InitInternal() is called.
92     struct healthd_config healthd_config_;
93     android::base::unique_fd wakealarm_fd_;
94     android::base::unique_fd uevent_fd_;
95 
96     android::base::unique_fd epollfd_;
97     std::vector<std::unique_ptr<EventHandler>> event_handlers_;
98     int awake_poll_interval_;  // -1 for no epoll timeout
99     int wakealarm_wake_interval_;
100 
101     // If set to true, future RegisterEvent() will be rejected. This is to ensure all
102     // events are registered before StartLoop().
103     bool reject_event_register_ = false;
104 };
105 
106 }  // namespace health
107 }  // namespace hardware
108 }  // namespace android
109