主要文件說(shuō)明
- MainEntry : 主界面
- SystemUpdateService:版本檢測(cè)服務(wù)蔗喂,
- SessionStateControlThread:去執(zhí)行檢測(cè)和下載的線程忘渔;
- HttpManager:網(wǎng)絡(luò)請(qǐng)求的發(fā)起和數(shù)據(jù)解析,版本檢測(cè)狀態(tài)通知的發(fā)出者
- OtaPkgManagerActivity:顯示版本狀態(tài)缰儿,下載和安裝的入口
- DownloadInfo 狀態(tài)的保存與查詢接口
- SystemUpdateRecever 廣播接收器畦粮,開機(jī)自動(dòng)檢測(cè)版本等
主要流程
MainEntry 在啟動(dòng)時(shí)綁定服務(wù),并調(diào)用SystemUpdateService 的版本查詢接口
@Override
protected void onStart()
{
...
if (activityId < 0) {
SdPkgInstallActivity.stopSelf();
OtaPkgManagerActivity.stopSelf();
Intent serviceIntent = new Intent(this, SystemUpdateService.class);
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
} }
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((SystemUpdateService.ServiceBinder) service).getService();
if (mService != null) {
mService.setHandler(mUiHandler);
}
boolean needRescan = mDownloadInfo.getIfNeedRefresh();
if (needRescan
|| (!loadHistoryPackage()
&& DownloadInfo.STATE_NEWVERSION_READY
!= mDownloadInfo.getDLSessionStatus())) {
queryPackagesInternal();
} else {
Xlog.d(TAG, "[onServiceConnected], DON'T need query, load from file");
refreshUI();
}
}
};
private void queryPackagesInternal() {
...
if (mService != null) {
mService.queryPackages();
}
}
SystemUpdateServcie 啟動(dòng)線程去執(zhí)行版本的檢查,
SessionControlThread 的執(zhí)行方法如下乖阵,它負(fù)責(zé)查詢和下載的具體任務(wù)宣赔。
查詢線程啟動(dòng)HttpManager 中的查詢接口checkNewVersion,訪問(wèn)OTA服務(wù)器瞪浸,并對(duì)查詢結(jié)果進(jìn)行解析儒将,如果有新版本信息,就會(huì)更新DownloadInfo中的狀態(tài)值对蒲,然后發(fā)送查詢結(jié)束的廣播钩蚊。
private boolean checkNewVersion() {
...
HttpResponse response = doPost(url, null, bnvpa);
if (response == null) {
Xlog.i(TAG, "onCheckNewVersion: response = null");
mErrorCode = HTTP_UNKNOWN_ERROR;
return false;
}
StatusLine status = response.getStatusLine();
...
String content = getChunkedContent(response.getEntity());
...解析服務(wù)器返回的數(shù)據(jù)
HttpResponseContent res = parseCheckVersionInfo(content);
if (res == null) {
return false;
}
if (res.mFileSize <= 0 || res.mPkgId < 0) {
mErrorCode = HTTP_RESPONSE_NO_NEW_VERSION;
Xlog.i(TAG, "onCheckNewVersion, fileSize = " + res.mFileSize + ", deltaId = "
+ res.mPkgId);
return false;
}
if ((!res.mIsFullPkg) && (!checkFingerPrint(res.mFingerprint))) {
mErrorCode = HTTP_RESPONSE_NO_NEW_VERSION;
return false;
}
mDownloadInfo.setDLSessionDeltaId(res.mPkgId);
mDownloadInfo.setFullPkgFlag(res.mIsFullPkg);
mDownloadInfo.setUpdateImageSize(res.mFileSize);
mDownloadInfo.setVersionNote(res.mReleaseNote);
mDownloadInfo.setVerNum(res.mVersionName);
mDownloadInfo.setAndroidNum(res.mAndroidNum);
mDownloadInfo.setDLSessionStatus(DownloadInfo.STATE_NEWVERSION_READY);
return true;
} catch (IOException e) {
e.printStackTrace();
mErrorCode = HTTP_RESPONSE_AUTHEN_ERROR;
return false;
}
}
HttpMangager 發(fā)送查詢結(jié)束的廣播后,EntryActivity 收到此廣播蹈矮,更新UI,顯示由新版本砰逻。
private Handler mUiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case SystemUpdateService.MSG_NOTIFY_QUERY_DONE:
processOtaBehavior();
break;
刷新界面,跳轉(zhuǎn)到OtaPkgManagerActivity含滴,此時(shí)顯示界面上的更新記錄和下載按鈕诱渤,點(diǎn)擊下載按鈕后丐巫,
private void refreshUI() {
int size = (mUpdateInfoList == null) ? 0 : mUpdateInfoList.size();
mParentPreference.removeAll();
boolean isOtaExist = isOtaPackageExist();
if (isOtaExist || size > 0) {
mIsFoundNewVersion = true;
if (mIsStopping && mIsQuerying) {
Xlog.v(TAG, "[refreshUI] is stopping, show notification instead");
mNotification.showNewVersionNotification();
mIsFoundNewVersion = false;
return;
}
mIsQuerying = false;
}
if (isOtaExist) {
if (size == 0) {
Xlog.v(TAG, "[refreshUI] Only OTA package exists, start OTA detail");
Intent intent = getInfoIntent(null);
mIsTurnToDetail = true;
startActivity(intent);
finish();
return;
}
在OtaPackageManagerActivity一啟動(dòng)谈况,就會(huì)根據(jù)DownloadInfo中的狀態(tài)值來(lái)顯示相應(yīng)的界面和進(jìn)行相應(yīng)的處理。上一步查詢到有新版本的時(shí)候递胧,已經(jīng)把狀態(tài)設(shè)置為STATE_NEWVERSION_READY了碑韵,這里就會(huì)顯示下載按鈕。下載的動(dòng)作又會(huì)回到SystemUpdateService中的 startDlPkg()接口缎脾,啟動(dòng)一個(gè)SessionControlThread 進(jìn)行下載祝闻,下載的網(wǎng)絡(luò)處理還是由HttpManager 來(lái)處理,實(shí)際操作在onDownloadImage()中
private void showUILayout(int state) {
switch (state) {
case DownloadInfo.STATE_QUERYNEWVERSION:
requeryPackages();
break;
case DownloadInfo.STATE_NEWVERSION_READY:
setContentView(R.layout.ota_package_download);
mDownloadBtn = (Button) this.findViewById(R.id.btn_download);
mDownloadBtn.setText(R.string.btn_download);
mDownloadBtn.setOnClickListener(mDlListener);
removeProBar();
mMenuStatus = MenuStatus.Menu_Download;
invalidateOptionsMenu();
initWifiOnlyCheckbox(true, true);
fillPkgInfo(mDownloadInfo.getAndroidNum(), mDownloadInfo.getVerNum(), mDownloadInfo.getUpdateImageSize(),
Util.getPackageFileName(this));
break;
case DownloadInfo.STATE_DOWNLOADING:
showDlInterface();
break;
void onDownloadImage() {
mNotification.showDownloadingNotificaton(mDownloadInfo.getVerNum(), (int) (((double) Util
.getFileSize(Util
.getPackageFileName(mContext)) / (double) mDownloadInfo
.getUpdateImageSize()) * 100), true);
if (mIsDownloading) {
return;
}
mIsDownloading = true;
notifyDlStarted();
boolean isunzip = mDownloadInfo.getDLSessionUnzipState();
boolean isren = mDownloadInfo.getDLSessionRenameState();
if (isren && isunzip) {
setNotDownload();
UpgradePkgManager.deleteCrashPkgFile(Util.getPackagePathName(mContext));
onDownloadPackageUnzipAndCheck();
return;
}
mDownloadInfo.setDLSessionStatus(DownloadInfo.STATE_DOWNLOADING);
String strNetWorkType = mDownloadInfo.getIfWifiDLOnly() ? NETTYPE_WIFI : "";
if (!Util.isNetWorkAvailable(mContext, strNetWorkType)) {
mErrorCode = HTTP_RESPONSE_NETWORK_ERROR;
sendErrorMessage();
setPauseState();
setNotDownload();
return;
}
HttpResponse response = doPost(url, null, bnvpa);
if (mDownloadInfo.getDLSessionStatus() != DownloadInfo.STATE_DOWNLOADING) {
Xlog.i(TAG, "onDownloadImage: status not right");
setNotDownload();
return;
}
...
StatusLine status = response.getStatusLine();
Intent service = new Intent(mContext, SystemUpdateService.class);
service.setAction(Util.Action.ACTION_LCA_PROTECT);
mContext.startService(service);
int ret = writeFile(response, currentSize);
mContext.stopService(service);
// Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
Xlog.i(TAG, "onDownloadImage, download result = " + ret);
if (ret == 0) {
int downloadStatus = mDownloadInfo.getDLSessionStatus();
if (downloadStatus == DownloadInfo.STATE_PAUSEDOWNLOAD
|| downloadStatus == DownloadInfo.STATE_QUERYNEWVERSION) {
setNotDownload();
return;
}
}
if (ret == HTTP_DETECTED_SDCARD_CRASH_OR_UNMOUNT) {
// resetDescriptionInfo();
resetDownloadFile();
sendErrorMessage();
setNotDownload();
return;
}
if (ret == HTTP_RESPONSE_NETWORK_ERROR) {
setNotDownload();
checkIfAutoDl();
return;
}
if (ret == HTTP_FILE_NOT_EXIST) {
setNotDownload();
return;
}
onDownloadPackageUnzipAndCheck();
mIsDownloading = false;
}
在下載完成后進(jìn)行包的解壓和校驗(yàn)工作,成功后進(jìn)入安裝步驟联喘,安裝時(shí)啟動(dòng)的另外一個(gè)App中的服務(wù)华蜒,然后重啟系統(tǒng),進(jìn)入recovery模式豁遭,完成系統(tǒng)升級(jí)叭喜。
class InstallPkgThread extends Thread {
/**
* Main executing function of this thread.
*/
public void run() {
if (checkUpgradePackage() && setInstallInfo(mPkgPath, mTarVer)) {
notifyUserInstall();
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.mediatek.systemupdate.sysoper",
"com.mediatek.systemupdate.sysoper.RebootRecoveryService"));
startService(intent);
} else {
return;
}
}
}
private boolean setInstallInfo(String strPkgPath, String strTarVer) {
Xlog.i(TAG, "onSetRebootRecoveryFlag");
try {
IBinder binder = ServiceManager.getService("GoogleOtaBinder");
SystemUpdateBinder agent = SystemUpdateBinder.Stub.asInterface(binder);
if (agent == null) {
Xlog.e(TAG, "agent is null");
return false;
}
if (Util.isEmmcSupport()) {
if (!agent.clearUpdateResult()) {
Xlog.e(TAG, "clearUpdateResult() false");
return false;
}
}
DownloadInfo dlInfo = DownloadInfo.getInstance(getApplicationContext());
dlInfo.setTargetVer(strTarVer);
Xlog.i(TAG, "setTargetVer");
if (!agent.setRebootFlag()) {
Xlog.e(TAG, "setRebootFlag() false");
return false;
}
Xlog.i(TAG, "setRebootFlag");
dlInfo.setUpgradeStartedState(true);
dlInfo.resetDownloadInfo();
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.mediatek.systemupdate.sysoper",
"com.mediatek.systemupdate.sysoper.WriteCommandService"));
intent.putExtra(COMMAND_PART2, OTA_PATH_IN_RECOVERY_PRE + strPkgPath);
startService(intent);
return true;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}
其中,在SystemUpdateRecever中會(huì)接收系統(tǒng)開機(jī)廣播蓖谢,并判斷是周幾捂蕴,然后根據(jù)util中的配置信息,自動(dòng)檢測(cè)版本闪幽。