File file = new File(Environment.getExternalStorageDirectory() + "/dload/update.zip");
                         if (file == null || !file.exists()) {
                              showToast(R.string.no_update_file);
                              return;
                         }
        //参数拼接,该参数最终会写入BCB,也就是说设备重启进入Recovery模式后,Recovery.cpp将会解析该参数,并且根据参数做出操作,它将会被传入到bootcommand(context,arg)函数中去。
        String arg = "--update_package=" + filename +
            "\n--locale=" + Locale.getDefault().toString();
        bootCommand(context, arg);
    }
   
4.下面是对bootCommand进行分析。
    private static void bootCommand(Context context, String arg) throws IOException {
        
RECOVERY_DIR.mkdirs();  
// 创建/cache/recovery目录
        COMMAND_FILE.delete();  
// 删除command文件,进行初始化
        LOG_FILE.delete();
//删除log文件,进行初始化
        Log.d(TAG,"Preapre to write command: " + arg +"\n");
        
WriteByFdSync(COMMAND_FILE,arg);
//将参数写入到command文件中
        Log.d(TAG,"Success to write command: " + arg +"\n");
        Log.d(TAG,"Current build type is: " + Build.TYPE +"\n");
        
ReadInAndPrint(COMMAND_FILE);
//读取command文件,并打印log
        // Having written the command file, go ahead and reboot
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
//从系统服务中获得PowerManager实例
        pm.
reboot("recovery");
//重启
        Log.d(TAG,"!!! pm.reboot failed !!!\n");
        throw new IOException("Reboot failed (no permissions?)");
    }
   
    下面的方法调用流程为PowerManager:reboot("recovery")-->PowerManagerService:reboot(reason)
                                                   -->PowerManagerService:shtudownOrRebootInternal(false,confirm,reason,wait)
                                                   -->PowerManagerService:shutdownOrRebootInternal(...)
                                                   -->ShutdownThread:reboot(mContext, reason, confirm);
                                                   -->ShutdownThread:run():running()......
   
   
    @Override // Binder call
    public void 
reboot(boolean confirm, String reason, boolean wait) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
        Slog.i(TAG, "reboot call pid: " + Binder.getCallingPid() + " uid: " + Binder.getCallingUid());
        final long ident = Binder.clearCallingIdentity();
        try {
            shutdownOrRebootInternal(false, confirm, reason, wait);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
   
    private void 
shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
            final String reason, boolean wait) {
        if (mHandler == null || !mSystemReady) {
            throw new IllegalStateException("Too early to call shutdown() or reboot()");
        }
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    if (shutdown) {
                        ShutdownThread.shutdown(mContext, confirm);
                    } else {
                        ShutdownThread.reboot(mContext, reason, confirm);
                    }
                }
            }
        };
        // ShutdownThread must run on a looper capable of displaying the UI.
        Message msg = Message.obtain(mHandler, runnable);
        msg.setAsynchronous(true);
        mHandler.sendMessage(msg);
        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
        if (wait) {
            synchronized (runnable) {
                while (true) {
                    try {
                        runnable.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }
    public static void 
reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootReason = reason;
        Log.d(TAG, "reboot");
        if (mSpew) {
            StackTraceElement[] stack = new Throwable().getStackTrace();
            for (StackTraceElement element : stack)
            {
                Log.d(TAG, "      |----" + element.toString());
            }
        }
        shutdownInner(context, confirm);
    }
   
    这里在run方法下的,running方法中将重启原因写入系统属性文件中去。
    。。。。。。
           {
            String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
        }
    。。。。。。
    最后,重启设备。