在andriod中加入充电指示

来源:互联网 发布:行业数据来源 编辑:程序博客网 时间:2024/06/10 09:03

             andriod中加入充电指示

作者:帅文

基于Andriod系统的平台在没有硬件充电指示的情况下只有进入andriod系统才能进行充电指示,而我们有时候仅仅需要充电而不需要进入系统,本文介绍了实现这种功能的方法。

具体过程如下:当内核启动后调用充电指示控制程序。充电指示程序发现如果外部供电就开始显示充电的画面,同时将设备的电源控制锁定为关闭状态(这样当拔掉电源时候系统自动关闭),如果在充电指示过程中又按了开机键,就重新开启电源按键。这个过程在单片机等简单系统上不值得一提,因为每个人都会想的比我好,这里重点介绍如何融合到andriod系统以及其中的我认为可以让别人参考的方法。

方法一  ui显示部分。显然我们不能让系统跑的太深,否则控制起来就过于麻烦,充电显示等老半天才启动别人也觉得奇怪。所以有必要仅仅使用微型系统,微型系统自然能用的功能就少,在图像显示上面只能使用c语言操作framebuff,我的方法是参考bootable/recovery/minui/里面的库,其支持png的图片也文本显示,对于充电指示足够用了。一个可能遇到的问题是andriod提供的minui显示使用驱动的双buffer机制,在有的系统上不具备该功能,你可以强制只使用一个,修改graphics.c的函数gr_flip,将gr_active_fb 赋值为0

方法二 电池检测。可以参考com_andriod_server_batteryService.cpp文件,基本上把里面的函数复制过来就可以使用。

完成的charge充电程序必须加入到init.rc中才能被调用,我把它当做一个只运行一次的服务运行。

service console /system/bin/busybox sh

   console

#shuaiwen added,init.c has been hacked toblock to wait this process to finish

service charge  /system/bin/charge

  oneshot

init启动服务的过程都是非阻塞型的(新开一个线程运行),这会导致虽然服务已经被加入,但是系统还会完整启动,显然不能满足要求,实际的需求为当charge运行起来不应该运行其他服务。要实现这个目的,必须对init.c进行一点修改。我的方法是让init对启动的服务名称做判断,如果为charge就等待到该程序结束才继续运行。具体修改为改动init.c的函数service_start

if (pid == 0) {

……..

}

//shuaiwen added begin

       else{

      int status;

    if(strcmp(svc->name,"charge")==0)

       {

      wait(&status); //wait child to exist

       load_565rle_image(INIT_IMAGE_FILE);//redrawbackground

       }

     // else printf("shuaiwen skip process %s.",svc->name);

    }

  //shuaiwen added end

if (pid < 0){

….}

这样系统就会被charge阻塞住。Init.rc中排在charge后面的服务就暂时不会被启动。我上面改动的init.rccharge服务放在console服务后面是因为我还是需要控制台调试。经过这样的改动,基本的充电服务就可以实现。我这里仅仅是举了一个例子,文中的例子仅仅供参考,请酌情参考。

我写的一个简单的充电指示文件内容列在下面供大家参考。

/*

Copyright:GNU

charge monitor.

revision history:

2010/5/10 create     shuaiwen

icon path:

/res/images/%s.png

*/

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

 

#include <linux/input.h>

#include <pthread.h>

#include <stdarg.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/reboot.h>

#include <sys/time.h>

#include <time.h>

#include <unistd.h>

 

#include "minui/minui.h"

#include "minzip/Zip.h"

#define KEY_PWR 116

 

#define AC_ONLINE_PATH"/sys/class/power_supply/ac/online"

#define USB_ONLINE_PATH"/sys/class/power_supply/usb/online"

#define BATTERY_STATUS_PATH"/sys/class/power_supply/battery/status"

#define BATTERY_HEALTH_PATH"/sys/class/power_supply/battery/health"

#define BATTERY_PRESENT_PATH"/sys/class/power_supply/battery/present"

#define BATTERY_CAPACITY_PATH"/sys/class/power_supply/battery/capacity"

#define BATTERY_VOLTAGE_PATH"/sys/class/power_supply/battery/batt_vol"

#define BATTERY_TEMPERATURE_PATH"/sys/class/power_supply/battery/batt_temp"

#define BATTERY_TECHNOLOGY_PATH"/sys/class/power_supply/battery/technology"

 

