关于framwork解密流程优化分析

一、问题来源

二、问题优化

 

一、问题来源

    我们都知道Android上如果升级包data区的话,会有解密的过程,这个过程uncryt.cpp中有详细的说明,大致意思就是recovery不能挂载并修改data分区,所以把包放在了dev/block/userdata节点上,并使用block.map文件知名在节点上的存储信息,大部分解密失败的问题在生成block.map时候就失败了

    针对常规的解密流程错误我们可以在最初去除,那么针对非常规操作造成的解密失败呢,例如线程中断,强制关机等等,那么首先我们说明下这个问题

在installpackage方法最初,执行了setupBcb方法也就是将包的路径和语言写入到了misc分区,以备重启之后进入recovery的信息,但是如果解密出现问题,还是会重启进入升级,而且升级失败,所以我们要处理的就是写入bcb和解密的先后关系

对于该问题,大致有两种方法

1、失败后不重启  查看代码后,如果修改涉及到的流程较多,代码修改量较大,所以暂时不考虑该方案

2、失败后直接重启,不在recovery报错

 

 

二、问题优化

 

修改代码之前做了几组测试

1、只删除seupBcb代码,重启后会进入recovery,但是相当于按键进入recovery,没有给到需要执行的command

2、只设定重启参数mReason = "userrequested";还是会重启进入reboot正常走升级的流程

 

根据以上两种测试,如果我们需要判断解密失败后直接重启,以上两个方面都需要考虑到

 

修改方法一

1、修改./framwork/base/core/java/android/os/RecoverySystem.java

修改clearBcb方法为public,因为我要在shutdown中用到

    /**
     * Talks to RecoverySystemService via Binder to clear up the BCB.
     *
     * @hide //加入@hde
     */
    public boolean clearBcb() {
        try {
            return mService.clearBcb();
        } catch (RemoteException unused) {
        }
        return false;
    }

2、修改./framwork/base/services/core/java/com/android/server/power/ShutdownThread.java

 增加标志位

  //by lbb test

  private boolean uncrypt_done;

修改uncrypt方法为boolean返回值

    //by lbb test
    private boolean uncrypt() {
        Log.i(TAG, "Calling uncrypt and monitoring the progress...");
        //进入方法后赋值为true
        uncrypt_done = true;
        final RecoverySystem.ProgressListener progressListener =
                new RecoverySystem.ProgressListener() {
            @Override
            public void onProgress(int status) {
                if (status >= 0 && status < 100) {
                    // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100).
                    status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100);
                    status += MOUNT_SERVICE_STOP_PERCENT;
                    CharSequence msg = mContext.getText(
                            com.android.internal.R.string.reboot_to_update_package);
                    sInstance.setRebootProgress(status, msg);
                } else if (status == 100) {
                    CharSequence msg = mContext.getText(
                            com.android.internal.R.string.reboot_to_update_reboot);
                    sInstance.setRebootProgress(status, msg);
                } else {
                    // Ignored
                }
            }
        };

        final boolean[] done = new boolean[1];
        done[0] = false;
        Thread t = new Thread() {
            @Override
            public void run() {
                RecoverySystem rs = (RecoverySystem) mContext.getSystemService(
                        Context.RECOVERY_SERVICE);
                String filename = null;
                try {
                    filename = FileUtils.readTextFile(RecoverySystem.UNCRYPT_PACKAGE_FILE, 0, null);
                    rs.processPackage(mContext, new File(filename), progressListener);
                } catch (IOException e) {
                    //解密失败会抛出异常进入catch方法,这里设定uncry_done为false
                    uncrypt_done = false;
                    Log.e(TAG, "Error uncrypting file", e);
                    //return false;
                }
                done[0] = true;
            }
        };
        t.start();
        Log.i(TAG, "uncrypt_done = " + uncrypt_done);
        try {
            t.join(MAX_UNCRYPT_WAIT_TIME);
        } catch (InterruptedException unused) {
        }
        if (!done[0]) {
            Log.w(TAG, "Timed out waiting for uncrypt.");
            final int uncryptTimeoutError = 100;
            String timeoutMessage = String.format("uncrypt_time: %d\n" + "uncrypt_error: %d\n",
                    MAX_UNCRYPT_WAIT_TIME / 1000, uncryptTimeoutError);
            try {
                FileUtils.stringToFile(RecoverySystem.UNCRYPT_STATUS_FILE, timeoutMessage);
            } catch (IOException e) {
                uncrypt_done = false;
                //return false;
                Log.e(TAG, "Failed to write timeout message to uncrypt status", e);
            }
        }
        Log.i(TAG, "uncrypt_done = " + uncrypt_done);
        //返回uncrypt_done
        return uncrypt_done;
    }

