RK3326 android10.0(Q) OTA 实战

175 阅读3分钟

编译指令

发布一个固件正确的顺序

1、make -j32

2、make otapackage -j32

3、./mkimage.sh ota

4、./build.sh -u

或者直接执行

make -j32 && make otapackage -j32 && ./mkimage.sh ota && ./build.sh -u

拷贝 rockdev\Image-RK3326Box\update.img 作为发放烧写软件包

直接用 AndroidTool_Release 烧写固件即可

整包升级

拷贝 \out\target\product\RK3326Box\RK3326Box-ota-eng.zip 作为完整升级包,

重命名为 update.zip 拷贝到设备SDCard卡根目录重启,RKUpdateService-box 应用会弹框提示升级

差分包升级

拷贝 out\target\product\RK3326Box\obj\PACKAGING\target_files_intermediates\RK3326Box-target_files-eng.zip 为 V1.zip,作为 V1 版本的基础素材包备用,拷贝至源码根目录

修改kernel、package等 新版本修改内容后再次执行编译指令

make -j32 && make otapackage -j32 && ./mkimage.sh ota && ./build.sh -u

拷贝 out\target\product\RK3326Box\obj\PACKAGING\target_files_intermediates\RK3326Box-target_files-eng.zip 为 V2.zip,作为 V2 版本的基础素材包备用,拷贝至源码根目录

编译生成差分包指令

./build/tools/releasetools/ota_from_target_files -v -i V1.zip  --block  -p out/host/linux-x86 -k build/target/product/security/testkey V2.zip  update.zip

更目录下的 update.zip 就是最终的差分升级包

生成差异包命令格式:

ota_from_target_files

-v -i 用于比较的前一个 target file

--block 使用 block 方式进行 OTA 升级,Android 版本>=7.1 时需加上这个参数

-p host 主机编译环境

-k 打包密钥 用于比较的后一个 target file 生成的 ota 差异包

调用系统升级API RecoverySystem.installPackage

SystemUpgradeHelper.java

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import android.R.string;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RecoverySystem;
import android.os.RemoteException;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import android.os.ServiceManager;


public class SystemUpgradeHelper {

	private Context context;
	private ProgressDialog verifyPackageProgressDialog = null;
	private String internalSdPath = "/data/media/";
	private File otaFile = null;
	private String TAG = new String("SystemUpgradeHelper:");

	public SystemUpgradeHelper(Context context, File file) {
		this.context = context;
		verifyPackageProgressDialog = new ProgressDialog(context);
		verifyPackageProgressDialog
				.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		verifyPackageProgressDialog.setTitle(context
				.getString(R.string.txtVerifying));
		verifyPackageProgressDialog.setMessage(context
				.getString(R.string.txtVerifyWarning));

		verifyPackageProgressDialog.setMax(100);
		verifyPackageProgressDialog.setProgress(0);
		verifyPackageProgressDialog.setSecondaryProgress(0);
		verifyPackageProgressDialog.setIndeterminate(false);
		verifyPackageProgressDialog.setCancelable(false);
		if (file == null) {
			this.otaFile = new File(internalSdPath + "/update.zip");
		} else {
			this.otaFile = file;
		}
	}


	Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			String msg_buf = null;
			switch (msg.what) {
				case 1:
					msg_buf = context.getString(R.string.txtRamFull);
					break;
				case 2:
					msg_buf = context.getString(R.string.txtUpgradeFail);
					break;
				case 3:
					msg_buf = context.getString(R.string.txtFileNotExist);
					break;
				case 4:
					msg_buf = context.getString(R.string.txtVerifyFail);
					break;
				default:
					break;
			}
			if (msg_buf != null)
				Toast.makeText(context, msg_buf, Toast.LENGTH_SHORT).show();
			super.handleMessage(msg);
		}
	};
	

	public void excuteUpdateZip() {
		final Message msg = new Message();
		msg.what = 0;
		verifyPackageProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
		verifyPackageProgressDialog.show();

		new Thread() {
			public void run() {
				try {
					Thread.sleep(3000);
					onConfirmUpdate();
				} catch (Exception ex) {
					verifyPackageProgressDialog.dismiss();
					msg.what = 1;
					mHandler.sendMessage(msg);
					Log.i(TAG, "Start Thread Error", ex);
				}
			}

			private void onConfirmUpdate() {
				try {
					RecoverySystem.verifyPackage(otaFile,
							new RecoverySystem.ProgressListener() {
								@Override
								public void onProgress(int progress) {
									verifyPackageProgressDialog.setProgress(progress);
								}
							}, null);
					Log.i(TAG, "verifyPackage is completed and it ok");
					
					try {
						Log.i(TAG, "It will install package");
						RecoverySystem.installPackage(context, otaFile);
					} catch (Exception e) {
						e.printStackTrace();
						Log.i(TAG, "installPackage Error", e);
						msg.what = 2;
						mHandler.sendMessage(msg);
					}
				} catch (IOException e) {
					verifyPackageProgressDialog.dismiss();
					e.printStackTrace();
					msg.what = 3;
					mHandler.sendMessage(msg);
				} catch (GeneralSecurityException e) {
					verifyPackageProgressDialog.dismiss();
					e.printStackTrace();
					msg.what = 4;
					mHandler.sendMessage(msg);
				}
			}
		}.start();
	}

}