enum {

BACKGROUND_ICON_CHARGE0,

BACKGROUND_ICON_CHARGE1,

BACKGROUND_ICON_CHARGE2,

BACKGROUND_ICON_CHARGE3,

BACKGROUND_ICON_CHARGE4,

BACKGROUND_ICON_CHARGE5,

BACKGROUND_ICON_END,

};

 

enum {

STATUSCHARGING,

STATUSDISCHARGING,

STATUSFULL,

STATUSNOTCHARGING,

STATUSUNKNOWN

};

 

enum{

HEALTHDEAD,

HEALTHGOOD,

HEALTHOVERHEAT,

HEALTHOVERVOLTAGE,

HEALTHUNKNOWN,

HEALTHUNSPECIFIEDFAILURE,

};

 

static gr_surface gBackgroundIcon[BACKGROUND_ICON_END];

static const struct { gr_surface* surface;const char *name; } BITMAPS[] = {

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE0], "battery001" },

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE1], "battery002" },

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE2], "battery003" },

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE3], "battery004" },

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE4], "battery005" },

    {&gBackgroundIcon[BACKGROUND_ICON_CHARGE5], "battery006" },

    {NULL,                             NULL },

};

 

static int readFromFile(const char* path,char* buf, size_t size)

{

   int fd = open(path, O_RDONLY, 0);

   if (fd == -1) {

       //LOGE("Could not open '%s'", path);

       return -1;

    }

   

   size_t count = read(fd, buf, size);

   if (count > 0) {

       count = (count < size) ? count : size - 1;

       while (count > 0 && buf[count-1] == '/n') count--;

       buf[count] = '/0';

    }else {

       buf[0] = '/0';

    }

 

   close(fd);

   return count;

}

 

static int getBatteryStatus(const char*status)

{

   switch (status[0]) {

       case 'C': return STATUSCHARGING;        // Charging

       case 'D': return STATUSDISCHARGING;     // Discharging

       case 'F': return STATUSFULL;            // Not charging

       case 'N': return STATUSNOTCHARGING;     // Full

       case 'U': return STATUSUNKNOWN;         // Unknown

           

       default: {

            printf("Unknown battery status '%s'", status);

           return STATUSUNKNOWN;

       }

    }

}

 

static int getBatteryHealth(const char*status)

{

   switch (status[0]) {

       case 'D': return HEALTHDEAD;        // Dead

       case 'G': return HEALTHGOOD;        // Good

       case 'O': {

           if (strcmp(status, "Overheat") == 0) {

                return HEALTHOVERHEAT;

           } else if (strcmp(status, "Over voltage") == 0) {

                return HEALTHOVERVOLTAGE;

           }

           printf("Unknown battery health[1] '%s'", status);

           return HEALTHUNKNOWN;

       }

       

       case 'U': {

           if (strcmp(status, "Unspecified failure") == 0) {

                returnHEALTHUNSPECIFIEDFAILURE;

           } else if (strcmp(status, "Unknown") == 0) {

                return HEALTHUNKNOWN;

           }

           // fall through

       }

           

       default: {

           printf("Unknown battery health[2] '%s'", status);

           return HEALTHUNKNOWN;

       }

    }

}

 

static void ui_set_background(int icon)

{

  gr_surface gIcon;

    gIcon=gBackgroundIcon[icon];

   gr_color(0, 0, 0, 255);

   gr_fill(0, 0, gr_fb_width(), gr_fb_height());

   if (gIcon) {

         //printf("setbackgroupd:%s/n/r",gBackgroundIcon[icon].name);

       int iconWidth = gr_get_width(gIcon);

        int iconHeight = gr_get_height(gIcon);

       int iconX = (gr_fb_width() - iconWidth) / 2;

       int iconY = (gr_fb_height() - iconHeight) / 2;

       gr_blit(gIcon, 0, 0, iconWidth, iconHeight, iconX, iconY);

    }

  gr_flip();

}

 

static void ui_init()

{

 gr_init();

 ev_init();

  inti;

   for (i = 0; BITMAPS[i].name != NULL; ++i) {

       int result = res_create_surface(BITMAPS[i].name, BITMAPS[i].surface);

       if (result < 0) {

           printf("Missing bitmap %s/n(Code %d)/n", BITMAPS[i].name,result);

           *BITMAPS[i].surface = NULL;

               }

               //elseprintf("create:%s/n/r",BITMAPS[i].name);

    }

 

}

const int SIZE = 128;

 

