www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 嵌入式云IOT技術圈
[導讀]Android的系統(tǒng)升級,Android的線刷,卡刷,格式化究竟有什么奇妙的地方呢?它又是怎么實現(xiàn)的呢?今天我將為大家揭開它的面紗!

overflow: auto;overflow-wrap: normal;word-break: normal;">

微信公眾號:嵌入式開發(fā)圈
關注可了解更多的教程。問題或建議,請公眾號留言;
如果你覺得本文對你有幫助,歡迎贊賞


▲長按圖片保存可分享至朋友圈


? ??

????Android的系統(tǒng)升級,Android的線刷,卡刷,格式化究竟有什么奇妙的地方呢?它又是怎么實現(xiàn)的呢?今天我將為大家揭開它的面紗!我們以Tiny4412的Recovery源代碼為例,雖然4412并沒有支持Recovery系統(tǒng),但弄明白它的原理,我們也可以開發(fā)或者移植一個出來。其實,在recovery.cpp中開頭就已經(jīng)做了詳細的說明,我們來看看。

 1/*
2?*?The?recovery?tool?communicates?with?the?main?system?through?/cache?files.
3?*???/cache/recovery/command?-?INPUT?-?command?line?for?tool,?one?arg?per?line
4?*???/cache/recovery/log?-?OUTPUT?-?combined?log?file?from?recovery?run(s)
5?*???/cache/recovery/intent?-?OUTPUT?-?intent?that?was?passed?in
6?*
7?*?The?arguments?which?may?be?supplied?in?the?recovery.command?file:
8?*???--send_intent=anystring?-?write?the?text?out?to?recovery.intent
9?*???--update_package=path?-?verify?install?an?OTA?package?file
10?*???--wipe_data?-?erase?user?data?(and?cache),?then?reboot
11?*???--wipe_cache?-?wipe?cache?(but?not?user?data),?then?reboot
12?*???--set_encrypted_filesystem=on|off?-?enables?/?diasables?encrypted?fs
13?*???--just_exit?-?do?nothing;?exit?and?reboot
14?*
15?*?After?completing,?we?remove?/cache/recovery/command?and?reboot.
16?*?Arguments?may?also?be?supplied?in?the?bootloader?control?block?(BCB).
17?*?These?important?scenarios?must?be?safely?restartable?at?any?point:
18?*
19?*?FACTORY?RESET
20?*?1.?user?selects?"factory?reset"
21?*?2.?main?system?writes?"--wipe_data"?to?/cache/recovery/command
22?*?3.?main?system?reboots?into?recovery
23?*?4.?get_args()?writes?BCB?with?"boot-recovery"?and?"--wipe_data"
24?*????--?after?this,?rebooting?will?restart?the?erase?--
25?*?5.?erase_volume()?reformats?/data
26?*?6.?erase_volume()?reformats?/cache
27?*?7.?finish_recovery()?erases?BCB
28?*????--?after?this,?rebooting?will?restart?the?main?system?--
29?*?8.?main()?calls?reboot()?to?boot?main?system
30?*
31?*?OTA?INSTALL
32?*?1.?main?system?downloads?OTA?package?to?/cache/some-filename.zip
33?*?2.?main?system?writes?"--update_package=/cache/some-filename.zip"
34?*?3.?main?system?reboots?into?recovery
35?*?4.?get_args()?writes?BCB?with?"boot-recovery"?and?"--update_package=..."
36?*????--?after?this,?rebooting?will?attempt?to?reinstall?the?update?--
37?*?5.?install_package()?attempts?to?install?the?update
38?*????NOTE:?the?package?install?must?itself?be?restartable?from?any?point
39?*?6.?finish_recovery()?erases?BCB
40?*????--?after?this,?rebooting?will?(try?to)?restart?the?main?system?--
41?*?7.?**?if?install?failed?**
42?*????7a.?prompt_and_wait()?shows?an?error?icon?and?waits?for?the?user
43?*????7b;?the?user?reboots?(pulling?the?battery,?etc)?into?the?main?system
44?*?8.?main()?calls?maybe_install_firmware_update()
45?*????**?if?the?update?contained?radio/hboot?firmware?**:
46?*????8a.?m_i_f_u()?writes?BCB?with?"boot-recovery"?and?"--wipe_cache"
47?*????????--?after?this,?rebooting?will?reformat?cache?&?restart?main?system?--
48?*????8b.?m_i_f_u()?writes?firmware?image?into?raw?cache?partition
49?*????8c.?m_i_f_u()?writes?BCB?with?"update-radio/hboot"?and?"--wipe_cache"
50?*????????--?after?this,?rebooting?will?attempt?to?reinstall?firmware?--
51?*????8d.?bootloader?tries?to?flash?firmware
52?*????8e.?bootloader?writes?BCB?with?"boot-recovery"?(keeping?"--wipe_cache")
53?*????????--?after?this,?rebooting?will?reformat?cache?&?restart?main?system?--
54?*????8f.?erase_volume()?reformats?/cache
55?*????8g.?finish_recovery()?erases?BCB
56?*????????--?after?this,?rebooting?will?(try?to)?restart?the?main?system?--
57?*?9.?main()?calls?reboot()?to?boot?main?system
58?*/

