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

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

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

微信公眾號(hào):嵌入式開(kāi)發(fā)圈
關(guān)注可了解更多的教程。問(wèn)題或建議,請(qǐng)公眾號(hào)留言;
如果你覺(jué)得本文對(duì)你有幫助,歡迎贊賞


▲長(zhǎng)按圖片保存可分享至朋友圈


? ??

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

 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?*/

?

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

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

比如寫(xiě)入:?

1--update_package=path(對(duì)應(yīng)的OTA更新的路徑)

例如:

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

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

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

1//重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)出錯(cuò)到/tmp/recovery.log?這個(gè)文件里
2//static?const?char?*TEMPORARY_LOG_FILE?=?"/tmp/recovery.log";
3redirect_stdio(TEMPORARY_LOG_FILE);

redirect_stdio函數(shù)源代碼實(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)生來(lái)自stdout和stderr的信息會(huì)使用freopen這個(gè)函數(shù)重定向到/tmp/recovery.log這個(gè)文件里。stdout就是標(biāo)準(zhǔn)輸出,stdout就是標(biāo)準(zhǔn)出錯(cuò)。標(biāo)準(zhǔn)輸出就是我們平時(shí)使用的printf輸出的信息。????

????當(dāng)然也可以使用fprintf(stdout,"hello world\n");也是一樣的標(biāo)準(zhǔn)出錯(cuò)就是fprintf(stderr,"hello world!\n");類(lèi)似的代碼。接下下來(lái),將會(huì)判斷是否使用adb的sideload來(lái)傳入,通過(guò)參數(shù)--adbd來(lái)判斷:

 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????}

????做完這些步驟以后,會(huì)初始化并裝載recovery的分區(qū)表recovery.fstab,然后掛載/cache/recovery/last_log這個(gè)文件,用來(lái)輸出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這個(gè)文件
5????//#define?LAST_LOG_FILE?"/cache/recovery/last_log"
6????ensure_path_mounted(LAST_LOG_FILE);
7????rotate_last_logs(KEEP_LOG_COUNT);

這里主要看如何裝載分區(qū)表的流程,先來(lái)看看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?這個(gè)分區(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????//將對(duì)應(yīng)的信息加入到一條鏈表中
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ū)表信息,這類(lèi)信息在
24????//recovery啟動(dòng)的時(shí)候的log可以看到
25????//分別是以下
26????//編號(hào)|???掛載節(jié)點(diǎn)|??文件系統(tǒng)類(lèi)型|??塊設(shè)備|???長(zhǎ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}

????掛載完相應(yīng)的分區(qū)以后,就需要獲取命令參數(shù),因?yàn)橹挥袙燧d了對(duì)應(yīng)的分區(qū),才能訪問(wèn)到前面要寫(xiě)入command的這個(gè)文件,這樣我們才能正確的打開(kāi)文件,如果分區(qū)都沒(méi)找到,那么當(dāng)然就找不到分區(qū)上的文件,上面這個(gè)步驟是至關(guān)重要的。

 1//獲取參數(shù)
2????//這個(gè)參數(shù)也可能是從/cache/recovery/command文件中得到相應(yīng)的命令
3????//也就是可以往command這個(gè)文件寫(xiě)入對(duì)應(yīng)的格式的命令即可
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????}

????獲取到對(duì)應(yīng)的命令,就會(huì)執(zhí)行對(duì)應(yīng)的標(biāo)志,后面會(huì)根據(jù)標(biāo)志來(lái)執(zhí)行對(duì)應(yīng)的操作。

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

 1//設(shè)置語(yǔ)言
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)建設(shè)備
9????Device*?device?=?make_device();
10????//獲取UI
11????ui?=?device->GetUI();
12????//設(shè)置當(dāng)前的UI
13????gCurrentUI?=?ui;
14????//設(shè)置UI的語(yǔ)言信息
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????//設(shè)置recovery的背景圖
24????ui->SetBackground(RecoveryUI::NONE);
25????//設(shè)置界面上是否能夠顯示字符,使能ui->print函數(shù)開(kāi)關(guān)
26????if?(show_text)?ui->ShowText(true);
27????//設(shè)置selinux權(quán)限,一般我會(huì)把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ù),沒(méi)有做什么流程
38????device->StartRecovery();
39
40????printf("Command:");
41????for?(arg?=?0;?arg?42????????printf("?\"%s\"",?argv[arg]);
43????}
44????printf("\n");?

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

 1//如果update_package(也就是要升級(jí)的OTA包)不為空的情況下
