OTA包添加自定义内容

起因

新开一条线,需要上传的OTA包里加点内容,好让后台校验它是否是当前这条线(短期最小改动)。

开整

之前看过ota包结构,整包和差分包里都有一个payload_properties.txt文件,所以最简单的就是给这个txt文件里追加点自定义内容,然后测试上传ota包到发布平台上之后,后端通过命令读取这个标志校验,如果校验成功,即可点击发布。
既然思路清楚了,那瞅瞅payload_properties.txt的内容是在哪开始写入的。

grep -rn "payload_properties.txt" *

发现在ota_from_target_files.py里有如下这段代码

 def Sign(self, payload_signer):
    """Generates and signs the hashes of the payload and metadata.

    Args:
      payload_signer: A PayloadSigner() instance that serves the signing work.

    Raises:
      AssertionError: On any failure when calling brillo_update_payload script.
    """
    assert isinstance(payload_signer, PayloadSigner)

    # 1. Generate hashes of the payload and metadata files.
    payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
    metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
    cmd = ["brillo_update_payload", "hash",
           "--unsigned_payload", self.payload_file,
           "--signature_size", str(payload_signer.maximum_signature_size),
           "--metadata_hash_file", metadata_sig_file,
           "--payload_hash_file", payload_sig_file]
    self._Run(cmd)

    # 2. Sign the hashes.
    signed_payload_sig_file = payload_signer.Sign(payload_sig_file)
    signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file)

    # 3. Insert the signatures back into the payload file.
    signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
                                              suffix=".bin")
    cmd = ["brillo_update_payload", "sign",
           "--unsigned_payload", self.payload_file,
           "--payload", signed_payload_file,
           "--signature_size", str(payload_signer.maximum_signature_size),
           "--metadata_signature_file", signed_metadata_sig_file,
           "--payload_signature_file", signed_payload_sig_file]
    self._Run(cmd)

    # 4. Dump the signed payload properties.
    properties_file = common.MakeTempFile(prefix="payload-properties-",
                                          suffix=".txt")
    cmd = ["brillo_update_payload", "properties",
           "--payload", signed_payload_file,
           "--properties_file", properties_file]
    self._Run(cmd)

    if self.secondary:
      with open(properties_file, "a") as f:
        f.write("SWITCH_SLOT_ON_REBOOT=0\n")

    if OPTIONS.wipe_user_data:
      with open(properties_file, "a") as f:
        f.write("POWERWASH=1\n")

    self.payload_file = signed_payload_file
    self.payload_properties = properties_file

可以看到最后这里有创建payload_properties.txt,并往里面写入的操作,那在这之前,我们可以加上标志

  # 4. Dump the signed payload properties.
    properties_file = common.MakeTempFile(prefix="payload-properties-",
                                          suffix=".txt")
    cmd = ["brillo_update_payload", "properties",
           "--payload", signed_payload_file,
           "--properties_file", properties_file]
    self._Run(cmd)
    with open(properties_file, "a") as f:
        f.write("Platform_API=1\n")

    if self.secondary:
      with open(properties_file, "a") as f:
        f.write("SWITCH_SLOT_ON_REBOOT=0\n")

    if OPTIONS.wipe_user_data:
      with open(properties_file, "a") as f:
        f.write("POWERWASH=1\n")

    self.payload_file = signed_payload_file
    self.payload_properties = properties_file

编译OTA 整包和差分包,解压后,发现payload_properties.txt里多了这一行,并且也丝毫没有影响正常升级。

读取

unzip -p oriUpdate.zip payload_properties.txt

如下图:
在这里插入图片描述
收工!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一段OTA添加镜像的代码示例: ```java import android.content.Context; import android.os.Build; import android.os.Environment; import android.os.StatFs; import android.util.Log; import android.webkit.MimeTypeMap; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class OTAPackageAddImage { private static final String TAG = "OTAPackageAddImage"; private static final int BUFFER_SIZE = 1024 * 1024; private static final int TIME_OUT = 60 * 1000; private static final String OTA_FOLDER_NAME = "ota"; private static final String OTA_UPDATE_FILE_NAME = "update.zip"; private static final String OTA_MD5_FILE_NAME = "update.zip.md5sum"; private static final String OTA_IMAGE_FOLDER_NAME = "image"; private static final String OTA_IMAGE_FILE_NAME = "new_image.img"; private static final String OTA_IMAGE_MD5_FILE_NAME = "new_image.img.md5sum"; public static void addImageToOTAPackage(Context context, String imageUrl) { try { // 获取OTA文件夹路径 File otaFolder = new File(Environment.getExternalStorageDirectory(), OTA_FOLDER_NAME); if (!otaFolder.exists()) { otaFolder.mkdirs(); } // 下载新的镜像文件 File newImageFile = downloadFile(imageUrl, otaFolder, OTA_IMAGE_FILE_NAME, OTA_IMAGE_MD5_FILE_NAME); // 获取OTA文件路径 File otaFile = new File(otaFolder, OTA_UPDATE_FILE_NAME); // 获取OTA镜像文件夹路径 File imageFolder = new File(otaFolder, OTA_IMAGE_FOLDER_NAME); if (!imageFolder.exists()) { imageFolder.mkdirs(); } // 将新的镜像文件复制到OTA镜像文件夹中 File imageFile = new File(imageFolder, OTA_IMAGE_FILE_NAME); copyFile(newImageFile, imageFile); // 生成OTAMD5文件 generateMD5File(otaFile, otaFolder, OTA_MD5_FILE_NAME); // 生成OTA描述文件 generateDescFile(context, otaFolder); } catch (Exception e) { Log.e(TAG, "addImageToOTAPackage error: " + e.getMessage()); } } private static File downloadFile(String urlStr, File folder, String fileName, String md5FileName) throws IOException { // 创建URL对象 URL url = new URL(urlStr); // 创建HttpURLConnection对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(TIME_OUT); conn.setReadTimeout(TIME_OUT); // 获取文件长度 int length = conn.getContentLength(); // 创建输入流 InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); // 创建输出流 File file = new File(folder, fileName); FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos); // 缓存数组 byte[] buffer = new byte[BUFFER_SIZE]; // 已经下载的长度 int downloadedLength = 0; // 读取数据并写入文件 int len; while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); downloadedLength += len; } // 关闭流 bos.flush(); bos.close(); fos.flush(); fos.close(); bis.close(); is.close(); // 验证文件MD5值 String md5 = getFileMD5(file); File md5File = new File(folder, md5FileName); if (md5File.exists()) { String md5sum = readTextFile(md5File); if (!md5.equals(md5sum.trim())) { throw new IOException("MD5 checksum not match"); } } else { generateMD5File(file, folder, md5FileName); } return file; } private static void copyFile(File srcFile, File dstFile) throws IOException { // 创建输入流 FileInputStream fis = new FileInputStream(srcFile); BufferedInputStream bis = new BufferedInputStream(fis); // 创建输出流 FileOutputStream fos = new FileOutputStream(dstFile); BufferedOutputStream bos = new BufferedOutputStream(fos); // 缓存数组 byte[] buffer = new byte[BUFFER_SIZE]; // 读取数据并写入文件 int len; while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); } // 关闭流 bos.flush(); bos.close(); fos.flush(); fos.close(); bis.close(); fis.close(); } private static String getFileMD5(File file) throws IOException { if (!file.isFile()) { throw new IOException("cannot get file md5, file is not a file"); } MessageDigest md5; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { throw new IOException("cannot get file md5, message digest error"); } FileInputStream fis = new FileInputStream(file); byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = fis.read(buffer)) != -1) { md5.update(buffer, 0, length); } fis.close(); byte[] md5Bytes = md5.digest(); StringBuilder sb = new StringBuilder(); for (byte b : md5Bytes) { sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3)); } return sb.toString(); } private static String readTextFile(File file) throws IOException { StringBuilder sb = new StringBuilder(); FileInputStream fis = new FileInputStream(file); byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = fis.read(buffer)) != -1) { sb.append(new String(buffer, 0, length)); } fis.close(); return sb.toString(); } private static void generateMD5File(File file, File folder, String fileName) throws IOException { String md5 = getFileMD5(file); File md5File = new File(folder, fileName); FileOutputStream fos = new FileOutputStream(md5File); fos.write(md5.getBytes()); fos.flush(); fos.close(); } private static void generateDescFile(Context context, File folder) throws IOException { // 获取OTA描述文件路径 File descFile = new File(folder, "desc.txt"); // 获取OTA文件路径 File otaFile = new File(folder, OTA_UPDATE_FILE_NAME); // 获取OTA镜像文件夹路径 File imageFolder = new File(folder, OTA_IMAGE_FOLDER_NAME); // 获取OTA镜像文件路径 File imageFile = new File(imageFolder, OTA_IMAGE_FILE_NAME); // 获取OTA文件长度 long fileSize = otaFile.length(); // 获取OTA镜像文件长度 long imageFileSize = imageFile.length(); // 获取OTA版本号 String versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; // 获取OTA安卓版本 String androidVersion = Build.VERSION.RELEASE; // 获取OTAABI类型 String abiType = Build.CPU_ABI; // 获取OTA构建类型 String buildType = Build.TYPE; // 获取OTA描述文件内容 StringBuilder sb = new StringBuilder(); sb.append("version=" + versionName + "\n"); sb.append("file_size=" + fileSize + "\n"); sb.append("image_file_size=" + imageFileSize + "\n"); sb.append("android_version=" + androidVersion + "\n"); sb.append("abi_type=" + abiType + "\n"); sb.append("build_type=" + buildType + "\n"); // 获取OTA镜像文件类型 String extension = MimeTypeMap.getFileExtensionFromUrl(imageFile.getAbsolutePath()); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); // 获取OTA镜像文件描述信息 Map<String, String> imageDescMap = new HashMap<>(); imageDescMap.put("partition_type", "raw"); imageDescMap.put("partition_name", "new_image"); imageDescMap.put("filename", imageFile.getName()); imageDescMap.put("filesize", String.valueOf(imageFile.length())); imageDescMap.put("filetype", mimeType); // 将OTA镜像文件描述信息添加OTA描述文件中 sb.append("image_desc="); for (Map.Entry<String, String> entry : imageDescMap.entrySet()) { sb.append(entry.getKey() + "=" + entry.getValue() + ","); } sb.deleteCharAt(sb.length() - 1); sb.append("\n"); // 将OTA描述文件写入文件 FileOutputStream fos = new FileOutputStream(descFile); fos.write(sb.toString().getBytes()); fos.flush(); fos.close(); } } ``` 这段代码可以实现从指定URL下载一个新的镜像文件,然后将其添加OTA中。同时,还会生成OTA的MD5文件和描述文件。请注意,这只是一个示例代码,您需要根据您的具体需求进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值