?

???在這段英文注釋里,詳細的說明了factory_reset(Android的恢復出廠設置功能)的流程以及OTA系統(tǒng)更新的流程。在這段注釋得最前面說得很明白,我們只要往/cache/recovery/command中寫入相應的命令即可完成對應的功能。

1*?The?arguments?which?may?be?supplied?in?the?recovery.command?file:
2?*???--send_intent=anystring?-?write?the?text?out?to?recovery.intent
3?*???--update_package=path?-?verify?install?an?OTA?package?file
4?*???--wipe_data?-?erase?user?data?(and?cache),?then?reboot
5?*???--wipe_cache?-?wipe?cache?(but?not?user?data),?then?reboot
6?*???--set_encrypted_filesystem=on|off?-?enables?/?diasables?encrypted?fs
7?*???--just_exit?-?do?nothing;?exit?and?reboot

比如寫入:?

1--update_package=path(對應的OTA更新的路徑)

例如:

1--update_package=/mnt/external_sd/xxx.zip

????將這條命令寫入后,再重啟Android系統(tǒng),recovery檢測到有這個命令存在,就會去搜索這個路徑,然后將這個路徑做路徑轉換,接下來獲取轉換后的路徑后,就掛載這個路徑,然后掛載這個路徑,獲取OTA包,解包,校驗,然后最后實現(xiàn)真正的更新。????

????如果我們往這個文件寫入: --wipe_data那么就會做出廠設置,格式化/data分區(qū)的內(nèi)容。接下來,我們來看看代碼,從main函數(shù)開始分析:進入main函數(shù)后,會將recovery產(chǎn)生的log信息重定向到/tmp/recovery.log這個文件里,具體代碼實現(xiàn)如下:

1//重定向標準輸出和標準出錯到/tmp/recovery.log?這個文件里
2//static?const?char?*TEMPORARY_LOG_FILE?=?"/tmp/recovery.log";
3redirect_stdio(TEMPORARY_LOG_FILE);

redirect_stdio函數(shù)源代碼實現(xiàn):

1static?void?redirect_stdio(const?char*?filename)?{
2????//?If?these?fail,?there's?not?really?anywhere?to?complain...
3????freopen(filename,?"a",?stdout);?setbuf(stdout,?NULL);
4????freopen(filename,?"a",?stderr);?setbuf(stderr,?NULL);
5}?

?????我們看到,所有產(chǎn)生來自stdout和stderr的信息會使用freopen這個函數(shù)重定向到/tmp/recovery.log這個文件里。stdout就是標準輸出,stdout就是標準出錯。標準輸出就是我們平時使用的printf輸出的信息。????

????當然也可以使用fprintf(stdout,"hello world\n");也是一樣的標準出錯就是fprintf(stderr,"hello world!\n");類似的代碼。接下下來,將會判斷是否使用adb的sideload來傳入,通過參數(shù)--adbd來判斷:

 1????//?If?this?binary?is?started?with?the?single?argument?"--adbd",
2????//?instead?of?being?the?normal?recovery?binary,?it?turns?into?kind
3????//?of?a?stripped-down?version?of?adbd?that?only?supports?the
4????//?'sideload'?command.??Note?this?must?be?a?real?argument,?not
5????//?anything?in?the?command?file?or?bootloader?control?block;?the
6????//?only?way?recovery?should?be?run?with?this?argument?is?when?it
7????//?starts?a?copy?of?itself?from?the?apply_from_adb()?function.
8????if?(argc?==?2?&&?strcmp(argv[1],?"--adbd")?==?0)?{
9????????adb_main();
10????????return?0;
11????}

