Home | History | Annotate | Download | only in healthd
      1 /*
      2  * Copyright (C) 2011-2013 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 
     17 #include <dirent.h>
     18 #include <errno.h>
     19 #include <fcntl.h>
     20 #include <inttypes.h>
     21 #include <linux/input.h>
     22 #include <stdbool.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <sys/epoll.h>
     27 #include <sys/stat.h>
     28 #include <sys/types.h>
     29 #include <sys/un.h>
     30 #include <time.h>
     31 #include <unistd.h>
     32 
     33 #include <sys/socket.h>
     34 #include <linux/netlink.h>
     35 
     36 #include <batteryservice/BatteryService.h>
     37 #include <cutils/android_reboot.h>
     38 #include <cutils/klog.h>
     39 #include <cutils/misc.h>
     40 #include <cutils/uevent.h>
     41 #include <cutils/properties.h>
     42 
     43 #ifdef CHARGER_ENABLE_SUSPEND
     44 #include <suspend/autosuspend.h>
     45 #endif
     46 
     47 #include "minui/minui.h"
     48 
     49 #include "healthd.h"
     50 
     51 char *locale;
     52 
     53 #ifndef max
     54 #define max(a,b) ((a) > (b) ? (a) : (b))
     55 #endif
     56 
     57 #ifndef min
     58 #define min(a,b) ((a) < (b) ? (a) : (b))
     59 #endif
     60 
     61 #define ARRAY_SIZE(x)           (sizeof(x)/sizeof(x[0]))
     62 
     63 #define MSEC_PER_SEC            (1000LL)
     64 #define NSEC_PER_MSEC           (1000000LL)
     65 
     66 #define BATTERY_UNKNOWN_TIME    (2 * MSEC_PER_SEC)
     67 #define POWER_ON_KEY_TIME       (2 * MSEC_PER_SEC)
     68 #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
     69 
     70 #define BATTERY_FULL_THRESH     95
     71 #define SCREEN_ON_BATTERY_THRESH 0
     72 
     73 #define LAST_KMSG_PATH          "/proc/last_kmsg"
     74 #define LAST_KMSG_PSTORE_PATH   "/sys/fs/pstore/console-ramoops"
     75 #define LAST_KMSG_MAX_SZ        (32 * 1024)
     76 
     77 #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
     78 #define LOGI(x...) do { KLOG_INFO("charger", x); } while (0)
     79 #define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
     80 
     81 struct key_state {
     82     bool pending;
     83     bool down;
     84     int64_t timestamp;
     85 };
     86 
     87 struct frame {
     88     int disp_time;
     89     int min_capacity;
     90     bool level_only;
     91 
     92     gr_surface surface;
     93 };
     94 
     95 struct animation {
     96     bool run;
     97 
     98     struct frame *frames;
     99     int cur_frame;
    100     int num_frames;
    101 
    102     int cur_cycle;
    103     int num_cycles;
    104 
    105     /* current capacity being animated */
    106     int capacity;
    107 };
    108 
    109 struct charger {
    110     bool have_battery_state;
    111     bool charger_connected;
    112     int capacity;
    113     int64_t next_screen_transition;
    114     int64_t next_key_check;
    115     int64_t next_pwr_check;
    116 
    117     struct key_state keys[KEY_MAX + 1];
    118 
    119     struct animation *batt_anim;
    120     gr_surface surf_unknown;
    121 };
    122 
    123 static struct frame batt_anim_frames[] = {
    124     {
    125         .disp_time = 750,
    126         .min_capacity = 0,
    127         .level_only = false,
    128         .surface = NULL,
    129     },
    130     {
    131         .disp_time = 750,
    132         .min_capacity = 20,
    133         .level_only = false,
    134         .surface = NULL,
    135     },
    136     {
    137         .disp_time = 750,
    138         .min_capacity = 40,
    139         .level_only = false,
    140         .surface = NULL,
    141     },
    142     {
    143         .disp_time = 750,
    144         .min_capacity = 60,
    145         .level_only = false,
    146         .surface = NULL,
    147     },
    148     {
    149         .disp_time = 750,
    150         .min_capacity = 80,
    151         .level_only = true,
    152         .surface = NULL,
    153     },
    154     {
    155         .disp_time = 750,
    156         .min_capacity = BATTERY_FULL_THRESH,
    157         .level_only = false,
    158         .surface = NULL,
    159     },
    160 };
    161 
    162 static struct animation battery_animation = {
    163     .run = false,
    164     .frames = batt_anim_frames,
    165     .cur_frame = 0,
    166     .num_frames = ARRAY_SIZE(batt_anim_frames),
    167     .cur_cycle = 0,
    168     .num_cycles = 3,
    169     .capacity = 0,
    170 };
    171 
    172 static struct charger charger_state;
    173 
    174 static int char_width;
    175 static int char_height;
    176 static bool minui_inited;
    177 
    178 /* current time in milliseconds */
    179 static int64_t curr_time_ms(void)
    180 {
    181     struct timespec tm;
    182     clock_gettime(CLOCK_MONOTONIC, &tm);
    183     return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC);
    184 }
    185 
    186 static void clear_screen(void)
    187 {
    188     gr_color(0, 0, 0, 255);
    189     gr_clear();
    190 }
    191 
    192 #define MAX_KLOG_WRITE_BUF_SZ 256
    193 
    194 static void dump_last_kmsg(void)
    195 {
    196     char *buf;
    197     char *ptr;
    198     unsigned sz = 0;
    199     int len;
    200 
    201     LOGI("\n");
    202     LOGI("*************** LAST KMSG ***************\n");
    203     LOGI("\n");
    204     buf = (char *)load_file(LAST_KMSG_PSTORE_PATH, &sz);
    205 
    206     if (!buf || !sz) {
    207         buf = (char *)load_file(LAST_KMSG_PATH, &sz);
    208         if (!buf || !sz) {
    209             LOGI("last_kmsg not found. Cold reset?\n");
    210             goto out;
    211         }
    212     }
    213 
    214     len = min(sz, LAST_KMSG_MAX_SZ);
    215     ptr = buf + (sz - len);
    216 
    217     while (len > 0) {
    218         int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
    219         char yoink;
    220         char *nl;
    221 
    222         nl = (char *)memrchr(ptr, '\n', cnt - 1);
    223         if (nl)
    224             cnt = nl - ptr + 1;
    225 
    226         yoink = ptr[cnt];
    227         ptr[cnt] = '\0';
    228         klog_write(6, "<6>%s", ptr);
    229         ptr[cnt] = yoink;
    230 
    231         len -= cnt;
    232         ptr += cnt;
    233     }
    234 
    235     free(buf);
    236 
    237 out:
    238     LOGI("\n");
    239     LOGI("************* END LAST KMSG *************\n");
    240     LOGI("\n");
    241 }
    242 
    243 static int get_battery_capacity()
    244 {
    245     return charger_state.capacity;
    246 }
    247 
    248 #ifdef CHARGER_ENABLE_SUSPEND
    249 static int request_suspend(bool enable)
    250 {
    251     if (enable)
    252         return autosuspend_enable();
    253     else
    254         return autosuspend_disable();
    255 }
    256 #else
    257 static int request_suspend(bool /*enable*/)
    258 {
    259     return 0;
    260 }
    261 #endif
    262 
    263 static int draw_text(const char *str, int x, int y)
    264 {
    265     int str_len_px = gr_measure(str);
    266 
    267     if (x < 0)
    268         x = (gr_fb_width() - str_len_px) / 2;
    269     if (y < 0)
    270         y = (gr_fb_height() - char_height) / 2;
    271     gr_text(x, y, str, 0);
    272 
    273     return y + char_height;
    274 }
    275 
    276 static void android_green(void)
    277 {
    278     gr_color(0xa4, 0xc6, 0x39, 255);
    279 }
    280 
    281 /* returns the last y-offset of where the surface ends */
    282 static int draw_surface_centered(struct charger* /*charger*/, gr_surface surface)
    283 {
    284     int w;
    285     int h;
    286     int x;
    287     int y;
    288 
    289     w = gr_get_width(surface);
    290     h = gr_get_height(surface);
    291     x = (gr_fb_width() - w) / 2 ;
    292     y = (gr_fb_height() - h) / 2 ;
    293 
    294     LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
    295     gr_blit(surface, 0, 0, w, h, x, y);
    296     return y + h;
    297 }
    298 
    299 static void draw_unknown(struct charger *charger)
    300 {
    301     int y;
    302     if (charger->surf_unknown) {
    303         draw_surface_centered(charger, charger->surf_unknown);
    304     } else {
    305         android_green();
    306         y = draw_text("Charging!", -1, -1);
    307         draw_text("?\?/100", -1, y + 25);
    308     }
    309 }
    310 
    311 static void draw_battery(struct charger *charger)
    312 {
    313     struct animation *batt_anim = charger->batt_anim;
    314     struct frame *frame = &batt_anim->frames[batt_anim->cur_frame];
    315 
    316     if (batt_anim->num_frames != 0) {
    317         draw_surface_centered(charger, frame->surface);
    318         LOGV("drawing frame #%d min_cap=%d time=%d\n",
    319              batt_anim->cur_frame, frame->min_capacity,
    320              frame->disp_time);
    321     }
    322 }
    323 
    324 static void redraw_screen(struct charger *charger)
    325 {
    326     struct animation *batt_anim = charger->batt_anim;
    327 
    328     clear_screen();
    329 
    330     /* try to display *something* */
    331     if (batt_anim->capacity < 0 || batt_anim->num_frames == 0)
    332         draw_unknown(charger);
    333     else
    334         draw_battery(charger);
    335     gr_flip();
    336 }
    337 
    338 static void kick_animation(struct animation *anim)
    339 {
    340     anim->run = true;
    341 }
    342 
    343 static void reset_animation(struct animation *anim)
    344 {
    345     anim->cur_cycle = 0;
    346     anim->cur_frame = 0;
    347     anim->run = false;
    348 }
    349 
    350 static void update_screen_state(struct charger *charger, int64_t now)
    351 {
    352     struct animation *batt_anim = charger->batt_anim;
    353     int cur_frame;
    354     int disp_time;
    355 
    356     if (!batt_anim->run || now < charger->next_screen_transition)
    357         return;
    358 
    359     if (!minui_inited) {
    360         int batt_cap = get_battery_capacity();
    361 
    362         if (batt_cap < SCREEN_ON_BATTERY_THRESH) {
    363             LOGV("[%" PRId64 "] level %d, leave screen off\n", now, batt_cap);
    364             batt_anim->run = false;
    365             charger->next_screen_transition = -1;
    366             if (charger->charger_connected)
    367                 request_suspend(true);
    368             return;
    369         }
    370 
    371         gr_init();
    372         gr_font_size(&char_width, &char_height);
    373 
    374 #ifndef CHARGER_DISABLE_INIT_BLANK
    375         gr_fb_blank(true);
    376 #endif
    377         minui_inited = true;
    378     }
    379 
    380     /* animation is over, blank screen and leave */
    381     if (batt_anim->cur_cycle == batt_anim->num_cycles) {
    382         reset_animation(batt_anim);
    383         charger->next_screen_transition = -1;
    384         gr_fb_blank(true);
    385         LOGV("[%" PRId64 "] animation done\n", now);
    386         if (charger->charger_connected)
    387             request_suspend(true);
    388         return;
    389     }
    390 
    391     disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;
    392 
    393     /* animation starting, set up the animation */
    394     if (batt_anim->cur_frame == 0) {
    395         int batt_cap;
    396         int ret;
    397 
    398         LOGV("[%" PRId64 "] animation starting\n", now);
    399         batt_cap = get_battery_capacity();
    400         if (batt_cap >= 0 && batt_anim->num_frames != 0) {
    401             int i;
    402 
    403             /* find first frame given current capacity */
    404             for (i = 1; i < batt_anim->num_frames; i++) {
    405                 if (batt_cap < batt_anim->frames[i].min_capacity)
    406                     break;
    407             }
    408             batt_anim->cur_frame = i - 1;
    409 
    410             /* show the first frame for twice as long */
    411             disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
    412         }
    413 
    414         batt_anim->capacity = batt_cap;
    415     }
    416 
    417     /* unblank the screen  on first cycle */
    418     if (batt_anim->cur_cycle == 0)
    419         gr_fb_blank(false);
    420 
    421     /* draw the new frame (@ cur_frame) */
    422     redraw_screen(charger);
    423 
    424     /* if we don't have anim frames, we only have one image, so just bump
    425      * the cycle counter and exit
    426      */
    427     if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {
    428         LOGV("[%" PRId64 "] animation missing or unknown battery status\n", now);
    429         charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
    430         batt_anim->cur_cycle++;
    431         return;
    432     }
    433 
    434     /* schedule next screen transition */
    435     charger->next_screen_transition = now + disp_time;
    436 
    437     /* advance frame cntr to the next valid frame only if we are charging
    438      * if necessary, advance cycle cntr, and reset frame cntr
    439      */
    440     if (charger->charger_connected) {
    441         batt_anim->cur_frame++;
    442 
    443         /* if the frame is used for level-only, that is only show it when it's
    444          * the current level, skip it during the animation.
    445          */
    446         while (batt_anim->cur_frame < batt_anim->num_frames &&
    447                batt_anim->frames[batt_anim->cur_frame].level_only)
    448             batt_anim->cur_frame++;
    449         if (batt_anim->cur_frame >= batt_anim->num_frames) {
    450             batt_anim->cur_cycle++;
    451             batt_anim->cur_frame = 0;
    452 
    453             /* don't reset the cycle counter, since we use that as a signal
    454              * in a test above to check if animation is over
    455              */
    456         }
    457     } else {
    458         /* Stop animating if we're not charging.
    459          * If we stop it immediately instead of going through this loop, then
    460          * the animation would stop somewhere in the middle.
    461          */
    462         batt_anim->cur_frame = 0;
    463         batt_anim->cur_cycle++;
    464     }
    465 }
    466 
    467 static int set_key_callback(int code, int value, void *data)
    468 {
    469     struct charger *charger = (struct charger *)data;
    470     int64_t now = curr_time_ms();
    471     int down = !!value;
    472 
    473     if (code > KEY_MAX)
    474         return -1;
    475 
    476     /* ignore events that don't modify our state */
    477     if (charger->keys[code].down == down)
    478         return 0;
    479 
    480     /* only record the down even timestamp, as the amount
    481      * of time the key spent not being pressed is not useful */
    482     if (down)
    483         charger->keys[code].timestamp = now;
    484     charger->keys[code].down = down;
    485     charger->keys[code].pending = true;
    486     if (down) {
    487         LOGV("[%" PRId64 "] key[%d] down\n", now, code);
    488     } else {
    489         int64_t duration = now - charger->keys[code].timestamp;
    490         int64_t secs = duration / 1000;
    491         int64_t msecs = duration - secs * 1000;
    492         LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n",
    493              now, code, secs, msecs);
    494     }
    495 
    496     return 0;
    497 }
    498 
    499 static void update_input_state(struct charger *charger,
    500                                struct input_event *ev)
    501 {
    502     if (ev->type != EV_KEY)
    503         return;
    504     set_key_callback(ev->code, ev->value, charger);
    505 }
    506 
    507 static void set_next_key_check(struct charger *charger,
    508                                struct key_state *key,
    509                                int64_t timeout)
    510 {
    511     int64_t then = key->timestamp + timeout;
    512 
    513     if (charger->next_key_check == -1 || then < charger->next_key_check)
    514         charger->next_key_check = then;
    515 }
    516 
    517 static void process_key(struct charger *charger, int code, int64_t now)
    518 {
    519     struct key_state *key = &charger->keys[code];
    520     int64_t next_key_check;
    521 
    522     if (code == KEY_POWER) {
    523         if (key->down) {
    524             int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;
    525             if (now >= reboot_timeout) {
    526                 /* We do not currently support booting from charger mode on
    527                    all devices. Check the property and continue booting or reboot
    528                    accordingly. */
    529                 if (property_get_bool("ro.enable_boot_charger_mode", false)) {
    530                     LOGI("[%" PRId64 "] booting from charger mode\n", now);
    531                     property_set("sys.boot_from_charger_mode", "1");
    532                 } else {
    533                     LOGI("[%" PRId64 "] rebooting\n", now);
    534                     android_reboot(ANDROID_RB_RESTART, 0, 0);
    535                 }
    536             } else {
    537                 /* if the key is pressed but timeout hasn't expired,
    538                  * make sure we wake up at the right-ish time to check
    539                  */
    540                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
    541             }
    542         } else {
    543             /* if the power key got released, force screen state cycle */
    544             if (key->pending) {
    545                 request_suspend(false);
    546                 kick_animation(charger->batt_anim);
    547             }
    548         }
    549     }
    550 
    551     key->pending = false;
    552 }
    553 
    554 static void handle_input_state(struct charger *charger, int64_t now)
    555 {
    556     process_key(charger, KEY_POWER, now);
    557 
    558     if (charger->next_key_check != -1 && now > charger->next_key_check)
    559         charger->next_key_check = -1;
    560 }
    561 
    562 static void handle_power_supply_state(struct charger *charger, int64_t now)
    563 {
    564     if (!charger->have_battery_state)
    565         return;
    566 
    567     if (!charger->charger_connected) {
    568         request_suspend(false);
    569         if (charger->next_pwr_check == -1) {
    570             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
    571             LOGI("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n",
    572                  now, (int64_t)UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);
    573         } else if (now >= charger->next_pwr_check) {
    574             LOGI("[%" PRId64 "] shutting down\n", now);
    575             android_reboot(ANDROID_RB_POWEROFF, 0, 0);
    576         } else {
    577             /* otherwise we already have a shutdown timer scheduled */
    578         }
    579     } else {
    580         /* online supply present, reset shutdown timer if set */
    581         if (charger->next_pwr_check != -1) {
    582             LOGI("[%" PRId64 "] device plugged in: shutdown cancelled\n", now);
    583             kick_animation(charger->batt_anim);
    584         }
    585         charger->next_pwr_check = -1;
    586     }
    587 }
    588 
    589 void healthd_mode_charger_heartbeat()
    590 {
    591     struct charger *charger = &charger_state;
    592     int64_t now = curr_time_ms();
    593     int ret;
    594 
    595     handle_input_state(charger, now);
    596     handle_power_supply_state(charger, now);
    597 
    598     /* do screen update last in case any of the above want to start
    599      * screen transitions (animations, etc)
    600      */
    601     update_screen_state(charger, now);
    602 }
    603 
    604 void healthd_mode_charger_battery_update(
    605     struct android::BatteryProperties *props)
    606 {
    607     struct charger *charger = &charger_state;
    608 
    609     charger->charger_connected =
    610         props->chargerAcOnline || props->chargerUsbOnline ||
    611         props->chargerWirelessOnline;
    612     charger->capacity = props->batteryLevel;
    613 
    614     if (!charger->have_battery_state) {
    615         charger->have_battery_state = true;
    616         charger->next_screen_transition = curr_time_ms() - 1;
    617         reset_animation(charger->batt_anim);
    618         kick_animation(charger->batt_anim);
    619     }
    620 }
    621 
    622 int healthd_mode_charger_preparetowait(void)
    623 {
    624     struct charger *charger = &charger_state;
    625     int64_t now = curr_time_ms();
    626     int64_t next_event = INT64_MAX;
    627     int64_t timeout;
    628     struct input_event ev;
    629     int ret;
    630 
    631     LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n", now,
    632          charger->next_screen_transition, charger->next_key_check,
    633          charger->next_pwr_check);
    634 
    635     if (charger->next_screen_transition != -1)
    636         next_event = charger->next_screen_transition;
    637     if (charger->next_key_check != -1 && charger->next_key_check < next_event)
    638         next_event = charger->next_key_check;
    639     if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event)
    640         next_event = charger->next_pwr_check;
    641 
    642     if (next_event != -1 && next_event != INT64_MAX)
    643         timeout = max(0, next_event - now);
    644     else
    645         timeout = -1;
    646 
    647    return (int)timeout;
    648 }
    649 
    650 static int input_callback(int fd, unsigned int epevents, void *data)
    651 {
    652     struct charger *charger = (struct charger *)data;
    653     struct input_event ev;
    654     int ret;
    655 
    656     ret = ev_get_input(fd, epevents, &ev);
    657     if (ret)
    658         return -1;
    659     update_input_state(charger, &ev);
    660     return 0;
    661 }
    662 
    663 static void charger_event_handler(uint32_t /*epevents*/)
    664 {
    665     int ret;
    666 
    667     ret = ev_wait(-1);
    668     if (!ret)
    669         ev_dispatch();
    670 }
    671 
    672 void healthd_mode_charger_init(struct healthd_config* /*config*/)
    673 {
    674     int ret;
    675     struct charger *charger = &charger_state;
    676     int i;
    677     int epollfd;
    678 
    679     dump_last_kmsg();
    680 
    681     LOGI("--------------- STARTING CHARGER MODE ---------------\n");
    682 
    683     ret = ev_init(input_callback, charger);
    684     if (!ret) {
    685         epollfd = ev_get_epollfd();
    686         healthd_register_event(epollfd, charger_event_handler);
    687     }
    688 
    689     ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
    690     if (ret < 0) {
    691         LOGE("Cannot load battery_fail image\n");
    692         charger->surf_unknown = NULL;
    693     }
    694 
    695     charger->batt_anim = &battery_animation;
    696 
    697     gr_surface* scale_frames;
    698     int scale_count;
    699     ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_frames);
    700     if (ret < 0) {
    701         LOGE("Cannot load battery_scale image\n");
    702         charger->batt_anim->num_frames = 0;
    703         charger->batt_anim->num_cycles = 1;
    704     } else if (scale_count != charger->batt_anim->num_frames) {
    705         LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
    706              scale_count, charger->batt_anim->num_frames);
    707         charger->batt_anim->num_frames = 0;
    708         charger->batt_anim->num_cycles = 1;
    709     } else {
    710         for (i = 0; i < charger->batt_anim->num_frames; i++) {
    711             charger->batt_anim->frames[i].surface = scale_frames[i];
    712         }
    713     }
    714 
    715     ev_sync_key_state(set_key_callback, charger);
    716 
    717     charger->next_screen_transition = -1;
    718     charger->next_key_check = -1;
    719     charger->next_pwr_check = -1;
    720 }
    721