为什么系统升级完后第一次启动,弹出升级成功的对话框:
这是什么原理?系统怎么知道系统更升级完了?下次启动为什么不会提示了?
首先用dumpsys window查下此对话框在哪个包里的,查到是:com.mediatek.systemupdate,但查不到activity(因为不是activity)。
com.mediatek.systemupdate位于vendor/mediatek/proprietary/packages/apps/SystemUpdate应用里。
然后,再在点击上面确定时查找logcat log,找到一个疑似的service:
vendor/mediatek/proprietary/packages/apps/SystemUpdate/src/com/mediatek/systemupdate/ForegroundDialogService.java
到此service里找一些代码,通过字面意思,在vendor/mediatek/proprietary/packages/apps/SystemUpdate/res/values-zh-rCN/strings.xml里面找到相应的字符串:
由此,推出了系统在OTA升级完后第一次启动,是如何弹出升级提示的:
SystemUpdateReceiver.java //此receiver被注册,接收ACTION_BOOT_COMPLETED消息
onReceive
else if (action.equalsIgnoreCase(Util.Action.ACTION_BOOT_COMPLETED)//收到消息
if (getUpdateStatus()) { //关键:这里获得升级状态
Util.setAlarm(context, AlarmManager.RTC, //设置alarm延时提示升级报告
Calendar.getInstance().getTimeInMillis()
+ SHOW_RESULT_TIME_DELAY,
Util.Action.ACTION_UPDATE_REPORT);
}
else if (action.equalsIgnoreCase(Util.Action.ACTION_UPDATE_REPORT)) {//收到提示
startReportActivity();//startService:ForegroundDialogService
resetUpdateResult();//并复位升级标志,这样下次启动不会提示
agent.clearUpdateResult() //通过agent清除升级标志
send com.mediatek.systemupdate.UPDATE_SUCCESSFUL
startService:ForegroundDialogService
ForegroundDialogService.java
onStartCommand //上面调用startService后,这里被调用
else if (dlgId == DIALOG_UPDATE_RESULT) {
showForeGroundDlg(dlgId); //显示升级结果对话框,id为DIALOG_UPDATE_RESULT
message = SystemProperties.get("ro.mediatek.version.release");//升级版本是
//从这获取
private boolean getUpdateStatus() {
updated = getUpdateResult();
}
boolean getUpdateResult() { //获取升级结果
if (Util.isEmmcSupport()) { //获取属性ro.mtk_emmc_support,这里为1
try {
IBinder binder = ServiceManager.getService("GoogleOtaBinder");
SystemUpdateBinder agent = SystemUpdateBinder.Stub.asInterface(binder);
if (agent == null) {
Log.e("@M_" + TAG, "Agent is null.");
return false;
}
return agent.readUpgradeResult();//调用agen来读升级结果
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}
}
agent的实现:vendor/mediatek/proprietary/external/GoogleOtaBinder/googleota_binder.cpp
int GoogleOtaAgent::readUpgradeResult()
{
rec = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
asprintf(&source, "%s", rec->blk_device);
strcpy(dev_name, source);
dev = open(dev_name, O_RDONLY); //打开/misc设备,seek到OTA_RESULT_OFFSET读取
if (lseek(dev, OTA_RESULT_OFFSET, SEEK_SET) == -1)
count = read(dev, &result, sizeof(result));
if (close(dev) != 0)
}
#define OTA_RESULT_OFFSET (2560)
到这里,大概知道,ota升级的结果是放在/misc分区的偏移OTA_RESULT_OFFSET下。
那么,就猜测,recovery代码里,也是在这个地方写了个标志?
在recovery代码里,搜索“2560”,果然找到:
bootable\recovery\mt_bootloader.h
#define OTA_RESULT_OFFSET (2560)
一步步往回找,终于知道recovery里写这个标志的流程:
main(int argc, char **argv) {
mt_main_update_package(status, update_package, &should_wipe_cache);//安装update.zip
mt_main_write_result(status, update_package);//写升级结果
}
const char *MOTA_RESULT_FILE = "/data/data/com.mediatek.systemupdate/files/updateResult";
mt_main_write_result
write_result_file(MOTA_RESULT_FILE, status);
if (INSTALL_SUCCESS == result) {
set_ota_result(1); //成功写1
} else {
set_ota_result(0); //失败写0
}
int set_ota_result(int result) {
Volume *v = volume_for_path("/misc");
if (strcmp(v->fs_type, "emmc") == 0) {
LOGE("open %s to set ota result\n", v->blk_device); //add test
dev = open(v->blk_device, O_WRONLY | O_SYNC);
if (lseek(dev, OTA_RESULT_OFFSET, SEEK_SET) == -1) {
count = write(dev, &result, sizeof(result));
if (close(dev) != 0) {
}
}
上面LOGE打印的信息是:
E:open /dev/block/platform/soc/11230000.mmc/by-name/MISC to set ota result
/MISC分区就是对应设备/dev/block/platform/soc/11230000.mmc/by-name/MISC。
于此,知道OTA升级后,保存了一个标志位于/MISC分区的偏移2560里,升级完第一次启动后,读这个位置的值,得知升级结果!并且读完后,就会复位它。下次不会提示。