????做完這些步驟以后,會初始化并裝載recovery的分區(qū)表recovery.fstab,然后掛載/cache/recovery/last_log這個文件,用來輸出log。

1????printf("Starting?recovery?(pid?%d)?on?%s",?getpid(),?ctime(&start));
2????//裝載recovery的分區(qū)表recovery.fstab
3????load_volume_table();
4????//在recovery中掛載/cache/recovery/last_log這個文件
5????//#define?LAST_LOG_FILE?"/cache/recovery/last_log"
6????ensure_path_mounted(LAST_LOG_FILE);
7????rotate_last_logs(KEEP_LOG_COUNT);

這里主要看如何裝載分區(qū)表的流程,先來看看recovery.fstab

1/dev/block/by-name/boot?????????/boot?????????emmc?????defaults????????????????????????????????????????????????????????????????defaults
2/dev/block/by-name/recovery?????/recovery?????emmc?????defaults????????????????????????????????????????????????????????????????defaults
3/dev/block/by-name/splashscreen?/splashscreen?emmc?????defaults????????????????????????????????????????????????????????????????defaults
4/dev/block/by-name/fastboot?????/fastboot?????emmc?????defaults????????????????????????????????????????????????????????????????defaults
5/dev/block/by-name/misc?????????/misc?????????emmc?????defaults????????????????????????????????????????????????????????????????defaults
6/dev/block/by-name/system???????/system???????ext4?????ro,noatime??????????????????????????????????????????????????????????????wait
7/dev/block/by-name/cache????????/cache????????ext4?????nosuid,nodev,noatime,barrier=1,data=ordered?????????????????????????????wait,check
8/dev/block/by-name/userdata?????/data?????????ext4?????nosuid,nodev,noatime,discard,barrier=1,data=ordered,noauto_da_alloc?????wait,check
9/dev/block/by-name/factory??????/factory??????ext4?????nosuid,nodev,noatime,barrier=1,data=ordered?????????????????????????????wait
 1void?load_volume_table()
2
{
3????int?i;
4????int?ret;
5????//讀recovery.fstab?這個分區(qū)表
6????fstab?=?fs_mgr_read_fstab("/etc/recovery.fstab");
7????if?(!fstab)?{
8????????LOGE("failed?to?read?/etc/recovery.fstab\n");
9????????return;
10????}
11????//將對應的信息加入到一條鏈表中
12????ret?=?fs_mgr_add_entry(fstab,?"/tmp",?"ramdisk",?"ramdisk");
13????//如果load到的分區(qū)表為空,后面做釋放操作
14????if?(ret?0?)?{
15????????LOGE("failed?to?add?/tmp?entry?to?fstab\n");
16????????fs_mgr_free_fstab(fstab);
17????????fstab?=?NULL;
18????????return;
19????}
20
21????printf("recovery?filesystem?table\n");
22????printf("=========================\n");
23????//到這一步,打印分區(qū)表信息,這類信息在
24????//recovery啟動的時候的log可以看到
25????//分別是以下
26????//編號|???掛載節(jié)點|??文件系統(tǒng)類型|??塊設備|???長度
27????for?(i?=?0;?i?num_entries;?++i)?{
28????????Volume*?v?=?&fstab->recs[i];
29????????printf("??%d?%s?%s?%s?%lld\n",?i,?v->mount_point,?v->fs_type,
30???????????????v->blk_device,?v->length);
31????}
32????printf("\n");
33}

????掛載完相應的分區(qū)以后,就需要獲取命令參數(shù),因為只有掛載了對應的分區(qū),才能訪問到前面要寫入command的這個文件,這樣我們才能正確的打開文件,如果分區(qū)都沒找到,那么當然就找不到分區(qū)上的文件,上面這個步驟是至關重要的。

 1//獲取參數(shù)
