代码路径:
frameworks/base/services/java/com/android/server/power/PowerManagerService.java
frameworks/base/services/java/com/android/server/power/ShutdownThread.java
日志关键TAG:ShutdownThread、PowerManagerService
在应用层调用shutdown()方法进行关机
private void shutdown() {
log("shutdown()");
try {
IPowerManager power = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
if (power != null) {
power.shutdown(false, false);
}
} catch (RemoteException doe) {
log("shutdown() RemoteException:"+doe.getMessage());
}
}
在/PowerManagerService.java文件中shutdown()方法进行关机
/**
* Shuts down the device.
*
* @param confirm If true, shows a shutdown confirmation dialog.
* @param wait If true, this call waits for the shutdown to complete and does not return.
*/
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
在/PowerManagerService.java文件中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) {
}
}
}
}
}
在ShutdownThread.java文件中最终调用shutdownInner函数进行关机
public static void shutdown(final Context context, boolean confirm) {
mReboot = false;
mRebootSafeMode = false;
// SPRD: add log for debug @{
Slog.i(TAG, "shutdown goto shutdownInner");
// @}
shutdownInner(context, confirm);
}
在ShutdownThread.java文件中shutdownInner方法中,如果confirm变量为true,则会弹出关机对话框,如果为false就不弹出,就执行beginShutdownSequence()方法
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;
}
}
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);
final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
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) {
/* SPRD: add for apct functions @{ */
if (APCTOption.self().isApctPowerOffSupport())
{
if (!mRebootSafeMode) {
shutdownBeginTime = System.currentTimeMillis();
}
}
final Runnable shutDownRun = new Runnable() {
@Override
public void run() {
Slog.i(TAG, "shutdownInner goto beginShutdownSequence");
beginShutdownSequence(context);
}
};
final Handler handler = new Handler();
if (tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
final PhoneStateListener listener = new PhoneStateListener(){
@Override
public void onCallStateChanged(int state,String incomingNumber) {
if(tm.getCallState() == TelephonyManager.CALL_STATE_IDLE){
try {
Thread.currentThread().sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//now the system is shutdown, we may not listen to none.
handler.removeCallbacks(shutDownRun);
shutDownRun.run();
}
}
};
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
tm.endCall();
handler.postDelayed(shutDownRun, 3500);
return;
}
/* @} */
// SPRD: add log for debug @{
Slog.i(TAG, "shutdownInner goto beginShutdownSequence");
// @}
beginShutdownSequence(context);
}
})
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
sConfirmDialog.show();
} else {
beginShutdownSequence(context);
}
}
在ShutdownThread.java文件中beginShutdownSequence方法中通过Runtime类中exec方法输入shutdown命令进行关机
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
}
ProgressDialog 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);
// SPRD: remove origin code
// pd.show();
shutdownTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_TIME;
for(int i = 0;i<boardname.length;i++){
if(SystemProperties.get("ro.product.board").equals(boardname[i])){
isLteBoard = true;
break;
}
}
{
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
try {
wm.setForceOrientation(0);
} catch (RemoteException e) {
Log.e(TAG, "stop orientation failed!", e);
}
// @}
String[] bootcmd = {"bootanimation", "shutdown"} ;
try {
Log.i(TAG, "exec the bootanimation ");
SystemProperties.set("service.bootanim.exit", "0");
Runtime.getRuntime().exec(bootcmd);
} catch (Exception e){
Log.e(TAG,"bootanimation command exe err!");
}
}
/* @} */
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
// SPRD: call scheduleButtonTimeout(long now).
sInstance.mPowerManager.scheduleButtonLightTimeout(SystemClock.uptimeMillis());
// make sure we never fall asleep again
sInstance.mCpuWakeLock = null;
try {
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
sInstance.mCpuWakeLock.setReferenceCounted(false);
sInstance.mCpuWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mCpuWakeLock = null;
}
// also make sure the screen stays on for better user experience
sInstance.mScreenWakeLock = null;
if (sInstance.mPowerManager.isScreenOn()) {
try {
sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
sInstance.mScreenWakeLock.setReferenceCounted(false);
sInstance.mScreenWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mScreenWakeLock = null;
}
}
disableAcc();
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start();
}