安卓怎样联想手机恢复出厂设置置

Android恢复出厂设置流程分析
Android恢复出厂设置流程分析【Android源码解析十】
最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程;
在setting--&备份与重置---&恢复出厂设置---&重置手机---&清除全部内容---&手机关机---&开机---&进行恢复出厂的操作---&开机流程;
1:前面找settings中的布局我就省略了,这部分相对简单一些,直接到清除全部内容这个按钮的操作,
对应的java类是setting中的MasterClearConfirm.java这个类,
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.
&&&&&&&&&&&&}
private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
public void onClick(View v) {
if (Utils.isMonkeyRunning()) {
if (mEraseSdCard) {
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
getActivity().startService(intent);
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”
2:这个广播接受的地方,参见AndroidManifest.xml中的代码,如下:
&&/SPAN&receiver&android:name="com.android.server.MasterClearReceiver"&&
&&&&&&&&&&&&android:permission="android.permission.MASTER_CLEAR"&&
&&&&&&&&&&&&android:priority="100"&&&&
&&&&&&&&&&&&&&/SPAN&intent-filter&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&/SPAN&action&android:name="android.intent.action.MASTER_CLEAR"&/&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&/SPAN&action&android:name="com.google.android.c2dm.intent.RECEIVE"&/&&&
&&&&&&&&&&&&&&&&&&/SPAN&category&android:name="android.intent.category.MASTER_CLEAR"&/&&&
&&&&&&&&&&&&&/&/SPAN&intent-filter&&&
&&&&&&&&&/&/SPAN&receiver&&&
找这个MasterClearReceiver.java这个receiver,下面来看看这个onReceiver()里面做了什么操作:
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();
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.");
Slog.w(TAG, "!!! FACTORY RESET !!!");
// The reboot call is blocking, so we need to do it on another thread.
Thread thr = new Thread("Reboot") {
public void run() {
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的数据;
3:接着来看看RecoverySystem.rebootWipeUserData()这个方法做了哪些操作:
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());
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() {
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=”
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?)");
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);
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();
4:接着我们来看看PowerManager的reboot方法做了哪些操作:
public&void&reboot(String&reason)&{
&&&&&&try&{
&&&&&&&&&&mService.reboot(false,&reason,&true);
&&&&&&}&catch&(RemoteException&e)&{
public void reboot(String reason) {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
这个调用到了PowerManagerService.java这个类的reboot方法中了:
@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);
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
重点来看看shutdownOrRebootInternal()这个方法,
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)&{
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&}
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() {
public void run() {
synchronized (this) {
if (shutdown) {
ShutdownThread.shutdown(mContext, confirm);
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) {
runnable.wait();
} catch (InterruptedException e) {
由于传递过来的shutdown为false,所以执行ShutdownThread.reboot(mContext,
reason, confirm);reason:recevory
下面调用到ShutdownThread
5:这个追踪ShutdownThread.reboot()这个方法,这就有点像破案电影,一点一点查找罪犯的难点;
来窥视一下这个类:
public&static&void&reboot(final&Context&context,&String&reason,&boolean&confirm)&{
&&&&&&&mReboot&=&true;
&&&&&&&mRebootSafeMode&=&false;
&&&&&&&mRebootReason&=&
&&&&&&&Log.d(TAG,&"reboot");
&&&&&&&shutdownInner(context,&confirm);
public static void reboot(final Context context, String reason, boolean confirm) {
mRebootSafeMode =
mRebootReason =
Log.d(TAG, "reboot");
shutdownInner(context, confirm);
这个里面做的操作就是给这个变量mRebootReason复制“recevory”,重点调用shutdownInner()这个方法;
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&=&
&&&&&&&&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&=&sConfirmD
&&&&&&&&&&&&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.");
Log.d(TAG, "Notifying thread to start radio shutdown");
bConfirmForAnimation =
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 =
.setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
synchronized (sIsStartedGuard) {
sIsStarted =
if (sConfirmDialog != null) {
sConfirmDialog =
.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 = sConfirmD
sConfirmDialog.setOnDismissListener(closer);
if (!sConfirmDialog.isShowing()) {
sConfirmDialog.show();
beginShutdownSequence(context);
看beginShutdownSequence()这个方法吧,重点调用到这个方法里面去了,来瞅瞅这个方法:
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&=&
&&&&&&&&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(
&&&&&&&&&&&&&&&&&&&&。。。&。。。
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.e(TAG, "ShutdownThread is already running, returning.");
sIsStarted =
// start the thread that initiates shutdown
sInstance.mContext =
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
sInstance.mHandler = new Handler() {
bPlayaudio =
if (!bConfirmForAnimation) {
if (!sInstance.mPowerManager.isScreenOn()) {
bPlayaudio =
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
beginAnimationTime = 0;
boolean mShutOffAnimation =
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 =
synchronized (mEnableAnimatingSync) {
if(!mEnableAnimating) {
sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM);
if (mShutOffAnimation) {
Log.e(TAG, "mIBootAnim.isCustBootAnim() is true");
bootanimCust();
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 =
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
。。。 。。。
这段代码有句话会影响关机动画播放不完
“sInstance.mHandler.postDelayed(mDelayDim,
screenTurnOffTime );&”
(1)“可以把这个screenTurnOffTime时间乘以2,这个时间看log是5000毫秒,就是5秒,乘以2就是10秒,大概就能播放完全关机动画了。”
(2)把这句话注释掉,但是有可能会引起问题,导致恢复出厂设置的时候没有进行恢复出厂的操作。目前正在追踪此问题;
这段代码中还有影响关机动画是否走客制化的关机动画,如果ro.operator.optr这个属性配置的是CUST,则会走客制化的关机动画,否则走系统默认的关机动画;
String&cust&=&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 =
然后重点看&sInstance.start();这个方法,就走到了run()方法里满了;
6: 来看看ShutDownThread.java这个类的run()方法;
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();
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()这个方法:
下面这个方法比较长,来分析一下:
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:&&ALPS&@{
&&&&&&&mContext.sendBroadcast(new&Intent("android.intent.action.ACTION_PRE_SHUTDOWN"));
&&&&&&&///&@}&
&&&&&&&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(<font COLOR="#C0);&
&&&&&&&&&&&synchronized&(mShutdownThreadSync)&{
&&&&&&&&&&&&&&&try&{
&&&&&&&&&&&&&&&&&&&mShutdownThreadSync.wait();
&&&&&&&&&&&&&&&}&catch&(InterruptedException&e)&{
&&&&&&&&&&&&&&&}
&&&&&&&&&&&}
&&&&&&&}&else&{
&&&&&&&&&&&rebootOrShutdown(mReboot,&mRebootReason);
public void running() {
if(sPreShutdownApi != null){
sPreShutdownApi.onPowerOff();
} catch (RemoteException e) {
Log.e(TAG, "onPowerOff exception" + e.getMessage());
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 =
mContext.sendBroadcast(new Intent("android.intent.action.ACTION_PRE_SHUTDOWN"));
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;
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
// Also send ACTION_SHUTDOWN_IPO in IPO shut down flow
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
mActionDone =
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;
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) {
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!");
// 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 =
final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
synchronized (mActionDoneSync) {
final IMountService mount = IMountService.Stub.asInterface(
ServiceManager.checkService("mount"));
if (mount != null) {
mount.shutdown(observer);
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;
mActionDoneSync.wait(delay);
} catch (InterruptedException e) {
// power off auto test, don't modify
//mountSerivce &#65533;&#65533;&#65533;
Log.i(TAG, "MountService shut done...");
// [MTK] fix shutdown animation timing issue
//==================================================================
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();
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.
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 =
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();
} else if (beginAnimationTime & 0) {
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 =
sInstance.mPowerManager.setBacklightBrightnessOff(false);
sInstance.mCpuWakeLock.acquire(2000);
synchronized (mShutdownThreadSync) {
mShutdownThreadSync.wait();
} catch (InterruptedException e) {
rebootOrShutdown(mReboot, mRebootReason);
这个方法做了一些列的操作,会关闭一些操作,如:
&shutdownRadios(MAX_RADIO_WAIT_TIME);
mount.shutdown(observer);
stMgr.shutdown(mContext);
重点看& rebootOrShutdown(mReboot,
mRebootReason);这个方法;准备重启的方法;
7:来看看rebootOrShutdown()这个方法:
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!");&&
public static void rebootOrShutdown(boolean reboot, String reason) {
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
if ( (reason != null) && reason.equals("recovery") ) {
delayForPlayAnimation();
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();
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.
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
if (ImHDMI == null)
ImHDMI=MediatekClassFactory.createInstance(IHDMINative.class);
} catch (Exception e) {
e.printStackTrace();
ImHDMI.hdmiPowerEnable(false);
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");
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也很重要,可以有助于我们分析代码;
8:下面来看看PowerManagerServices.java这个类的lowLevelReboot()这个方法:
public&static&void&lowLevelReboot(String&reason)&throws&IOException&{
&&&&&&&&nativeReboot(reason);
public static void lowLevelReboot(String reason) throws IOException {
nativeReboot(reason);
这个方法调用到了native里面,后面的操作我就不分析了。。。
大致流程是:
&关机,然后开机,底层判断节点后进入恢复出厂模式,recevory.img释放完全后,进入开机的流程。。。
以后有进展再补充这部分的流程,整个过程大致就是这个样子了,里面的细节有好多没有分析,大家可以自行研究。。。,抛砖引玉的目的达到了。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 联想手机恢复出厂设置 的文章

 

随机推荐