2????//這個參數(shù)也可能是從/cache/recovery/command文件中得到相應的命令
3????//也就是可以往command這個文件寫入對應的格式的命令即可
4????get_args(&argc,?&argv);
5
6????const?char?*send_intent?=?NULL;
7????const?char?*update_package?=?NULL;
8????int?wipe_data?=?0,?wipe_cache?=?0,?show_text?=?0;
9????bool?just_exit?=?false;
10????bool?shutdown_after?=?false;
11
12????int?arg;
13????//參數(shù)有擦除分區(qū),OTA更新等
14????while?((arg?=?getopt_long(argc,?argv,?"",?OPTIONS,?NULL))?!=?-1)?{
15????????switch?(arg)?{
16????????case?'s':?send_intent?=?optarg;?break;
17????????case?'u':?update_package?=?optarg;?break;
18????????case?'w':?wipe_data?=?wipe_cache?=?1;?break;
19????????case?'c':?wipe_cache?=?1;?break;
20????????case?'t':?show_text?=?1;?break;
21????????case?'x':?just_exit?=?true;?break;
22????????case?'l':?locale?=?optarg;?break;
23????????case?'g':?{
24????????????if?(stage?==?NULL?||?*stage?==?'\0')?{
25????????????????char?buffer[20]?=?"1/";
26????????????????strncat(buffer,?optarg,?sizeof(buffer)-3);
27????????????????stage?=?strdup(buffer);
28????????????}
29????????????break;
30????????}
31????????case?'p':?shutdown_after?=?true;?break;
32????????case?'r':?reason?=?optarg;?break;
33????????case?'?':
34????????????LOGE("Invalid?command?argument\n");
35????????????continue;
36????????}
37????}

????獲取到對應的命令,就會執(zhí)行對應的標志,后面會根據(jù)標志來執(zhí)行對應的操作。

????做完以上的流程后,下面就是創(chuàng)建設備,設置語言信息,初始化recovery的UI界面,設置Selinux權限,代碼如下:

 1//設置語言
2????if?(locale?==?NULL)?{
3????????load_locale_from_cache();
4????}
5????printf("locale?is?[%s]\n",?locale);
6????printf("stage?is?[%s]\n",?stage);
7????printf("reason?is?[%s]\n",?reason);
8????//創(chuàng)建設備
9????Device*?device?=?make_device();
10????//獲取UI
11????ui?=?device->GetUI();
12????//設置當前的UI
13????gCurrentUI?=?ui;
14????//設置UI的語言信息
15????ui->SetLocale(locale);
16????//UI初始化
17????ui->Init();
18
19????int?st_cur,?st_max;
20????if?(stage?!=?NULL?&&?sscanf(stage,?"%d/%d",?&st_cur,?&st_max)?==?2)?{
21????????ui->SetStage(st_cur,?st_max);
22????}
23????//設置recovery的背景圖
24????ui->SetBackground(RecoveryUI::NONE);
25????//設置界面上是否能夠顯示字符,使能ui->print函數(shù)開關
26????if?(show_text)?ui->ShowText(true);
27????//設置selinux權限,一般我會把selinux?給disabled
28????struct?selinux_opt?seopts[]?=?{
29??????{?SELABEL_OPT_PATH,?"/file_contexts"?}
30????};
31
32????sehandle?=?selabel_open(SELABEL_CTX_FILE,?seopts,?1);
33
34????if?(!sehandle)?{
35????????ui->Print("Warning:?No?file_contexts\n");
36????}
37????//虛函數(shù),沒有做什么流程
38????device->StartRecovery();
39
40????printf("Command:");
41????for?(arg?=?0;?arg?42????????printf("?\"%s\"",?argv[arg]);
43????}
44????printf("\n");?

????接下來是重要的環(huán)節(jié),這個環(huán)節(jié)將會根據(jù)上面命令參數(shù)來做真正的事情了,比如恢復出廠設置,OTA更新等。

 1//如果update_package(也就是要升級的OTA包)不為空的情況下
