Android恢复出厂设置流程分析【Android源码解析十】
最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程;
在setting-->备份与重置--->恢复出厂设置--->重置手机--->清除全部内容--->手机关机--->开机--->进行恢复出厂的操作--->开机流程;
Step1:前面找settings中的布局我就省略了,这部分相对简单一些,直接到清除全部内容这个按钮的操作,
对应的java类是setting中的MasterClearConfirm.java这个类,
privateButton.OnClickListenermFinalClickListener=newButton.OnClickListener(){- publicvoidonClick(Viewv){
- if(Utils.isMonkeyRunning()){
- return;
- }
- if(mEraseSdCard){
- Intentintent=newIntent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
- intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
- getActivity().startService(intent);
- }else{
- getActivity().sendBroadcast(newIntent("android.intent.action.MASTER_CLEAR"));
- //Intenthandlingisasynchronous--assumeitwillhappensoon.
- }
- }
- };
private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() { public void onClick(View v) { if (Utils.isMonkeyRunning()) { return; } if (mEraseSdCard) { Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET); intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); getActivity().startService(intent); } else { getActivity().sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); // Intent handling is asynchronous -- assume it will happen soon. } } };
通过上述的代码,可以看出,实际上点击清除全部内容的时候,如果前面勾选上格式哈SD卡,就会执行mEraseSdCard为true里面的逻辑,如果没有勾选,就执行mEraseSdCard=false的逻辑,其实就是发送一个广播,
查看文本copy toclipboard打印?- “android.intent.action.MASTER_CLEAR”
“android.intent.action.MASTER_CLEAR”Step2:这个广播接受的地方,参见AndroidManifest.xml中的代码,如下:查看文本copy toclipboard打印?
- <</SPAN>receiverandroid:name="com.android.server.MasterClearReceiver"
- android:permission="android.permission.MASTER_CLEAR"
- android:priority="100">
- <</SPAN>intent-filter>
- <</SPAN>actionandroid:name="android.intent.action.MASTER_CLEAR"/>
- <</SPAN>actionandroid:name="com.google.android.c2dm.intent.RECEIVE"/>
- <</SPAN>categoryandroid:name="android.intent.category.MASTER_CLEAR"/>
- </</SPAN>intent-filter>
- </</SPAN>receiver>
找这个MasterClearReceiver.java这个receiver,下面来看看这个onReceiver()里面做了什么操作:查看文本copy toclipboard打印?
- publicvoidonReceive(finalContextcontext,finalIntentintent){
- if(intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)){
- if(!"google.com".equals(intent.getStringExtra("from"))){
- Slog.w(TAG,"Ignoringmasterclearrequest--notfromtrustedserver.");
- return;
- }
- }
- Slog.w(TAG,"!!!FACTORYRESET!!!");
- //Therebootcallisblocking,soweneedtodoitonanotherthread.
- Threadthr=newThread("Reboot"){
- @Override
- publicvoidrun(){
- try{
- RecoverySystem.rebootWipeUserData(context);
- Log.wtf(TAG,"Stillrunningaftermasterclear?!");
- }catch(IOExceptione){
- Slog.e(TAG,"Can'tperformmasterclear/factoryreset",e);
- }
- }
- };
- thr.start();
- }
public void onReceive(final Context context, final Intent intent) { if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) { if (!"google.com".equals(intent.getStringExtra("from"))) { Slog.w(TAG, "Ignoring master clear request -- not from trusted server."); return; } } Slog.w(TAG, "!!! FACTORY RESET !!!"); // The reboot call is blocking, so we need to do it on another thread. Thread thr = new Thread("Reboot") { @Override public void run() { try { RecoverySystem.rebootWipeUserData(context); Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); } } }; thr.start(); }
这个里面主要的操作是:RecoverySystem.rebootWipeUserData(context);准备做重启的动作,告诉手机要清除userData的数据;
Step3:接着来看看RecoverySystem.rebootWipeUserData()这个方法做了哪些操作:
查看文本copy toclipboard打印?- publicstaticvoidrebootWipeUserData(Contextcontext)throwsIOException{
- finalConditionVariablecondition=newConditionVariable();
- Intentintent=newIntent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
- context.sendOrderedBroadcastAsUser(intent,UserHandle.OWNER,
- android.Manifest.permission.MASTER_CLEAR,
- newBroadcastReceiver(){
- @Override
- publicvoidonReceive(Contextcontext,Intentintent){
- condition.open();
- }
- },null,0,null,null);
- //Blockuntiltheorderedbroadcasthascompleted.
- condition.block();
- bootCommand(context,"--wipe_datan--locale="+Locale.getDefault().toString());
- }
public static void rebootWipeUserData(Context context) throws IOException { final ConditionVariable condition = new ConditionVariable(); Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION"); context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER, android.Manifest.permission.MASTER_CLEAR, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { condition.open(); } }, null, 0, null, null); // Block until the ordered broadcast has completed. condition.block(); bootCommand(context, "--wipe_datan--locale=" + Locale.getDefault().toString()); }这个里面的广播可以先忽略不计,重点来看看bootCommand()这个方法,注意这个参数“--wipe_datan--locale=”查看文本copy toclipboard打印?
- privatestaticvoidbootCommand(Contextcontext,Stringarg)throwsIOException{
- RECOVERY_DIR.mkdirs();//Incaseweneedit
- COMMAND_FILE.delete();//Incaseit'snotwritable
- LOG_FILE.delete();
- FileWritercommand=newFileWriter(COMMAND_FILE);
- try{
- command.write(arg);
- command.write("n");
- }finally{
- command.close();
- }
- //Havingwrittenthecommandfile,goaheadandreboot
- PowerManagerpm=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
- pm.reboot("recovery");
- thrownewIOException("Rebootfailed(nopermissions?)");
- }
private static void bootCommand(Context context, String arg) throws IOException { RECOVERY_DIR.mkdirs(); // In case we need it COMMAND_FILE.delete(); // In case it's not writable LOG_FILE.delete(); FileWriter command = new FileWriter(COMMAND_FILE); try { command.write(arg); command.write("n"); } finally { command.close(); } // Having written the command file, go ahead and reboot PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); pm.reboot("recovery"); throw new IOException("Reboot failed (no permissions?)"); }这个方法的操作大致是“写节点/cache/recovery/command”,把传递过来的字符串写进去;然后调用PowerManager进行重启操作,reboot();
Step4:接着我们来看看PowerManager的reboot方法做了哪些操作:
查看文本copy toclipboard打印?- publicvoidreboot(Stringreason){
- try{
- mService.reboot(false,reason,true);
- }catch(RemoteExceptione){
- }
- }
public void reboot(String reason) { try { mService.reboot(false, reason, true); } catch (RemoteException e) { } }
这个调用到了PowerManagerService.java这个类的reboot方法中了:
查看文本copy toclipboard打印?- @Override//Bindercall
- publicvoidreboot(booleanconfirm,Stringreason,booleanwait){
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT,null);
- finallongident=Binder.clearCallingIdentity();
- try{
- shutdownOrRebootInternal(false,confirm,reason,wait);
- }finally{
- Binder.restoreCallingIdentity(ident);
- }
- }
@Override // Binder call public void reboot(boolean confirm, String reason, boolean wait) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); final long ident = Binder.clearCallingIdentity(); try { shutdownOrRebootInternal(false, confirm, reason, wait); } finally { Binder.restoreCallingIdentity(ident); } }重点来看看shutdownOrRebootInternal()这个方法,查看文本copy toclipboard打印?
- privatevoidshutdownOrRebootInternal(finalbooleanshutdown,finalbooleanconfirm,
- finalStringreason,booleanwait){
- if(mHandler==null||!mSystemReady){
- thrownewIllegalStateException("Tooearlytocallshutdown()orreboot()");
- }
- Runnablerunnable=newRunnable(){
- @Override
- publicvoidrun(){
- synchronized(this){
- if(shutdown){
- ShutdownThread.shutdown(mContext,confirm);
- }else{
- ShutdownThread.reboot(mContext,reason,confirm);
- }
- }
- }
- };
- //ShutdownThreadmustrunonaloopercapableofdisplayingtheUI.
- Messagemsg=Message.obtain(mHandler,runnable);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- //PowerManager.reboot()isdocumentednottoreturnsojustwaitfortheinevitable.
- if(wait){
- synchronized(runnable){
- while(true){
- try{
- runnable.wait();
- }catch(InterruptedExceptione){
- }
- }
- }
- }
- }
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) { } } } } }由于传递过来的shutdown为false,所以执行ShutdownThread.reboot(mContext,reason, confirm);reason:recevory
下面调用到ShutdownThread
Step5:这个追踪ShutdownThread.reboot()这个方法,这就有点像破案电影,一点一点查找罪犯的难点;
来窥视一下这个类:
查看文本copy toclipboard打印?- publicstaticvoidreboot(finalContextcontext,Stringreason,booleanconfirm){
- mReboot=true;
- mRebootSafeMode=false;
- mRebootReason=reason;
- Log.d(TAG,"reboot");
- shutdownInner(context,confirm);
- }
public static void reboot(final Context context, String reason, boolean confirm) { mReboot = true; mRebootSafeMode = false; mRebootReason = reason; Log.d(TAG, "reboot"); shutdownInner(context, confirm); }这个里面做的操作就是给这个变量mRebootReason复制“recevory”,重点调用shutdownInner()这个方法;查看文本copy toclipboard打印?
- staticvoidshutdownInner(finalContextcontext,booleanconfirm){
- //ensurethatonlyonethreadistryingtopowerdown.
- //anyadditionalcallsarejustreturned
- synchronized(sIsStartedGuard){
- if(sIsStarted){
- Log.d(TAG,"Requesttoshutdownalreadyrunning,returning.");
- return;
- }
- }
- Log.d(TAG,"Notifyingthreadtostartradioshutdown");
- bConfirmForAnimation=confirm;
- finalintlongPressBehavior=context.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
- finalintresourceId=mRebootSafeMode
- ?com.android.internal.R.string.reboot_safemode_confirm
- :(longPressBehavior==2
- ?com.android.internal.R.string.shutdown_confirm_question
- :com.android.internal.R.string.shutdown_confirm);
- Log.d(TAG,"NotifyingthreadtostartshutdownlongPressBehavior="+longPressBehavior);
- if(confirm){
- finalCloseDialogReceivercloser=newCloseDialogReceiver(context);
- if(sConfirmDialog!=null){
- sConfirmDialog.dismiss();
- }
- if(sConfirmDialog==null){
- Log.d(TAG,"PowerOffdialogdoesn'texist.Createitfirst");
- sConfirmDialog=newAlertDialog.Builder(context)
- .setTitle(mRebootSafeMode
- ?com.android.internal.R.string.reboot_safemode_title
- :com.android.internal.R.string.power_off)
- .setMessage(resourceId)
- .setPositiveButton(com.android.internal.R.string.yes,newDialogInterface.OnClickListener(){
- publicvoidonClick(DialogInterfacedialog,intwhich){
- beginShutdownSequence(context);
- if(sConfirmDialog!=null){
- sConfirmDialog=null;
- }
- }
- })
- .setNegativeButton(com.android.internal.R.string.no,newDialogInterface.OnClickListener(){
- publicvoidonClick(DialogInterfacedialog,intwhich){
- synchronized(sIsStartedGuard){
- sIsStarted=false;
- }
- if(sConfirmDialog!=null){
- sConfirmDialog=null;
- }
- }
- })
- .create();
- sConfirmDialog.setCancelable(false);//blockingbackkey
- sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- }
- closer.dialog=sConfirmDialog;
- sConfirmDialog.setOnDismissListener(closer);
- if(!sConfirmDialog.isShowing()){
- sConfirmDialog.show();
- }
- }else{
- beginShutdownSequence(context);
- }
- }
static void shutdownInner(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. // any additional calls are just returned synchronized (sIsStartedGuard) { if (sIsStarted) { Log.d(TAG, "Request to shutdown already running, returning."); return; } } Log.d(TAG, "Notifying thread to start radio shutdown"); bConfirmForAnimation = confirm; final int longPressBehavior = context.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior); final int resourceId = mRebootSafeMode ? com.android.internal.R.string.reboot_safemode_confirm : (longPressBehavior == 2 ? com.android.internal.R.string.shutdown_confirm_question : com.android.internal.R.string.shutdown_confirm); Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior); if (confirm) { final CloseDialogReceiver closer = new CloseDialogReceiver(context); if (sConfirmDialog != null) { sConfirmDialog.dismiss(); } if (sConfirmDialog == null) { Log.d(TAG, "PowerOff dialog doesn't exist. Create it first"); sConfirmDialog = new AlertDialog.Builder(context) .setTitle(mRebootSafeMode ? com.android.internal.R.string.reboot_safemode_title : com.android.internal.R.string.power_off) .setMessage(resourceId) .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { beginShutdownSequence(context); if (sConfirmDialog != null) { sConfirmDialog = null; } } }) .setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { synchronized (sIsStartedGuard) { sIsStarted = false; } if (sConfirmDialog != null) { sConfirmDialog = null; } } }) .create(); sConfirmDialog.setCancelable(false);//blocking back key sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); } closer.dialog = sConfirmDialog; sConfirmDialog.setOnDismissListener(closer); if (!sConfirmDialog.isShowing()) { sConfirmDialog.show(); } } else { beginShutdownSequence(context); } }看beginShutdownSequence()这个方法吧,重点调用到这个方法里面去了,来瞅瞅这个方法:查看文本copy toclipboard打印?
- privatestaticvoidbeginShutdownSequence(Contextcontext){
- synchronized(sIsStartedGuard){
- if(sIsStarted){
- Log.e(TAG,"ShutdownThreadisalreadyrunning,returning.");
- return;
- }
- sIsStarted=true;
- }
- //startthethreadthatinitiatesshutdown
- sInstance.mContext=context;
- sInstance.mPowerManager=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
- sInstance.mHandler=newHandler(){
- };
- bPlayaudio=true;
- if(!bConfirmForAnimation){
- if(!sInstance.mPowerManager.isScreenOn()){
- bPlayaudio=false;
- }
- }
- //throwupanindeterminatesystemdialogtoindicateradiois
- //shuttingdown.
- beginAnimationTime=0;
- booleanmShutOffAnimation=false;
- try{
- if(mIBootAnim==null){
- mIBootAnim=MediatekClassFactory.createInstance(IBootAnimExt.class);
- }
- }catch(Exceptione){
- e.printStackTrace();
- }
- intscreenTurnOffTime=mIBootAnim.getScreenTurnOffTime();
- mShutOffAnimation=mIBootAnim.isCustBootAnim();
- Log.e(TAG,"mIBootAnimgetscreenTurnOffTime:"+screenTurnOffTime);
- Stringcust=SystemProperties.get("ro.operator.optr");
- if(cust!=null){
- if(cust.equals("CUST")){
- mShutOffAnimation=true;
- }
- }
- synchronized(mEnableAnimatingSync){
- if(!mEnableAnimating){
- //sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM);
- }else{
- if(mShutOffAnimation){
- Log.e(TAG,"mIBootAnim.isCustBootAnim()istrue");
- bootanimCust();
- }else{
- pd=newProgressDialog(context);
- pd.setTitle(context.getText(com.android.internal.R.string.power_off));
- pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
- pd.setIndeterminate(true);
- pd.setCancelable(false);
- pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- pd.show();
- }
- sInstance.mHandler.postDelayed(mDelayDim,screenTurnOffTime);
- }
- }
- //makesureweneverfallasleepagain
- sInstance.mCpuWakeLock=null;
- try{
- sInstance.mCpuWakeLock=sInstance.mPowerManager.newWakeLock(
- 。。。。。。
- }
private static void beginShutdownSequence(Context context) { synchronized (sIsStartedGuard) { if (sIsStarted) { Log.e(TAG, "ShutdownThread is already running, returning."); return; } sIsStarted = true; } // start the thread that initiates shutdown sInstance.mContext = context; sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); sInstance.mHandler = new Handler() { }; bPlayaudio = true; if (!bConfirmForAnimation) { if (!sInstance.mPowerManager.isScreenOn()) { bPlayaudio = false; } } // throw up an indeterminate system dialog to indicate radio is // shutting down. beginAnimationTime = 0; boolean mShutOffAnimation = false; try { if (mIBootAnim == null) { mIBootAnim = MediatekClassFactory.createInstance(IBootAnimExt.class); } } catch (Exception e) { e.printStackTrace(); } int screenTurnOffTime = mIBootAnim.getScreenTurnOffTime(); mShutOffAnimation = mIBootAnim.isCustBootAnim(); Log.e(TAG, "mIBootAnim get screenTurnOffTime : " + screenTurnOffTime); String cust = SystemProperties.get("ro.operator.optr"); if (cust != null) { if (cust.equals("CUST")) { mShutOffAnimation = true; } } synchronized (mEnableAnimatingSync) { if(!mEnableAnimating) {// sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM); } else { if (mShutOffAnimation) { Log.e(TAG, "mIBootAnim.isCustBootAnim() is true"); bootanimCust(); } else { pd = new ProgressDialog(context); pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); pd.setIndeterminate(true); pd.setCancelable(false); pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); pd.show(); } sInstance.mHandler.postDelayed(mDelayDim, screenTurnOffTime ); } } // make sure we never fall asleep again sInstance.mCpuWakeLock = null; try { sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 。。。 。。。}
这段代码有句话会影响关机动画播放不完
“sInstance.mHandler.postDelayed(mDelayDim,screenTurnOffTime );”
解决办法
(1)“可以把这个screenTurnOffTime时间乘以2,这个时间看log是5000毫秒,就是5秒,乘以2就是10秒,大概就能播放完全关机动画了。”
(2)把这句话注释掉,但是有可能会引起问题,导致恢复出厂设置的时候没有进行恢复出厂的操作。目前正在追踪此问题;
这段代码中还有影响关机动画是否走客制化的关机动画,如果ro.operator.optr这个属性配置的是CUST,则会走客制化的关机动画,否则走系统默认的关机动画;
查看文本copy toclipboard打印?- Stringcust=SystemProperties.get("ro.operator.optr");
- if(cust!=null){
- if(cust.equals("CUST")){
- mShutOffAnimation=true;
- }
- }
String cust = SystemProperties.get("ro.operator.optr"); if (cust != null) { if (cust.equals("CUST")) { mShutOffAnimation = true; } }
然后重点看sInstance.start();这个方法,就走到了run()方法里满了;
Step6: 来看看ShutDownThread.java这个类的run()方法;
查看文本copy toclipboard打印?- publicvoidrun(){
- checkShutdownFlow();
- while(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- stMgr.saveStates(mContext);
- stMgr.enterShutdown(mContext);
- running();
- }
- if(mShutdownFlow!=IPO_SHUTDOWN_FLOW){
- stMgr.enterShutdown(mContext);
- running();
- }
- }
public void run() { checkShutdownFlow(); while (mShutdownFlow == IPO_SHUTDOWN_FLOW) { stMgr.saveStates(mContext); stMgr.enterShutdown(mContext); running(); } if (mShutdownFlow != IPO_SHUTDOWN_FLOW) { stMgr.enterShutdown(mContext); running(); } }重点看running()这个方法:
下面这个方法比较长,来分析一下:
查看文本copy toclipboard打印?- publicvoidrunning(){
- if(sPreShutdownApi!=null){
- try{
- sPreShutdownApi.onPowerOff();
- }catch(RemoteExceptione){
- Log.e(TAG,"onPowerOffexception"+e.getMessage());
- }
- }else{
- Log.w(TAG,"sPreShutdownApiisnull");
- }
- command=SystemProperties.get("sys.ipo.pwrdncap");
- BroadcastReceiverbr=newBroadcastReceiver(){
- @OverridepublicvoidonReceive(Contextcontext,Intentintent){
- //Wedon'tallowappstocancelthis,soignoretheresult.
- actionDone();
- }
- };
- {
- Stringreason=(mReboot?"1":"0")+(mRebootReason!=null?mRebootReason:"");
- SystemProperties.set(SHUTDOWN_ACTION_PROPERTY,reason);
- }
- if(mRebootSafeMode){
- SystemProperties.set(REBOOT_SAFEMODE_PROPERTY,"1");
- }
- Log.i(TAG,"Sendingshutdownbroadcast...");
- //Firstsendthehigh-levelshutdownbroadcast.
- mActionDone=false;
- ///M:2012-05-20ALPS00286063@{
- mContext.sendBroadcast(newIntent("android.intent.action.ACTION_PRE_SHUTDOWN"));
- ///@}2012-05-20
- mContext.sendOrderedBroadcastAsUser((newIntent()).setAction(Intent.ACTION_SHUTDOWN).putExtra("_mode",mShutdownFlow),
- UserHandle.ALL,null,br,mHandler,0,null,null);
- finallongendTime=SystemClock.elapsedRealtime()+MAX_BROADCAST_TIME;
- synchronized(mActionDoneSync){
- while(!mActionDone){
- longdelay=endTime-SystemClock.elapsedRealtime();
- if(delay<=0){
- Log.w(TAG,"ShutdownbroadcastACTION_SHUTDOWNtimedout");
- if(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- Log.d(TAG,"changeshutdownflowfromipotonormal:ACTION_SHUTDOWNtimeout");
- mShutdownFlow=NORMAL_SHUTDOWN_FLOW;
- }
- break;
- }
- try{
- mActionDoneSync.wait(delay);
- }catch(InterruptedExceptione){
- }
- }
- }
- //AlsosendACTION_SHUTDOWN_IPOinIPOshutdownflow
- if(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- mActionDone=false;
- mContext.sendOrderedBroadcast(newIntent("android.intent.action.ACTION_SHUTDOWN_IPO"),null,
- br,mHandler,0,null,null);
- finallongendTimeIPO=SystemClock.elapsedRealtime()+MAX_BROADCAST_TIME;
- synchronized(mActionDoneSync){
- while(!mActionDone){
- longdelay=endTimeIPO-SystemClock.elapsedRealtime();
- if(delay<=0){
- Log.w(TAG,"ShutdownbroadcastACTION_SHUTDOWN_IPOtimedout");
- if(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- Log.d(TAG,"changeshutdownflowfromipotonormal:ACTION_SHUTDOWN_IPOtimeout");
- mShutdownFlow=NORMAL_SHUTDOWN_FLOW;
- }
- break;
- }
- try{
- mActionDoneSync.wait(delay);
- }catch(InterruptedExceptione){
- }
- }
- }
- }
- if(mShutdownFlow!=IPO_SHUTDOWN_FLOW){
- //poweroffautotest,don'tmodify
- Log.i(TAG,"Shuttingdownactivitymanager...");
- finalIActivityManageram=
- ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
- if(am!=null){
- try{
- am.shutdown(MAX_BROADCAST_TIME);
- }catch(RemoteExceptione){
- }
- }
- }
- //poweroffautotest,don'tmodify
- //Shutdownradios.
- Log.i(TAG,"Shuttingdownradios...");
- shutdownRadios(MAX_RADIO_WAIT_TIME);
- //poweroffautotest,don'tmodify
- Log.i(TAG,"ShuttingdownMountService...");
- if((mShutdownFlow==IPO_SHUTDOWN_FLOW)&&(command.equals("1")||command.equals("3"))){
- Log.i(TAG,"bypassMountService!");
- }else{
- //ShutdownMountServicetoensuremediaisinasafestate
- IMountShutdownObserverobserver=newIMountShutdownObserver.Stub(){
- publicvoidonShutDownComplete(intstatusCode)throwsRemoteException{
- Log.w(TAG,"Resultcode"+statusCode+"fromMountService.shutdown");
- if(statusCode<0){
- mShutdownFlow=NORMAL_SHUTDOWN_FLOW;
- }
- actionDone();
- }
- };
- //Setinitialvariablesandtimeouttime.
- mActionDone=false;
- finallongendShutTime=SystemClock.elapsedRealtime()+MAX_SHUTDOWN_WAIT_TIME;
- synchronized(mActionDoneSync){
- try{
- finalIMountServicemount=IMountService.Stub.asInterface(
- ServiceManager.checkService("mount"));
- if(mount!=null){
- mount.shutdown(observer);
- }else{
- Log.w(TAG,"MountServiceunavailableforshutdown");
- }
- }catch(Exceptione){
- Log.e(TAG,"ExceptionduringMountServiceshutdown",e);
- }
- while(!mActionDone){
- longdelay=endShutTime-SystemClock.elapsedRealtime();
- if(delay<=0){
- Log.w(TAG,"Shutdownwaittimedout");
- if(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- Log.d(TAG,"changeshutdownflowfromipotonormal:MountService");
- mShutdownFlow=NORMAL_SHUTDOWN_FLOW;
- }
- break;
- }
- try{
- mActionDoneSync.wait(delay);
- }catch(InterruptedExceptione){
- }
- }
- }
- }
- //poweroffautotest,don'tmodify
- //mountSerivce���
- Log.i(TAG,"MountServiceshutdone...");
- //[MTK]fixshutdownanimationtimingissue
- //==================================================================
- try{
- SystemProperties.set("service.shutanim.running","1");
- Log.i(TAG,"setservice.shutanim.runningto1");
- }catch(Exceptionex){
- Log.e(TAG,"Failedtoset'service.shutanim.running'=1).");
- }
- //==================================================================
- if(mShutdownFlow==IPO_SHUTDOWN_FLOW){
- if(SHUTDOWN_VIBRATE_MS>0){
- //vibratebeforeshuttingdown
- Vibratorvibrator=newSystemVibrator();
- try{
- vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
- }catch(Exceptione){
- //Failuretovibrateshouldn'tinterruptshutdown.Justlogit.
- Log.w(TAG,"Failedtovibrateduringshutdown.",e);
- }
- //vibratorisasynchronoussoweneedtowaittoavoidshuttingdowntoosoon.
- try{
- Thread.sleep(SHUTDOWN_VIBRATE_MS);
- }catch(InterruptedExceptionunused){
- }
- }
- //Shutdownpower
- //poweroffautotest,don'tmodify
- Log.i(TAG,"Performingipolow-levelshutdown...");
- delayForPlayAnimation();
- if(sInstance.mScreenWakeLock!=null&&sInstance.mScreenWakeLock.isHeld()){
- sInstance.mScreenWakeLock.release();
- sInstance.mScreenWakeLock=null;
- }
- sInstance.mHandler.removeCallbacks(mDelayDim);
- stMgr.shutdown(mContext);
- stMgr.finishShutdown(mContext);
- //TovoidpreviousUIflickcausedbyshutdownanimationstoppingbeforeBKLturningoff
- if(pd!=null){
- pd.dismiss();
- pd=null;
- }elseif(beginAnimationTime>0){
- try{
- SystemProperties.set("service.bootanim.exit","1");
- Log.i(TAG,"set'service.bootanim.exit'=1).");
- }catch(Exceptionex){
- Log.e(TAG,"Failedtoset'service.bootanim.exit'=1).");
- }
- //SystemProperties.set("ctl.stop","bootanim");
- }
- synchronized(sIsStartedGuard){
- sIsStarted=false;
- }
- sInstance.mPowerManager.setBacklightBrightnessOff(false);
- sInstance.mCpuWakeLock.acquire(2000);
- synchronized(mShutdownThreadSync){
- try{
- mShutdownThreadSync.wait();
- }catch(InterruptedExceptione){
- }
- }
- }else{
- rebootOrShutdown(mReboot,mRebootReason);
- }
- }
public void running() { if(sPreShutdownApi != null){ try { sPreShutdownApi.onPowerOff(); } catch (RemoteException e) { Log.e(TAG, "onPowerOff exception" + e.getMessage()); } }else{ Log.w(TAG, "sPreShutdownApi is null"); } command = SystemProperties.get("sys.ipo.pwrdncap"); BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. actionDone(); } }; { String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : ""); SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); } if (mRebootSafeMode) { SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); } Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. mActionDone = false; /// M: 2012-05-20 ALPS00286063 @{ mContext.sendBroadcast(new Intent("android.intent.action.ACTION_PRE_SHUTDOWN")); /// @} 2012-05-20 mContext.sendOrderedBroadcastAsUser((new Intent()).setAction(Intent.ACTION_SHUTDOWN).putExtra("_mode", mShutdownFlow), UserHandle.ALL, null, br, mHandler, 0, null, null); final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; synchronized (mActionDoneSync) { while (!mActionDone) { long delay = endTime - SystemClock.elapsedRealtime(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast ACTION_SHUTDOWN timed out"); if (mShutdownFlow == IPO_SHUTDOWN_FLOW) { Log.d(TAG, "change shutdown flow from ipo to normal: ACTION_SHUTDOWN timeout"); mShutdownFlow = NORMAL_SHUTDOWN_FLOW; } break; } try { mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } } // Also send ACTION_SHUTDOWN_IPO in IPO shut down flow if (mShutdownFlow == IPO_SHUTDOWN_FLOW) { mActionDone = false; mContext.sendOrderedBroadcast(new Intent("android.intent.action.ACTION_SHUTDOWN_IPO"), null, br, mHandler, 0, null, null); final long endTimeIPO = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; synchronized (mActionDoneSync) { while (!mActionDone) { long delay = endTimeIPO - SystemClock.elapsedRealtime(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast ACTION_SHUTDOWN_IPO timed out"); if (mShutdownFlow == IPO_SHUTDOWN_FLOW) { Log.d(TAG, "change shutdown flow from ipo to normal: ACTION_SHUTDOWN_IPO timeout"); mShutdownFlow = NORMAL_SHUTDOWN_FLOW; } break; } try { mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } } } if (mShutdownFlow != IPO_SHUTDOWN_FLOW) { // power off auto test, --don't modify Log.i(TAG, "Shutting down activity manager..."); final IActivityManager am = ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); if (am != null) { try { am.shutdown(MAX_BROADCAST_TIME); } catch (RemoteException e) { } } } // power off auto test, don't modify // Shutdown radios. Log.i(TAG, "Shutting down radios..."); shutdownRadios(MAX_RADIO_WAIT_TIME); // power off auto test, don't modify Log.i(TAG, "Shutting down MountService..."); if ( (mShutdownFlow == IPO_SHUTDOWN_FLOW) && (command.equals("1")||command.equals("3")) ) { Log.i(TAG, "bypass MountService!"); } else { // Shutdown MountService to ensure media is in a safe state IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { public void onShutDownComplete(int statusCode) throws RemoteException { Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); if (statusCode < 0) { mShutdownFlow = NORMAL_SHUTDOWN_FLOW; } actionDone(); } }; // Set initial variables and time out time. mActionDone = false; final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; synchronized (mActionDoneSync) { try { final IMountService mount = IMountService.Stub.asInterface( ServiceManager.checkService("mount")); if (mount != null) { mount.shutdown(observer); } else { Log.w(TAG, "MountService unavailable for shutdown"); } } catch (Exception e) { Log.e(TAG, "Exception during MountService shutdown", e); } while (!mActionDone) { long delay = endShutTime - SystemClock.elapsedRealtime(); if (delay <= 0) { Log.w(TAG, "Shutdown wait timed out"); if (mShutdownFlow == IPO_SHUTDOWN_FLOW) { Log.d(TAG, "change shutdown flow from ipo to normal: MountService"); mShutdownFlow = NORMAL_SHUTDOWN_FLOW; } break; } try { mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } } } // power off auto test, don't modify //mountSerivce ��� Log.i(TAG, "MountService shut done..."); // [MTK] fix shutdown animation timing issue //================================================================== try { SystemProperties.set("service.shutanim.running","1"); Log.i(TAG, "set service.shutanim.running to 1"); } catch (Exception ex) { Log.e(TAG, "Failed to set 'service.shutanim.running' = 1)."); } //================================================================== if (mShutdownFlow == IPO_SHUTDOWN_FLOW) { if (SHUTDOWN_VIBRATE_MS > 0) { // vibrate before shutting down Vibrator vibrator = new SystemVibrator(); try { vibrator.vibrate(SHUTDOWN_VIBRATE_MS); } catch (Exception e) { // Failure to vibrate shouldn't interrupt shutdown. Just log it. Log.w(TAG, "Failed to vibrate during shutdown.", e); } // vibrator is asynchronous so we need to wait to avoid shutting down too soon. try { Thread.sleep(SHUTDOWN_VIBRATE_MS); } catch (InterruptedException unused) { } } // Shutdown power // power off auto test, don't modify Log.i(TAG, "Performing ipo low-level shutdown..."); delayForPlayAnimation(); if (sInstance.mScreenWakeLock != null && sInstance.mScreenWakeLock.isHeld()) { sInstance.mScreenWakeLock.release(); sInstance.mScreenWakeLock = null; } sInstance.mHandler.removeCallbacks(mDelayDim); stMgr.shutdown(mContext); stMgr.finishShutdown(mContext); //To void previous UI flick caused by shutdown animation stopping before BKL turning off if (pd != null) { pd.dismiss(); pd = null; } else if (beginAnimationTime > 0) { try { SystemProperties.set("service.bootanim.exit","1"); Log.i(TAG, "set 'service.bootanim.exit' = 1)."); } catch (Exception ex) { Log.e(TAG, "Failed to set 'service.bootanim.exit' = 1)."); } //SystemProperties.set("ctl.stop","bootanim"); } synchronized (sIsStartedGuard) { sIsStarted = false; } sInstance.mPowerManager.setBacklightBrightnessOff(false); sInstance.mCpuWakeLock.acquire(2000); synchronized (mShutdownThreadSync) { try { mShutdownThreadSync.wait(); } catch (InterruptedException e) { } } } else { rebootOrShutdown(mReboot, mRebootReason); } }这个方法做了一些列的操作,会关闭一些操作,如:
- shutdownRadios(MAX_RADIO_WAIT_TIME);
- mount.shutdown(observer);
- stMgr.shutdown(mContext);
Step7:来看看rebootOrShutdown()这个方法:
查看文本copy toclipboard打印?- publicstaticvoidrebootOrShutdown(booleanreboot,Stringreason){
- if(reboot){
- Log.i(TAG,"Rebooting,reason:"+reason);
- if((reason!=null)&&reason.equals("recovery")){
- delayForPlayAnimation();
- }
- try{
- PowerManagerService.lowLevelReboot(reason);
- }catch(Exceptione){
- Log.e(TAG,"Rebootfailed,willattemptshutdowninstead",e);
- }
- }elseif(SHUTDOWN_VIBRATE_MS>0){
- //vibratebeforeshuttingdown
- Vibratorvibrator=newSystemVibrator();
- try{
- vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
- }catch(Exceptione){
- //Failuretovibrateshouldn'tinterruptshutdown.Justlogit.
- Log.w(TAG,"Failedtovibrateduringshutdown.",e);
- }
- //vibratorisasynchronoussoweneedtowaittoavoidshuttingdowntoosoon.
- try{
- Thread.sleep(SHUTDOWN_VIBRATE_MS);
- }catch(InterruptedExceptionunused){
- }
- }
- delayForPlayAnimation();
- //Shutdownpower
- //poweroffautotest,don'tmodify
- Log.i(TAG,"Performinglow-levelshutdown...");
- //PowerManagerService.lowLevelShutdown();
- //addyourfunc:HDMIoff
- //addforMFR
- try{
- if(ImHDMI==null)
- ImHDMI=MediatekClassFactory.createInstance(IHDMINative.class);
- }catch(Exceptione){
- e.printStackTrace();
- }
- ImHDMI.hdmiPowerEnable(false);
- try{
- if(mTvOut==null)
- mTvOut=MediatekClassFactory.createInstance(ITVOUTNative.class);
- }catch(Exceptione){
- e.printStackTrace();
- }
- mTvOut.tvoutPowerEnable(false);
- //addyourfunc:HDMIoff
- //unmoutdata/cachepartitionswhileperformingshutdown
- SystemProperties.set("ctl.start","shutdown");
- try{
- Thread.currentThread().sleep(Integer.MAX_VALUE);
- }catch(Exceptione){
- Log.e(TAG,"ShutdownrebootOrShutdownThread.currentThread().sleepexception!");
- }
- }
public static void rebootOrShutdown(boolean reboot, String reason) { if (reboot) { Log.i(TAG, "Rebooting, reason: " + reason); if ( (reason != null) && reason.equals("recovery") ) { delayForPlayAnimation(); } try { PowerManagerService.lowLevelReboot(reason); } catch (Exception e) { Log.e(TAG, "Reboot failed, will attempt shutdown instead", e); } } else if (SHUTDOWN_VIBRATE_MS > 0) { // vibrate before shutting down Vibrator vibrator = new SystemVibrator(); try { vibrator.vibrate(SHUTDOWN_VIBRATE_MS); } catch (Exception e) { // Failure to vibrate shouldn't interrupt shutdown. Just log it. Log.w(TAG, "Failed to vibrate during shutdown.", e); } // vibrator is asynchronous so we need to wait to avoid shutting down too soon. try { Thread.sleep(SHUTDOWN_VIBRATE_MS); } catch (InterruptedException unused) { } } delayForPlayAnimation(); // Shutdown power // power off auto test, don't modify Log.i(TAG, "Performing low-level shutdown..."); //PowerManagerService.lowLevelShutdown(); //add your func: HDMI off //add for MFR try { if (ImHDMI == null) ImHDMI=MediatekClassFactory.createInstance(IHDMINative.class); } catch (Exception e) { e.printStackTrace(); } ImHDMI.hdmiPowerEnable(false); try { if (mTvOut == null) mTvOut =MediatekClassFactory.createInstance(ITVOUTNative.class); } catch (Exception e) { e.printStackTrace(); } mTvOut.tvoutPowerEnable(false); //add your func: HDMI off //unmout data/cache partitions while performing shutdown SystemProperties.set("ctl.start", "shutdown"); try { Thread.currentThread().sleep(Integer.MAX_VALUE); } catch ( Exception e) { Log.e(TAG, "Shutdown rebootOrShutdown Thread.currentThread().sleep exception!"); } }关机震动也在这个方法里面;这个方法重点看PowerManagerService.lowLevelReboot(reason);
Log.i(TAG, "Rebooting, reason: " +reason);这句log也很重要,可以有助于我们分析代码;
Step8:下面来看看PowerManagerServices.java这个类的lowLevelReboot()这个方法:
查看文本copy toclipboard打印?- publicstaticvoidlowLevelReboot(Stringreason)throwsIOException{
- nativeReboot(reason);
- }
public static void lowLevelReboot(String reason) throws IOException { nativeReboot(reason); }这个方法调用到了native里面,后面的操作我就不分析了。。。
大致流程是:
关机,然后开机,底层判断节点后进入恢复出厂模式,recevory.img释放完全后,进入开机的流程。。。
以后有进展再补充这部分的流程,整个过程大致就是这个样子了,里面的细节有好多没有分析,大家可以自行研究。。。,抛砖引玉的目的达到了。