android ota 升级脚本,Android OTA升級包制作腳本詳解(五,升級腳本updater-script的執行1)...
寫在前面:
首先當我們執行升級腳本updater-script的時候,就表示我們已經進入了升級安裝狀態。那么在我們就從實際的安裝作為入口開始分析。也就是說我們從install.cpp中的install_package函數開始一步步來分析。
這里主要分析與腳本相關的部分,其他的請參考這位朋友的博文http://blog.chinaunix.net/uid-22028566-id-3533856.html,我也很受啟發。這里也借用一張圖來幫助流程上的分析。
下面是調用的流程:install_package()-->really_install_package(),那么在really_install_package()函數中真正開始安裝的邏輯如下:
/* Verify and install the contents of the package.
*/
ui->Print("Installing update...\n");
err = try_update_binary(path, &zip, wipe_cache);
if(err != INSTALL_SUCCESS)
return err; try_update_binary是真正實現讀取升級包中的腳本文件並執行相應的函數。在此函數中,通過調用fork函數創建出一個子進程,在子進程中開始讀取並執行升級腳本文件。在此需要注意的是函數fork的用法,fork被調用一次,將做兩次返回,在父進程中返回的是子進程的進程ID,為正數;而在子進程中,則返回0。子進程中所進行的操作,即execv(binary, args)。子進程創建成功后,開始執行升級代碼,並通過管道與父進程交互(創建管道,並將pipefd[1]作為參數傳遞給子進程,子進程則將相關信息寫入到此管道描述符中);而父進程則通過讀取子進程傳遞過來的信息更新UI。
那么下面我們來具體來分析一下這個方法具體的邏輯。
static int
try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
//定義一個常量用來封裝查找相zip關信息的結果如“META-INF/com/google/android/update-binary”,便於后面進行解壓,因為之前mzOpenZipArchive函數並沒有對更新包進行解壓操作,*zip是之前mzOpenZipArchive方法返回的一個ZipArchive對象。mzOpenZipArchive是打開升級包,並將相關的信息拷貝到一個臨時的ZipArchinve變量中。
//ASSUMED_UPDATE_BINARY_NAME="META-INF/com/google/android/update-binary"
const ZipEntry* binary_entry =
mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
if (binary_entry == NULL) {
mzCloseZipArchive(zip);
return INSTALL_CORRUPT;
}
const char* binary = "/tmp/update_binary";
unlink(binary);
//創建“/tmp/update_binary”文件
int fd = creat(binary, 0755);
if (fd < 0) {
mzCloseZipArchive(zip);
LOGE("Can't make %s\n", binary);
return INSTALL_ERROR;
}
//將META-INF/com/google/android/update-binary中的內容解壓縮到"/tmp/update_binary"下面。其實這個方法中主要是對update_binary操作的,如解壓和執行等。
bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
close(fd);
mzCloseZipArchive(zip);
if (!ok) {
LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
return INSTALL_ERROR;
}
int pipefd[2];
//創建管道,用於下面的子進程和父進程之間的通信
pipe(pipefd);
// When executing the update binary contained in the package, the
// arguments passed are:
//
// - the version number for this interface
//
// - an fd to which the program can write in order to update the
// progress bar. The program can write single-line commands:
//
// progress
// fill up the next part of of the progress bar
// over seconds. If is zero, use
// set_progress commands to manually control the
// progress of this segment of the bar
//
// set_progress
// should be between 0.0 and 1.0; sets the
// progress bar within the segment defined by the most
// recent progress command.
//
// firmware
// arrange to install the contents of in the
// given partition on reboot.
//
// (API v2: may start with "PACKAGE:" to
// indicate taking a file from the OTA package.)
//
// (API v3: this command no longer exists.)
//
// ui_print
// display on the screen.
//
// - the name of the package zip file.
//
const char** args = (const char**)malloc(sizeof(char*) * 5);
args[0] = binary;
args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk
char* temp = (char*)malloc(10);
sprintf(temp, "%d", pipefd[1]);
args[2] = temp;
args[3] = (char*)path;
args[4] = NULL;
//創建子進程。其中的子進程主要負責執行binary(execv(binary,args),即執行我們的安裝命令腳本),父進程負責接受子進程發送的命令去更新ui顯示(顯示當前的進度)。子父進程間通信依靠管道。
pid_t pid = fork();
if (pid == 0) {
close(pipefd[0]);
//執行update-binary,這個程序的實質就是去解析update.zip包中的updater-script腳本中的命令並執行。由此,Recovery服務就進入了實際安裝update.zip包的過程。在執行execv函數時,execv會停止執行當前的進程,並且以progname應用進程替換被停止執行的進程,進程ID沒有改變。這里的progname就是指update-binary,也就是被執行的應用程序。第二個參數argv,是指運行update-binaryt時,傳遞給執行程序的參數列表, 注意,這個數組的第一個參數應該是應用程序名字本身,並且最后一個參數應該為NULL,不參將多個參數合並為一個參數放入數組。
此外,如果應用程序正常執行完畢,那么execv是永遠不會返回的;當execv在調用進程中返回時,那么這個應用程序應該出錯了(可能是程序本身沒找到,權限不夠...),此時它的返回值應該是-1,具體的錯誤代碼可以通過全局變量errno查看,還可以通過stderr得到具體的錯誤描述字符串。
execv(binary, (char* const*)args);//其實我的理解就是update-binary相當一個exe可執行程序,這里就是一個雙擊可執行程序的動作
fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
_exit(-1);
}
close(pipefd[1]);
*wipe_cache = 0;
char buffer[1024];
FILE* from_child = fdopen(pipefd[0], "r");
while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
char* command = strtok(buffer, " \n");
if (command == NULL) {
continue;
} else if (strcmp(command, "progress") == 0) {
char* fraction_s = strtok(NULL, " \n");
char* seconds_s = strtok(NULL, " \n");
float fraction = strtof(fraction_s, NULL);
int seconds = strtol(seconds_s, NULL, 10);
ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
} else if (strcmp(command, "set_progress") == 0) {
char* fraction_s = strtok(NULL, " \n");
float fraction = strtof(fraction_s, NULL);
ui->SetProgress(fraction);
} else if (strcmp(command, "ui_print") == 0) {
char* str = strtok(NULL, "\n");
if (str) {
ui->Print("%s", str);
} else {
ui->Print("\n");
}
fflush(stdout);
} else if (strcmp(command, "wipe_cache") == 0) {
*wipe_cache = 1;
#if 1 //wschen 2012-07-25
} else if (strcmp(command, "special_factory_reset") == 0) {
*wipe_cache = 2;
#endif
} else if (strcmp(command, "clear_display") == 0) {
ui->SetBackground(RecoveryUI::NONE);
} else {
LOGE("unknown command [%s]\n", command);
}
}
fclose(from_child);
int status;
waitpid(pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
return INSTALL_ERROR;
}
#ifdef SUPPORT_DATA_BACKUP_RESTORE //wschen 2011-03-09
//Skip userdata restore if updating from /data with no /data layout change
if(!usrdata_changed && update_from_data){
ui->Print("/data offset remains the same no need to restore usrdata\n");
}else{
if (part_size_changed) {
if (ensure_path_mounted("/sdcard") != 0) {
LOGE("Can't mount %s\n", path);
return INSTALL_NO_SDCARD;
}
if (userdata_restore(backup_path, 1)) {
return INSTALL_FILE_SYSTEM_ERROR;
}
}
}
#endif //SUPPORT_DATA_BACKUP_RESTORE
/* ----------------------------- */
/* SECURE BOOT UPDATE */
/* ----------------------------- */
#ifdef SUPPORT_SBOOT_UPDATE
sec_update(false);
#endif
return INSTALL_SUCCESS;
}
android ota 升级脚本,Android OTA升級包制作腳本詳解(五,升級腳本updater-script的執行1)...相关推荐
- android ota升级服务,android 标准OTA升级流程
标准的OTA升级流程包括一下几个步骤: 1.Android设备首先会与OTA服务器进行交互,如果有更新会推送给客户.推送的信息常常会包含OTA更新包的下载地址和一些版本信息. 2.Update程序会将 ...
- RTOS设备如何快速实现OTA升级--快速接入OTA平台
目录 一. 创建产品和零件 1.1 登陆平台 1.2 添加产品 1.3 配置产品 1.4 添加升级零件 二. 添加设备 2.1 单个添加 2.2 批量添加 三. 设备注册激活 3.1 发起请求 3.2 ...
- ESP32 OTA升级之HTTP OTA
ESP32 OTA升级之 HTTP OTA 文章目录 ESP32 OTA升级之 HTTP OTA 1. 前言 2. 搭建http本地服务器 2. HTTP OTA 3. 补充学习 1. 前言 在所有电 ...
- android.mk 执行脚本,Android.mk的用法
(1)Android.mk是什么? Android.mk是Android提供的一种makefile文件.Android.mk其实是把真正的Makefile包装起来,做成了一个对使用者来说很简单的东西. ...
- 58 ESP32 OTA升级(双OTA分区无factory APP)
1 引言 产品功能实现后,就要对产品的维护进行考虑.产品出来后,卖了N台出去,如果突然发现自己一行代码写错了,怎么办,肯定不能去现场吧N台设备,免费出差旅游也累啊,所以一般需要有远程升级设备的功能,此 ...
- android魅族升级,魅族Android 4.4 Flyme升级教程教学详细介绍
魅族Android 4.4 Flyme升级教程教学详细介绍 注意事项: 1)已ROOT,或安装安全类软件进行了Android签名漏洞修补的'用户,请务必在升级时清除数据,否则可能会无法开机.清除数据会 ...
- android静默升级方案,Android静默更新程序
先说我的应用场景,android板子嵌在机器里面.因为没有显示器,所以版本更新需要用到静默安装.先root... 静默更新流程: 1.服务里定时去检测是否有新的版本,下载新版本保存在本地 2.静默更新 ...
- android fota升级 开发,android fota升级
1. 简介 fota(Firmware Over The Air),移动终端空中下载软件升级技术.原理是根据算法把新旧版本之间的差别做成一个软件包,手机从服务器上下载到手机里,由手机完成软件版本 ...
- android 在线升级apk,Android 在线升级APK
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setC ...
最新文章
- 【全网之最】最短代码清除数组中的假、空值(0、空、null、undefined、false)
- PyInstaller库的使用
- js jquery 数组的合并 对象的合并
- 关于jasmine里debugElement.query和fixture.detectChanges的依赖关系
- 【自己给自己题目做】:如何在Canvas上实现魔方效果
- Java基础---方法的重载(overload)+ 优先向上匹配原则
- pip安装gluonts
- 牛逼!支付宝 App架构
- 2021-06-27 方法的调用
- win7休眠 计算机管理,Win7休眠功能怎么关闭?
- Google 应用与游戏出海 4 月刊: 带您连线 GDC,赢在发布前!
- 计算机软件工作室起名'',游戏工作室起名大全
- 【JAVA】贪吃蛇的初步实现(三)
- ImportError: cannot import name ‘xxx‘ from ‘xxx‘
- WooCommerce Product Feed指南 – Google Shopping和Facebook[2022]
- 汉服经济迎来“井喷式”发展!vr全景助力汉服数字化蜕变
- C++ 计算直线的交点数(动态规划)
- 高数上册第七章小结笔记
- 2018东华计算机复试,18东华双控初试复试经验
- Opencv学习笔记 基于HOG和SVM的行人检测
热门文章
- 影像组学视频学习笔记(15)-ROC曲线及其绘制、Li‘s have a solution and plan.
- 机器学习-第九章 聚类
- R语言 (温度 随时间变化)
- C++所提供的类模板应用(堆栈)
- tf.keras.activations.softmax 激活函数 示例
- photoshop 图片转 pdf
- Linux (CentOS)安装VNC+XFCE可视化桌面环境 附安装FireFox浏览器
- php t double arrow,关于php:php – 语法错误,意外T_DOUBLE_ARROW
- qq说说时间轴php实现,PHP实现时间轴函数
- matlab门槛回归,重磅!这可能是最全的门槛回归汇总了