2????//這里要對升級包的路徑做一下路徑轉換,這里可以自由定制自己升級包的路徑
3????if?(update_package)?{
4????????//?For?backwards?compatibility?on?the?cache?partition?only,?if
5????????//?we're?given?an?old?'root'?path?"CACHE:foo",?change?it?to
6????????//?"/cache/foo".
7
8????//這里就是做轉換的方法
9????//先比較傳進來的recovery參數(shù)的前6個byte是否是CACHE
10????//如果是將其路徑轉化為/cache/CACHE:?......
11????????if?(strncmp(update_package,?"CACHE:",?6)?==?0)?{
12????????????int?len?=?strlen(update_package)?+?10;
13????????????char*?modified_path?=?(char*)malloc(len);
14????????????strlcpy(modified_path,?"/cache/",?len);
15????????????strlcat(modified_path,?update_package+6,?len);
16????????????printf("(replacing?path?\"%s\"?with?\"%s\")\n",
17???????????????????update_package,?modified_path);
18????????????//這個update_package就是轉換后的路徑
19????????????update_package?=?modified_path;
20????????}
21????}
22????printf("\n");
23????property_list(print_property,?NULL);
24????//獲取屬性,這里應該是從一個文件中找到ro.build.display.id
25????//獲取recovery的版本信息
26????property_get("ro.build.display.id",?recovery_version,?"");
27????printf("\n");
28
29????//定義一個安裝成功的標志位INSTALL_SUCCESS??---->?其實是個枚舉,值為0
30????int?status?=?INSTALL_SUCCESS;
31????//判斷轉換后的OTA升級包的路徑是否不為空,如果不為空
32????//執(zhí)行install_package?函數(shù)進行升級
33????if?(update_package?!=?NULL)?{
34????????status?=?install_package(update_package,?&wipe_cache,?TEMPORARY_INSTALL_FILE,?true);
35????????//判斷是否升級成功
36????????if?(status?==?INSTALL_SUCCESS?&&?wipe_cache)?{
37????????????//擦除這個路徑,相當于刪除了這個路徑下的OTA升級包
38????????????if?(erase_volume("/cache"))?{
39????????????????LOGE("Cache?wipe?(requested?by?package)?failed.");
40????????????}
41????????}
42????????//如果安裝不成功
43????????if?(status?!=?INSTALL_SUCCESS)?{
44????????????ui->Print("Installation?aborted.\n");
45
46????????????//?If?this?is?an?eng?or?userdebug?build,?then?automatically
47????????????//?turn?the?text?display?on?if?the?script?fails?so?the?error
48????????????//?message?is?visible.
49????????????char?buffer[PROPERTY_VALUE_MAX+1];
50????????????property_get("ro.build.fingerprint",?buffer,?"");
51????????????if?(strstr(buffer,?":userdebug/")?||?strstr(buffer,?":eng/"))?{
52????????????????ui->ShowText(true);
53????????????}
54????????}
55????}
56????//如果跑的是格式化數(shù)據(jù)區(qū),那么就走這個流程
57????else?if?(wipe_data)?{
58????????if?(device->WipeData())?status?=?INSTALL_ERROR;
59????????//格式化/data分區(qū)
60????????if?(erase_volume("/data"))?status?=?INSTALL_ERROR;
61????????if?(wipe_cache?&&?erase_volume("/cache"))?status?=?INSTALL_ERROR;
62????????if?(erase_persistent_partition()?==?-1?)?status?=?INSTALL_ERROR;
63????????if?(status?!=?INSTALL_SUCCESS)?ui->Print("Data?wipe?failed.\n");
64????}?
65????//格式化cache分區(qū)
66????else?if?(wipe_cache)?{
67????????if?(wipe_cache?&&?erase_volume("/cache"))?status?=?INSTALL_ERROR;
68????????if?(status?!=?INSTALL_SUCCESS)?ui->Print("Cache?wipe?failed.\n");
69????}?
70????else?if?(!just_exit)?{
71????????status?=?INSTALL_NONE;??//?No?command?specified
72????????ui->SetBackground(RecoveryUI::NO_COMMAND);
73????}
74????//如果安裝失敗或者。。。
75????if?(status?==?INSTALL_ERROR?||?status?==?INSTALL_CORRUPT)?{
76????????copy_logs();
77????????//顯示錯誤的LOGO
78????????ui->SetBackground(RecoveryUI::ERROR);
79????}
80????Device::BuiltinAction?after?=?shutdown_after???Device::SHUTDOWN?:?Device::REBOOT;
81????if?(status?!=?INSTALL_SUCCESS?||?ui->IsTextVisible())?{
82????????Device::BuiltinAction?temp?=?prompt_and_wait(device,?status);
83????????if?(temp?!=?Device::NO_ACTION)?after?=?temp;
84????}
85
86????//?Save?logs?and?clean?up?before?rebooting?or?shutting?down.
87????//完成recovery升級
88????finish_recovery(send_intent);
89
90????switch?(after)?{
91????????case?Device::SHUTDOWN:
92????????????ui->Print("Shutting?down...\n");
93????????????property_set(ANDROID_RB_PROPERTY,?"shutdown,");
94????????????break;
95
96????????case?Device::REBOOT_BOOTLOADER:
97????????????ui->Print("Rebooting?to?bootloader...\n");
98????????????property_set(ANDROID_RB_PROPERTY,?"reboot,bootloader");
99????????????break;
100
101????????default:
102????????????ui->Print("Rebooting...\n");
103????????????property_set(ANDROID_RB_PROPERTY,?"reboot,");
104????????????break;
105????}
106????sleep(5);?//?should?reboot?before?this?finishes
107????return?EXIT_SUCCESS;

