Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 1 | /* |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 2 | * Copyright (C) 2011-2017 The Android Open Source Project |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 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 | |
| 17 | #include <dirent.h> |
| 18 | #include <errno.h> |
| 19 | #include <fcntl.h> |
Colin Cross | e1d5247 | 2014-05-15 17:49:06 -0700 | [diff] [blame] | 20 | #include <inttypes.h> |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 21 | #include <stdio.h> |
| 22 | #include <stdlib.h> |
| 23 | #include <string.h> |
| 24 | #include <sys/epoll.h> |
| 25 | #include <sys/stat.h> |
| 26 | #include <sys/types.h> |
| 27 | #include <sys/un.h> |
| 28 | #include <time.h> |
| 29 | #include <unistd.h> |
| 30 | |
Tao Bao | 92c2601 | 2017-01-18 22:54:54 -0800 | [diff] [blame] | 31 | #include <functional> |
| 32 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 33 | #include <android-base/file.h> |
Mark Salyzyn | 26f1dd7 | 2017-06-27 09:19:09 -0700 | [diff] [blame] | 34 | #include <android-base/macros.h> |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 35 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 36 | #include <linux/netlink.h> |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 37 | #include <sys/socket.h> |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 38 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 39 | #include <cutils/klog.h> |
| 40 | #include <cutils/misc.h> |
Riley Andrews | 6bd4588 | 2014-06-23 15:20:51 -0700 | [diff] [blame] | 41 | #include <cutils/properties.h> |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 42 | #include <cutils/uevent.h> |
Todd Poynor | c8183bb | 2017-01-31 15:51:50 -0800 | [diff] [blame] | 43 | #include <sys/reboot.h> |
Bharath | c0d2a47 | 2020-04-15 11:39:06 +0530 | [diff] [blame] | 44 | #include <cutils/android_reboot.h> |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 45 | #ifdef CHARGER_ENABLE_SUSPEND |
| 46 | #include <suspend/autosuspend.h> |
| 47 | #endif |
| 48 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 49 | #include "AnimationParser.h" |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 50 | #include "healthd_draw.h" |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 51 | |
Yifan Hong | 10c2b40 | 2017-11-08 10:57:52 -0800 | [diff] [blame] | 52 | #include <health2/Health.h> |
Yabin Cui | e98e177 | 2016-02-17 12:21:34 -0800 | [diff] [blame] | 53 | #include <healthd/healthd.h> |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 54 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 55 | using namespace android; |
| 56 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 57 | char* locale; |
Colin Cross | 1c38f5d | 2014-02-13 13:34:37 -0800 | [diff] [blame] | 58 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 59 | #ifndef max |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 60 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 61 | #endif |
| 62 | |
| 63 | #ifndef min |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 64 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 65 | #endif |
| 66 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 67 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 68 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 69 | #define MSEC_PER_SEC (1000LL) |
| 70 | #define NSEC_PER_MSEC (1000000LL) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 71 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 72 | #define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC) |
| 73 | #define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 74 | #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) |
| 75 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 76 | #define LAST_KMSG_MAX_SZ (32 * 1024) |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 77 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 78 | #define LOGE(x...) KLOG_ERROR("charger", x); |
| 79 | #define LOGW(x...) KLOG_WARNING("charger", x); |
| 80 | #define LOGV(x...) KLOG_DEBUG("charger", x); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 81 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 82 | static constexpr const char* animation_desc_path = |
| 83 | "/res/values/charger/animation.txt"; |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 84 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 85 | struct key_state { |
| 86 | bool pending; |
| 87 | bool down; |
| 88 | int64_t timestamp; |
| 89 | }; |
| 90 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 91 | struct charger { |
| 92 | bool have_battery_state; |
| 93 | bool charger_connected; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 94 | int64_t next_screen_transition; |
| 95 | int64_t next_key_check; |
| 96 | int64_t next_pwr_check; |
| 97 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 98 | key_state keys[KEY_MAX + 1]; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 99 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 100 | animation* batt_anim; |
Elliott Hughes | 9e85ea1 | 2015-04-15 10:25:55 -0700 | [diff] [blame] | 101 | GRSurface* surf_unknown; |
Ruchi Kandoi | a84b1f6 | 2014-10-21 18:24:11 -0700 | [diff] [blame] | 102 | int boot_min_cap; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 103 | }; |
| 104 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 105 | static const animation BASE_ANIMATION = { |
| 106 | .text_clock = |
| 107 | { |
| 108 | .pos_x = 0, |
| 109 | .pos_y = 0, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 110 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 111 | .color_r = 255, |
| 112 | .color_g = 255, |
| 113 | .color_b = 255, |
| 114 | .color_a = 255, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 115 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 116 | .font = nullptr, |
| 117 | }, |
| 118 | .text_percent = |
| 119 | { |
| 120 | .pos_x = 0, |
| 121 | .pos_y = 0, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 122 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 123 | .color_r = 255, |
| 124 | .color_g = 255, |
| 125 | .color_b = 255, |
| 126 | .color_a = 255, |
| 127 | }, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 128 | |
| 129 | .run = false, |
| 130 | |
| 131 | .frames = nullptr, |
| 132 | .cur_frame = 0, |
| 133 | .num_frames = 0, |
| 134 | .first_frame_repeats = 2, |
| 135 | |
| 136 | .cur_cycle = 0, |
| 137 | .num_cycles = 3, |
| 138 | |
| 139 | .cur_level = 0, |
| 140 | .cur_status = BATTERY_STATUS_UNKNOWN, |
| 141 | }; |
| 142 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 143 | static animation::frame default_animation_frames[] = { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 144 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 145 | .disp_time = 500, |
| 146 | .min_level = 0, |
| 147 | .max_level = 9, |
| 148 | .surface = NULL, |
| 149 | }, |
| 150 | { |
| 151 | .disp_time = 500, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 152 | .min_level = 0, |
| 153 | .max_level = 19, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 154 | .surface = NULL, |
| 155 | }, |
| 156 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 157 | .disp_time = 500, |
| 158 | .min_level = 0, |
| 159 | .max_level = 29, |
| 160 | .surface = NULL, |
| 161 | }, |
| 162 | { |
| 163 | .disp_time = 500, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 164 | .min_level = 0, |
| 165 | .max_level = 39, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 166 | .surface = NULL, |
| 167 | }, |
| 168 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 169 | .disp_time = 500, |
| 170 | .min_level = 0, |
| 171 | .max_level = 49, |
| 172 | .surface = NULL, |
| 173 | }, |
| 174 | { |
| 175 | .disp_time = 500, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 176 | .min_level = 0, |
| 177 | .max_level = 59, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 178 | .surface = NULL, |
| 179 | }, |
| 180 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 181 | .disp_time = 500, |
| 182 | .min_level = 0, |
| 183 | .max_level = 69, |
| 184 | .surface = NULL, |
| 185 | }, |
| 186 | { |
| 187 | .disp_time = 500, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 188 | .min_level = 0, |
| 189 | .max_level = 79, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 190 | .surface = NULL, |
| 191 | }, |
| 192 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 193 | .disp_time = 500, |
| 194 | .min_level = 0, |
| 195 | .max_level = 89, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 196 | .surface = NULL, |
| 197 | }, |
| 198 | { |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 199 | .disp_time = 500, |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 200 | .min_level = 0, |
Filipe | c4546e9 | 2015-09-23 13:36:30 +0000 | [diff] [blame] | 201 | .max_level = 97, |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 202 | .surface = NULL, |
| 203 | }, |
| 204 | }; |
| 205 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 206 | static animation battery_animation = BASE_ANIMATION; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 207 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 208 | static charger charger_state; |
| 209 | static healthd_config* healthd_config; |
| 210 | static android::BatteryProperties* batt_prop; |
| 211 | static std::unique_ptr<HealthdDraw> healthd_draw; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 212 | |
| 213 | /* current time in milliseconds */ |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 214 | static int64_t curr_time_ms() { |
| 215 | timespec tm; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 216 | clock_gettime(CLOCK_MONOTONIC, &tm); |
| 217 | return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC); |
| 218 | } |
| 219 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 220 | #define MAX_KLOG_WRITE_BUF_SZ 256 |
| 221 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 222 | static void dump_last_kmsg(void) { |
| 223 | char* buf; |
| 224 | char* ptr; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 225 | unsigned sz = 0; |
| 226 | int len; |
| 227 | |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 228 | LOGW("\n"); |
| 229 | LOGW("*************** LAST KMSG ***************\n"); |
| 230 | LOGW("\n"); |
Mark Salyzyn | 26f1dd7 | 2017-06-27 09:19:09 -0700 | [diff] [blame] | 231 | const char* kmsg[] = { |
| 232 | // clang-format off |
| 233 | "/sys/fs/pstore/console-ramoops-0", |
| 234 | "/sys/fs/pstore/console-ramoops", |
| 235 | "/proc/last_kmsg", |
| 236 | // clang-format on |
| 237 | }; |
| 238 | for (size_t i = 0; i < arraysize(kmsg); ++i) { |
| 239 | buf = (char*)load_file(kmsg[i], &sz); |
| 240 | if (buf && sz) break; |
| 241 | } |
Todd Poynor | cd7c104 | 2013-11-22 17:52:59 -0800 | [diff] [blame] | 242 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 243 | if (!buf || !sz) { |
Mark Salyzyn | 26f1dd7 | 2017-06-27 09:19:09 -0700 | [diff] [blame] | 244 | LOGW("last_kmsg not found. Cold reset?\n"); |
| 245 | goto out; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | len = min(sz, LAST_KMSG_MAX_SZ); |
| 249 | ptr = buf + (sz - len); |
| 250 | |
| 251 | while (len > 0) { |
| 252 | int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ); |
| 253 | char yoink; |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 254 | char* nl; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 255 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 256 | nl = (char*)memrchr(ptr, '\n', cnt - 1); |
| 257 | if (nl) cnt = nl - ptr + 1; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 258 | |
| 259 | yoink = ptr[cnt]; |
| 260 | ptr[cnt] = '\0'; |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 261 | klog_write(6, "<4>%s", ptr); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 262 | ptr[cnt] = yoink; |
| 263 | |
| 264 | len -= cnt; |
| 265 | ptr += cnt; |
| 266 | } |
| 267 | |
| 268 | free(buf); |
| 269 | |
| 270 | out: |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 271 | LOGW("\n"); |
| 272 | LOGW("************* END LAST KMSG *************\n"); |
| 273 | LOGW("\n"); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 274 | } |
| 275 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 276 | #ifdef CHARGER_ENABLE_SUSPEND |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 277 | static int request_suspend(bool enable) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 278 | if (enable) |
| 279 | return autosuspend_enable(); |
| 280 | else |
| 281 | return autosuspend_disable(); |
| 282 | } |
| 283 | #else |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 284 | static int request_suspend(bool /*enable*/) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 285 | return 0; |
| 286 | } |
| 287 | #endif |
| 288 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 289 | static void kick_animation(animation* anim) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 290 | anim->run = true; |
| 291 | } |
| 292 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 293 | static void reset_animation(animation* anim) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 294 | anim->cur_cycle = 0; |
| 295 | anim->cur_frame = 0; |
| 296 | anim->run = false; |
| 297 | } |
| 298 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 299 | static void update_screen_state(charger* charger, int64_t now) { |
| 300 | animation* batt_anim = charger->batt_anim; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 301 | int disp_time; |
| 302 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 303 | if (!batt_anim->run || now < charger->next_screen_transition) return; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 304 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 305 | if (healthd_draw == nullptr) { |
Ruchi Kandoi | bdf11c7 | 2014-09-25 19:44:42 -0700 | [diff] [blame] | 306 | if (healthd_config && healthd_config->screen_on) { |
| 307 | if (!healthd_config->screen_on(batt_prop)) { |
| 308 | LOGV("[%" PRId64 "] leave screen off\n", now); |
| 309 | batt_anim->run = false; |
| 310 | charger->next_screen_transition = -1; |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 311 | if (charger->charger_connected) request_suspend(true); |
Ruchi Kandoi | bdf11c7 | 2014-09-25 19:44:42 -0700 | [diff] [blame] | 312 | return; |
| 313 | } |
Todd Poynor | a730027 | 2014-06-30 13:15:05 -0700 | [diff] [blame] | 314 | } |
| 315 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 316 | healthd_draw.reset(new HealthdDraw(batt_anim)); |
Todd Poynor | a730027 | 2014-06-30 13:15:05 -0700 | [diff] [blame] | 317 | |
| 318 | #ifndef CHARGER_DISABLE_INIT_BLANK |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 319 | healthd_draw->blank_screen(true); |
Todd Poynor | a730027 | 2014-06-30 13:15:05 -0700 | [diff] [blame] | 320 | #endif |
Todd Poynor | a730027 | 2014-06-30 13:15:05 -0700 | [diff] [blame] | 321 | } |
| 322 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 323 | /* animation is over, blank screen and leave */ |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 324 | if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 325 | reset_animation(batt_anim); |
| 326 | charger->next_screen_transition = -1; |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 327 | healthd_draw->blank_screen(true); |
Colin Cross | e1d5247 | 2014-05-15 17:49:06 -0700 | [diff] [blame] | 328 | LOGV("[%" PRId64 "] animation done\n", now); |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 329 | if (charger->charger_connected) request_suspend(true); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 330 | return; |
| 331 | } |
| 332 | |
| 333 | disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time; |
| 334 | |
Thierry Strudel | ac2aa7d | 2018-05-23 15:48:46 -0700 | [diff] [blame] | 335 | /* unblank the screen on first cycle and first frame */ |
| 336 | if (batt_anim->cur_cycle == 0 && batt_anim->cur_frame == 0) healthd_draw->blank_screen(false); |
| 337 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 338 | /* animation starting, set up the animation */ |
| 339 | if (batt_anim->cur_frame == 0) { |
Colin Cross | e1d5247 | 2014-05-15 17:49:06 -0700 | [diff] [blame] | 340 | LOGV("[%" PRId64 "] animation starting\n", now); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 341 | if (batt_prop) { |
| 342 | batt_anim->cur_level = batt_prop->batteryLevel; |
| 343 | batt_anim->cur_status = batt_prop->batteryStatus; |
| 344 | if (batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) { |
| 345 | /* find first frame given current battery level */ |
| 346 | for (int i = 0; i < batt_anim->num_frames; i++) { |
| 347 | if (batt_anim->cur_level >= batt_anim->frames[i].min_level && |
| 348 | batt_anim->cur_level <= batt_anim->frames[i].max_level) { |
| 349 | batt_anim->cur_frame = i; |
| 350 | break; |
| 351 | } |
| 352 | } |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 353 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 354 | // repeat the first frame first_frame_repeats times |
| 355 | disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 356 | batt_anim->first_frame_repeats; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 357 | } |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 358 | } |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 359 | } |
| 360 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 361 | /* draw the new frame (@ cur_frame) */ |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 362 | healthd_draw->redraw_screen(charger->batt_anim, charger->surf_unknown); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 363 | |
| 364 | /* if we don't have anim frames, we only have one image, so just bump |
| 365 | * the cycle counter and exit |
| 366 | */ |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 367 | if (batt_anim->num_frames == 0 || batt_anim->cur_level < 0) { |
| 368 | LOGW("[%" PRId64 "] animation missing or unknown battery status\n", now); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 369 | charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME; |
| 370 | batt_anim->cur_cycle++; |
| 371 | return; |
| 372 | } |
| 373 | |
| 374 | /* schedule next screen transition */ |
| 375 | charger->next_screen_transition = now + disp_time; |
| 376 | |
Ruchi Kandoi | 9015eaa | 2014-06-23 11:13:15 -0700 | [diff] [blame] | 377 | /* advance frame cntr to the next valid frame only if we are charging |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 378 | * if necessary, advance cycle cntr, and reset frame cntr |
| 379 | */ |
Ruchi Kandoi | 9015eaa | 2014-06-23 11:13:15 -0700 | [diff] [blame] | 380 | if (charger->charger_connected) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 381 | batt_anim->cur_frame++; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 382 | |
Ruchi Kandoi | 9015eaa | 2014-06-23 11:13:15 -0700 | [diff] [blame] | 383 | while (batt_anim->cur_frame < batt_anim->num_frames && |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 384 | (batt_anim->cur_level < batt_anim->frames[batt_anim->cur_frame].min_level || |
| 385 | batt_anim->cur_level > batt_anim->frames[batt_anim->cur_frame].max_level)) { |
Ruchi Kandoi | 9015eaa | 2014-06-23 11:13:15 -0700 | [diff] [blame] | 386 | batt_anim->cur_frame++; |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 387 | } |
Ruchi Kandoi | 9015eaa | 2014-06-23 11:13:15 -0700 | [diff] [blame] | 388 | if (batt_anim->cur_frame >= batt_anim->num_frames) { |
| 389 | batt_anim->cur_cycle++; |
| 390 | batt_anim->cur_frame = 0; |
| 391 | |
| 392 | /* don't reset the cycle counter, since we use that as a signal |
| 393 | * in a test above to check if animation is over |
| 394 | */ |
| 395 | } |
| 396 | } else { |
| 397 | /* Stop animating if we're not charging. |
| 398 | * If we stop it immediately instead of going through this loop, then |
| 399 | * the animation would stop somewhere in the middle. |
| 400 | */ |
| 401 | batt_anim->cur_frame = 0; |
| 402 | batt_anim->cur_cycle++; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 403 | } |
| 404 | } |
| 405 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 406 | static int set_key_callback(charger* charger, int code, int value) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 407 | int64_t now = curr_time_ms(); |
| 408 | int down = !!value; |
| 409 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 410 | if (code > KEY_MAX) return -1; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 411 | |
| 412 | /* ignore events that don't modify our state */ |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 413 | if (charger->keys[code].down == down) return 0; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 414 | |
| 415 | /* only record the down even timestamp, as the amount |
| 416 | * of time the key spent not being pressed is not useful */ |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 417 | if (down) charger->keys[code].timestamp = now; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 418 | charger->keys[code].down = down; |
| 419 | charger->keys[code].pending = true; |
| 420 | if (down) { |
Colin Cross | e1d5247 | 2014-05-15 17:49:06 -0700 | [diff] [blame] | 421 | LOGV("[%" PRId64 "] key[%d] down\n", now, code); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 422 | } else { |
| 423 | int64_t duration = now - charger->keys[code].timestamp; |
| 424 | int64_t secs = duration / 1000; |
| 425 | int64_t msecs = duration - secs * 1000; |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 426 | LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n", now, code, |
| 427 | secs, msecs); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 428 | } |
| 429 | |
| 430 | return 0; |
| 431 | } |
| 432 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 433 | static void update_input_state(charger* charger, input_event* ev) { |
| 434 | if (ev->type != EV_KEY) return; |
Tao Bao | 92c2601 | 2017-01-18 22:54:54 -0800 | [diff] [blame] | 435 | set_key_callback(charger, ev->code, ev->value); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 436 | } |
| 437 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 438 | static void set_next_key_check(charger* charger, key_state* key, int64_t timeout) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 439 | int64_t then = key->timestamp + timeout; |
| 440 | |
| 441 | if (charger->next_key_check == -1 || then < charger->next_key_check) |
| 442 | charger->next_key_check = then; |
| 443 | } |
| 444 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 445 | static void process_key(charger* charger, int code, int64_t now) { |
| 446 | key_state* key = &charger->keys[code]; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 447 | |
| 448 | if (code == KEY_POWER) { |
| 449 | if (key->down) { |
| 450 | int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME; |
| 451 | if (now >= reboot_timeout) { |
Riley Andrews | 6bd4588 | 2014-06-23 15:20:51 -0700 | [diff] [blame] | 452 | /* We do not currently support booting from charger mode on |
| 453 | all devices. Check the property and continue booting or reboot |
| 454 | accordingly. */ |
| 455 | if (property_get_bool("ro.enable_boot_charger_mode", false)) { |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 456 | LOGW("[%" PRId64 "] booting from charger mode\n", now); |
Riley Andrews | 6bd4588 | 2014-06-23 15:20:51 -0700 | [diff] [blame] | 457 | property_set("sys.boot_from_charger_mode", "1"); |
| 458 | } else { |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 459 | if (charger->batt_anim->cur_level >= charger->boot_min_cap) { |
Ruchi Kandoi | a84b1f6 | 2014-10-21 18:24:11 -0700 | [diff] [blame] | 460 | LOGW("[%" PRId64 "] rebooting\n", now); |
Todd Poynor | c8183bb | 2017-01-31 15:51:50 -0800 | [diff] [blame] | 461 | reboot(RB_AUTOBOOT); |
Ruchi Kandoi | a84b1f6 | 2014-10-21 18:24:11 -0700 | [diff] [blame] | 462 | } else { |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 463 | LOGV("[%" PRId64 |
| 464 | "] ignore power-button press, battery level " |
| 465 | "less than minimum\n", |
| 466 | now); |
Ruchi Kandoi | a84b1f6 | 2014-10-21 18:24:11 -0700 | [diff] [blame] | 467 | } |
Riley Andrews | 6bd4588 | 2014-06-23 15:20:51 -0700 | [diff] [blame] | 468 | } |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 469 | } else { |
| 470 | /* if the key is pressed but timeout hasn't expired, |
| 471 | * make sure we wake up at the right-ish time to check |
| 472 | */ |
| 473 | set_next_key_check(charger, key, POWER_ON_KEY_TIME); |
Ruchi Kandoi | 9a11aaa | 2014-10-22 14:16:35 -0700 | [diff] [blame] | 474 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 475 | /* Turn on the display and kick animation on power-key press |
| 476 | * rather than on key release |
| 477 | */ |
Ruchi Kandoi | 9a11aaa | 2014-10-22 14:16:35 -0700 | [diff] [blame] | 478 | kick_animation(charger->batt_anim); |
| 479 | request_suspend(false); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 480 | } |
| 481 | } else { |
| 482 | /* if the power key got released, force screen state cycle */ |
| 483 | if (key->pending) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 484 | kick_animation(charger->batt_anim); |
| 485 | } |
| 486 | } |
| 487 | } |
| 488 | |
| 489 | key->pending = false; |
| 490 | } |
| 491 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 492 | static void handle_input_state(charger* charger, int64_t now) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 493 | process_key(charger, KEY_POWER, now); |
| 494 | |
| 495 | if (charger->next_key_check != -1 && now > charger->next_key_check) |
| 496 | charger->next_key_check = -1; |
| 497 | } |
| 498 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 499 | static void handle_power_supply_state(charger* charger, int64_t now) { |
| 500 | if (!charger->have_battery_state) return; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 501 | |
Bharath | c0d2a47 | 2020-04-15 11:39:06 +0530 | [diff] [blame] | 502 | healthd_board_mode_charger_battery_update(batt_prop); |
| 503 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 504 | if (!charger->charger_connected) { |
Ruchi Kandoi | 9a11aaa | 2014-10-22 14:16:35 -0700 | [diff] [blame] | 505 | /* Last cycle would have stopped at the extreme top of battery-icon |
| 506 | * Need to show the correct level corresponding to capacity. |
| 507 | */ |
| 508 | kick_animation(charger->batt_anim); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 509 | request_suspend(false); |
| 510 | if (charger->next_pwr_check == -1) { |
| 511 | charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 512 | LOGW("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n", |
Colin Cross | e1d5247 | 2014-05-15 17:49:06 -0700 | [diff] [blame] | 513 | now, (int64_t)UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 514 | } else if (now >= charger->next_pwr_check) { |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 515 | LOGW("[%" PRId64 "] shutting down\n", now); |
Todd Poynor | c8183bb | 2017-01-31 15:51:50 -0800 | [diff] [blame] | 516 | reboot(RB_POWER_OFF); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 517 | } else { |
| 518 | /* otherwise we already have a shutdown timer scheduled */ |
| 519 | } |
| 520 | } else { |
| 521 | /* online supply present, reset shutdown timer if set */ |
| 522 | if (charger->next_pwr_check != -1) { |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 523 | LOGW("[%" PRId64 "] device plugged in: shutdown cancelled\n", now); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 524 | kick_animation(charger->batt_anim); |
| 525 | } |
| 526 | charger->next_pwr_check = -1; |
| 527 | } |
| 528 | } |
| 529 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 530 | void healthd_mode_charger_heartbeat() { |
| 531 | charger* charger = &charger_state; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 532 | int64_t now = curr_time_ms(); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 533 | |
| 534 | handle_input_state(charger, now); |
| 535 | handle_power_supply_state(charger, now); |
| 536 | |
| 537 | /* do screen update last in case any of the above want to start |
| 538 | * screen transitions (animations, etc) |
| 539 | */ |
| 540 | update_screen_state(charger, now); |
| 541 | } |
| 542 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 543 | void healthd_mode_charger_battery_update(android::BatteryProperties* props) { |
| 544 | charger* charger = &charger_state; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 545 | |
| 546 | charger->charger_connected = |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 547 | props->chargerAcOnline || props->chargerUsbOnline || props->chargerWirelessOnline; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 548 | |
| 549 | if (!charger->have_battery_state) { |
| 550 | charger->have_battery_state = true; |
| 551 | charger->next_screen_transition = curr_time_ms() - 1; |
| 552 | reset_animation(charger->batt_anim); |
| 553 | kick_animation(charger->batt_anim); |
| 554 | } |
Ruchi Kandoi | bdf11c7 | 2014-09-25 19:44:42 -0700 | [diff] [blame] | 555 | batt_prop = props; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 556 | } |
| 557 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 558 | int healthd_mode_charger_preparetowait(void) { |
| 559 | charger* charger = &charger_state; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 560 | int64_t now = curr_time_ms(); |
| 561 | int64_t next_event = INT64_MAX; |
| 562 | int64_t timeout; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 563 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 564 | LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n", |
| 565 | now, charger->next_screen_transition, charger->next_key_check, charger->next_pwr_check); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 566 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 567 | if (charger->next_screen_transition != -1) next_event = charger->next_screen_transition; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 568 | if (charger->next_key_check != -1 && charger->next_key_check < next_event) |
| 569 | next_event = charger->next_key_check; |
| 570 | if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event) |
| 571 | next_event = charger->next_pwr_check; |
| 572 | |
| 573 | if (next_event != -1 && next_event != INT64_MAX) |
| 574 | timeout = max(0, next_event - now); |
| 575 | else |
| 576 | timeout = -1; |
| 577 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 578 | return (int)timeout; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 579 | } |
| 580 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 581 | static int input_callback(charger* charger, int fd, unsigned int epevents) { |
| 582 | input_event ev; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 583 | int ret; |
| 584 | |
| 585 | ret = ev_get_input(fd, epevents, &ev); |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 586 | if (ret) return -1; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 587 | update_input_state(charger, &ev); |
| 588 | return 0; |
| 589 | } |
| 590 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 591 | static void charger_event_handler(uint32_t /*epevents*/) { |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 592 | int ret; |
| 593 | |
| 594 | ret = ev_wait(-1); |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 595 | if (!ret) ev_dispatch(); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 596 | } |
| 597 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 598 | animation* init_animation() { |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 599 | bool parse_success; |
| 600 | |
| 601 | std::string content; |
| 602 | if (base::ReadFileToString(animation_desc_path, &content)) { |
| 603 | parse_success = parse_animation_desc(content, &battery_animation); |
| 604 | } else { |
| 605 | LOGW("Could not open animation description at %s\n", animation_desc_path); |
| 606 | parse_success = false; |
| 607 | } |
| 608 | |
| 609 | if (!parse_success) { |
| 610 | LOGW("Could not parse animation description. Using default animation.\n"); |
| 611 | battery_animation = BASE_ANIMATION; |
| 612 | battery_animation.animation_file.assign("charger/battery_scale"); |
| 613 | battery_animation.frames = default_animation_frames; |
| 614 | battery_animation.num_frames = ARRAY_SIZE(default_animation_frames); |
| 615 | } |
| 616 | if (battery_animation.fail_file.empty()) { |
| 617 | battery_animation.fail_file.assign("charger/battery_fail"); |
| 618 | } |
| 619 | |
| 620 | LOGV("Animation Description:\n"); |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 621 | LOGV(" animation: %d %d '%s' (%d)\n", battery_animation.num_cycles, |
| 622 | battery_animation.first_frame_repeats, battery_animation.animation_file.c_str(), |
| 623 | battery_animation.num_frames); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 624 | LOGV(" fail_file: '%s'\n", battery_animation.fail_file.c_str()); |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 625 | LOGV(" clock: %d %d %d %d %d %d '%s'\n", battery_animation.text_clock.pos_x, |
| 626 | battery_animation.text_clock.pos_y, battery_animation.text_clock.color_r, |
| 627 | battery_animation.text_clock.color_g, battery_animation.text_clock.color_b, |
| 628 | battery_animation.text_clock.color_a, battery_animation.text_clock.font_file.c_str()); |
| 629 | LOGV(" percent: %d %d %d %d %d %d '%s'\n", battery_animation.text_percent.pos_x, |
| 630 | battery_animation.text_percent.pos_y, battery_animation.text_percent.color_r, |
| 631 | battery_animation.text_percent.color_g, battery_animation.text_percent.color_b, |
| 632 | battery_animation.text_percent.color_a, battery_animation.text_percent.font_file.c_str()); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 633 | for (int i = 0; i < battery_animation.num_frames; i++) { |
| 634 | LOGV(" frame %.2d: %d %d %d\n", i, battery_animation.frames[i].disp_time, |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 635 | battery_animation.frames[i].min_level, battery_animation.frames[i].max_level); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 636 | } |
| 637 | |
| 638 | return &battery_animation; |
| 639 | } |
| 640 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 641 | void healthd_mode_charger_init(struct healthd_config* config) { |
Yifan Hong | 10c2b40 | 2017-11-08 10:57:52 -0800 | [diff] [blame] | 642 | using android::hardware::health::V2_0::implementation::Health; |
| 643 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 644 | int ret; |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 645 | charger* charger = &charger_state; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 646 | int i; |
| 647 | int epollfd; |
| 648 | |
| 649 | dump_last_kmsg(); |
| 650 | |
Todd Poynor | ebeb0c0 | 2014-09-23 14:54:24 -0700 | [diff] [blame] | 651 | LOGW("--------------- STARTING CHARGER MODE ---------------\n"); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 652 | |
Bharath | c0d2a47 | 2020-04-15 11:39:06 +0530 | [diff] [blame] | 653 | if(!healthd_board_mode_charger_init()) { |
| 654 | LOGE("healthd_mode_charger_init failed restarting\n"); |
| 655 | android_reboot(ANDROID_RB_RESTART2, 0, 0); |
| 656 | } |
| 657 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 658 | ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1, std::placeholders::_2)); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 659 | if (!ret) { |
| 660 | epollfd = ev_get_epollfd(); |
Tim Murray | e89ea5e | 2016-10-18 16:35:15 -0700 | [diff] [blame] | 661 | healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 662 | } |
| 663 | |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 664 | animation* anim = init_animation(); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 665 | charger->batt_anim = anim; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 666 | |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 667 | ret = res_create_display_surface(anim->fail_file.c_str(), &charger->surf_unknown); |
| 668 | if (ret < 0) { |
Thierry Strudel | ac2aa7d | 2018-05-23 15:48:46 -0700 | [diff] [blame] | 669 | LOGE("Cannot load custom battery_fail image. Reverting to built in: %d\n", ret); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 670 | ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown); |
| 671 | if (ret < 0) { |
| 672 | LOGE("Cannot load built in battery_fail image\n"); |
| 673 | charger->surf_unknown = NULL; |
| 674 | } |
| 675 | } |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 676 | |
Elliott Hughes | 9e85ea1 | 2015-04-15 10:25:55 -0700 | [diff] [blame] | 677 | GRSurface** scale_frames; |
Doug Zongker | ee6ef15 | 2014-03-11 08:42:09 -0700 | [diff] [blame] | 678 | int scale_count; |
Tao Bao | 0db8023 | 2015-12-16 10:57:10 -0800 | [diff] [blame] | 679 | int scale_fps; // Not in use (charger/battery_scale doesn't have FPS text |
| 680 | // chunk). We are using hard-coded frame.disp_time instead. |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 681 | ret = res_create_multi_display_surface(anim->animation_file.c_str(), &scale_count, &scale_fps, |
| 682 | &scale_frames); |
Doug Zongker | ee6ef15 | 2014-03-11 08:42:09 -0700 | [diff] [blame] | 683 | if (ret < 0) { |
| 684 | LOGE("Cannot load battery_scale image\n"); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 685 | anim->num_frames = 0; |
| 686 | anim->num_cycles = 1; |
| 687 | } else if (scale_count != anim->num_frames) { |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 688 | LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n", scale_count, |
| 689 | anim->num_frames); |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 690 | anim->num_frames = 0; |
| 691 | anim->num_cycles = 1; |
Doug Zongker | ee6ef15 | 2014-03-11 08:42:09 -0700 | [diff] [blame] | 692 | } else { |
Damien Bargiacchi | 565ba02 | 2016-08-11 15:29:50 -0700 | [diff] [blame] | 693 | for (i = 0; i < anim->num_frames; i++) { |
| 694 | anim->frames[i].surface = scale_frames[i]; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 695 | } |
| 696 | } |
Luke Song | 1d540dd | 2017-07-13 15:10:35 -0700 | [diff] [blame] | 697 | ev_sync_key_state( |
| 698 | std::bind(&set_key_callback, charger, std::placeholders::_1, std::placeholders::_2)); |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 699 | |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 700 | charger->next_screen_transition = -1; |
| 701 | charger->next_key_check = -1; |
| 702 | charger->next_pwr_check = -1; |
Yifan Hong | 10c2b40 | 2017-11-08 10:57:52 -0800 | [diff] [blame] | 703 | |
| 704 | // Initialize Health implementation (which initializes the internal BatteryMonitor). |
| 705 | Health::initInstance(config); |
| 706 | |
Ruchi Kandoi | bdf11c7 | 2014-09-25 19:44:42 -0700 | [diff] [blame] | 707 | healthd_config = config; |
Ruchi Kandoi | a84b1f6 | 2014-10-21 18:24:11 -0700 | [diff] [blame] | 708 | charger->boot_min_cap = config->boot_min_cap; |
Todd Poynor | fea5b4d | 2013-09-09 12:09:08 -0700 | [diff] [blame] | 709 | } |