从上一篇可以看到,最终会调用此类的shutdown以及reboot等函数,我们来看一下这些函数的实现。
(A)被调用函数
//frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
public static void shutdown(final Context context, String reason, boolean confirm) {
mReboot = false;
mRebootSafeMode = false;
mReason = reason;
shutdownInner(context, confirm);
}
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootHasProgressBar = false;
mReason = reason;
shutdownInner(context, confirm);
}
public static void rebootSafeMode(final Context context, boolean confirm) {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
return;
}
mReboot = true;
mRebootSafeMode = true;
mRebootHasProgressBar = false;
mReason = null;
shutdownInner(context, confirm);
}
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);
Log.e(TAG, "Reboot failed, will attempt shutdown instead");
reason = null;
} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
// vibrate before shutting down
Vibrator vibrator = new SystemVibrator(context);
try {
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
} 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) {
}
}
///M: added for shutdown Enhancement@{
sInstance.mLowLevelShutdownSeq(context);
/// @}
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
PowerManagerService.lowLevelShutdown(reason);
}
(B)shutdownInner函数实现
接下来看一下shutdownInner内部实现。
private static void shutdownInner(final Context context, boolean confirm) {
// ShutdownThread is called from many places, so best to verify here that the context passed
// in is themed.
context.assertRuntimeOverlayThemable();
//xinghui add.avoid shutdown when monkey test.
if (ActivityManager.isUserAMonkey()) {
Log.d(TAG, "Cannot request to shutdown when Monkey is running, returning.");
return;
}
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();
}
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);
}
})
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
if (mReboot && !mRebootSafeMode) {
sConfirmDialog.setTitle(com.android.internal.R.string.global_action_restart);
sConfirmDialog.setMessage(context.getText(com.android.internal.R.string.reboot_confirm_question));
}
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
sConfirmDialog.show();
} else {
beginShutdownSequence(context);
}
}
由于这段代码融合了phone,TV,tablet等平台,所以字符串有不同的区分。
<string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"您的平板电脑会关闭。"</string>
<string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"您的 Android TV 设备将关闭。"</string>
<string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"您的手表即将关机。"</string>
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"您的手机将会关机。"</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"您要关机吗?"</string>
而具体是如何区分phone,TV,tablet等平台的,因为会根据系统的如下属性。
PRODUCT_CHARACTERISTICS := nosdcard
PRODUCT_CHARACTERISTICS := tv
ifndef PRODUCT_CHARACTERISTICS
TARGET_AAPT_CHARACTERISTICS := default
else
TARGET_AAPT_CHARACTERISTICS := $(PRODUCT_CHARACTERISTICS)
endif
ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)
(C)MTK重载的部分关机流程函数
这里要提一下,MTK平台有自定义部分关机流程函数,我们可以同步了解一下。
public class ShutdownThread extends Thread {
protected boolean mIsShowShutdownSysui() {
return true;
}
protected boolean mIsShowShutdownDialog(Context c) {
return true;
}
//add by fenghuan for 开关机动画 end
protected boolean mStartShutdownSeq(Context c, boolean IsReboot) {
return true;
}
protected void mShutdownSeqFinish(Context c) {
return;
}
protected void mLowLevelShutdownSeq(Context c) {
return;
}
}
(D)beginShutdownSequence函数实现
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
}
sInstance.mProgressDialog = showShutdownDialog(context);
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
//...
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
///M: added for Shutdown Enhancement @{
if(sInstance.mStartShutdownSeq(context, mReboot)) {
sInstance.start();
}
}
//vendor/mediatek/proprietary/frameworks/base/services/core/java/com/mediatek/server/MtkShutdownThread.java
public class MtkShutdownThread extends ShutdownThread {
@Override
protected boolean mIsShowShutdownSysui() {
//...
return true;
}
@Override
protected boolean mIsShowShutdownDialog(Context context) {
//...
return true;
}
@Override
protected boolean mStartShutdownSeq(Context context, boolean isReboot) {
//...
return true;
}
@Override
protected void mShutdownSeqFinish(Context context) {
//...
}
@Override
protected void mLowLevelShutdownSeq(Context context) {
//...
}
}
大致关机Log如下:
03-30 07:48:25.865 1342 1342 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
03-30 07:48:27.303 1342 1342 D ShutdownThread: Attempting to use SysUI shutdown UI
03-30 07:48:27.303 1342 1342 D ShutdownThread: SysUI handling shutdown UI
03-30 07:48:27.311 1342 1342 I MtkShutdownThread: hct screen turn off time shutdown_animation_play_time =6000
03-30 07:48:27.312 1342 1342 I MtkShutdownThread: screen turn off time screenTurnOffTime =6000
03-30 07:48:27.321 1342 7625 I ShutdownThread: Sending shutdown broadcast...
03-30 07:48:27.554 1342 7625 I ShutdownThread: Shutting down activity manager...
03-30 07:48:27.842 1342 7625 I ShutdownThread: Shutting down package manager...
03-30 07:48:27.888 1342 7630 W ShutdownThread: Turning off cellular radios...
03-30 07:48:27.902 1342 7630 I ShutdownThread: Waiting for Radio...
03-30 07:48:28.413 1342 7630 I ShutdownThread: Radio turned off.
03-30 07:48:28.414 1342 7630 I ShutdownThread: Radio shutdown complete.
03-30 07:48:28.415 1342 7625 I MtkShutdownThread: mShutOffAnimation: 1
03-30 07:48:28.418 1342 7625 I ShutdownThread: rebootOrShutdown:goToSleep
03-30 07:48:28.918 1342 7625 I ShutdownThread: Rebooting, reason: user requested
在boot_normal中可以看到开机原因。
//adb reboot
bootstat: Canonical boot reason: reboot,shell
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : reboot,shell. Last reboot reason read from persist.sys.boot.reason : reboot,shell
bootstat: Normalized last reboot reason : reboot,shell
//adb reboot -p
bootstat: Canonical boot reason: cold,powerkey
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : shutdown,shell. Last reboot reason read from persist.sys.boot.reason : shutdown,shell
bootstat: Normalized last reboot reason : shutdown,shell
//power键关机
bootstat: Canonical boot reason: cold,powerkey
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : shutdown,userrequested. Last reboot reason read from persist.sys.boot.reason : shutdown,userrequested
bootstat: Normalized last reboot reason : shutdown,userrequested
//power键重启
bootstat: Canonical boot reason: reboot,userrequested
bootstat: Last reboot reason read from /metadata/bootstat/persist.sys.boot.reason : reboot,userrequested. Last reboot reason read from persist.sys.boot.reason : reboot,userrequested
bootstat: Normalized last reboot reason : reboot,userrequested
因篇幅问题不能全部显示,请点此查看更多更全内容