错误排查

wPYTG6.png

完整包并未遇到该问题

在升级差分包时,出现了上图所示的错误

错误代码

E3001 this device has unknown/RK3326Box/....:userdebug/test-keys

E:Error in @/cache/recovery/block.map(status 7)

开始其实提示的是 E3001 this device has unknown/RK3326Box/....:userdebug/release-keys

去签名文件夹下中寻找 \build\target\product\security 确实没有 releasekey 相关

于是猜想和这里有关系,修改编译使用 test-keys

build/make/core/Makefile

 ifeq ($(TARGET_BUILD_VARIANT),eng)
 BUILD_KEYS := test-keys
 else
-BUILD_KEYS := release-keys
+# BUILD_KEYS := release-keys
+BUILD_KEYS := test-keys
 endif
 
 BUILD_VERSION_TAGS += $(BUILD_KEYS)

编译后可以通过 out\target\product\RK3326Box\system\build.prop 文件中 ro.system.build.tags=test-keys 确认

再次烧写ota升级验证,发现问题依旧,仔细品了品错误提示后发现 build fingerprint 这个关键字

机智的我立马去和 8.0 的 build.prop 进行了对比,最终发现差异

Q 版本

ro.system.build.fingerprint=rockchip/RK3326Box/RK3326Box:10/QQ2A.200501.001.B3/09021634:userdebug/test-keys

O版本 ro.build.fingerprint=rockchip/rk3288/rk3288:8.1.0/OPM8.190305.001/133946:userdebug/test-keys

Q版本中不存在 ro.build.fingerprint 字段,会不会和这有关系呢?先加上试试吧

搜索 ro.system.build.fingerprin 发现在 build/make/tools/buildinfo_common.sh 中进行写入

我们新增一条 ro.build.fingerprint

+++ b/build/make/tools/buildinfo_common.sh
@@ -13,6 +13,7 @@ echo "# autogenerated by $0"
 echo "ro.${partition}.build.date=`$DATE`"
 echo "ro.${partition}.build.date.utc=`$DATE +%s`"
 echo "ro.${partition}.build.fingerprint=$BUILD_FINGERPRINT"
+echo "ro.build.fingerprint=$BUILD_FINGERPRINT"
 echo "ro.${partition}.build.id=$BUILD_ID"
 echo "ro.${partition}.build.tags=$BUILD_VERSION_TAGS"
 echo "ro.${partition}.build.type=$TARGET_BUILD_TYPE"

再次重新编译烧写ota问题解决,升级成功啦!

参考文章

OTA升级失败排查

Android系统更新防互刷功能实现与分析