Browse Source

Charger: Remove old alarm interface and update timerfd interface

Oreo doesn't allow usage of the old alarm interface anymore, so
simply remove it and switch to timerfd. Also update the timerfd
interface from CAF O release

Change-Id: I22fc00630072cbf18976239dc039bf2135946045
Luca Stefani 2 years ago
parent
commit
f7e7a56548
1 changed files with 73 additions and 86 deletions
  1. 73
    86
      charger/healthd_board_lineage.cpp

+ 73
- 86
charger/healthd_board_lineage.cpp View File

@@ -33,9 +33,10 @@
33 33
 #include <cutils/properties.h>
34 34
 
35 35
 #include <pthread.h>
36
-#include <linux/android_alarm.h>
37
-#include <sys/timerfd.h>
38 36
 #include <linux/rtc.h>
37
+#include <linux/time.h>
38
+#include <sys/epoll.h>
39
+#include <sys/timerfd.h>
39 40
 
40 41
 #include "healthd/healthd.h"
41 42
 #include "minui/minui.h"
@@ -106,12 +107,6 @@ enum alarm_time_type {
106 107
     RTC_TIME,
107 108
 };
108 109
 
109
-/*
110
- * shouldn't be changed after
111
- * reading from alarm register
112
- */
113
-static time_t alm_secs;
114
-
115 110
 static int alarm_get_time(enum alarm_time_type time_type,
116 111
                           time_t *secs)
117 112
 {
@@ -160,104 +155,88 @@ err:
160 155
     return -1;
161 156
 }
162 157
 
163
-#define ERR_SECS 2
164
-static int alarm_is_alm_expired()
158
+static void alarm_reboot(void)
165 159
 {
166
-    int rc;
167
-    time_t rtc_secs;
168
-
169
-    rc = alarm_get_time(RTC_TIME, &rtc_secs);
170
-    if (rc < 0)
171
-        return 0;
172
-
173
-    return (alm_secs >= rtc_secs - ERR_SECS &&
174
-            alm_secs <= rtc_secs + ERR_SECS) ? 1 : 0;
175
-}
176
-
177
-static int timerfd_set_reboot_time_and_wait(time_t secs)
178
-{
179
-    int fd;
180
-    int ret = -1;
181
-    fd = timerfd_create(CLOCK_REALTIME_ALARM, 0);
182
-    if (fd < 0) {
183
-        LOGE("Can't open timerfd alarm node\n");
184
-        goto err_return;
185
-    }
186
-
187
-    struct itimerspec spec;
188
-    memset(&spec, 0, sizeof(spec));
189
-    spec.it_value.tv_sec = secs;
190
-
191
-    if (timerfd_settime(fd, 0 /* relative */, &spec, NULL)) {
192
-        LOGE("Can't set timerfd alarm\n");
193
-        goto err_close;
194
-    }
195
-
196
-    uint64_t unused;
197
-    if (read(fd, &unused, sizeof(unused)) < 0) {
198
-       LOGE("Wait alarm error\n");
199
-       goto err_close;
200
-    }
201
-
202
-    ret = 0;
203
-err_close:
204
-    close(fd);
205
-err_return:
206
-    return ret;
160
+    LOGI("alarm time is up, reboot the phone!\n");
161
+    syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
162
+            LINUX_REBOOT_CMD_RESTART2, "rtc");
207 163
 }
208 164
 
209 165
 static int alarm_set_reboot_time_and_wait(time_t secs)
