===== 应用流程 =====
====>frameworks/base/services/java/com/android/server/MasterClearReceiver.java
RecoverySystem.rebootWipeUserData(context);

====>framesworks/base/core/java/android/os/RecoverySystem.java
rebootWipeUserData ===> bootCommand(context, "--wipe_data");
bootCommand写参数"--wipe_data"到/cache/recovery/command后,
调用pm.reboot("recovery");

====>frameworks/base/core/java/android/os/Power.java
reboot ===> rebootNative

====>frameworks/base/core/jni/android_os_Power.cpp
JNI 映射
{ "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
android_os_Power_reboot ===> __reboot

====>bionic/libc/arch-arm/syscalls/__reboot.S
ldr r7, =__NR_reboot  // bionic/libc/include/sys/linux-syscalls.h
b  __set_syscall_errno

#define __NR_reboot  (__NR_SYSCALL_BASE + 88)

===== 内核流程 =====
====>kernel/arch/arm/kernel/calls.S
/* 88 */    CALL(sys_reboot)

====>kernel/sys.c
sys_reboot定义在kernel/include/linux/syscalls.h,实现在kernel/kernel/sys.c

在这里,判断buffer的内容,用一个寄存器记录是否是recovery mode,以便boot loader去查询。
sys_reboot会调用kernel_restart
kernel_restart调用每一个架构特定的machine_restart, 即machine_restart执行每个架构特定的函数

====>kernel/arch/arm/kernel/process.c
machine_restart==>arm_pm_restart==>arm_machine_restart==>arch_reset

====>kernel/arch/arm/mach-tegra/include/mach/system.h
arch_reset

===== bootloader流程 =====
机器重启, 重新进入bootloader。bootloader首先会读寄存器的内容, 根据这个值决定是否进入recovery模式或者其它模式。
bootloader然后加载recovery内核。

===== recovery应用流程 =====
recovery内核中的init.rc会运行recovery

recovery应用会读取cache/recovery/command
读取参数后执行相应操作, 这里参数是--wipe_data, 放在cache/recovery/command里

把DATA和CACHE清空后重启系统,此时内核重启时写的寄存器参数RB_AUTOBOOT跟前面不同的
bionic/libc/include/sys/reboot.h
#define RB_AUTOBOOT     LINUX_REBOOT_CMD_RESTART
不会再让bootloader进入recovery模式,而是正常启动。


下面的转载于:

最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程;

      在setting-->备份与重置--->恢复出厂设置--->重置手机--->清除全部内容--->手机关机--->开机--->进行恢复出厂的操作--->开机流程;


     Step 1:前面找settings中的布局我就省略了,这部分相对简单一些,直接到清除全部内容这个按钮的操作,

    对应的java类是setting中的MasterClearConfirm.java这个类,



1. private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {  
2.   
3. public void onClick(View v) {  
4. if (Utils.isMonkeyRunning()) {  
5. return;  
6.             }  
7.   
8. if (mEraseSdCard) {  
9. new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);  
10.                 intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);  
11.                 getActivity().startService(intent);  
12. else {  
13. new Intent("android.intent.action.MASTER_CLEAR"));  
14. // Intent handling is asynchronous -- assume it will happen soon.  
15.             }  
16.         }  
17.     };

通过上述的代码,可以看出,实际上点击清除全部内容的时候,如果前面勾选上格式哈SD卡,就会执行mEraseSdCard为true里面的逻辑,如果没有勾选,就执行mEraseSdCard=false的逻辑,其实就是发送一个广播,


