Android旧式的系统升级是在Recover模式下将U盘里面的update.zip升级包进行安装,这种方式不是特别的安全,如果升级过程中出现掉电,或者其他升级错误,容易造成机器变成砖,只能通过烧录才能修复。现在已使用全新的一套升级系统update_engine,这套系统的加入使原有的Recover变得多余,但是为了向下兼容和恢复出厂设置需要使用所以还保留了Recover模块。update_engine升级思路是A/B升级模式,意思就是机器上有两套可引导系统,如果目前运行的是A系统则通过A引导升级B系统,如果是B系统则引导升级A系统。这样能保证手机不会变成砖,就算升级失败,那也还是原来的系统。升级过程后台运行,不影响用户使用。要想深入学习需要做大量功课,以下一个成功的demo。
模块路径:system/update_engine
测试程序:system/update_engine/update_engine_client_android.cc
测试模块是否打通:
- 制作升级包make otapackage
- 解压升级包out\target\product\product\update.zip
- 提取payload.bin、payload_properties.txt放置到指定下载路径或者U盘
- FILE_HASH、FILE_SIZE、METADATA_HASH这些参数在payload_properties.txt文件中
- --payload=可以是HTTP形式的URL,直接进行OTA
- 特别要注意--headers="最好在第一行,格式解析有换行的要求,不然参数传不下去
测试指令:
- update_engine_client --payload=file:///storage/udisk/payload.bin --update --headers="
- FILE_HASH=wpG0gLjbUg3uTQ4LTnXjPfH3rvjxCPAEHzCspps28Sg=
- FILE_SIZE=589122832
- METADATA_HASH=EAlcdErle8BiZLOMZUkWAcwVYdmZc6StLfPMQE0OwE4=
- METADATA_SIZE=54970"
解析程序通过\n来进行切割,然后调用service_->applyPayload进行升级。
- if (FLAGS_update) {
- std::vector
headers = base::SplitString( - FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- std::vector
and_headers; - for (const auto& header : headers) {
- and_headers.push_back(android::String16{header.data(), header.size()});
- }
- Status status = service_->applyPayload(
- android::String16{FLAGS_payload.data(), FLAGS_payload.size()},
- FLAGS_offset,
- FLAGS_size,
- and_headers);
- if (!status.isOk())
- return ExitWhenIdle(status);
- }
如果使用测试指令能成功升级,则可以直接用java接口进行升级工作。
- package com.test.update.manager;
-
- import java.net.MalformedURLException;
- import java.net.URI;
- import java.text.DecimalFormat;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
-
- import android.os.UpdateEngine;
- import android.os.UpdateEngineCallback;
- import android.os.Build;
- import android.os.Handler;
- import android.os.Message;
- import android.net.Uri;
- import android.util.Log;
-
- public class SystemUpdateManager {
-
- public static final String ROOTDIR = "/storage/udisk/UpdatePack";
-
- public static final String PATH_PAYLOAD_BIN = ROOTDIR + "/OS/payload.bin";
- public static final String PATH_PAYLOAD_PROPERTIES = ROOTDIR + "/OS/payload_properties.txt";
-
- UpdateEngine mUpdateEngine;
-
- public SystemUpdateManager(Context context) throws MalformedURLException {
- mUpdateEngine = new UpdateEngine();
- }
-
- UpdateEngineCallback mUpdateEngineCallback = new UpdateEngineCallback {
-
- @Override
- public void onStatusUpdate(int status, float percent) {
- if (status == UpdateEngine.UpdateStatusConstants.DOWNLOADING) {// 回调状态,升级进度
- DecimalFormat df = new DecimalFormat("#");
- String progress = df.format(percent * 100);
- Log.d(TAG, "update progress: " + progress);
- if (this.mUpdateEngine != null) {
- this.mUpdateEngine.onStateOrProgress(UpdateChangeListener.MESSAGE_UPDATE_PROGRESS,
- 0, progress);
- }
- }
- }
-
- @Override
- public void onPayloadApplicationComplete(int errorCode) {
- if (errorCode == UpdateEngine.ErrorCodeConstants.SUCCESS) {// 回调状态
- Log.d(TAG, "UPDATE SUCCESS!");
- if (this.mUpdateEngine != null) {
- this.mUpdateEngine.onStateOrProgress(UpdateChangeListener.MESSAGE_WAIT_REBOOT, 0,
- null);
- }
- }
- }
-
- };
-
- public void startUpdateSystem() {
- Uri uri = Uri.fromFile(new File(PATH_PAYLOAD_BIN));
- mUpdateEngine.bind(mUpdateEngineCallback);// 绑定callback
- mUpdateEngine.applyPayload(uri.toString(), 0l, 0l, getPayloadProperties());// 进行升级
- }
-
- // 读取payload_properties.txt
- public static String[] getPayloadProperties() {
- try {
- File file = new File(PATH_PAYLOAD_PROPERTIES);
- InputStreamReader is = new InputStreamReader(new FileInputStream(file));
- BufferedReader br = new BufferedReader(is);
- List
lines = new ArrayList(); - String line = null;
- while ((line = br.readLine()) != null) {
- Log.d(TAG, "getPayloadProperties line: " + line);
- lines.add(line);
- }
- br.close();
- is.close();
- return lines.toArray(new String[lines.size()]);
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- }
数据通常是在两个站(点对点)之间进行传输,按照数据流的方向可分为三种传输模式:单
工、半双工、全双工。
一、单工通信(simplex)
单工通信只支持信号在一个方向上传输(正向或反向),任何时候不能改变信号的传输方向。
为保证正确传送数据信号,接收端要对接收的数据进行校验,若校验出错,则通过监控信道发
送请求重发的信号。
此种方式适用于数据收集系统,如气象数据的收集、电话费的集中计算等。
例如计算机和打印机之间的通信是单工模式,因为只有计算机向打印机传输数据,而没有相反
方向的数据传输。还有在某些通信信道中,如单工无线发送等。
二、半双工通信(half-duplex)
半双工通信允许信号在两个方向上传输,但某一时刻只允许信号在一个信道上单向传输。
因此,半双工通信实际上是一种可切换方向的单工通信。
此种方式适用于问讯、检索、科学计算等数据通信系统;
传统的对讲机使用的就是半双工通信方式。由于对讲机传送及接收使用相同的频率,不允许同
时进行。因此一方讲完后,需设法告知另一方讲话结束(例如讲完后加上’OVER’),另一方
才知道可以开始讲话。
三、全双工(full-duplex)
全双工通信允许数据同时在两个方向上传输,即有两个信道,因此允许同时进行双向传输。
全双工通信是两个单工通信方式的结合,要求收发双方都有独立的接收和发送能力。
全双工通信效率高,控制简单,但造价高。
计算机之间的通信是全双工方式。一般的电话、手机也是全双工的系统,因为在讲话时可以听到对方的声音。
总结
通常四线线路实现全双工数据传输,二线线路实现单工或半双工数据传输。在采用频分法、时间压缩法、回波抵消技术时,二
线线路也可实现全双工数据传输。
评论记录:
回复评论: