首页 > 其他分享 >记一次原生AB分区OTA升级实现

记一次原生AB分区OTA升级实现

时间:2024-07-12 14:41:27浏览次数:12  
标签:原生 AB int OTA update public code static final

记一次原生AB分区OTA升级实现

系统需要实现软件ota功能

具体代码实现

UpdateEngine mUpdateEngine = new UpdateEngine();
UpdateParser.ParsedUpdate mParsedUpdate;
try {
    mParsedUpdate = UpdateParser.parse(new File(Environment.getDataDirectory(), "ota_package/update.zip"));
    Log.d(TAG,"mParsedUpdate = " + mParsedUpdate);
} catch (IOException e) {
    throw new RuntimeException(e);
}
if (!mParsedUpdate.isValid()){
    return;
}
mUpdateEngine.bind(new UpdateEngineCallback() {
    @Override
    public void onStatusUpdate(int status, float percent) {
        Log.d(TAG,"onStatusUpdate status = " + status + ",percent = " + percent);
    }

    @Override
    public void onPayloadApplicationComplete(int errorCode) {
        Log.d(TAG,"onPayloadApplicationComplete errorCode = " + errorCode);
    }
});
mUpdateEngine.applyPayload(mParsedUpdate.mUrl, mParsedUpdate.mOffset, mParsedUpdate.mSize, mParsedUpdate.mProps);

升级流程

onStatusUpdate回调status变化值,状态码参考UpdateEngine UpdateEngine#UpdateStatusConstants、UpdateEngine#ErrorCodeConstants

IDLE(0)-UPDATE_AVAILABLE(2)-11-DOWNLOADING (3)-VERIFYING(4)-FINALIZING(5)-UPDATED_NEED_REBOOT(6)

UpdateStatusConstants

/**
184       * Status codes for update engine. Values must agree with the ones in
185       * {@code system/update_engine/client_library/include/update_engine/update_status.h}.
186       */
187      public static final class UpdateStatusConstants {
188          /**
189           * Update status code: update engine is in idle state.
190           */
191          public static final int IDLE = 0;
192  
193          /**
194           * Update status code: update engine is checking for update.
195           */
196          public static final int CHECKING_FOR_UPDATE = 1;
197  
198          /**
199           * Update status code: an update is available.
200           */
201          public static final int UPDATE_AVAILABLE = 2;
202  
203          /**
204           * Update status code: update engine is downloading an update.
205           */
206          public static final int DOWNLOADING = 3;
207  
208          /**
209           * Update status code: update engine is verifying an update.
210           */
211          public static final int VERIFYING = 4;
212  
213          /**
214           * Update status code: update engine is finalizing an update.
215           */
216          public static final int FINALIZING = 5;
217  
218          /**
219           * Update status code: an update has been applied and is pending for
220           * reboot.
221           */
222          public static final int UPDATED_NEED_REBOOT = 6;
223  
224          /**
225           * Update status code: update engine is reporting an error event.
226           */
227          public static final int REPORTING_ERROR_EVENT = 7;
228  
229          /**
230           * Update status code: update engine is attempting to rollback an
231           * update.
232           */
233          public static final int ATTEMPTING_ROLLBACK = 8;
234  
235          /**
236           * Update status code: update engine is in disabled state.
237           */
238          public static final int DISABLED = 9;
239      }

ErrorCodeConstants

/**
59       * Error codes from update engine upon finishing a call to
60       * {@link applyPayload}. Values will be passed via the callback function
61       * {@link UpdateEngineCallback#onPayloadApplicationComplete}. Values must
62       * agree with the ones in {@code system/update_engine/common/error_code.h}.
63       */
64      public static final class ErrorCodeConstants {
65          /**
66           * Error code: a request finished successfully.
67           */
68          public static final int SUCCESS = 0;
69          /**
70           * Error code: a request failed due to a generic error.
71           */
72          public static final int ERROR = 1;
73          /**
74           * Error code: an update failed to apply due to filesystem copier
75           * error.
76           */
77          public static final int FILESYSTEM_COPIER_ERROR = 4;
78          /**
79           * Error code: an update failed to apply due to an error in running
80           * post-install hooks.
81           */
82          public static final int POST_INSTALL_RUNNER_ERROR = 5;
83          /**
84           * Error code: an update failed to apply due to a mismatching payload.
85           *
86           * <p>For example, the given payload uses a feature that's not
87           * supported by the current update engine.
88           */
89          public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6;
90          /**
91           * Error code: an update failed to apply due to an error in opening
92           * devices.
93           */
94          public static final int INSTALL_DEVICE_OPEN_ERROR = 7;
95          /**
96           * Error code: an update failed to apply due to an error in opening
97           * kernel device.
98           */
99          public static final int KERNEL_DEVICE_OPEN_ERROR = 8;
100          /**
101           * Error code: an update failed to apply due to an error in fetching
102           * the payload.
103           *
104           * <p>For example, this could be a result of bad network connection
105           * when streaming an update.
106           */
107          public static final int DOWNLOAD_TRANSFER_ERROR = 9;
108          /**
109           * Error code: an update failed to apply due to a mismatch in payload
110           * hash.
111           *
112           * <p>Update engine does validity checks for the given payload and its
113           * metadata.
114           */
115          public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10;
116  
117          /**
118           * Error code: an update failed to apply due to a mismatch in payload
119           * size.
120           */
121          public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11;
122  
123          /**
124           * Error code: an update failed to apply due to failing to verify
125           * payload signatures.
126           */
127          public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12;
128  
129          /**
130           * Error code: an update failed to apply due to a downgrade in payload
131           * timestamp.
132           *
133           * <p>The timestamp of a build is encoded into the payload, which will
134           * be enforced during install to prevent downgrading a device.
135           */
136          public static final int PAYLOAD_TIMESTAMP_ERROR = 51;
137  
138          /**
139           * Error code: an update has been applied successfully but the new slot
140           * hasn't been set to active.
141           *
142           * <p>It indicates a successful finish of calling {@link #applyPayload} with
143           * {@code SWITCH_SLOT_ON_REBOOT=0}. See {@link #applyPayload}.
144           */
145          public static final int UPDATED_BUT_NOT_ACTIVE = 52;
146  
147          /**
148           * Error code: there is not enough space on the device to apply the update. User should
149           * be prompted to free up space and re-try the update.
150           *
151           * <p>See {@link UpdateEngine#allocateSpace}.
152           */
153          public static final int NOT_ENOUGH_SPACE = 60;
154  
155          /**
156           * Error code: the device is corrupted and no further updates may be applied.
157           *
158           * <p>See {@link UpdateEngine#cleanupAppliedPayload}.
159           */
160          public static final int DEVICE_CORRUPTED = 61;
161      }

!!! 注意事项:

adb remount后会导致失败会通过UpdateEngineCallback#onPayloadApplicationComplete(int errorCode)返回errorCode = 7

remount的解决方式:

adb root
adb enable-verity
adb reboot

参考代码

UpdateEngineUpdateEngineCallback可叫系统提供sdk支持

**UpdateParser **参考android-13.0.0_r3源码UpdateParser

import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


/** Parse an A/B update zip file. */
public class UpdateParser {

    private static final String TAG = "ROTAUpdateManager";
    private static final String PAYLOAD_BIN_FILE = "payload.bin";
    private static final String PAYLOAD_PROPERTIES = "payload_properties.txt";
    private static final String FILE_URL_PREFIX = "file://";
    private static final int ZIP_FILE_HEADER = 30;

    private UpdateParser() {
    }


    private long getOffset(ZipEntry zipEntry, String str) {
        return (zipEntry.getMethod() != 0 ? 16 : 0) + 30 + str.length() + zipEntry.getCompressedSize() + (zipEntry.getExtra() != null ? zipEntry.getExtra().length : 0);
    }

    /**
     * Parse a zip file containing a system update and return a non null ParsedUpdate.
     */
    public static ParsedUpdate parse(File file) throws IOException {
        long payloadOffset = 0;
        long payloadSize = 0;
        boolean payloadFound = false;
        String[] props = null;

        try (ZipFile zipFile = new ZipFile(file)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                long fileSize = entry.getCompressedSize();
                if (!payloadFound) {
                    payloadOffset += ZIP_FILE_HEADER + entry.getName().length();
                    if (entry.getExtra() != null) {
                        payloadOffset += entry.getExtra().length;
                    }
                }

                if (entry.isDirectory()) {
                    continue;
                } else if (entry.getName().equals(PAYLOAD_BIN_FILE)) {
                    payloadSize = fileSize;
                    payloadFound = true;
                } else if (entry.getName().equals(PAYLOAD_PROPERTIES)) {
                    try (BufferedReader buffer = new BufferedReader(
                            new InputStreamReader(zipFile.getInputStream(entry)))) {
                        props = buffer.lines().toArray(String[]::new);
                    }
                }
                if (!payloadFound) {
                    payloadOffset += fileSize;
                }

                //if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, String.format("Entry %s", entry.getName()));
                //}
            }
        }
        return new ParsedUpdate(file, payloadOffset, payloadSize, props);
    }

    /** Information parsed from an update file. */
    public static class ParsedUpdate {
        public final String mUrl;
        public final long mOffset;
        public final long mSize;
        public final String[] mProps;

        ParsedUpdate(File file, long offset, long size, String[] props) {
            mUrl = FILE_URL_PREFIX + file.getAbsolutePath();
            mOffset = offset;
            mSize = size;
            mProps = props;
        }

        /** Verify the update information is correct. */
        public boolean isValid() {
            return mOffset >= 0 && mSize > 0 && mProps != null;
        }

        @Override
        public String toString() {
            return String.format(Locale.getDefault(),
                    "ParsedUpdate: URL=%s, offset=%d, size=%s, props=%s",
                    mUrl, mOffset, mSize, Arrays.toString(mProps));
        }
    }
}

