android MTK平台设置下添加OTA升级接口验证升级

 

因为项目需求,要自己添加一个OTA升级的接口验证是否能正常升级,所以自己在设置下加了个Receiver,收到广播后验证升级,也可以自己在设置随便哪个界面添加一个菜单,点击升级。

下面来看具体实现的代码

1.alps/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ota/OtaUpdateReceiver.java    

package com.android.settings.ota;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
import android.os.PowerManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import android.os.Build;
import com.android.settings.ota.UpdateParser;

public class OtaUpdateReceiver extends BroadcastReceiver {
    private static final String TAG = "OtaUpdateReceiver";

    Context mContext;
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.d(TAG, " OtaUpdateReceiver");
        mContext = context;

    //收到升级广播"com.android.action.updateOta"后开始升级
        if (("com.android.action.updateOta").equals(intent.getAction())) {
            String path = intent.getStringExtra("path"); //升级所需的update.zip具体放的位置
            Log.d("TAG", "intent.getAction():" + intent.getAction()+"; path:"+path);
            startUpdate(path); //开始升级
        }
    }
    private UpdateEngine mUpdateEngine;
    String updateFilePath;
    private void startUpdate(String path) {
        mUpdateEngine = new UpdateEngine();
        UpdateParser.ParsedUpdate parsedUpdate = null;
        copyFile(path,"/cache/recovery/update.zip"); //copy升级的update.zip到cache分区
        try{
            parsedUpdate = UpdateParser.parse(new File("/cache/recovery/update.zip"));
            Log.e(TAG,"parsedUpdate:"+parsedUpdate.toString());
        }catch(Exception e){
            Log.e(TAG,"e="+e.toString());
            e.printStackTrace();
        }
        Log.d(TAG, "startUpdate: start");
        mUpdateEngine.bind(new UpdateEngineCallback() {
            public void onStatusUpdate(int status, float percent) {
                // 处理升级状态更新
                Log.d(TAG, "onStatusUpdate: status :" + status + "; percent" + percent + "%");
                switch (status) {
                    case UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT:
                        rebootNow();
                        break;
                    case UpdateEngine.UpdateStatusConstants.DOWNLOADING:
                        break;
                    default:
                        // noop
                }
            }

            public void onPayloadApplicationComplete(int errorCode) {
                // 处理升级完成
                Log.d(TAG, "onPayloadApplicationComplete: errorCode :" + errorCode);
            }

            public void onVerificationComplete(int errorCode) {
                // 处理升级包验证完成
                Log.d(TAG, "onVerificationComplete: errorCode :" + errorCode);
            }
        });
        Log.d(TAG, "startUpdate: parsedUpdate:"+parsedUpdate);
        if(parsedUpdate != null) {
            try {
                Log.d(TAG, "startUpdate: applyPayload:");
                mUpdateEngine.applyPayload(parsedUpdate.mUrl, parsedUpdate.mOffset, parsedUpdate.mSize, parsedUpdate.mProps);
            } catch (Exception e) {
                e.printStackTrace();
                Log.d(TAG, "startUpdate: printStackTrace:");
            }
        }

    }

    public  void copyFile(String srcPath, String destPath) {
        File srcFile = new File(srcPath); // 源文件
        if (!srcFile.exists()) {
            Log.e("TAG", "源文件不存在");
            return;
        }
        try {
            FileInputStream fis = new FileInputStream(srcPath);
            FileOutputStream fos = new FileOutputStream(destPath);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                android.os.FileUtils.copy(fis, fos);
            } else {
                byte[] buf = new byte[1024];
                int c;
                while ((c = fis.read(buf)) != -1) {
                    fos.write(buf, 0, c);
                }
                fis.close();
                fos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void rebootNow() {
        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        powerManager.reboot(null);
    }
}

2.alps/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ota/UpdateParser.java

package com.android.settings.ota;

import android.annotation.SuppressLint;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Preconditions;

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

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

    private static final String TAG = "UpdateParser";
    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() {
    }

    /**
     * Parse a zip file containing a system update and return a non null ParsedUpdate.
     */
    @SuppressLint("RestrictedApi")
    @Nullable
    static ParsedUpdate parse(@NonNull File file) throws IOException {
        Preconditions.checkNotNull(file);

        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)) {
                    InputStreamReader is =new InputStreamReader(zipFile.getInputStream(entry));
                    BufferedReader br = new BufferedReader(is);

                    List<String> lines = new ArrayList<String>();
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        Log.e(TAG, "getPayloadProperties line: " + line);
                        lines.add(line);
                    }
                    props = lines.toArray(new String[lines.size()]);
                    br.close();
                    is.close();
                }
                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. */
    static class ParsedUpdate {
        final String mUrl;
        final long mOffset;
        final long mSize;
        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. */
        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));
        }
    }
}
 

可能还会有一些te权限问题,自己添加下权限即可

alps/device/mediatek/sepolicy/basic/plat_private/system_app.te

alps/device/mediatek/sepolicy/basic/plat_private/system_server.te

主要的升级逻辑就是执行 startUpdate(path)方法,通过调用系统UpdateEngine来进行升级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值