int power_ac()

{

   char buf[SIZE];

     if (readFromFile(AC_ONLINE_PATH, buf, SIZE) > 0) {

       if (buf[0] == '1') {

           return 1;

       }

    }

return 0;

  }

 

/*

function to indicate if the battery ispresent.

*/

int battery_present()

{

char buf[SIZE];

     if (readFromFile(BATTERY_PRESENT_PATH, buf, SIZE) > 0) {

        if (buf[0] == '1') {

           return 1;

       }

    }

return 0;

}

 

int battery_capacity()

{

char buf[SIZE];

   

   if (readFromFile(BATTERY_CAPACITY_PATH, buf, SIZE) > 0) {

       return atoi(buf);

    }

 return 0;

}

 

int battery_voltage()

{

char buf[SIZE];

   

   if (readFromFile(BATTERY_VOLTAGE_PATH, buf, SIZE) > 0) {

       return atoi(buf);

    }

 return 0;

}

 

 

int battery_temperature()

{

char buf[SIZE];

   

   if (readFromFile(BATTERY_TEMPERATURE_PATH, buf, SIZE) > 0) {

       return atoi(buf);

    }

 return 0;

}

 

int capacity_full()

{

 char buf[SIZE];

 if(readFromFile(BATTERY_STATUS_PATH, buf, SIZE) > 0)

    {

       returngetBatteryStatus(buf);

    }

 

}

 

void do_nothing()    //don't commnet it before fix ziperror.  shuaiwen

{

 ZipArchivezip;

 mzOpenZipArchive(NULL, &zip);

 

}

int main(int argc, char **argv)

{

  int index=0;

#define CIRCLE   100  //1000x1000 microsecond

   int circle=0;//interval to update battery status.

struct input_event ev;

 

//is AC power charging?

if(!power_ac())

{

printf("battery supply,don't entercharge mode./n/r");

return 0; //continue runing.

}

printf("entern charge mode/n/r");

//powerio_low();  //fixme,set power io low to shutdown systemwhen unplug the power.

  ui_init();

  while(1)

    {

       circle=0;

    ui_set_background(capacity_full()==STATUSCHARGING?index++%BACKGROUND_ICON_END:BACKGROUND_ICON_END-1);//todo:morecondition must be considered.

    // ui_set_background(index++%BACKGROUND_ICON_END);

       while(circle++<CIRCLE)

       {

          usleep(1000);

        ev_get(&ev, 10);

        if((ev.type == EV_KEY)&&(ev.code==62))

             {

                 //  powerio_high();  //fixme

                 ev_exit();

                 gr_exit();

              return 0;//the system willcontinue running

               }

         //debug

           if(ev.type==EV_KEY)printf("key:%d pressed/n",ev.code);

          //

       }

 

    }

ev_exit();

gr_exit();

return 0;

}

 

 

对应的andriod.mk文件如下:

LOCAL_PATH :=$(call my-dir)

 

include $(CLEAR_VARS)

 

charge_local_path := $(LOCAL_PATH)

LOCAL_SRC_FILES :=main.c

LOCAL_MODULE := charge

LOCAL_FORCE_STATIC_EXECUTABLE := true

# This binary is in the recovery ramdisk,which is otherwise a copy of root.

# It gets copied there inconfig/Makefile.  LOCAL_MODULE_TAGSsuppresses

# a (redundant) copy of the binary in/system/bin for user builds.

# TODO: Build the ramdisk image in a moreprincipled way.

 

LOCAL_MODULE_TAGS := eng

 

LOCAL_STATIC_LIBRARIES := libminzip libunzlibminui libpixelflinger_static libpng libcutils libstdc++ libc

 

include $(BUILD_EXECUTABLE)

 

include$(charge_local_path)/minui/Android.mk

include$(charge_local_path)/minzip/Android.mk

 

PRODUCT_COPY_FILES += /

       $(charge_local_path)/res/images/battery001.PNG:system/res/images/battery001.png/

       $(charge_local_path)/res/images/battery002.PNG:system/res/images/battery002.png/

       $(charge_local_path)/res/images/battery003.PNG:system/res/images/battery003.png/

       $(charge_local_path)/res/images/battery004.PNG:system/res/images/battery004.png/

       $(charge_local_path)/res/images/battery005.PNG:system/res/images/battery005.png/

       $(charge_local_path)/res/images/battery006.PNG:system/res/images/battery006.png

 

原创粉丝点击