标签:原生,AB,int,OTA,update,public,code,static,final
From: https://www.cnblogs.com/jamebeta/p/18298336

相关文章

  • AI绘画Stable DIffusion教程实战:分分钟带你拿捏SD中的色彩控制
    大家好,我是设计师阿威大家或许已经通过各种《三分钟包会》《五分钟出道》的教程,可以手拿把掐的将一张商品图,完美植入需要的背景中。客观的说,无论从角度、投影、还是商品与背景的语义关系,以下都能算是合格的图片。但是作为视力255³的设计师,总能发现它的不完美——颜色,更准......
  • AI绘画StableDiffusion固定角色大法,无限生成统一风格的图片
    大家好,我是设计师阿威今天给大家介绍StableDiffusion中ControlNet的两个用法,其中一个是Shuffle(随机洗牌),另一个是Reference(参考),其中Reference还能起到固定角色的功能,无限生成统一风格的角色图片。一、Shuffle(随机洗牌)(预处理器下载请看文末扫描获取)找到ControlNet,勾选......
  • 全网最全AI绘画 StablDiffusion系列进阶篇-ControlNet插件介绍
    大家好,我是设计师阿威之前,我已经分享了众多AI绘画方面的学习教程文章,对于想自娱自乐的小伙伴们来说,这些内容应该已经足够使用了。但如果你的工作需要更精细的控制,想要达到更专业的水准,那就得进一步使用一些插件工具了。今天,就让我们来简单聊聊StablDiffusion的高级用法-C......
  • [1032] SQLAlchemy—the magical bridge between Python and databases!
    Ah,SQLAlchemy—themagicalbridgebetweenPythonanddatabases!......
  • AI绘画Stable Diffusion应用场景探索,AI绘画到底能做什么?小白入门必看!
    大家好,我是画画的小强StableDiffusion自2022年开源发布以来,其应用场景已经迅速扩展到了多个领域,艺术家和设计师使用SD来生成创意图像,探索新的视觉风格,或者作为灵感来源。它可以用于生成插图、概念艺术、角色设计等。游戏开发者利用SD来快速创建游戏资产,如角色、环境和道具......
  • AI绘画零基础入门必看,新手小白扫盲教程,一文搞懂MIdjourney和Stable Diffusion有什么不
    大家好,我是画画的小强Midjourney是目前全网最强大的AI绘画平台,用户只需要简单地输入关键词描述,就能获得多幅风格各异的绘画作品,无需任何专业的绘画技能,即刻拥有让人惊叹的艺术创造力。在MidjourneyV5版本之前,用户可以享受免费使用额度,只需要注册一个账户即可在线体验AI......
  • 全网最全,保姆级Stable Diffusion系列入门使用教程(图生图、LoRA、提示词权重),建议收藏!
    大家好,我是画画的小强今天将给大家讲解StableDiffusion入门使用教程的图生图、LoRA和提示词权重的教程,如果你还没有使用或者安装SD,那么可以看看我的往期入门教程AI绘画『StableDiffusion』面向小白的免费AI绘画工具:解压即用,无需安装,超全教程!1、什么是LoRALoRA通常称......
  • 如何使用 Unity 的 ScriptableObjects 和 Resources 系统来创建一个简易的数据库系统,
    1.引言问题:如何在Unity中存储数据?解决方案:使用ScriptableObjects和Resources系统创建一个易于使用和管理的数据库。优势:自动读写数据自动处理资源实例化和更改无需额外插件使用用户定义键进行访问可扩展性强2.实现2.1项目结构四个主要的脚本:Item......
  • [ABC328D] Take ABC 题解
    题目翻译题目描述给你一个字符串\(S\)包含A、B和C三个不用的字符。只要字符串\(S\)中包含连续的ABC就将ABC删除掉再字符串\(S\)不能操作之后输出这个字符串限制\(S\)的长度小于\(2\times10^5\)思路1总结一下这道题目的操作,可以发现就是将字符串删除一......
  • [CF1646F] Playing Around the Table 的题解
    题目大意有\(n\)种牌,一种\(n\)张,一共\(n\)个玩家,一人\(n\)个。每个人一次将一张牌对给下家,求构造方案使可以在\(n\cdot(n-1)\)次操作之内使第\(i\)个人拥有\(n\)张\(i\)。数据范围满足,\(1\len\le100\)。思路因为直接构造出题目要求的情况会出现如果一个人提......