這幾天解一個defect,主要需求是修改關機充電的圖標,把原來的樣式進行修該成如圖1所示樣子:
![]()
圖 1
修改後充電各個階段具體要求如圖2所示:
![]()
圖 2
本來的樣式爲藍色電池,充電動畫爲電量波動狀,指望修改後變成5格滾動狀。(其實我的感受仍是本來的好看,而新樣式設計是一個UE作,反正以爲她這個設計很腦殘並且估計是抄襲把別的手機的樣式吧,並且這個UE很坑壁,給的圖片根本不符合要求,後面還要和她各類斯比各類gloomy).shell
分析以下:bash
關機充電實際上是一個單獨的應用,主要是由init進程開啓,充電部分相關源碼主要在vendor/mediatek/proprietary/external/charger/目錄下。應用的入口在文件vendor/mediatek/proprietary/external/charger/main.cpp中,首先看看main函數。less
int main(int argc, char *argv[]) { set_draw_anim_mode(1); pthread_mutex_init(&lights_mutex, NULL); setpriority(PRIO_PROCESS, 0, -20); FILE *oom_adj = fopen("/proc/self/oom_adj", "w"); if (oom_adj) { fputs("-17", oom_adj); fclose(oom_adj); } //stop_backlight(); KPOC_LOGI("stop_backlight 1\n"); bootlogo_init(); alarm_control(); charging_control(); int i; for (i=0; i< ARRAY_SIZE(pwrkeys); i++) KPOC_LOGI("pwrkeys[%d]:%d\n",i,pwrkeys[i]); key_control(pwrkeys, ARRAY_SIZE(pwrkeys)); //will loop inside return 0;}
爲設置充電動畫的繪製模式,其中有2個模式:ide
這個函數做用沒看懂,略過。函數
這個函數從名字上就能夠看出主要是作一些初始化工做,主要包括充電動畫版本(mtk有2個充電動畫的版本)、動畫繪製方式以及其餘參數的初始化,下面看看這個函數的具體實現。oop
void bootlogo_init(){ KPOC_LOGI("[ChargingAnimation: %s %d]\n",__FUNCTION__,__LINE__); sync_anim_version(); anim_init();}
在bootlogo_init();中有2個函數動畫
主要是設定關機充電充電動畫的版本,
version 0: show 4 recatangle growing animation without battery number
version 1: show wave animation with battery number
因此在這裏控制了究竟是用哪一種充電動畫ui
充電動畫logo初始化,應該就是得到充電圖片的在文件系統中的位置吧,方便後面調用指定圖片。spa
這個函數做用沒看懂,略過。.net
這個函數比較重要,主要控制充電時led燈和動畫效果的,具體來看看它的代碼實現。
void charging_control(){ int ret = 0; pthread_attr_t attr, attrd, attrl; pthread_t uevent_thread, draw_thread, light_thread; //charging led control if (!is_charging_source_available()) { lights_exit(); } pthread_mutex_init(&mutexlstate, NULL); pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); pthread_attr_init(&attr); pthread_attr_init(&attrd); pthread_attr_init(&attrl); inDraw = 0; ret = pthread_create(&uevent_thread, &attr, uevent_thread_routine, NULL); if (ret != 0) { KPOC_LOGI("create uevt pthread failed.\n"); exit_charger(EXIT_ERROR_SHUTDOWN); } firstTime = 1; ret = pthread_create(&draw_thread, &attrd, draw_thread_routine, NULL); if (ret != 0) { KPOC_LOGI("create draw pthread failed.\n"); exit_charger(EXIT_ERROR_SHUTDOWN); }}
在該函數中,最開始對led進行檢測,而後是對線程資源的初始化,後面分別開了2個線程,第一個線程主要是操做led燈的,第二個線程是操做充電動畫效果的。
接下來看看函數draw_thread_routine()作了些什麼。
static void* draw_thread_routine(void *arg){ int i, bc, bc_offset = 0; int fd_fb = -1, err =0; char buf[PROPERTY_VALUE_MAX]; char filename[32] = {0}; // protect the following critical section for the 1st time pthread_mutex_lock(&mutex); do { KPOC_LOGI("draw thread working...\n"); // move here to avoid suspend when syncing with surfaceflinger if(firstTime){ // make sure charging source online when in KPOC mode // add 2s tolerance if(wait_until(is_charging_source_available, charging_source_waiting_duration_ms, charging_source_waiting_interval_ms)) { KPOC_LOGI("wait until charging source available\n"); }else{ KPOC_LOGI("charging source not available for %d ms at KPOC starup\n", charging_source_waiting_duration_ms); } firstTime = 0; } inDraw = 1; // check the bc offest value bc = get_capacity(); //動畫播放的函數 draw_with_interval(bootlogo_show_charging, bc, nChgAnimDuration_msec, nCbInterval_msec); stop_backlight(); // @@@ draw fb again to refresh ddp bootlogo_show_charging(bc, 1); /* make fb blank */ snprintf(filename, sizeof(filename), "/dev/graphics/fb0"); fd_fb = open(filename, O_RDWR); if (fd_fb < 0) { KPOC_LOGI("Failed to open fb0 device: %s", strerror(errno)); } err = ioctl(fd_fb, FBIOBLANK, FB_BLANK_POWERDOWN); if (err < 0) { KPOC_LOGI("Failed to blank fb0 device: %s", strerror(errno)); } if (fd_fb >= 0) close(fd_fb); request_suspend(true); inDraw = 0; pthread_mutex_unlock(&mutex); KPOC_LOGI("draw thread waiting...\n"); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); } while(1); pthread_exit(NULL); return NULL;}
這個函數功能主要是設置播放充電動畫時長和動畫圖片間時間間隔的
void (*func)(int, int)
這個就是進行圖片顯示的函數,經過它循環調用它實現動畫效果int bc
這個參數沒搞懂是作什麼用的int total_time_msec
看名字就知道是播放動畫的總時長int interval_msec
上一個圖片和下一個圖片之間的時間間隔// total_time : ms// interval : msstatic void draw_with_interval(void (*func)(int, int), int bc, int total_time_msec, int interval_msec){ struct timeval start; int resume_started = 0, backlight_started = 0, cnt = 0; int fd_fb = -1, err = 0; char filename[32] = {0}; gettimeofday(&start, NULL); /*這裏的while循環就是動畫效果的實現,不斷的調用顯示不一樣圖片的函數來達到動態效果,當播放時長達到total_time_msec設定值或者有power鍵按下,跳出while循環中止動畫效果*/ while(!time_exceed(start, total_time_msec) && !key_trigger_suspend) { // check if need to draw animation before performing drawing if (!is_charging_source_available()) return; if (!resume_started) { resume_started = 1; request_suspend(false); /* make fb unblank */ snprintf(filename, sizeof(filename), "/dev/graphics/fb0"); fd_fb = open(filename, O_RDWR); if (fd_fb < 0) { KPOC_LOGI("Failed to open fb0 device: %s", strerror(errno)); } err = ioctl(fd_fb, FBIOBLANK, FB_BLANK_UNBLANK); if (err < 0) { KPOC_LOGI("Failed to unblank fb0 device: %s", strerror(errno)); } if (fd_fb >= 0) close(fd_fb); } func(bc, ++cnt); if (!backlight_started) { backlight_started = 1; usleep(200*1000); start_backlight(); } KPOC_LOGI("draw_with_interval... key_trigger_suspend = %d\n",key_trigger_suspend); /*這裏就上一個圖片和下一個圖片之間的時間間隔,經過usleep();實現,它是以微秒爲單位的。若是設置的時間長,播放的速度就比較慢,若是設置的時間短,播放的速度就比較快*/ usleep(interval_msec*1000); }}
而後是函數bootlogo_show_charging,就是經過它來顯示充電動畫的圖片和顯示充電電量的。
/** Show charging animation with battery capacity * */void bootlogo_show_charging(int capacity, int cnt){ KPOC_LOGI("[ChargingAnimation: %s %d]%d, %d",__FUNCTION__,__LINE__, capacity, cnt); if (get_battnotify_status()) { KPOC_LOGI("[ChargingAnimation: %s %d] show_charger_error_logo, get_battnotify_status()= %d \n",__FUNCTION__,__LINE__, get_battnotify_status()); show_charger_ov_logo(); return; } if (showLowBattLogo) { KPOC_LOGI("[ChargingAnimation: %s %d] show_low_battery , showLowBattLogo = %d \n",__FUNCTION__,__LINE__,showLowBattLogo); show_low_battery(); return; } show_battery_capacity(capacity);}
show_charger_ov_logo();和 show_low_battery();分別顯示電壓太高的圖片和低電量圖片,若是出現這2個狀況中一個,就return;,程序就不在向下走了,不然根據當前的電量來顯示不的動畫效果。
show_battery_capacity一樣是在根據不一樣的動畫版本(version 0 or version 1)來決定如何在屏幕上顯示動畫,
/* * Show charging animation with battery capacity * */void show_battery_capacity(unsigned int capacity){ if (MTK_LOG_ENABLE == 1) { SLOGD("[libshowlogo: %s %d]capacity =%d\n",__FUNCTION__,__LINE__, capacity); } if (draw_anim_mode == (DRAW_ANIM_MODE_FB)) { anim_fb_addr_switch();#if defined(MTK_PUMP_EXPRESS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_20_SUPPORT) if (2 != show_animationm_ver && get_fast_charging_state()) { fill_animation_battery_fast_charging(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, draw_anim_mode); } else { fill_animation_battery_by_ver(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver); }#else fill_animation_battery_by_ver(capacity, (void *)fb_addr, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);#endif anim_fb_disp_update(); } else { ARect tmpRect; tmpRect.left = 0; tmpRect.top = 0; tmpRect.right = phical_screen.width; tmpRect.bottom = phical_screen.height; status_t lockResult = surface->lock(&outBuffer, &tmpRect); if (MTK_LOG_ENABLE == 1) { SLOGD("[libshowlogo: %s %d]outBuffer.bits = %d, surface->lock return = 0x%08x,\n",__FUNCTION__,__LINE__, (int)outBuffer.bits,lockResult); } if (0 == lockResult) {#if defined(MTK_PUMP_EXPRESS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_SUPPORT) || defined(MTK_PUMP_EXPRESS_PLUS_20_SUPPORT) if (2 != show_animationm_ver && get_fast_charging_state()) { fill_animation_battery_fast_charging(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, draw_anim_mode); } else { fill_animation_battery_by_ver(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver); }#else fill_animation_battery_by_ver(capacity, (void *)outBuffer.bits, dec_logo_addr, logo_addr, phical_screen, show_animationm_ver);#endif surface->unlockAndPost(); } }}
在vendor/mediatek/proprietary/external/libshowlogo/show_animation_common.c文件中的fill_animation_battery_by_ver方法控制關機充電的樣式,根本不一樣的version值使用不一樣充電動畫,方法具體實現以下。
/* * Show charging animation by version * */void fill_animation_battery_by_ver(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen, int version){ if (MTK_LOG_ENABLE == 1) { SLOGD("[show_animation_common: %s %d]version : %d\n",__FUNCTION__,__LINE__, version); } switch (version) { case VERION_OLD_ANIMATION: fill_animation_battery_old(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen); break; case VERION_NEW_ANIMATION: fill_animation_battery_new(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen); break; case VERION_WIRELESS_CHARGING_ANIMATION: fill_animation_battery_wireless_charging(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen); break; default: fill_animation_battery_old(capacity, fill_addr, dec_logo_addr, logo_addr, phical_screen); break; }}
而後繼續查找show_animationm_ver賦值狀況,能夠看到文件開始位置有以下賦值語句:
/* * Get the defined charging animation version * */void sync_anim_version(){ dprintf(INFO, "[lk logo: %s %d]\n",__FUNCTION__,__LINE__);#ifdef ANIMATION_NEW show_animationm_ver = VERION_NEW_ANIMATION;#else show_animationm_ver = VERION_OLD_ANIMATION; dprintf(INFO, "[lk logo %s %d]not define ANIMATION_NEW:show old animation \n",__FUNCTION__,__LINE__);#endif}
而宏定義ANIMATION_NEW是在文件vendor/mediatek/proprietary/external/libshowlogo/cust_display.h中定義的。也就是說若是定義了字段ANIMATION_NEW,則使用fill_animation_battery_new動畫,不然使用fill_animation_battery_old。無論使用哪一個充電動畫效果,2個方法都須要使用圖片組合來達到動畫的效果,而圖片的存放位置在一個名爲logo的文件加中。名爲logo的文件夾可能會比較多,具體使用哪一個文件夾中的圖片須要根據具體編譯的項目決定,同時在device/jrdcsh[project]/ProjectConfig.mk文件中,看到BOOT_LOGO = fhd;LCM_HEIGHT =1920;LCM_WIDTH=1080;
這3個字段,分別表示存放logo圖片的文件加名以及手機所用屏幕分辨率。若是須要客製化這些圖片,須要用新logo圖片替換掉原圖片。(最開始作的時候沒找對路徑因此替換圖片後仍是沒有效果,主要是許多公司都會對基線代碼添加定製值,項目最終使用的是定製化代碼中fhd文件中的logo圖標,因此必定要找對logo圖標存儲的文件夾再替換)。fill_animation_battery_new方法和fill_animation_battery_old方法使用到的圖片共40張。
低電量充電顯示的動畫是由[fhd_bat_10_01.bmp~ fhd_bat_10_01.bmp]這10張靜態圖片組成,針對verion 1.
充電背景圖片[fhd_bat_bg.bmp] 共1張,針對verion 1.
正常充電填充圖片[fhd_bat_img.bmp] 共1張,針對verion 1.
充電時動畫顯示是由[fhd_bat_animation_01.bmp~ fhd_bat_animation_10.bmp] 這10張靜態圖片組成,針對verion 1.
數字圖片[fhd_num_0.bmp~ fhd_num_9.bmp]共10張,,針對verion 1.
百分比圖片[fhd_mun_percent.bmp] 共1張 ,針對verion 1.
100%電量圖[fhd_bat_100.bmp] 共1張 ,針對verion 1.
低電量圖片[fhd_low_battery.bmp] 共1張 ,未見過此狀況 。
過電壓圖片[fhd_change_ov.bmp] 共1張,未見過此狀況 。
電壓太低的圖片[fhd_low_voltage.bmp] 共1張,未見過此狀況 。
Kernel圖片[fhd_kernal.bmp] 共1張 ,
關機插入充電器顯示第一張圖片[fhd_uboot.bmp] 共1張 ,mt_disp_show_boot_logo();方法調用,入口函數爲platform_init();
圖片fhd_battery[fhd_battery.bmp]共1張,由方法fill_animation_battery_old調用,針對verion 0。
而這些圖片都由腳本vendor/jrdcom/build/common/update_logo.sh打包爲一個文件,腳本具體以下。
#!/bin/bashif [ "$1" = "" ]; then echo "Please input resolution," echo "Such as: qvga, wqvga, wvga, hvga" exitfip=${1}product_path=${2}logo_path=${3}output_path=${4}boot_logo=${5}${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp0.raw ${logo_path}/$p/"${boot_logo}_uboot".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp1.raw ${logo_path}/$p/"${boot_logo}_battery".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp2.raw ${logo_path}/$p/"${boot_logo}_low_battery".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp3.raw ${logo_path}/$p/"${boot_logo}_charger_ov".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp4.raw ${logo_path}/$p/"${boot_logo}_num_0".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp5.raw ${logo_path}/$p/"${boot_logo}_num_1".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp6.raw ${logo_path}/$p/"${boot_logo}_num_2".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp7.raw ${logo_path}/$p/"${boot_logo}_num_3".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp8.raw ${logo_path}/$p/"${boot_logo}_num_4".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp9.raw ${logo_path}/$p/"${boot_logo}_num_5".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp10.raw ${logo_path}/$p/"${boot_logo}_num_6".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp11.raw ${logo_path}/$p/"${boot_logo}_num_7".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp12.raw ${logo_path}/$p/"${boot_logo}_num_8".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp13.raw ${logo_path}/$p/"${boot_logo}_num_9".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp14.raw ${logo_path}/$p/"${boot_logo}_num_percent".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp15.raw ${logo_path}/$p/"${boot_logo}_bat_animation_01".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp16.raw ${logo_path}/$p/"${boot_logo}_bat_animation_02".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp17.raw ${logo_path}/$p/"${boot_logo}_bat_animation_03".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp18.raw ${logo_path}/$p/"${boot_logo}_bat_animation_04".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp19.raw ${logo_path}/$p/"${boot_logo}_bat_animation_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp20.raw ${logo_path}/$p/"${boot_logo}_bat_animation_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp21.raw ${logo_path}/$p/"${boot_logo}_bat_animation_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp22.raw ${logo_path}/$p/"${boot_logo}_bat_animation_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp23.raw ${logo_path}/$p/"${boot_logo}_bat_animation_09".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp24.raw ${logo_path}/$p/"${boot_logo}_bat_animation_10".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp25.raw ${logo_path}/$p/"${boot_logo}_bat_10_01".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp26.raw ${logo_path}/$p/"${boot_logo}_bat_10_02".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp27.raw ${logo_path}/$p/"${boot_logo}_bat_10_03".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp28.raw ${logo_path}/$p/"${boot_logo}_bat_10_04".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp29.raw ${logo_path}/$p/"${boot_logo}_bat_10_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp30.raw ${logo_path}/$p/"${boot_logo}_bat_10_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp31.raw ${logo_path}/$p/"${boot_logo}_bat_10_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp32.raw ${logo_path}/$p/"${boot_logo}_bat_10_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp33.raw ${logo_path}/$p/"${boot_logo}_bat_10_09".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp34.raw ${logo_path}/$p/"${boot_logo}_bat_10_10".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp35.raw ${logo_path}/$p/"${boot_logo}_bat_bg".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp36.raw ${logo_path}/$p/"${boot_logo}_bat_img".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp37.raw ${logo_path}/$p/"${boot_logo}_bat_100_".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp38.raw ${logo_path}/$p/"${boot_logo}_kernel".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp39.raw ${logo_path}/$p/"${boot_logo}_low_voltage".bmp${product_path}/vendor/jrdcom/build/jrdtools/zpipe -l 9 ${output_path}/"${p}".raw ${output_path}/temp0.raw ${output_path}/temp1.raw ${output_path}/temp2.raw ${output_path}/temp3.raw ${output_path}/temp4.raw ${output_path}/temp5.raw ${output_path}/temp6.raw ${output_path}/temp7.raw ${output_path}/temp8.raw ${output_path}/temp9.raw ${output_path}/temp10.raw ${output_path}/temp11.raw ${output_path}/temp12.raw ${output_path}/temp13.raw ${output_path}/temp14.raw ${output_path}/temp15.raw ${output_path}/temp16.raw ${output_path}/temp17.raw ${output_path}/temp18.raw ${output_path}/temp19.raw ${output_path}/temp20.raw ${output_path}/temp21.raw ${output_path}/temp22.raw ${output_path}/temp23.raw ${output_path}/temp24.raw ${output_path}/temp25.raw ${output_path}/temp26.raw ${output_path}/temp27.raw ${output_path}/temp28.raw ${output_path}/temp29.raw ${output_path}/temp30.raw ${output_path}/temp31.raw ${output_path}/temp32.raw ${output_path}/temp33.raw ${output_path}/temp34.raw ${output_path}/temp35.raw ${output_path}/temp36.raw ${output_path}/temp37.raw ${output_path}/temp38.raw ${output_path}/temp39.rawrm -rf ${output_path}/temp0.raw ${output_path}/temp1.raw ${output_path}/temp2.raw ${output_path}/temp3.raw ${output_path}/temp4.raw ${output_path}/temp5.raw ${output_path}/temp6.raw ${output_path}/temp7.raw ${output_path}/temp8.raw ${output_path}/temp9.raw ${output_path}/temp10.raw ${output_path}/temp11.raw ${output_path}/temp12.raw ${output_path}/temp13.raw ${output_path}/temp14.raw ${output_path}/temp15.raw ${output_path}/temp16.raw ${output_path}/temp17.raw ${output_path}/temp18.raw ${output_path}/temp19.raw ${output_path}/temp20.raw ${output_path}/temp21.raw ${output_path}/temp22.raw ${output_path}/temp23.raw ${output_path}/temp24.raw ${output_path}/temp25.raw ${output_path}/temp26.raw ${output_path}/temp27.raw ${output_path}/temp28.raw ${output_path}/temp29.raw ${output_path}/temp30.raw ${output_path}/temp31.raw ${output_path}/temp32.raw ${output_path}/temp33.raw ${output_path}/temp34.raw ${output_path}/temp35.raw ${output_path}/temp36.raw ${output_path}/temp37.raw ${output_path}/temp38.raw ${output_path}/temp39.rawecho "conversion finished"
而這些圖片被打包後如何使用呢?在文件vendor/mediatek/proprietary/external/libshowlogo/cust_display.h中,會把圖片序號定義爲宏,在代碼中經過這些宏來調用指定圖片。
#ifndef __CUST_DISPLAY_H__#define __CUST_DISPLAY_H__/* change*/// color #00FF00 #ffffff#define BAR_OCCUPIED_COLOR (0xFF7ED321) // Green#define BAR_EMPTY_COLOR (0xFF000000) // White#define BAR_BG_COLOR (0xFF000000) // Black/* change*/// LOGO number#define ANIM_V0_LOGO_NUM 5 // version 0: show 4 recatangle growing animation without battery number#define ANIM_V1_LOGO_NUM 39 // version 1: show wave animation with battery number #define ANIM_V2_LOGO_NUM 86 // version 2: show wireless charging animation // Common LOGO index#define BOOT_LOGO_INDEX 0 #define KERNEL_LOGO_INDEX 38 #define ANIM_V0_BACKGROUND_INDEX 1 /* change*/#define SHOW_BO_POWER 34/* change*/#define ANIM_V1_BACKGROUND_INDEX 35#define LOW_BATTERY_INDEX 2 #define CHARGER_OV_INDEX 3 #define FULL_BATTERY_INDEX 37 // version 1: show wave animation with battery number // NUMBER LOGO INDEX#define NUMBER_PIC_START_0 4 #define NUMBER_PIC_PERCENT 14 // DYNAMIC ANIMATION LOGO INDEX#define BAT_ANIM_START_0 15 // LOW BATTERY(0~10%) ANIMATION LOGO#define LOW_BAT_ANIM_START_0 25 #define ANIM_LINE_INDEX 36 // version 2: show wireless charging animation logo index#define V2_NUM_START_0_INDEX 57 #define V2_NUM_PERCENT_INDEX 67 #define V2_BAT_0_10_START_INDEX 68 #define V2_BAT_10_40_START_INDEX 72 #define V2_BAT_40_80_START_INDEX 76 #define V2_BAT_80_100_START_NDEX 80#define V2_BAT_0_INDEX 84#define V2_BAT_100_INDEX 85// show fast charging animation logo index#define FAST_CHARGING_BAT_100_INDEX 39#define FAST_CHARGING_BAT_START_0_INDEX 40#define FAST_CHARGING_NUM_START_0_INDEX 46#define FAST_CHARGING_NUM_PERCENT_INDEX 56#if defined(FHD) || defined(CU_FHD) || defined(CMCC_FHD) || defined(CT_FHD) || defined(CMCC_LTE_FHD) || defined(CT_LTE_FHD) || defined(CU_LTE_FHD) // fhd 1080*1920 // battery capacity rectangle #define CAPACITY_LEFT (387) // battery capacity center #define CAPACITY_TOP (802) #define CAPACITY_RIGHT (691) #define CAPACITY_BOTTOM (1292) /* change*/ // first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) /* change*/ // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) /* change*/ // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) /* change*/ // for old animation #define BAR_LEFT (463) #define BAR_TOP (760) #define BAR_RIGHT (619) #define BAR_BOTTOM (1049) /* change*/#elif defined(WQHD) || defined(CU_WQHD) || defined(CMCC_WQHD) || defined(CT_WQHD) || defined(CMCC_LTE_WQHD) || defined(CT_LTE_WQHD) || defined(CU_LTE_WQHD) // wqhd 1440*2560 // battery capacity rectangle #define CAPACITY_LEFT (556) // battery capacity center #define CAPACITY_TOP (1112) #define CAPACITY_RIGHT (882) #define CAPACITY_BOTTOM (1630) // first number rectangle #define NUMBER_LEFT (570) // number #define NUMBER_TOP (770) #define NUMBER_RIGHT (660) #define NUMBER_BOTTOM (898) // % rectangle #define PERCENT_LEFT (750) // percent number_left + 2*number_width #define PERCENT_TOP (770) #define PERCENT_RIGHT (864) #define PERCENT_BOTTOM (898) // top animation part #define TOP_ANIMATION_LEFT (556) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (882) #define TOP_ANIMATION_BOTTOM (158) // for old animation #define BAR_LEFT (443) #define BAR_TOP (337) #define BAR_RIGHT (574) #define BAR_BOTTOM (641)#elif defined(HD720) || defined(CU_HD720) || defined(CMCC_HD720) || defined(CT_HD720) || defined(CMCC_LTE_HD720) || defined(CT_LTE_HD720) || defined(CU_LTE_HD720) // hd720 720*1280 // battery capacity rectangle #define CAPACITY_LEFT (278) // battery capacity center #define CAPACITY_TOP (556) #define CAPACITY_RIGHT (441) #define CAPACITY_BOTTOM (817) // first number rectangle #define NUMBER_LEFT (290) // number #define NUMBER_TOP (386) #define NUMBER_RIGHT (335) #define NUMBER_BOTTOM (450) // % rectangle #define PERCENT_LEFT (380) // percent number_left + 2*number_width #define PERCENT_TOP (386) #define PERCENT_RIGHT (437) #define PERCENT_BOTTOM (450) // top animation part #define TOP_ANIMATION_LEFT (278) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (441) #define TOP_ANIMATION_BOTTOM (129) // for old animation #define BAR_LEFT (313) #define BAR_TOP (238) #define BAR_RIGHT (406) #define BAR_BOTTOM (453)
同時,在這個文件中還定義了各個圖片在屏幕上的座標位置,以fhd 1080*1920
這個屏幕爲例,手機屏幕左上角的座標爲(0,0)(是以一個像素爲一個單位來計的)右下角的座標爲(1080,1920)。
#if defined(FHD) || defined(CU_FHD) || defined(CMCC_FHD) || defined(CT_FHD) || defined(CMCC_LTE_FHD) || defined(CT_LTE_FHD) || defined(CU_LTE_FHD) // fhd 1080*1920 // battery capacity rectangle #define CAPACITY_LEFT (387) // battery capacity center #define CAPACITY_TOP (802) #define CAPACITY_RIGHT (691) #define CAPACITY_BOTTOM (1292) // first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) // for old animation #define BAR_LEFT (463) #define BAR_TOP (760) #define BAR_RIGHT (619) #define BAR_BOTTOM (1049)
接下來分別查看fill_animation_battery_new()與fill_animation_battery_old這2個函數的具體邏輯。
/*change*//* * Show new charging animation * */void fill_animation_battery_new(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen){ if (MTK_LOG_ENABLE == 1) { SLOGD("[show_animation_common: %s %d]capacity : %d\n",__FUNCTION__,__LINE__, capacity); } if (capacity >= 100) { //show_logo(37); // battery 100 fill_animation_logo(FULL_BATTERY_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); } else if (capacity < 10) { if (MTK_LOG_ENABLE == 1) { SLOGD("[show_animation_common: %s %d]charging_low_index = %d\n",__FUNCTION__,__LINE__, charging_low_index); } //經過charging_low_index++來循環顯示低電量的10張圖片 charging_low_index ++ ; fill_animation_logo(LOW_BAT_ANIM_START_0 + charging_low_index, fill_addr, dec_logo_addr, logo_addr,phical_screen); //顯示電量值上個位數的值 fill_animation_number(NUMBER_PIC_START_0 + capacity, 1, fill_addr, logo_addr, phical_screen); fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen); if (charging_low_index >= 9) charging_low_index = 0; } else { unsigned int capacity_grids = 0; //static RECT_REGION_T battery_rect = {CAPACITY_LEFT,CAPACITY_TOP,CAPACITY_RIGHT,CAPACITY_BOTTOM}; /*把電池分紅100等分,而後計算當前電量所佔比重(由於背景圖片已近畫了10%電量,因此這裏有capacity - 10這個操做)*/ capacity_grids = CAPACITY_BOTTOM - (CAPACITY_BOTTOM - CAPACITY_TOP) * (capacity - 10) / 90; if (MTK_LOG_ENABLE == 1) { SLOGD("[show_animation_common: %s %d]capacity_grids : %d,charging_animation_index = %d\n" ,__FUNCTION__,__LINE__, capacity_grids,charging_animation_index); } //background,即充電時的背景圖片fhd_bat_bg.bmp,在該圖中已經畫出了10%電量 fill_animation_logo(ANIM_V1_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); //畫出當前電池對應的電量 fill_animation_line(ANIM_LINE_INDEX, capacity_grids, fill_addr, logo_addr, phical_screen); fill_animation_number(NUMBER_PIC_START_0 + (capacity/10), 0, fill_addr, logo_addr, phical_screen); fill_animation_number(NUMBER_PIC_START_0 + (capacity%10), 1, fill_addr, logo_addr, phical_screen); fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen); //若是電量小於90%,加上充電動畫效果 if (capacity <= 90) { RECT_REGION_T top_animation_rect = {TOP_ANIMATION_LEFT, capacity_grids - (TOP_ANIMATION_BOTTOM - TOP_ANIMATION_TOP), TOP_ANIMATION_RIGHT, capacity_grids}; //top_animation_rect.bottom = capacity_grids; //top_animation_rect.top = capacity_grids - top_animation_height; charging_animation_index++; //show_animation_dynamic(15 + charging_animation_index, top_animation_rect, top_animation_addr); fill_animation_dynamic(BAT_ANIM_START_0 + charging_animation_index, top_animation_rect, fill_addr, top_animation_addr, logo_addr, phical_screen); if (charging_animation_index >= 9) charging_animation_index = 0; } }}
/* * * Show old charging animation * */void fill_animation_battery_old(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen){ int capacity_grids = 0; if (capacity > 100) capacity = 100; //這裏表示計算當前電量佔的比重,字段ANIM_V0_REGIONS表示把電池劃分紅幾個格的電量 capacity_grids = (capacity * (ANIM_V0_REGIONS)) / 100; if (version0_charging_index < capacity_grids * 2) version0_charging_index = capacity_grids * 2; if (capacity < 100){ version0_charging_index > 7? version0_charging_index = capacity_grids * 2 : version0_charging_index++; } else { version0_charging_index = ANIM_V0_REGIONS * 2; } //此處爲顯示背景圖片fhd_battery.bmp的函數 fill_animation_logo(ANIM_V0_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); RECT_REGION_T rect_bar = {bar_rect.left + 1, bar_rect.top + 1, bar_rect.right, bar_rect.bottom}; //此處動態畫出第0格到version0_charging_index/2格的電量 fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_OCCUPIED_COLOR), 0, version0_charging_index/2, fill_addr, phical_screen); /*此處動態畫出第version0_charging_index/2格到ANIM_V0_REGIONS - version0_charging_index/2格的電量,與前面的函數交替使用就會出現4格電量滾動的效果(固然還須要在draw_thread_routine中不斷while循環)*/ fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_EMPTY_COLOR), version0_charging_index/2, ANIM_V0_REGIONS - version0_charging_index/2, fill_addr, phical_screen);}
接下老看看函數fill_animation_prog_bar的具體實現。
/* * Fill a rectangle size address with special color * */void fill_animation_prog_bar(RECT_REGION_T rect_bar, unsigned int fgColor, unsigned int start_div, unsigned int occupied_div, void *fill_addr, LCM_SCREEN_T phical_screen){ //計算每個格電量佔多少像素 unsigned int div_size = (rect_bar.bottom - rect_bar.top) / (ANIM_V0_REGIONS); /*這是計算每格電量實際須要畫多少像素的圖像,字段ANIM_V0_SPACE_AFTER_REGION爲各個電量格之間的空隙,若是爲0則表示電量格之間無空隙*/ unsigned int draw_size = div_size - (ANIM_V0_SPACE_AFTER_REGION); unsigned int i; for (i = start_div; i < start_div + occupied_div; ++ i) { unsigned int draw_bottom = rect_bar.bottom - div_size * i - (ANIM_V0_SPACE_AFTER_REGION); unsigned int draw_top = draw_bottom - draw_size; RECT_REGION_T rect = {rect_bar.left, draw_top, rect_bar.right, draw_bottom}; //這是函數纔是真正進行電量格繪畫的 fill_rect_with_color(fill_addr, rect, fgColor, phical_screen); }}
這個函數從名字上看該是對按鍵進行控制的函數,推測該是檢測power鍵是否被按下的,字段longPressDuration = 500;該是設定須要長按power的時間,函數long_press_control();會開啓一個線程進行檢測,當長按power達到指定時間,就會退出關機充電的線程而後設定bootingUp = true;估計會經過設定的bootingUp值來進行手機的重啓操做,下面是key_control函數的具體實現。
void key_control(int * pwrkeys, int pwrkeys_num){ int res,i,j,k; int pollres; const char *device = NULL; struct input_event event; longPressDuration = 500; long_press_control(); num_fds = 1; ufds = (struct pollfd*)calloc(1, sizeof(ufds[0])); ufds[0].fd = inotify_init(); ufds[0].events = POLLIN; wd = inotify_add_watch(ufds[0].fd, INPUT_DEVICE_PATH, IN_DELETE | IN_CREATE); if(wd < 0) { KPOC_LOGI("could not add watch for %s, %s\n", INPUT_DEVICE_PATH, strerror(errno)); exit_charger(EXIT_ERROR_SHUTDOWN); } res = scan_dir(INPUT_DEVICE_PATH); if(res < 0) { KPOC_LOGI("scan dir failed for %s\n", INPUT_DEVICE_PATH); exit_charger(EXIT_ERROR_SHUTDOWN); } while(1) { pollres = poll(ufds, num_fds, -1); if(ufds[0].revents & POLLIN) { read_notify(INPUT_DEVICE_PATH, ufds[0].fd); } for(i = 1; i < num_fds; i++) { if(ufds[i].revents) { if(ufds[i].revents & POLLIN) { res = read(ufds[i].fd, &event, sizeof(event)); if(res < (int)sizeof(event)) { KPOC_LOGI("could not get event\n"); exit_charger(EXIT_ERROR_SHUTDOWN); }#ifdef VERBOSE_OUTPUT KPOC_LOGI("%s: event.type:%d,%d:%d\n", __FUNCTION__, event.type, event.code, event.value);#endif if (EV_KEY == event.type) { for (k=0; k<pwrkeys_num; k++) { if(event.code == pwrkeys[k]) { if (1 == event.value) { powerKeyPressed = true; pthread_cond_signal(&keycond); } else powerKeyPressed = false; break; } } } } } } }}
而後看看函數long_press_control(),在該函數中先對開啓線程所需各類資源進行初始化,而後開啓線程,線程開啓後並不表示就進行重啓操做了,它還要等待其餘條件也知足纔會重啓,long_press_control函數的具體實現以下所示。
void long_press_control(){ int ret = 0; pthread_attr_t attr; pthread_t pwrkey_thread; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&keycond, NULL); pthread_attr_init(&attr); ret = pthread_create(&pwrkey_thread, &attr, key_thread_routine, NULL); if (ret != 0) { KPOC_LOGI("create key pthread failed.\n"); exit_charger(EXIT_ERROR_SHUTDOWN); }}
線程中的具體操做以下,先要判斷powerKey是否被按下,而對powerKey是否被按下操做的檢測是在函數key_control中實現的,當powerKey被按下則powerKeyPressed = true,在線程的實現函數中能夠看到有2個while循環,最外層的while應該是循環等待powerKey被按下,達到要求會進入內層while進行計時等待的循環。
static void* key_thread_routine(void *arg){ static bool bootingUp = false; static bool long_press = false; struct timeval start; while(1) { pthread_mutex_lock(&mutex); pthread_cond_wait(&keycond, &mutex); /* longPressDetecting = true; */ gettimeofday(&start, NULL); KPOC_LOGI("pwr key long press check start\n"); while(powerKeyPressed) { usleep(1000*100); //200ms long_press = time_exceed(start, longPressDuration); if(long_press) { KPOC_LOGI("pwr key reaches boot condition\n"); if(get_voltage() > VBAT_POWER_ON) { showLowBattLogo = 0; // ready to boot up. inotify_rm_watch(ufds[0].fd, wd); if (keyDownPressed || keyUpPressed) exit_charger(EXIT_REBOOT_UBOOT); else exit_charger(EXIT_POWER_UP); bootingUp = true; } else { showLowBattLogo = 1; KPOC_LOGI("VBAT <= %d\n", VBAT_POWER_ON); break; } } } if (!long_press) showLowBattLogo = 0; if(!bootingUp) start_charging_anim(TRIGGER_ANIM_KEY); KPOC_LOGI("pwr key long press check end\n"); pthread_mutex_unlock(&mutex); } return NULL;}
進過上面的分析(固然不少都是猜想,分析也比較水),就開始動手改代碼,但願可以實現指望的效果。
總共修改/增長共16張圖片:
由於在顯示充電動畫以前,還須要先顯示一張低電量圖片,時長1秒鐘。原本在插入充電器後,在啓動lk/kernel會顯示一個logo,原本想直接該這個logo的。可是發現從這個logo顯示到開始播放充電動畫之間間隔5~6秒鐘,這固然不行,因此在開始播放充電動畫前面加了個顯示低電量圖片時長1秒鐘的邏輯,也不知道這樣搞會不會被叼。先無論,改了看看效果再說,具體修改以下。
/* * Show charging animation with battery capacity * */void bootlogo_show_charging(int capacity, int cnt){ KPOC_LOGI("[ChargingAnimation: %s %d]%d, %d",__FUNCTION__,__LINE__, capacity, cnt); if (get_battnotify_status()) { KPOC_LOGI("[ChargingAnimation: %s %d] show_charger_error_logo, get_battnotify_status()= %d \n",__FUNCTION__,__LINE__, get_battnotify_status()); show_charger_ov_logo(); return; } if (showLowBattLogo) { KPOC_LOGI("[ChargingAnimation: %s %d] show_low_battery , showLowBattLogo = %d \n",__FUNCTION__,__LINE__,showLowBattLogo); show_low_battery(); return; }/*change*///字段show_low_battery_one_time在前面還須要定義下,否則編譯報錯 if(show_low_battery_one_time) { //delay 1000ms show_low_battery(); usleep(1000*1000); show_low_battery_one_time=0; }/*change*/ show_battery_capacity(capacity);}
這個文件就是對圖片進行打包成raw文件的腳本,由於前面添加一張無電量圖片,因此也要在這個文件中添加,否則只在logo目錄中添加是沒用的,修改以下。
${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp29.raw ${logo_path}/$p/"${boot_logo}_bat_10_05".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp30.raw ${logo_path}/$p/"${boot_logo}_bat_10_06".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp31.raw ${logo_path}/$p/"${boot_logo}_bat_10_07".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp32.raw ${logo_path}/$p/"${boot_logo}_bat_10_08".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp33.raw ${logo_path}/$p/"${boot_logo}_bat_10_09".bmp#change 直接在原來低電量圖片上改的,反正低電量效果不須要了${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp34.raw ${logo_path}/$p/"${boot_logo}_no_power".bmp#change${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp35.raw ${logo_path}/$p/"${boot_logo}_bat_bg".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp36.raw ${logo_path}/$p/"${boot_logo}_bat_img".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp37.raw ${logo_path}/$p/"${boot_logo}_bat_100".bmp${product_path}/vendor/jrdcom/build/jrdtools/bmp_to_raw ${output_path}/temp38.raw ${logo_path}/$p/"${boot_logo}_kernel".bmp
修改這個文件主要是調整新充電樣式中電池電量、電量值、百分號的位置(坑爹的UE不給具體座標,就說按設計文檔上搞,臥槽真是被狗咬了一口的感受,文檔上根本不是寫的很清楚,座標也是用GD表示的,沒辦法只能慢慢調了),電池電量的顏色還有就是添加無電量圖片的宏定義,具體修改以下。
/*change*/// color #00FF00 #ffffff#define BAR_OCCUPIED_COLOR (0xFF7ED321) // Green#define BAR_EMPTY_COLOR (0xFF000000) // Black#define BAR_BG_COLOR (0xFF000000) // Black#define SHOW_NO_POWER 34 //這個是無電量圖片對應的序號// first number rectangle #define NUMBER_LEFT (512) // number #define NUMBER_TOP (1097) #define NUMBER_RIGHT (540) #define NUMBER_BOTTOM (1137) // % rectangle #define PERCENT_LEFT (568) // percent number_left + 2*number_width #define PERCENT_TOP (1110) #define PERCENT_RIGHT (592) #define PERCENT_BOTTOM (1137) // top animation part #define TOP_ANIMATION_LEFT (387) // top animation #define TOP_ANIMATION_TOP (100) #define TOP_ANIMATION_RIGHT (691) #define TOP_ANIMATION_BOTTOM (152) // for old animation #define BAR_LEFT (465) #define BAR_TOP (773) #define BAR_RIGHT (616) #define BAR_BOTTOM (1048)/*change*/
修改這個文件主要是調整電池電量的格數,原來是4個格,並且每一個格之間有間隙,須要弄成5個格,每一個格之間無間隙,只須要修改2個宏,具體修改以下。
/*change*/// version_0 animation#define ANIM_V0_REGIONS 5#define ANIM_V0_SPACE_AFTER_REGION 0/*change*/
這個文件主要修改函數void fill_animation_battery_old,由於這個函數的功能就是實現4格滾動效果,因此直接在它上面改。
具體的修改以下所示。
/* * Show old charging animation * */void fill_animation_battery_old(int capacity, void *fill_addr, void * dec_logo_addr, void * logo_addr, LCM_SCREEN_T phical_screen){ int capacity_grids = 0; if (capacity > 100) capacity = 100; capacity_grids = (capacity * (ANIM_V0_REGIONS)) / 100;/*change*/ if (version0_charging_index < capacity_grids * 2) version0_charging_index = capacity_grids * 2; if (capacity < 100){ if(capacity < 90){ version0_charging_index > 9? version0_charging_index = capacity_grids * 2 : version0_charging_index++; }else{ version0_charging_index > 7? version0_charging_index = capacity_grids * 2 : version0_charging_index++; } } else { version0_charging_index = ANIM_V0_REGIONS * 2; } if(capacity>0) { fill_animation_logo(ANIM_V0_BACKGROUND_INDEX, fill_addr, dec_logo_addr, logo_addr,phical_screen); if (capacity < 10) { fill_animation_number(NUMBER_PIC_START_0 + capacity, 1, fill_addr, logo_addr, phical_screen); fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen); }else{ if(capacity >=100){ fill_animation_number(NUMBER_PIC_START_0 + ((capacity%100)/10), 0, fill_addr, logo_addr, phical_screen); fill_animation_number(NUMBER_PIC_START_0 + (capacity%10), 1, fill_addr, logo_addr, phical_screen); fill_animation_number(NUMBER_PIC_START_0 + (capacity/100), -1, fill_addr, logo_addr, phical_screen); fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen); }else{ fill_animation_number(NUMBER_PIC_START_0 + (capacity/10), 0, fill_addr, logo_addr, phical_screen); fill_animation_number(NUMBER_PIC_START_0 + (capacity%10), 1, fill_addr, logo_addr, phical_screen); fill_animation_dynamic(NUMBER_PIC_PERCENT, percent_location_rect, fill_addr, percent_pic_addr, logo_addr, phical_screen); } } RECT_REGION_T rect_bar = {bar_rect.left + 1, bar_rect.top + 1, bar_rect.right, bar_rect.bottom}; fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_OCCUPIED_COLOR), 0, version0_charging_index/2, fill_addr, phical_screen); fill_animation_prog_bar(rect_bar, (unsigned int)(BAR_EMPTY_COLOR), version0_charging_index/2, ANIM_V0_REGIONS - version0_charging_index/2, fill_addr, phical_screen); }else{ fill_animation_logo(SHOW_NO_POWER, fill_addr, dec_logo_addr, logo_addr,phical_screen); }}/*change*/
改完後編譯發現是能夠達到需求上面的要求(固然不是一下就編成功了的,都編了n次,並且每次編譯都要費很長的時間,看來作事要細心,否則錯了或者漏改了都會報錯),這樣也算馬馬虎虎完成任務吧,最後就看設計的人是否以爲達到她指望效果,否則估計還要坑壁的繼續改。
最開始作這個還真的不知道怎麼入手,而後是各類找資料,固然網上也會有一些參考的例子,不過看了後也仍是不是很是懂,主要是不理解關機充電在什麼階段開始的。而且對lk、kernel這些流程不是很是熟悉,只能慢慢嘗試在圖片上作標記,改不一樣的座標來看編譯出來是什麼效果。最開始找到的就是fill_animation_battery_new這個函數,只知道是它實現的充電動畫效果,還想就在這個函數上面改爲5格滾動的動畫效果。後面看到關機充電動畫實現四格滾動動畫問題分析才知道原來原版系統原本就有這個滾動的動畫效果實現(要是對相關代碼有個全局觀估計就不會這麼狼狽),只要在它上修改其實就方便多了。同時,只要知道關機充電這個功能就是一個應用而已,它是由第一個進程init開啓的,而後從這應用的入口函數vendor/mediatek/proprietary/external/charger/main.cpp中的main開始追,整個充電邏輯就會比較清楚了。
以上是我的對mtk關機充電部分的理解,應該會有一些錯誤和遺漏,歡迎批評指正!