App更新提示的目的:
由于系統(tǒng)開機(jī)的時候會做一些比較耗時的操作剩拢, 如果一直顯示開機(jī)動畫, 則會導(dǎo)致用戶感覺整個開機(jī)流程時間太長瓢阴, 系統(tǒng)通過顯示特定的提示語句來降低用戶對開機(jī)時間過長的負(fù)面體驗.
特別耗時的操作:
解壓App络拌, 一個App是不能直接加載到內(nèi)存里運(yùn)行的鬼癣, 但是提前對App做處理之后饵骨, 可以直接把相關(guān)的文件直接加載到內(nèi)存中.可以降低App首次啟動的時間.
代碼級分析情景:
1:優(yōu)化數(shù)據(jù)存儲
一般的復(fù)現(xiàn)步驟: 關(guān)機(jī)時間超過3天翘悉, 系統(tǒng)會去做存儲空間的優(yōu)化[由于系統(tǒng)一般在凌晨的時候做這種優(yōu)化, 理論上開機(jī)設(shè)置重啟不會碰到這個情況]
2:更新了系統(tǒng)居触, 需要更新
進(jìn)行了OTA升級妖混, 如果升級到相關(guān)的核心組件, 例如÷盅蟆framework.jar制市, 則會導(dǎo)致大部分的APP都需要優(yōu)化.
3:偶爾出現(xiàn)
這個是art虛擬機(jī)判斷某些APP的緩存文件過期, 則會再次進(jìn)行更新.
4: ART級別的重啟類似于V1上重啟的原因
原理同V1是一樣的弊予, 每次開機(jī)息堂, ART虛擬機(jī)會記錄一次開機(jī)次數(shù)块促, 如果連續(xù)10次開機(jī)失敗, 則刪除所有的緩存文件床未, 下次開機(jī)會出現(xiàn)轉(zhuǎn)圈的問題.
5: 開機(jī):
測試提到某些機(jī)器開機(jī)出現(xiàn)轉(zhuǎn)圈竭翠, 某些機(jī)器開機(jī)不出現(xiàn)轉(zhuǎn)圈.
原理:
系統(tǒng)會判斷是否是第一次開機(jī), 如果是第一次開機(jī)則不轉(zhuǎn)圈, 那么問題就出在是否是第一次開機(jī).
如果 /data/system/packages.xml 或 /data/system/packages_backup.xml 文件存在, 則認(rèn)為機(jī)器不是第一次開機(jī).
這個文件在開機(jī)掃描APP的過程中生產(chǎn), 這個文件生產(chǎn)之后才進(jìn)行APK的優(yōu)化.
復(fù)現(xiàn)步驟:
機(jī)器第一次開機(jī), 開機(jī)進(jìn)行到一半的時候, 這個時候 /data/system/packages.xml 已經(jīng)生成, 但是APK還沒有優(yōu)化完畢, 這個時候強(qiáng)制關(guān)機(jī), 然后再開機(jī), 下次轉(zhuǎn)圈是必現(xiàn)的.
以下是代碼分析的關(guān)鍵流程:
1: CustomDialog.show
PhoneWindowManager.showBootMessage
WindowManagerService.showBootMessage
- mAllowBootMessages [mFirstBoot] PackageManagerService - packages.xml and packages-backup.xml [always] [mSystemBooted]
- mShowingBootMessages
- mSystemBooted
ActivityManagerService.showBootMessage(****, [false])
- PreBootContinuation [正在準(zhǔn)備升級***]
- Intent.ACTION_PRE_BOOT_COMPLETEDS
- [即將完成啟動]
- PackageManagerService.performBootDexOpt() [1: mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();]
- isUpgrade (Build.FINGERPRINT) && !isFirstBoot()
- [正在優(yōu)化存儲空間] [true]
- mPackageDexOptimizer -> sortedPkgs
- filterRecentlyUsedApps (sortedPkgs)
- PackageManagerService.performBootDexOpt(PackageParser.Package pkg, int curr, int total)
- !isFirstBoot()
- [*-**][true]
- ActivityManagerNative.getDefault().showBootMessage[正在啟動應(yīng)用] SystemServer
以下是ART虛擬機(jī)的判斷APP是否需要更新的邏輯:
// TODO: Verify the dex location is well formed, and throw an IOException if
// not?
OatFileAssistant oat_file_assistant(filename, target_instruction_set, false, pkgname);
// Always treat elements of the bootclasspath as up-to-date.
if (oat_file_assistant.IsInBootClassPath()) {∞备椤framework更新
return OatFileAssistant::kNoDexOptNeeded;
}
// TODO: Checking the profile should probably be done in the GetStatus()
// function. We have it here because GetStatus() should not be copying
// profile files. But who should be copying profile files?
if (oat_file_assistant.OdexFileIsOutOfDate()) { 文件緩存超時
// Needs recompile if profile has changed significantly.
if (Runtime::Current()->GetProfilerOptions().IsEnabled()) {
if (oat_file_assistant.IsProfileChangeSignificant()) {
if (!defer) {
oat_file_assistant.CopyProfileFile();
}
return OatFileAssistant::kDex2OatNeeded;
} else if (oat_file_assistant.ProfileExists()
&& !oat_file_assistant.OldProfileExists()) { 緩存文件是否存在
if (!defer) {
oat_file_assistant.CopyProfileFile();
}
}
}
}
return oat_file_assistant.GetDexOptNeeded();
PS: 以上是基于android6.0源碼進(jìn)行分析的.
還有就是 我的flyme 每次更新都會提示更新APP斋扰, 理論上 MIUI 和 華為 應(yīng)該都不會去修改這部分邏輯.