700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > android 恢复出厂设置流程分析 Android恢复出厂设置流程分析

android 恢复出厂设置流程分析 Android恢复出厂设置流程分析

时间:2021-12-10 12:59:47

相关推荐

android 恢复出厂设置流程分析 Android恢复出厂设置流程分析

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

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

Step

1:前面找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(PONENT_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(PONENT_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的逻辑,其实就是发送一个广播,

“android.intent.action.MASTER_CLEAR”

“android.intent.action.MASTER_CLEAR”

Step

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

<receiverandroid:name="com.android.server.MasterClearReceiver"

android:permission="android.permission.MASTER_CLEAR"

android:priority="100">

<intent-filter>

<actionandroid:name="android.intent.action.MASTER_CLEAR"/>

<actionandroid:name="com.google.android.c2dm.intent.RECEIVE"/>

<categoryandroid:name="android.intent.category.MASTER_CLEAR"/>

intent-filter>

receiver>

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

publicvoidonReceive(finalContextcontext,finalIntentintent){

if(intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)){

if(!"".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 (!"".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的数据;

Step

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

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_data\n--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_data\n--locale=" + Locale.getDefault().toString());

}

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

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();

Step

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

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方法中了:

@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()这个方法,

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

Step

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

来窥视一下这个类:

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()这个方法;

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()这个方法吧,重点调用到这个方法里面去了,来瞅瞅这个方法:

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,则会走客制化的关机动画,否则走系统默认的关机动画;

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()方法里满了;

Step

6: 来看看ShutDownThread.java这个类的run()方法;

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()这个方法:

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

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:-05-20ALPS00286063@{

mContext.sendBroadcast(newIntent("android.intent.action.ACTION_PRE_SHUTDOWN"));

///@}-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: -05-20 ALPS00286063 @{

mContext.sendBroadcast(new Intent("android.intent.action.ACTION_PRE_SHUTDOWN"));

/// @} -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);

重点看rebootOrShutdown(mReboot,

mRebootReason);这个方法;准备重启的方法;

Step

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

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也很重要,可以有助于我们分析代码;

Step

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

publicstaticvoidlowLevelReboot(Stringreason)throwsIOException{

nativeReboot(reason);

}

public static void lowLevelReboot(String reason) throws IOException {

nativeReboot(reason);

}

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

大致流程是:

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。