修改run方法

    /**
     * Makes sure we handle the shutdown gracefully.
     * Shuts off power regardless of radio state if the allotted time has passed.
     */
    public void run() {
        ......   
        ......
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);

            // If it's to reboot to install an update and uncrypt hasn't been
            // done yet, trigger it now.
            //by lbb test
            //如果解密成功,继续执行后续的升级流程
            if(uncrypt()){
                Log.i(TAG, "uncryt succeed");
            }else{
                //如果解密失败,那么调用clearBcb方法清除misc分区的信息
                Log.i(TAG, "uncryt failed,normal reboot");
                RecoverySystem rs = (RecoverySystem) mContext.getSystemService(Context.RECOVERY_SERVICE);
                try {
                  rs.clearBcb(); 
                  Log.i(TAG, "clearBcb succeed");
                  //更改mReason为userrequested ,正常reboot的reboot也为该字段
                  mReason = "userrequested";
                }catch (Exception e){
                  Log.e(TAG, "clearBcb failed");               
                }
            }
        }
        ///M: added for Shutdown Enhancement@{
        mShutdownSeqFinish(mContext);
        /// @}

        shutdownTimingLog.traceEnd(); // SystemServerShutdown
        metricEnded(METRIC_SYSTEM_SERVER);
        saveMetrics(mReboot, mReason);
        // Remaining work will be done by init, including vold shutdown
        rebootOrShutdown(mContext, mReboot, mReason);
    }

 

修改方法二

1、修改./framwork/base/core/java/android/os/RecoverySystem.java

修改setupBcb为public

 

    /**
     * Talks to RecoverySystemService via Binder to set up the BCB.
     *
     * @hide
     */
    pulic boolean setupBcb(String command) {
        try {
            return mService.setupBcb(command);
        } catch (RemoteException unused) {
        }
        return false;
    }

删除instalpackage中的setupBcb方法

           RecoverySystem rs = (RecoverySystem) context.getSystemService(
                    Context.RECOVERY_SERVICE);
            if (!rs.setupBcb(command)) {
                throw new IOException("Setup BCB failed");
            }

 

2、修改./framwork/base/services/core/java/com/android/server/power/ShutdownThread.java

uncry_done标志位和uncrypt方法的修改与上述方法相同

修改run方法

 

    /**
     * Makes sure we handle the shutdown gracefully.
     * Shuts off power regardless of radio state if the allotted time has passed.
     */
    public void run() {
        ......   
        ......
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);

            // If it's to reboot to install an update and uncrypt hasn't been
            // done yet, trigger it now.
            //by lbb test
            //如果解密成功,继续执行后续的升级流程
            if(uncrypt()){
                Log.i(TAG, "uncryt succeed");
                //如果解密成功,写入bcb信息
                RecoverySystem rs = (RecoverySystem) mContext.getSystemService(Context.RECOVERY_SERVICE);
                try {
                  rs.setupBcb(); 
                  Log.i(TAG, "setupBcb succeed");
                }catch (Exception e){
                  Log.e(TAG, "setupBcb failed");               
                }
            }else{
                //如果解密失败,将reason信息设定为正常restart的值
                mReason = "userrequested";
            }
        }
        ///M: added for Shutdown Enhancement@{
        mShutdownSeqFinish(mContext);
        /// @}

        shutdownTimingLog.traceEnd(); // SystemServerShutdown
        metricEnded(METRIC_SYSTEM_SERVER);
        saveMetrics(mReboot, mReason);
        // Remaining work will be done by init, including vold shutdown
        rebootOrShutdown(mContext, mReboot, mReason);
    }

你可能感兴趣的:(Andrdoid,OTA升级)