2????//這里要對(duì)升級(jí)包的路徑做一下路徑轉(zhuǎn)換,這里可以自由定制自己升級(jí)包的路徑
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????//這里就是做轉(zhuǎn)換的方法
9????//先比較傳進(jìn)來(lái)的recovery參數(shù)的前6個(gè)byte是否是CACHE
10????//如果是將其路徑轉(zhuǎn)化為/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????????????//這個(gè)update_package就是轉(zhuǎn)換后的路徑
19????????????update_package?=?modified_path;
20????????}
21????}
22????printf("\n");
23????property_list(print_property,?NULL);
24????//獲取屬性,這里應(yīng)該是從一個(gè)文件中找到ro.build.display.id
25????//獲取recovery的版本信息
26????property_get("ro.build.display.id",?recovery_version,?"");
27????printf("\n");
28
29????//定義一個(gè)安裝成功的標(biāo)志位INSTALL_SUCCESS??---->?其實(shí)是個(gè)枚舉,值為0
30????int?status?=?INSTALL_SUCCESS;
31????//判斷轉(zhuǎn)換后的OTA升級(jí)包的路徑是否不為空,如果不為空
32????//執(zhí)行install_package?函數(shù)進(jìn)行升級(jí)
33????if?(update_package?!=?NULL)?{
34????????status?=?install_package(update_package,?&wipe_cache,?TEMPORARY_INSTALL_FILE,?true);
35????????//判斷是否升級(jí)成功
36????????if?(status?==?INSTALL_SUCCESS?&&?wipe_cache)?{
37????????????//擦除這個(gè)路徑,相當(dāng)于刪除了這個(gè)路徑下的OTA升級(jí)包
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ū),那么就走這個(gè)流程
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????????//顯示錯(cuò)誤的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升級(jí)
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更新和恢復(fù)出廠設(shè)置,先來(lái)說(shuō)說(shuō)恢復(fù)出廠設(shè)置,這個(gè)功能就是所謂的手機(jī)雙清,眾所周知,Android手機(jī)在使用很久后,由于垃圾數(shù)據(jù),以及其它的因素會(huì)導(dǎo)致手機(jī)的反應(yīng)越來(lái)越慢,這讓人煩惱不已,所以就需要雙清,雙清一般就是清除/data分區(qū)和/cache分區(qū),代碼流程很詳細(xì),有興趣可以自己去分析。??

????接下來(lái)看看OTA是如何實(shí)現(xiàn)更新的,我們看到install_ota_package這個(gè)函數(shù),執(zhí)行到這個(gè)函數(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????//設(shè)置安裝掛載對(duì)應(yīng)的節(jié)點(diǎn)
15????//這一步是關(guān)鍵
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????//如果返回結(jié)果為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}

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

 1//設(shè)置安裝掛載的節(jié)點(diǎn)
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????//那么就掛載對(duì)應(yīng)的節(jié)點(diǎn),而其它的節(jié)點(diǎn)都不會(huì)去掛載
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這兩個(gè)節(jié)點(diǎn),則默認(rèn)就會(huì)卸載所有的掛載節(jié)點(diǎn)
20????????else?{
21????????????//卸載所有的掛載節(jié)點(diǎn)
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}?

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

 1static?int
2really_install_package(const?char?*path,?int*?wipe_cache,?bool?needs_mount)
3
{
4????//設(shè)置更新時(shí)的背景
5????ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
6????ui->Print("Finding?update?package...\n");
7????//?Give?verification?half?the?progress?bar...
8????//設(shè)置進(jìn)度條的類(lèi)型
9????ui->SetProgressType(RecoveryUI::DETERMINATE);
10????//顯示進(jìn)度條
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升級(jí)包的路徑------>?一般是執(zhí)行這個(gè)流程
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????//獲取校驗(yàn)公鑰文件
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????//校驗(yàn)文件
45????err?=?verify_file(map.addr,?map.length,?loadedKeys,?numKeys);
46????free(loadedKeys);
47????LOGI("verify_file?returned?%d\n",?err);
48????//如果校驗(yàn)不成功
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????//嘗試去打開(kāi)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????//開(kāi)始安裝升級(jí)包
70????ui->Print("Installing?update...\n");
71????ui->SetEnableReboot(false);
72????int?result?=?try_update_binary(path,?&zip,?wipe_cache);
73????//安裝成功后自動(dòng)重啟
74????ui->SetEnableReboot(true);
75????ui->Print("\n");
76
77????sysReleaseMap(&map);
78????//返回結(jié)果
79????return?result;
80}

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

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

另外推薦相關(guān)課程:

? 韋東山老師優(yōu)質(zhì)嵌入式學(xué)習(xí)干貨推薦:包括ARM裸機(jī)開(kāi)發(fā)、Linux設(shè)備驅(qū)動(dòng)程序、Linux應(yīng)用程序開(kāi)發(fā)、Android系統(tǒng)學(xué)習(xí)、Linux設(shè)備樹(shù)等。

王爭(zhēng)老師優(yōu)秀數(shù)據(jù)結(jié)構(gòu)算法學(xué)習(xí)課程推薦


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

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

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

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

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

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

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

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

關(guān)鍵字: 騰訊 編碼器 CPU

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

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

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

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

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

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

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

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

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

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