Android恢复出厂设置流程分析
(2013-12-03 15:59:53)分类: android开关机 |
Android恢复出厂设置流程分析【Android源码解析十】
-
-
void onClick(View v) { -
(Utils.isMonkeyRunning()) { -
-
} -
-
(mEraseSdCard) { -
Intent intent = Intent(ExternalStorageFormatter .FORMAT_AND_FACTORY_RESET); -
intent.setComponent(ExternalStorageFormatter .COMPONENT_NAME); -
getActivity().startService(intent); -
} { -
getActivity().sendBroadcast( 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()) { 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的逻辑,其实就是发送一个广播,
-
“android.intent.action.MASTER_CLEAR”
“android.intent.action.MASTER_CLEAR”
- <</SPAN>receiver
android:name="com.android.server.MasterClearReceiver" -
-
> -
-
-
android:name="android.intent.action.MASTER_CLEAR" /> -
-
-
android:name="com.google.android.c2dm.intent.RECEIVE" /> -
android:name="android.intent.category.MASTER_CLEAR" /> -
-
找这个MasterClearReceiver.java这个receiver,下面来看看这个onReceiver()里面做了什么操作:
- public
void onReceive( finalContext finalcontext, Intent intent) { -
(intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) { -
(! "google.com".equals(intent.getStringExtra("from"))){ -
Slog.w(TAG, 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 = Thread( "Reboot"){ -
-
void run() { -
{ -
RecoverySystem.rebootWipeUserData(context); -
Log.wtf(TAG, running );after master clear?!" -
} (IOException e) { -
Slog.e(TAG, 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 (!"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的数据;
- public
static void rebootWipeUserData(Context throwscontext) IOException { -
ConditionVariable newcondition = ConditionVariable(); -
-
Intent intent = Intent( "android.intent.action.MASTER_CLEAR_NOTIFICATION"); -
context.sendOrderedBroadcastAsUs er(intent, UserHandle.OWNER, -
android.Manifest.permission.MASTER_CLEAR, -
BroadcastReceiver() { -
-
void onReceive(Context context, Intent intent) { -
condition.open(); -
} -
}, 0, null, null); -
-
Block until the ordered broadcast has completed. -
condition.block(); -
-
bootCommand(context, + 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.sendOrderedBroadcastAsUs这个里面的广播可以先忽略不计,重点来看看bootCommand()这个方法,注意这个参数“--wipe_data\n--locale=”er(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()); }
- private
static void bootCommand(Context throwscontext, String arg) IOException { -
RECOVERY_DIR.mkdirs(); In case we need it -
COMMAND_FILE.delete(); In case it's not writable -
LOG_FILE.delete(); -
-
FileWriter command = FileWriter(COMMAND_FILE); -
{ -
command.write(arg); -
command.write( -
} { -
command.close(); -
} -
-
Having written the command file, go ahead and reboot -
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); -
pm.reboot( -
-
new IOException( "Rebootfailed );(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); 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();
- public
void reboot(String reason) { -
{ -
mService.reboot( reason, true); -
} (RemoteException e) { -
} -
}
public void reboot(String reason) { try { mService.reboot(false, reason, true); } catch (RemoteException e) { } }
这个调用到了PowerManagerService.java这个类的reboot方法中了:
- @Override
// Binder call -
void reboot( booleanconfirm, booleanString reason, wait) { -
mContext.enforceCallingOrSelfPerm ission(android.Manifest.permission.REBOOT, -
-
long ident = Binder.clearCallingIdentity(); -
{ -
shutdownOrRebootInternal ( confirm, reason, wait); -
} { -
Binder.restoreCallingIdentity(ident); -
} -
}
@Override // Binder call public void reboot(boolean confirm, String reason, boolean wait) { mContext.enforceCallingOrSelfPerm重点来看看shutdownOrRebootInternalission(android.Manifest.permission.REBOOT, null); final long ident = Binder.clearCallingIdentity(); try { shutdownOrRebootInternal (false, confirm, reason, wait); } finally { Binder.restoreCallingIdentity(ident); } }
- private
void shutdownOrRebootInternal final( boolean shutdown, finalboolean confirm, -
String booleanreason, wait) { -
(mHandler null== || !mSystemReady) { -
new IllegalStateException( "Tooearly );to call shutdown() or reboot()" -
} -
-
Runnable runnable = Runnable() { -
-
void run() { -
( this){ -
(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( -
mHandler.sendMessage(msg); -
-
PowerManager.reboot() is documented not to return so just wait for the inevitable. -
(wait) { -
(runnable) { -
( true){ -
{ -
runnable.wait(); -
} (InterruptedException e) { -
} -
} -
} -
} -
}
private void shutdownOrRebootInternal由于传递过来的shutdown为false,所以执行ShutdownThread.reboot(mContext, reason, confirm);reason:recevory(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) { } } } } }
下面调用到ShutdownThread
来窥视一下这个类:
- public
static void reboot( finalContext booleancontext, String reason, confirm) { -
mReboot = -
mRebootSafeMode = -
mRebootReason = reason; -
Log.d(TAG, -
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()这个方法;
- static
void shutdownInner( finalContext booleancontext, confirm) { -
ensure that only one thread is trying to power down. -
any additional calls are just returned -
(sIsStartedGuard) { -
(sIsStarted) { -
Log.d(TAG, to );shutdown already running, returning." -
-
} -
} -
-
Log.d(TAG, thread );to start radio shutdown" -
bConfirmForAnimation = confirm; -
int longPressBehavior = context.getResources().getInteger( -
com.android.internal.R.integer.config_longPressOnPowerBehavior ); -
int resourceId = mRebootSafeMode -
? com.android.internal.R.string.reboot_safemode_confirm -
: (longPressBehavior == -
? com.android.internal.R.string.shutdown_confirm_question -
: com.android.internal.R.string.shutdown_confirm); -
-
Log.d(TAG, thread to start shutdown longPressBehavior=" + longPressBehavior); -
-
(confirm) { -
CloseDialogReceiver newcloser = CloseDialogReceiver(context); -
(sConfirmDialog null)!= { -
sConfirmDialog.dismiss(); -
} -
(sConfirmDialog null)== { -
Log.d(TAG, dialog );doesn't exist. Create it first" -
sConfirmDialog = 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, DialogInterface.OnClickListener() { -
void onClick(DialogInterface intdialog, which) { -
beginShutdownSequence(context); -
(sConfirmDialog null)!= { -
sConfirmDialog = -
} -
} -
}) -
.setNegativeButton(com.android.internal.R.string.no, DialogInterface.OnClickListener() { -
void onClick(DialogInterface intdialog, which) { -
(sIsStartedGuard) { -
sIsStarted = -
} -
(sConfirmDialog null)!= { -
sConfirmDialog = -
} -
} -
}) -
.create(); -
sConfirmDialog.setCancelable( back key -
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); -
-
-
sConfirmDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); -
} -
-
closer.dialog = sConfirmDialog; -
sConfirmDialog.setOnDismissListener(closer); -
-
(!sConfirmDialog.isShowing()) { -
sConfirmDialog.show(); -
} -
} { -
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()这个方法吧,重点调用到这个方法里面去了,来瞅瞅这个方法:
- private
static void beginShutdownSequence(Context context) { -
(sIsStartedGuard) { -
(sIsStarted) { -
Log.e(TAG, is );already running, returning." -
-
} -
sIsStarted = -
} -
-
start the thread that initiates shutdown -
sInstance.mContext = context; -
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); -
sInstance.mHandler = Handler() { -
}; -
-
bPlayaudio = -
(!bConfirmForAnimation) { -
(!sInstance.mPowerManager.isScreenOn()) { -
bPlayaudio = -
} -
} -
-
throw up an indeterminate system dialog to indicate radio is -
shutting down. -
beginAnimationTime = -
mShutOffAnimation false;= -
-
{ -
(mIBootAnim null)== { -
mIBootAnim = MediatekClassFactory.createInstance(IBootAnimExt. -
} -
} (Exception e) { -
e.printStackTrace(); -
} -
-
screenTurnOffTime = mIBootAnim.getScreenTurnOffTime(); -
mShutOffAnimation = mIBootAnim.isCustBootAnim(); -
Log.e(TAG, get screenTurnOffTime : " + screenTurnOffTime); -
-
String cust = SystemProperties.get( -
-
(cust null)!= { -
(cust.equals( "CUST")){ -
mShutOffAnimation = -
} -
} -
-
(mEnableAnimatingSync) { -
-
{ - //
sInstance.mPowerManager.setBacklightBrightness(PowerManager.BRIGHTNESS_DIM); -
} { -
(mShutOffAnimation) { -
Log.e(TAG, is );true" -
bootanimCust(); -
} { -
pd = 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( -
pd.setCancelable( -
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( -
。。。 。。。 - }
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 );
解决办法
这段代码中还有影响关机动画是否走客制化的关机动画,如果ro.operator.optr这个属性配置的是CUST,则会走客制化的关机动画,否则走系统默认的关机动画;
-
String
cust "ro.operator.optr");= SystemProperties.get( -
-
-
(cust null)!= { -
(cust.equals( "CUST")){ -
mShutOffAnimation = -
} -
}
String cust = SystemProperties.get("ro.operator.optr"); if (cust != null) { if (cust.equals("CUST")) { mShutOffAnimation = true; } }
然后重点看
- public
void run() { -
checkShutdownFlow(); -
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
stMgr.saveStates(mContext); -
stMgr.enterShutdown(mContext); -
running(); -
} -
(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() { -
!= null){ -
{ -
sPreShutdownApi.onPowerOff(); -
} (RemoteException e) { -
Log.e(TAG, exception" + e.getMessage()); -
} -
} -
Log.w(TAG, is );null" -
} -
-
command = SystemProperties.get( -
-
BroadcastReceiver br = BroadcastReceiver() { -
public void onReceive(Context context, Intent intent) { -
We don't allow apps to cancel this, so ignore the result. -
actionDone(); -
} -
}; -
-
-
{ -
String reason = (mReboot ? : "0")+ null(mRebootReason != ? "");mRebootReason : -
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); -
} -
-
-
(mRebootSafeMode) { -
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, -
} -
-
Log.i(TAG, shutdown );broadcast..." -
-
First send the high-level shut down broadcast. -
mActionDone = -
M: 2012-05-20 ALPS00286063 @{ -
mContext.sendBroadcast( Intent( "android.intent.action.ACTION_PRE_SHUTDOWN")); -
@} 2012-05-20 -
mContext.sendOrderedBroadcastAsUs er(( Intent()).setAction(Intent.ACTION_SHUTDOWN).putExtra( "_mode",mShutdownFlow), -
UserHandle.ALL, br, 0,mHandler, null, null); -
-
long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; -
(mActionDoneSync) { -
(!mActionDone) { -
delay = endTime - SystemClock.elapsedRealtime(); -
(delay 0)<= { -
Log.w(TAG, broadcast );ACTION_SHUTDOWN timed out" -
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
Log.d(TAG, shutdown );flow from ipo to normal: ACTION_SHUTDOWN timeout" -
mShutdownFlow = NORMAL_SHUTDOWN_FLOW; -
} -
-
} -
{ -
mActionDoneSync.wait(delay); -
} (InterruptedException e) { -
} -
} -
} -
-
Also send ACTION_SHUTDOWN_IPO in IPO shut down flow -
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
mActionDone = -
mContext.sendOrderedBroadcast( Intent( "android.intent.action.ACTION_SHUTDOWN_IPO"),null, -
br, mHandler, null, null); -
long endTimeIPO = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; -
(mActionDoneSync) { -
(!mActionDone) { -
delay = endTimeIPO - SystemClock.elapsedRealtime(); -
(delay 0)<= { -
Log.w(TAG, broadcast );ACTION_SHUTDOWN_IPO timed out" -
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
Log.d(TAG, shutdown );flow from ipo to normal: ACTION_SHUTDOWN_IPO timeout" -
mShutdownFlow = NORMAL_SHUTDOWN_FLOW; -
} -
-
} -
{ -
mActionDoneSync.wait(delay); -
} (InterruptedException e) { -
} -
} -
} -
} -
-
(mShutdownFlow != IPO_SHUTDOWN_FLOW) { -
power off auto test, don't modify -
Log.i(TAG, down );activity manager..." -
-
IActivityManager am = -
ActivityManagerNative.asInterface(ServiceManager.checkService( -
(am null)!= { -
{ -
am.shutdown(MAX_BROADCAST_TIME); -
} (RemoteException e) { -
} -
} -
} -
-
power off auto test, don't modify -
Shutdown radios. -
Log.i(TAG, down );radios..." -
shutdownRadios(MAX_RADIO_WAIT_TIME); -
-
power off auto test, don't modify -
Log.i(TAG, down );MountService..." -
( "1")||command.equals("3"))(mShutdownFlow == IPO_SHUTDOWN_FLOW) && (command.equals( ) { -
Log.i(TAG, MountService!" ); -
} { -
Shutdown MountService to ensure media is in a safe state -
IMountShutdownObserver observer = IMountShutdownObserver.Stub() { -
void onShutDownComplete( intstatusCode) throwsRemoteException { -
Log.w(TAG, code " + "statusCode + from );MountService.shutdown" -
(statusCode 0)< { -
mShutdownFlow = NORMAL_SHUTDOWN_FLOW; -
} -
actionDone(); -
} -
}; -
-
-
-
Set initial variables and time out time. -
mActionDone = -
long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; -
(mActionDoneSync) { -
{ -
IMountService mount = IMountService.Stub.asInterface( -
ServiceManager.checkService( -
(mount null)!= { -
mount.shutdown(observer); -
} { -
Log.w(TAG, unavailable );for shutdown" -
} -
} (Exception e) { -
Log.e(TAG, during ,MountService shutdown" e); -
} -
(!mActionDone) { -
delay = endShutTime - SystemClock.elapsedRealtime(); -
(delay 0)<= { -
Log.w(TAG, wait );timed out" -
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
Log.d(TAG, shutdown );flow from ipo to normal: MountService" -
mShutdownFlow = NORMAL_SHUTDOWN_FLOW; -
} -
-
} -
{ -
mActionDoneSync.wait(delay); -
} (InterruptedException e) { -
} -
} -
} -
} -
-
power off auto test, don't modify -
��� -
Log.i(TAG, shut );done..." -
[MTK] fix shutdown animation timing issue -
-
{ -
SystemProperties.set( -
Log.i(TAG, service.shutanim.running );to 1" -
-
} (Exception ex) { -
Log.e(TAG, to );set 'service.shutanim.running' = 1)." -
} -
-
-
(mShutdownFlow == IPO_SHUTDOWN_FLOW) { -
(SHUTDOWN_VIBRATE_MS 0)> { -
vibrate before shutting down -
Vibrator vibrator = SystemVibrator(); -
{ -
vibrator.vibrate(SHUTDOWN_VIBRATE_MS); -
} (Exception e) { -
Failure to vibrate shouldn't interrupt shutdown. Just log it. -
Log.w(TAG, to ,vibrate during shutdown." e); -
} -
-
vibrator is asynchronous so we need to wait to avoid shutting down too soon. -
{ -
Thread.sleep(SHUTDOWN_VIBRATE_MS); -
} (InterruptedException unused) { -
} -
} -
-
Shutdown power -
power off auto test, don't modify -
Log.i(TAG, ipo );low-level shutdown..." -
-
delayForPlayAnimation(); -
-
(sInstance.mScreenWakeLock null!= && sInstance.mScreenWakeLock.isHeld()) { -
sInstance.mScreenWakeLock.release(); -
sInstance.mScreenWakeLock = -
} -
-
sInstance.mHandler.removeCallbacks(mDelayDim); -
stMgr.shutdown(mContext); -
stMgr.finishShutdown(mContext); -
-
void previous UI flick caused by shutdown animation stopping before BKL turning off -
(pd null)!= { -
pd.dismiss(); -
pd = -
} if (beginAnimationTime 0)> { -
{ -
SystemProperties.set( -
Log.i(TAG, 'service.bootanim.exit' );= 1)." -
} (Exception ex) { -
Log.e(TAG, to );set 'service.bootanim.exit' = 1)." -
} -
-
} -
-
(sIsStartedGuard) { -
sIsStarted = -
} -
-
sInstance.mPowerManager.setBacklightBrightnessOf f( -
sInstance.mCpuWakeLock.acquire( -
-
(mShutdownThreadSync) { -
{ -
mShutdownThreadSync.wait(); -
} (InterruptedException e) { -
} -
} -
} { -
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);
- public
static void rebootOrShutdown( booleanreboot, String reason) { -
(reboot) { -
Log.i(TAG, reason: " + reason); -
( null)(reason != && "recovery")reason.equals( ) { -
delayForPlayAnimation(); -
} -
{ -
PowerManagerService.lowLevelReboot(reason); -
} (Exception e) { -
Log.e(TAG, failed, ,will attempt shutdown instead" e); -
} -
} if (SHUTDOWN_VIBRATE_MS 0)> { -
vibrate before shutting down -
Vibrator vibrator = SystemVibrator(); -
{ -
vibrator.vibrate(SHUTDOWN_VIBRATE_MS); -
} (Exception e) { -
Failure to vibrate shouldn't interrupt shutdown. Just log it. -
Log.w(TAG, to ,vibrate during shutdown." e); -
} -
-
vibrator is asynchronous so we need to wait to avoid shutting down too soon. -
{ -
Thread.sleep(SHUTDOWN_VIBRATE_MS); -
} (InterruptedException unused) { -
} -
} -
-
delayForPlayAnimation(); -
Shutdown power -
power off auto test, don't modify -
Log.i(TAG, low-level );shutdown..." -
-
your func: HDMI off -
for MFR -
{ -
(ImHDMI null)== -
ImHDMI=MediatekClassFactory.createInstance(IHDMINative. -
} (Exception e) { -
e.printStackTrace(); -
} -
ImHDMI.hdmiPowerEnable( -
{ -
(mTvOut null)== -
mTvOut =MediatekClassFactory.createInstance(ITVOUTNative. -
} (Exception e) { -
e.printStackTrace(); -
} -
-
mTvOut.tvoutPowerEnable( -
your func: HDMI off -
data/cache partitions while performing shutdown -
-
SystemProperties.set( "shutdown"); -
-
-
{ -
Thread.currentThread().sleep(Integer.MAX_VALUE); -
} ( Exception e) { -
Log.e(TAG, 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();
}
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);
- public
static void lowLevelReboot(String throwsreason) IOException { -
nativeReboot(reason); -
}
public static void lowLevelReboot(String reason) throws IOException {
nativeReboot(reason);
}
这个方法调用到了native里面,后面的操作我就不分析了。。。
大致流程是:
以后有进展再补充这部分的流程,整个过程大致就是这个样子了,里面的细节有好多没有分析,大家可以自行研究。。。,抛砖引玉的目的达到了。