210 166
 {
211
-    int rc, fd;
167
+    int rc, epollfd, nevents;
168
+    int fd = 0;
212 169
     struct timespec ts;
170
+    epoll_event event, events[1];
171
+    struct itimerspec itval;
172
+
173
+    epollfd = epoll_create(1);
174
+    if (epollfd < 0) {
175
+        LOGE("epoll_create failed\n");
176
+        goto err;
177
+    }
213 178
 
214
-    fd = open("/dev/alarm", O_RDWR);
179
+    fd = timerfd_create(CLOCK_REALTIME_ALARM, 0);
215 180
     if (fd < 0) {
216
-        LOGE("Can't open alarm devfs node, trying timerfd\n");
217
-        return timerfd_set_reboot_time_and_wait(secs);
181
+        LOGE("timerfd_create failed\n");
182
+        goto err;
218 183
     }
219 184
 
220
-    /* get the elapsed realtime from boot time to now */
221
-    rc = ioctl(fd, ANDROID_ALARM_GET_TIME(
222
-                      ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP), &ts);
185
+    event.events = EPOLLIN | EPOLLWAKEUP;
186
+    event.data.ptr = (void *)alarm_reboot;
187
+    rc = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
223 188
     if (rc < 0) {
224
-        LOGE("Unable to get elapsed realtime\n");
189
+        LOGE("epoll_ctl(EPOLL_CTL_ADD) failed \n");
225 190
         goto err;
226 191
     }
227 192
 
228
-    /* calculate the elapsed time from boot time to reboot time */
229
-    ts.tv_sec += secs;
230
-    ts.tv_nsec = 0;
193
+    itval.it_value.tv_sec = secs;
194
+    itval.it_value.tv_nsec = 0;
195
+
196
+    itval.it_interval.tv_sec = 0;
197
+    itval.it_interval.tv_nsec = 0;
231 198
 
232
-    rc = ioctl(fd, ANDROID_ALARM_SET(
233
-                      ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP), &ts);
199
+    rc = timerfd_settime(fd, TFD_TIMER_ABSTIME, &itval, NULL);
234 200
     if (rc < 0) {
235
-        LOGE("Unable to set reboot time to %ld\n", secs);
201
+        LOGE("timerfd_settime failed %d\n",rc);
236 202
         goto err;
237 203
     }
238 204
 
239
-    do {
240
-        rc = ioctl(fd, ANDROID_ALARM_WAIT);
241
-    } while ((rc < 0 && errno == EINTR) || !alarm_is_alm_expired());
205
+    nevents = epoll_wait(epollfd, events, 1, -1);
242 206
 
243
-    if (rc <= 0) {
207
+    if (nevents <= 0) {
244 208
         LOGE("Unable to wait on alarm\n");
245 209
         goto err;
210
+    } else {
211
+        (*(void (*)())events[0].data.ptr)();
246 212
     }
247 213
 
214
+    close(epollfd);
248 215
     close(fd);
249 216
     return 0;
250 217
 
251 218
 err:
219
+    if (epollfd > 0)
220
+        close(epollfd);
221
+
252 222
     if (fd >= 0)
253 223
         close(fd);
254 224
     return -1;
255 225
 }
256 226
 
227
+/*
228
+ * 10s the estimated time from timestamp of alarm thread start
229
+ * to timestamp of android boot completed.
230
+ */
231
+#define TIME_DELTA 10
232
+
233
+/* seconds of 1 minute*/
234
+#define ONE_MINUTE 60
257 235
 static void *alarm_thread(void *)
258 236
 {
259
-    time_t rtc_secs, rb_secs;
237
+    time_t rtc_secs, alarm_secs;
260 238
     int rc;
239
+    timespec ts;
261 240
 
262 241
     /*
263 242
      * to support power off alarm, the time
@@ -266,31 +245,39 @@ static void *alarm_thread(void *)
266 245
      * earlier than the actual alarm time
267 246
      * set by user
268 247
      */
269
-    rc = alarm_get_time(ALARM_TIME, &alm_secs);
270
-    LOGI("RTC Alarm %ld\n", alm_secs);
271
-    if (rc < 0 || !alm_secs)
248
+    rc = alarm_get_time(ALARM_TIME, &alarm_secs);
249
+    if (rc < 0 || !alarm_secs)
272 250
         goto err;
273 251
 
274 252
     rc = alarm_get_time(RTC_TIME, &rtc_secs);
275
-    LOGI("RTC Clock %ld\n", rtc_secs);
276
-    if (rc < 0)
253
+    if (rc < 0 || !rtc_secs)
277 254
         goto err;
255
+    LOGI("alarm time in rtc is %ld, rtc time is %ld\n", alarm_secs, rtc_secs);
256
+
257
+    if (alarm_secs <= rtc_secs) {
258
+        clock_gettime(CLOCK_BOOTTIME, &ts);
259
+
260
+        /*
261
+         * It is possible that last power off alarm time is up at this point.
262
+         * (alarm_secs + ONE_MINUTE) is the final alarm time to fire.
263
+         * (rtc_secs + ts.tv_sec + TIME_DELTA) is the estimated time of next
264
+         * boot completed to fire alarm.
265
+         * If the final alarm time is less than the estimated time of next boot
266
+         * completed to fire, that means it is not able to fire the last power
267
+         * off alarm at the right time, so just miss it.
268
+         */
269
+        if (alarm_secs + ONE_MINUTE < rtc_secs + ts.tv_sec + TIME_DELTA) {
270
+            LOGE("alarm is missed\n");
271
+            goto err;
272
+        }
278 273
 
279
-    /*
280
-     * calculate the reboot time after which
281
-     * the phone will reboot
282
-     */
283
-    rb_secs = alm_secs - rtc_secs;
284
-    if (rb_secs <= 0)
285
-        goto err;
274
+        alarm_reboot();
275
+    }
286 276
 
287
-    rc = alarm_set_reboot_time_and_wait(rb_secs);
277
+    rc = alarm_set_reboot_time_and_wait(alarm_secs);
288 278
     if (rc < 0)
289 279
         goto err;
290 280
 
291
-    LOGI("Exit from power off charging, reboot the phone!\n");
292
-    android_reboot(ANDROID_RB_RESTART, 0, 0);
293
-
294 281
 err:
295 282
     LOGE("Exit from alarm thread\n");
296 283
     return NULL;