java SystemUpdater 到 c++ updateEngine

一、java SystemUpdater
代码路径:packages/apps/Car/SystemUpdater
原生UI画面:setting ->
主要代码文件
在这里插入图片描述
这是android9上Google提供的一个apk,可以理解就是本地U盘测试update_engine升级的一个app。
这个app的主要作用就是:
1、读取U盘中的升级文件,用户点击目标升级文件。

2、调用updateEngine传递主要参数,收updateEngine的callback向用户显示升级升级进度

3、在升级结束之后通知powermanager重启机器。

分析代码:
在这里我们有一条重要的时序,就是java的updateEngine applyUpdate()方法的调用关系,因为这个方法在U盘升级中负责将,升级文件的path和升级文件的size 、payload.bin的偏移量、hash值等传给c++的updateEngine。

DeviceListFragment.java
........
        @Override
        public ListItem get(int position) {
            if (position < 0 || position >= mListItems.size()) {
                return null;
            }
            TextListItem item = new TextListItem(mContext);
            File file = mListItems.get(position);
            if (file != null) {
                item.setTitle(file.getName());
                item.setOnClickListener(v -> onFileSelected(file)); //item选中了我们的升级文件
            } else {
                item.setTitle(getString(R.string.unknown_file));
            }
            return item;
        }
  .......

    private void onFileSelected(File file) {
        if (isUpdateFile(file)) {
            mFileStack.clear();
            mSystemUpdater.applyUpdate(file); //调到了SystemUpdaterActivity中的applyUpdate()传入升级文件的path
        } else if (file.isDirectory()) {
            showFolderContent(file);
            mFileStack.push(file);
        } else {
            Toast.makeText(getContext(), R.string.invalid_file_type, Toast.LENGTH_LONG).show();
        }
    }
.........
SystemUpdaterActivity.java
.........
    public void applyUpdate(File file) {
        UpdateLayoutFragment fragment = UpdateLayoutFragment.getInstance(file);  //得到UpdateLayoutFragment对象,将升级文件路径传递给UpdateLayoutFragment 
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.device_container, fragment, FRAGMENT_TAG)
                .addToBackStack(null)
                .commit();
    }
........
UpdateLayoutFragment.java
..........
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
.............
        if (getArguments().getBoolean(EXTRA_RESUME_UPDATE)) {
            // Rejoin the update already in progress.
            showInstallationInProgress();
        } else {
            // Extract the necessary information and begin the update.
            mPackageVerifier.execute(mUpdateFile);  //异步执行UpdateVerifier的方法doInBackground和onPostExecute
        }
    }
.............
UpdateVerifier.java //这个类里的这个方法都是比价重要的
        @Override
        protected UpdateParser.ParsedUpdate doInBackground(File... files) { 
            Preconditions.checkArgument(files.length > 0, "No file specified");
            File file = files[0];
            try {
                return UpdateParser.parse(file); //在UpdateParser的parse解析升级文件
            } catch (IOException e) {
                Log.e(TAG, String.format("For file %s", file), e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(UpdateParser.ParsedUpdate result) {
            mProgressBar.setVisibility(View.GONE);
            if (result == null) {
                showStatus(R.string.verify_failure);
                return;
            }
            if (!result.isValid()) {
                showStatus(R.string.verify_failure);
                Log.e(TAG, String.format("Failed verification %s", result));
                return;
            }
            if (Log.isLoggable(TAG, Log.INFO)) {
                Log.i(TAG, result.toString());
            }

            showInstallNow(result); //解析升级之后在这个方法里面简洁调用UpdateEngine.applyPayload()
        }
    }
UpdateParser.java
    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; // 得到 PAYLOAD_BIN_FILE(payload.bin)的文件大小
                    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); //得到hash值
                    }
                }
                if (!payloadFound) {
                    payloadOffset += fileSize; //在没有遍历到payload.bin之前,前面的文件都是记录为偏移量
                }

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, String.format("Entry %s", entry.getName()));
                }
            }
        }
        return new ParsedUpdate(file, payloadOffset, payloadSize, props);  //关于这几个参数后面会讲到
    }
frameworks/base/core/java/android/os/UpdateEngine.java
//从UpdateLayoutFragment的showInstallNow() ——> installUpdate() 到 updateEngine的applyPayload()
    public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {
        try {
            mUpdateEngine.applyPayload(url, offset, size, headerKeyValuePairs); // 是从serviceManager中拿到的
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    public UpdateEngine() {
        mUpdateEngine = IUpdateEngine.Stub.asInterface(
                ServiceManager.getService(UPDATE_ENGINE_SERVICE)); //是c++层的updateEngine注册到serviceManager中的
    }

接下来把上面systemUpdater调到updateEngine的时序图画一下。
在这里插入图片描述

二、java updateEngine到c++ updateEngine
这部分比较简单,c++ updateEngine(其实是BinderUpdateEngineAndroidService)会将自己注册到serviceManager中去,然后Java updateEngine通过binder调用, ServiceManager.getService(UPDATE_ENGINE_SERVICE)),得到c++ updateEngine的代理对象。
代码分析:

UpdateEngine.java
.............
    public UpdateEngine() {
        mUpdateEngine = IUpdateEngine.Stub.asInterface(
                ServiceManager.getService(UPDATE_ENGINE_SERVICE)); //得到update_engine service
    }
    
     @SystemApi
    public boolean bind(final UpdateEngineCallback callback, final Handler handler) { // UpdateEngineCallback 在 UpdateLayoutFragment.java中实现了,具体的回调通知流程就是 BinderUpdateEngineAndroidService ->  UpdateEngineCallback -> CarUpdateEngineCallback
        synchronized (mUpdateEngineCallbackLock) {
            mUpdateEngineCallback = new IUpdateEngineCallback.Stub() {  //BinderUpdateEngineAndroidService提供的代码路径在 system/update_engin/binder_service_android.cc
                @Override
                public void onStatusUpdate(final int status, final float percent) {
                    if (handler != null) {
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onStatusUpdate(status, percent);
                            }
                        });
                    } else {
                        callback.onStatusUpdate(status, percent);
                    }
                }

                @Override
                public void onPayloadApplicationComplete(final int errorCode) {
                    if (handler != null) {
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                callback.onPayloadApplicationComplete(errorCode);
                            }
                        });
                    } else {
                        callback.onPayloadApplicationComplete(errorCode);
                    }
                }
            };

            try {
                return mUpdateEngine.bind(mUpdateEngineCallback); //mUpdateEngineCallback 注册到BinderUpdateEngineAndroidService,后面升级的进度会通过这个回调通知。
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
................
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值