????在這里面,我們最常用的即是OTA更新和恢復出廠設置,先來說說恢復出廠設置,這個功能就是所謂的手機雙清,眾所周知,Android手機在使用很久后,由于垃圾數(shù)據(jù),以及其它的因素會導致手機的反應越來越慢,這讓人煩惱不已,所以就需要雙清,雙清一般就是清除/data分區(qū)和/cache分區(qū),代碼流程很詳細,有興趣可以自己去分析。??

????接下來看看OTA是如何實現(xiàn)更新的,我們看到install_ota_package這個函數(shù),執(zhí)行到這個函數(shù),看到源碼:

 1//安裝更新包
2int
3install_package(const?char*?path,?int*?wipe_cache,?const?char*?install_file,
4????????????????bool?needs_mount)

5
{
6????FILE*?install_log?=?fopen_path(install_file,?"w");
7????if?(install_log)?{
8????????fputs(path,?install_log);
9????????fputc('\n',?install_log);
10????}?else?{
11????????LOGE("failed?to?open?last_install:?%s\n",?strerror(errno));
12????}
13????int?result;
14????//設置安裝掛載對應的節(jié)點
15????//這一步是關鍵
16????if?(setup_install_mounts()?!=?0)?{
17????????LOGE("failed?to?set?up?expected?mounts?for?install;?aborting\n");
18????????result?=?INSTALL_ERROR;
19????}?else?{
20????????//到這里才是真正的去安裝OTA包
21????????result?=?really_install_package(path,?wipe_cache,?needs_mount);
22????}
23????//如果返回結果為0,那么安裝就成功了
24????if?(install_log)?{
25????????fputc(result?==?INSTALL_SUCCESS???'1'?:?'0',?install_log);
26????????fputc('\n',?install_log);
27????????fclose(install_log);
28????}
29????return?result;
30}

????其實到了really_install_package這一步,才是真正做到OTA更新,但是在OTA更新之前至關重要的一步就是設置安裝掛載對應的節(jié)點了,我曾經(jīng)掉入此坑,現(xiàn)在拿出來分析一下,我們來看看setup_install_mounts這個函數(shù):

 1//設置安裝掛載的節(jié)點
2int?setup_install_mounts()?{
3????if?(fstab?==?NULL)?{
4????????LOGE("can't?set?up?install?mounts:?no?fstab?loaded\n");
5????????return?-1;
6????}
7????for?(int?i?=?0;?i?num_entries;?++i)?{
8????????Volume*?v?=?fstab->recs?+?i;
9????//如果判斷掛載的路徑是/tmp?或者/cache
10????//那么就掛載對應的節(jié)點,而其它的節(jié)點都不會去掛載
11????????if?(strcmp(v->mount_point,?"/tmp")?==?0?||
12????????????strcmp(v->mount_point,?"/cache")?==?0)?{
13????????????if?(ensure_path_mounted(v->mount_point)?!=?0)?{
14????????????????LOGE("failed?to?mount?%s\n",?v->mount_point);
15????????????????return?-1;
16????????????}
17
18????????}
19????????//如果不是/tmp或者/cache這兩個節(jié)點,則默認就會卸載所有的掛載節(jié)點
20????????else?{
21????????????//卸載所有的掛載節(jié)點
22????????????if?(ensure_path_unmounted(v->mount_point)?!=?0)?{
23????????????????LOGE("failed?to?unmount?%s\n",?v->mount_point);
24????????????????return?-1;
25????????????}
26????????}
27????}
28????return?0;
29}?

????如果在安裝更新的時候,OTA包經(jīng)過路徑轉換后不是放在/tmp和/cache這個路徑下的時候,那么就會走else分支,從而卸載所有的掛載節(jié)點,這樣就會導致,傳的路徑正確,卻OTA更新不成功,如果是做自己定制的路徑,這一步一定要小心,我們可以在這里繼續(xù)添加定制的掛載點。那么,執(zhí)行完設置掛載節(jié)點的函數(shù)后,接下來就是執(zhí)行真正的OTA更新了,我們來看看:

 1static?int