1. <span style="font-size:14px;">“android.intent.action.MASTER_CLEAR”</span>



        Step 2:这个广播接受的地方,参见AndroidManifest.xml中的代码,如下:




    1. <receiver android:name="com.android.server.MasterClearReceiver"  
    2. android:permission="android.permission.MASTER_CLEAR"  
    3. android:priority="100" >  
    4. <intent-filter>  
    5. <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->  
    6. <action android:name="android.intent.action.MASTER_CLEAR" />  
    7.   
    8. <!-- MCS always uses REMOTE_INTENT: category=MASTER_CLEAR -->  
    9. <action android:name="com.google.android.c2dm.intent.RECEIVE" />  
    10. <category android:name="android.intent.category.MASTER_CLEAR" />  
    11. </intent-filter>  
    12. </receiver>


    找这个MasterClearReceiver.java这个receiver,下面来看看这个onReceiver()里面做了什么操作:


    1. public void onReceive(final Context context, final Intent intent) {  
    2. if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {  
    3. if (!"google.com".equals(intent.getStringExtra("from"))) {  
    4. "Ignoring master clear request -- not from trusted server.");  
    5. return;  
    6.             }  
    7.         }  
    8.   
    9. "!!! FACTORY RESET !!!");  
    10. // The reboot call is blocking, so we need to do it on another thread.  
    11. new Thread("Reboot") {  
    12. @Override  
    13. public void run() {  
    14. try {  
    15.                     RecoverySystem.rebootWipeUserData(context);  
    16. "Still running after master clear?!");  
    17. catch (IOException e) {  
    18. "Can't perform master clear/factory reset", e);  
    19.                 }  
    20.             }  
    21.         };  
    22.         thr.start();  
    23.     }

    这个里面主要的操作是:RecoverySystem.rebootWipeUserData(context);准备做重启的动作,告诉手机要清除userData的数据;


          Step 3:接着来看看RecoverySystem.rebootWipeUserData()这个方法做了哪些操作:



    1. public static void rebootWipeUserData(Context context) throws IOException {  
    2. final ConditionVariable condition = new ConditionVariable();  
    3.   
    4. new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");  
    5.         context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,  
    6.                 android.Manifest.permission.MASTER_CLEAR,  
    7. new BroadcastReceiver() {  
    8. @Override  
    9. public void onReceive(Context context, Intent intent) {  
    10.                         condition.open();  
    11.                     }  
    12. null, 0, null, null);  
    13.   
    14. // Block until the ordered broadcast has completed.  
    15.         condition.block();  
    16.   
    17. "--wipe_data\n--locale=" + Locale.getDefault().toString());  
    18.     }


    这个里面的广播可以先忽略不计,重点来看看bootCommand()这个方法,注意这个参数“--wipe_data\n--locale=”



    1. private static void bootCommand(Context context, String arg) throws IOException {  
    2. // In case we need it  
    3. // In case it's not writable  
    4.         LOG_FILE.delete();  
    5.   
    6. new FileWriter(COMMAND_FILE);  
    7. try {  
    8.             command.write(arg);  
    9. "\n");  
    10. finally {  
    11.             command.close();  
    12.         }  
    13.   
    14. // Having written the command file, go ahead and reboot  
    15.         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
    16. "recovery");  
    17.   
    18. throw new IOException("Reboot failed (no permissions?)");  
    19.     }


    这个方法的操作大致是“写节点/cache/recovery/command”,把传递过来的字符串写进去;然后调用PowerManager进行重启操作,reboot();


     Step 4:接着我们来看看PowerManager的reboot方法做了哪些操作:



    1. public void reboot(String reason) {  
    2. try {  
    3. false, reason, true);  
    4. catch (RemoteException e) {  
    5.       }  
    6.   }

    这个调用到了PowerManagerService.java这个类的reboot方法中了:



    1. @Override // Binder call  
    2. public void reboot(boolean confirm, String reason, boolean wait) {  
    3. null);  
    4.   
    5. final long ident = Binder.clearCallingIdentity();  
    6. try {  
    7. false, confirm, reason, wait);  
    8. finally {  
    9.             Binder.restoreCallingIdentity(ident);  
    10.         }  
    11.     }


    重点来看看shutdownOrRebootInternal()这个方法,


    1. private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,  
    2. final String reason, boolean wait) {  
    3. if (mHandler == null || !mSystemReady) {  
    4. throw new IllegalStateException("Too early to call shutdown() or reboot()");  
    5.         }  
    6.   
    7. new Runnable() {  
    8. @Override  
    9. public void run() {  
    10. synchronized (this) {  
    11. if (shutdown) {  
    12.                         ShutdownThread.shutdown(mContext, confirm);  
    13. else {  
    14.                         ShutdownThread.reboot(mContext, reason, confirm);  
    15.                     }  
    16.                 }  
    17.             }  
    18.         };  
    19.   
    20. // ShutdownThread must run on a looper capable of displaying the UI.  
    21.         Message msg = Message.obtain(mHandler, runnable);  
    22. true);  
    23.         mHandler.sendMessage(msg);  
    24.   
    25. // PowerManager.reboot() is documented not to return so just wait for the inevitable.  
    26. if (wait) {  
    27. synchronized (runnable) {  
    28. while (true) {  
    29. try {  
    30.                         runnable.wait();  
    31. catch (InterruptedException e) {  
    32.                     }  
    33.                 }  
    34.             }  
    35.

    由于传递过来的shutdown为false,所以执行ShutdownThread.reboot(mContext, reason, confirm);reason:recevory

    下面调用到ShutdownThread


       Step 5:这个追踪ShutdownThread.reboot()这个方法,这就有点像破案电影,一点一点查找罪犯的难点;

    来窥视一下这个类:



    1. public static void reboot(final Context context, String reason, boolean confirm) {  
    2. true;  
    3. false;  
    4.        mRebootReason = reason;  
    5. "reboot");  
    6.        shutdownInner(context, confirm);  
    7.    }

    这个里面做的操作就是给这个变量mRebootReason复制“recevory”,重点调用shutdownInner()这个方法;



    1. <span style="font-size:14px;">static void shutdownInner(final Context context, boolean confirm) {  
    2. // ensure that only one thread is trying to power down.  
    3. // any additional calls are just returned  
    4. synchronized (sIsStartedGuard) {  
    5. if (sIsStarted) {  
    6. "Request to shutdown already running, returning.");  
    7. return;  
    8.             }  
    9.         }  
    10.   
    11. "Notifying thread to start radio shutdown");  
    12.         bConfirmForAnimation = confirm;  
    13. final int longPressBehavior = context.getResources().getInteger(  
    14.                 com.android.internal.R.integer.config_longPressOnPowerBehavior);  
    15. final int resourceId = mRebootSafeMode  
    16.             ? com.android.internal.R.string.reboot_safemode_confirm  
    17. 2  
    18.                     ? com.android.internal.R.string.shutdown_confirm_question  
    19.                     : com.android.internal.R.string.shutdown_confirm);  
    20.   
    21. "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);  
    22.   
    23. if (confirm) {  
    24. final CloseDialogReceiver closer = new CloseDialogReceiver(context);  
    25. if (sConfirmDialog != null) {  
    26.                 sConfirmDialog.dismiss();  
    27.             }  
    28. if (sConfirmDialog == null) {  
    29. "PowerOff dialog doesn't exist. Create it first");  
    30. new AlertDialog.Builder(context)  
    31.                     .setTitle(mRebootSafeMode  
    32.                             ? com.android.internal.R.string.reboot_safemode_title  
    33.                             : com.android.internal.R.string.power_off)  
    34.                     .setMessage(resourceId)  
    35. new DialogInterface.OnClickListener() {  
    36. public void onClick(DialogInterface dialog, int which) {  
    37.                             beginShutdownSequence(context);  
    38. if (sConfirmDialog != null) {  
    39. null;  
    40.                             }  
    41.                             }  
    42.                             })  
    43. new DialogInterface.OnClickListener() {  
    44. public void onClick(DialogInterface dialog, int which) {  
    45. synchronized (sIsStartedGuard) {  
    46. false;  
    47.                         }  
    48. if (sConfirmDialog != null) {  
    49. null;  
    50.                         }  
    51.                         }  
    52.                         })  
    53.                 .create();  
    54. false);//blocking back key  
    55.                 sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);  
    56. /*if (!context.getResources().getBoolean(
    57.                   com.android.internal.R.bool.config_sf_slowBlur)) {
    58.                   sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
    59.                   }*/  
    60. /* To fix video+UI+blur flick issue */  
    61.                 sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);  
    62.             }  
    63.   
    64.             closer.dialog = sConfirmDialog;  
    65.             sConfirmDialog.setOnDismissListener(closer);  
    66.   
    67. if (!sConfirmDialog.isShowing()) {  
    68.                 sConfirmDialog.show();  
    69.             }  
    70. else {  
    71.             beginShutdownSequence(context);  
    72.         }  
    73.     }</span>

    看beginShutdownSequence()这个方法吧,重点调用到这个方法里面去了,来瞅瞅这个方法:



    1. <span style="font-size:14px;">private static void beginShutdownSequence(Context context) {  
    2. synchronized (sIsStartedGuard) {  
    3. if (sIsStarted) {  
    4. "ShutdownThread is already running, returning.");          
    5. return;  
    6.             }  
    7. true;  
    8.         }  
    9.   
    10. // start the thread that initiates shutdown  
    11.         sInstance.mContext = context;  
    12.         sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);  
    13. new Handler() {  
    14.         };      
    15.   
    16. true;  
    17. if (!bConfirmForAnimation) {  
    18. if (!sInstance.mPowerManager.isScreenOn()) {  
    19. false;  
    20.             }  
    21.         }  
    22.   
    23. // throw up an indeterminate system dialog to indicate radio is  
    24. // shutting down.  
    25. 0;  
    26. boolean mShutOffAnimation = false;  
    27.   
    28. try {  
    29. if (mIBootAnim == null) {  
    30. class);  
    31.             }  
    32. catch (Exception e) {  
    33.             e.printStackTrace();  
    34.         }  
    35.   
    36. int screenTurnOffTime = mIBootAnim.getScreenTurnOffTime();  
    37.         mShutOffAnimation = mIBootAnim.isCustBootAnim();  
    38. "mIBootAnim get screenTurnOffTime : " + screenTurnOffTime);  
    39.   
    40. "ro.operator.optr");  
    41.   
    42. if (cust != null) {  
    43. if (cust.equals("CUST")) {  
    44. true;  
    45.             }  
    46.         }  
    47.   
    48. synchronized (mEnableAnimatingSync) {  
    49.   
    50. if(!mEnableAnimating) {  
    51. //                sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM);  
    52. else {  
    53. if (mShutOffAnimation) {  
    54. "mIBootAnim.isCustBootAnim() is true");  
    55.                     bootanimCust();  
    56. else {  
    57. new ProgressDialog(context);  
    58.                     pd.setTitle(context.getText(com.android.internal.R.string.power_off));  
    59.                     pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));  
    60. true);  
    61. false);  
    62.                     pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);  
    63. /* To fix video+UI+blur flick issue */  
    64.                     pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);  
    65.                     pd.show();  
    66.                 }  
    67.                 sInstance.mHandler.postDelayed(mDelayDim, screenTurnOffTime );   
    68.             }  
    69.         }  
    70.   
    71. // make sure we never fall asleep again  
    72. null;  
    73. try {  
    74.             sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(  
    75.                     。。。 。。。  
    76. }</span>


    这段代码有句话会影响关机动画播放不完

    “sInstance.mHandler.postDelayed(mDelayDim, screenTurnOffTime ); ”

    解决办法

        (1)“可以把这个screenTurnOffTime时间乘以2,这个时间看log是5000毫秒,就是5秒,乘以2就是10秒,大概就能播放完全关机动画了。”

        (2)把这句话注释掉,但是有可能会引起问题,导致恢复出厂设置的时候没有进行恢复出厂的操作。目前正在追踪此问题;


    这段代码中还有影响关机动画是否走客制化的关机动画,如果ro.operator.optr这个属性配置的是CUST,则会走客制化的关机动画,否则走系统默认的关机动画;



    1. String cust = SystemProperties.get("ro.operator.optr");  
    2.   
    3.   
    4. if (cust != null) {  
    5. if (cust.equals("CUST")) {  
    6. true;  
    7.             }  
    8.         }




    然后重点看 sInstance.start();这个方法,就走到了run()方法里满了;


        Step 6:



    1. <span style="font-size:14px;">public void run() {  
    2.         checkShutdownFlow();  
    3. while (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    4.             stMgr.saveStates(mContext);  
    5.             stMgr.enterShutdown(mContext);  
    6.             running();  
    7.         }   
    8. if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {  
    9.             stMgr.enterShutdown(mContext);  
    10.             running();  
    11.         }  
    12.     }</span>


    重点看running()这个方法:

    下面这个方法比较长,来分析一下:


    1. <span style="font-size:14px;">public void running() {  
    2. if(sPreShutdownApi != null){  
    3. try {  
    4.                sPreShutdownApi.onPowerOff();  
    5. catch (RemoteException e) {  
    6. "onPowerOff exception" + e.getMessage());  
    7.            }  
    8. else{  
    9. "sPreShutdownApi is null");  
    10.        }  
    11.   
    12. "sys.ipo.pwrdncap");  
    13.   
    14. new BroadcastReceiver() {  
    15. @Override public void onReceive(Context context, Intent intent) {  
    16. // We don't allow apps to cancel this, so ignore the result.  
    17.                actionDone();  
    18.            }  
    19.        };  
    20.   
    21. /*
    22.         * Write a system property in case the system_server reboots before we
    23.         * get to the actual hardware restart. If that happens, we'll retry at
    24.         * the beginning of the SystemServer startup.
    25.         */  
    26.        {  
    27. "1" : "0") + (mRebootReason != null ? mRebootReason : "");  
    28.            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);  
    29.        }  
    30.   
    31. /*
    32.         * If we are rebooting into safe mode, write a system property
    33.         * indicating so.
    34.         */  
    35. if (mRebootSafeMode) {  
    36. "1");  
    37.        }  
    38.   
    39. "Sending shutdown broadcast...");  
    40.   
    41. // First send the high-level shut down broadcast.  
    42. false;  
    43. /// M: 2012-05-20 ALPS00286063 @{  
    44. new Intent("android.intent.action.ACTION_PRE_SHUTDOWN"));  
    45. /// @} 2012-05-20  
    46. new Intent()).setAction(Intent.ACTION_SHUTDOWN).putExtra("_mode", mShutdownFlow),  
    47. null, br, mHandler, 0, null, null);  
    48.          
    49. final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;  
    50. synchronized (mActionDoneSync) {  
    51. while (!mActionDone) {  
    52. long delay = endTime - SystemClock.elapsedRealtime();  
    53. if (delay <= 0) {  
    54. "Shutdown broadcast ACTION_SHUTDOWN timed out");  
    55. if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    56. "change shutdown flow from ipo to normal: ACTION_SHUTDOWN timeout");  
    57.                        mShutdownFlow = NORMAL_SHUTDOWN_FLOW;  
    58.                    }  
    59. break;  
    60.                }  
    61. try {  
    62.                    mActionDoneSync.wait(delay);  
    63. catch (InterruptedException e) {  
    64.                }  
    65.            }  
    66.        }  
    67.   
    68. // Also send ACTION_SHUTDOWN_IPO in IPO shut down flow  
    69. if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    70. false;  
    71. new Intent("android.intent.action.ACTION_SHUTDOWN_IPO"), null,  
    72. 0, null, null);  
    73. final long endTimeIPO = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;  
    74. synchronized (mActionDoneSync) {  
    75. while (!mActionDone) {  
    76. long delay = endTimeIPO - SystemClock.elapsedRealtime();  
    77. if (delay <= 0) {  
    78. "Shutdown broadcast ACTION_SHUTDOWN_IPO timed out");  
    79. if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    80. "change shutdown flow from ipo to normal: ACTION_SHUTDOWN_IPO timeout");  
    81.                            mShutdownFlow = NORMAL_SHUTDOWN_FLOW;  
    82.                        }  
    83. break;  
    84.                    }  
    85. try {  
    86.                        mActionDoneSync.wait(delay);  
    87. catch (InterruptedException e) {  
    88.                    }  
    89.                }  
    90.            }  
    91.        }  
    92.   
    93. if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {  
    94. // power off auto test, don't modify  
    95. "Shutting down activity manager...");  
    96.   
    97. final IActivityManager am =  
    98. "activity"));  
    99. if (am != null) {  
    100. try {  
    101.                    am.shutdown(MAX_BROADCAST_TIME);  
    102. catch (RemoteException e) {  
    103.                }  
    104.            }  
    105.        }  
    106.   
    107. // power off auto test, don't modify  
    108. // Shutdown radios.  
    109. "Shutting down radios...");  
    110.        shutdownRadios(MAX_RADIO_WAIT_TIME);  
    111.   
    112. // power off auto test, don't modify  
    113. "Shutting down MountService...");  
    114. if ( (mShutdownFlow == IPO_SHUTDOWN_FLOW) && (command.equals("1")||command.equals("3")) ) {  
    115. "bypass MountService!");  
    116. else {  
    117. // Shutdown MountService to ensure media is in a safe state  
    118. new IMountShutdownObserver.Stub() {  
    119. public void onShutDownComplete(int statusCode) throws RemoteException {  
    120. "Result code " + statusCode + " from MountService.shutdown");  
    121. if (statusCode < 0) {  
    122.                        mShutdownFlow = NORMAL_SHUTDOWN_FLOW;   
    123.                    }  
    124.                    actionDone();  
    125.                }  
    126.            };  
    127.   
    128.              
    129.   
    130. // Set initial variables and time out time.  
    131. false;  
    132. final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;  
    133. synchronized (mActionDoneSync) {  
    134. try {  
    135. final IMountService mount = IMountService.Stub.asInterface(  
    136. "mount"));  
    137. if (mount != null) {  
    138.                        mount.shutdown(observer);  
    139. else {  
    140. "MountService unavailable for shutdown");  
    141.                    }  
    142. catch (Exception e) {  
    143. "Exception during MountService shutdown", e);  
    144.                }  
    145. while (!mActionDone) {  
    146. long delay = endShutTime - SystemClock.elapsedRealtime();  
    147. if (delay <= 0) {  
    148. "Shutdown wait timed out");  
    149. if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    150. "change shutdown flow from ipo to normal: MountService");  
    151.                            mShutdownFlow = NORMAL_SHUTDOWN_FLOW;  
    152.                        }  
    153. break;  
    154.                    }  
    155. try {  
    156.                        mActionDoneSync.wait(delay);  
    157. catch (InterruptedException e) {  
    158.                    }  
    159.                }  
    160.            }  
    161.        }  
    162.   
    163. // power off auto test, don't modify  
    164. //mountSerivce ���  
    165. "MountService shut done...");  
    166. // [MTK] fix shutdown animation timing issue  
    167. //==================================================================  
    168. try {  
    169. "service.shutanim.running","1");  
    170. "set service.shutanim.running to 1");  
    171.   
    172. catch (Exception ex) {  
    173. "Failed to set 'service.shutanim.running' = 1).");  
    174.        }  
    175. //==================================================================  
    176.   
    177. if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {  
    178. if (SHUTDOWN_VIBRATE_MS > 0) {  
    179. // vibrate before shutting down  
    180. new SystemVibrator();  
    181. try {  
    182.                    vibrator.vibrate(SHUTDOWN_VIBRATE_MS);  
    183. catch (Exception e) {  
    184. // Failure to vibrate shouldn't interrupt shutdown.  Just log it.  
    185. "Failed to vibrate during shutdown.", e);  
    186.                }  
    187.   
    188. // vibrator is asynchronous so we need to wait to avoid shutting down too soon.  
    189. try {  
    190.                    Thread.sleep(SHUTDOWN_VIBRATE_MS);  
    191. catch (InterruptedException unused) {  
    192.                }  
    193.            }  
    194.   
    195. // Shutdown power  
    196. // power off auto test, don't modify  
    197. "Performing ipo low-level shutdown...");  
    198.   
    199.            delayForPlayAnimation();  
    200.   
    201. if (sInstance.mScreenWakeLock != null && sInstance.mScreenWakeLock.isHeld()) {  
    202.                sInstance.mScreenWakeLock.release();  
    203. null;  
    204.            }  
    205.   
    206.            sInstance.mHandler.removeCallbacks(mDelayDim);   
    207.            stMgr.shutdown(mContext);  
    208.            stMgr.finishShutdown(mContext);  
    209.   
    210. //To void previous UI flick caused by shutdown animation stopping before BKL turning off           
    211. if (pd != null) {  
    212.                pd.dismiss();  
    213. null;  
    214. else if (beginAnimationTime > 0) {  
    215. try {  
    216. "service.bootanim.exit","1");  
    217. "set 'service.bootanim.exit' = 1).");  
    218. catch (Exception ex) {  
    219. "Failed to set 'service.bootanim.exit' = 1).");  
    220.                }    
    221. //SystemProperties.set("ctl.stop","bootanim");  
    222.            }  
    223.   
    224. synchronized (sIsStartedGuard) {  
    225. false;  
    226.            }  
    227.   
    228. false);   
    229. 2000);   
    230.   
    231. synchronized (mShutdownThreadSync) {  
    232. try {  
    233.                    mShutdownThreadSync.wait();  
    234. catch (InterruptedException e) {  
    235.                }  
    236.            }  
    237. else {  
    238.            rebootOrShutdown(mReboot, mRebootReason);  
    239.        }  
    240.    }</span>


    这个方法做了一些列的操作,会关闭一些操作,如:

    1.  shutdownRadios(MAX_RADIO_WAIT_TIME);
    2. mount.shutdown(observer);
    3. stMgr.shutdown(mContext);

    重点看  rebootOrShutdown(mReboot, mRebootReason);这个方法;准备重启的方法;


     Step 7:来看看rebootOrShutdown()这个方法:




    1. <span style="font-size:14px;">public static void rebootOrShutdown(boolean reboot, String reason) {  
    2. if (reboot) {  
    3. "Rebooting, reason: " + reason);  
    4. if ( (reason != null) && reason.equals("recovery") ) {  
    5.                 delayForPlayAnimation();  
    6.             }  
    7. try {  
    8.                 PowerManagerService.lowLevelReboot(reason);  
    9. catch (Exception e) {  
    10. "Reboot failed, will attempt shutdown instead", e);  
    11.             }  
    12. else if (SHUTDOWN_VIBRATE_MS > 0) {  
    13. // vibrate before shutting down  
    14. new SystemVibrator();  
    15. try {  
    16.                 vibrator.vibrate(SHUTDOWN_VIBRATE_MS);  
    17. catch (Exception e) {  
    18. // Failure to vibrate shouldn't interrupt shutdown.  Just log it.  
    19. "Failed to vibrate during shutdown.", e);  
    20.             }  
    21.   
    22. // vibrator is asynchronous so we need to wait to avoid shutting down too soon.  
    23. try {  
    24.                 Thread.sleep(SHUTDOWN_VIBRATE_MS);  
    25. catch (InterruptedException unused) {  
    26.             }  
    27.         }  
    28.   
    29.         delayForPlayAnimation();  
    30. // Shutdown power  
    31. // power off auto test, don't modify  
    32. "Performing low-level shutdown...");  
    33. //PowerManagerService.lowLevelShutdown();  
    34. //add your func: HDMI off  
    35. //add for MFR  
    36. try {  
    37. if (ImHDMI == null)  
    38. class);  
    39. catch (Exception e) {  
    40.             e.printStackTrace();              
    41.         }  
    42. false);  
    43. try {  
    44. if (mTvOut == null)  
    45. class);  
    46. catch (Exception e) {  
    47.             e.printStackTrace();              
    48.         }  
    49.   
    50. false);  
    51. //add your func: HDMI off  
    52. //unmout data/cache partitions while performing shutdown  
    53.   
    54. "ctl.start", "shutdown");  
    55.   
    56. /* sleep for a long time, prevent start another service */  
    57. try {  
    58.             Thread.currentThread().sleep(Integer.MAX_VALUE);  
    59. catch ( Exception e) {  
    60. "Shutdown rebootOrShutdown Thread.currentThread().sleep exception!");    
    61.         }  
    62.     }</span>


    关机震动也在这个方法里面;这个方法重点看PowerManagerService.lowLevelReboot(reason);

      Log.i(TAG, "Rebooting, reason: " + reason);这句log也很重要,可以有助于我们分析代码;


        Step 8:下面来看看PowerManagerServices.java这个类的lowLevelReboot()这个方法:




    1. <span style="font-size:18px;">public static void lowLevelReboot(String reason) throws IOException {  
    2.         nativeReboot(reason);  
    3.     }</span>

    这个方法调用到了native里面,后面的操作我就不分析了。。。


    大致流程是:

       关机,然后开机,底层判断节点后进入恢复出厂模式,recevory.img释放完全后,进入开机的流程。。。

    以后有进展再补充这部分的流程,整个过程大致就是这个样子了,里面的细节有好多没有分析,大家可以自行研究。。。,抛砖引玉的目的达到了。