2really_install_package(const?char?*path,?int*?wipe_cache,?bool?needs_mount)
3
{
4????//設置更新時的背景
5????ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
6????ui->Print("Finding?update?package...\n");
7????//?Give?verification?half?the?progress?bar...
8????//設置進度條的類型
9????ui->SetProgressType(RecoveryUI::DETERMINATE);
10????//顯示進度條
11????ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION,?VERIFICATION_PROGRESS_TIME);
12????LOGI("Update?location:?%s\n",?path);
13????//在屏幕上打印?Opening?update?package..
14????//?Map?the?update?package?into?memory.
15????ui->Print("Opening?update?package...\n");
16????//patch是OTA的路徑,need_mount參數(shù)表示是否需要掛載,1掛載,0,不掛載
17????if?(path?&&?needs_mount)?{
18????????if?(path[0]?==?'@')?{
19????????????ensure_path_mounted(path+1);
20????????}?else?{
21????????????//掛載OTA升級包的路徑------>?一般是執(zhí)行這個流程
22????????????ensure_path_mounted(path);
23????????}
24????}
25
26????MemMapping?map;
27????if?(sysMapFile(path,?&map)?!=?0)?{
28????????LOGE("failed?to?map?file\n");
29????????return?INSTALL_CORRUPT;
30????}
31
32????int?numKeys;
33????//獲取校驗公鑰文件
34????Certificate*?loadedKeys?=?load_keys(PUBLIC_KEYS_FILE,?&numKeys);
35????if?(loadedKeys?==?NULL)?{
36????????LOGE("Failed?to?load?keys\n");
37????????return?INSTALL_CORRUPT;
38????}
39????LOGI("%d?key(s)?loaded?from?%s\n",?numKeys,?PUBLIC_KEYS_FILE);
40
41????ui->Print("Verifying?update?package...\n");
42
43????int?err;
44????//校驗文件
45????err?=?verify_file(map.addr,?map.length,?loadedKeys,?numKeys);
46????free(loadedKeys);
47????LOGI("verify_file?returned?%d\n",?err);
48????//如果校驗不成功
49????if?(err?!=?VERIFY_SUCCESS)?{
50????????//打印簽名失敗
51????????LOGE("signature?verification?failed\n");
52????????sysReleaseMap(&map);
53????????return?INSTALL_CORRUPT;
54????}
55
56????/*?Try?to?open?the?package.
57?????*/

58????//嘗試去打開ota壓縮包
59????ZipArchive?zip;
60????err?=?mzOpenZipArchive(map.addr,?map.length,?&zip);
61????if?(err?!=?0)?{
62????????LOGE("Can't?open?%s\n(%s)\n",?path,?err?!=?-1???strerror(err)?:?"bad");
63????????sysReleaseMap(&map);
64????????return?INSTALL_CORRUPT;
65????}
66
67????/*?Verify?and?install?the?contents?of?the?package.
68?????*/

69????//開始安裝升級包
70????ui->Print("Installing?update...\n");
71????ui->SetEnableReboot(false);
72????int?result?=?try_update_binary(path,?&zip,?wipe_cache);
73????//安裝成功后自動重啟
74????ui->SetEnableReboot(true);
75????ui->Print("\n");
76
77????sysReleaseMap(&map);
78????//返回結果
79????return?result;
80}

????關于recovery的大致流程,我們分析至此,關于如何像MTK平臺一樣,定制recovery,這就需要讀者能夠讀懂recovery的流程,然后加入自己的代碼進行定制,當然我們也會看到,一些recovery花樣百出,很多UI做了自己的,而不是用安卓系統(tǒng)原生態(tài)的,安卓系統(tǒng)recovery原生態(tài)的UI如下:

????如何定制相應的UI,后續(xù)我們會對recovery源代碼中的UI顯示做進一步的分析。。。。

另外推薦相關課程:

? 韋東山老師優(yōu)質嵌入式學習干貨推薦:包括ARM裸機開發(fā)、Linux設備驅動程序、Linux應用程序開發(fā)、Android系統(tǒng)學習、Linux設備樹等。

王爭老師優(yōu)秀數(shù)據(jù)結構算法學習課程推薦


免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