一、PowerManager(电源服务)
简介:Android系统为我们提供的电源管理的一个API,其相关接口与设备电池的续航能力有很大的关联, 官方也说了,除非是迫不得已吧,不然的话,应该尽量避免使用这个类,并且使用完以后一定要及时释放。所谓的电源管理包括:CPU运行,键盘或者屏幕亮起来!核心其实就是wakelock锁机制,只要我们拿着这个锁, 那么系统就无法进入休眠状态,可以给用户态程序或内核获取到。锁可以是:”有超时的“或者 “没有超时“,超时的锁到时间后会自动解锁,如果没有了锁或超时,内核会启动休眠机制来进入休眠。
1、PowerManager的使用
1.1、添加权限
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DEVICE_POWER"/>
1.2、代码使用
private PowerManager mPowerManager;
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
2、PowerManager方法使用
2.1、系统重启流程分析
//这个方法是让系统重启
if(mPowerManager != null)
{
mPowerManager.reboot("");
}
//执行上面那个方法会到PowerManager中
frameworks/base/core/java/android/os/PowerManager.java
final IPowerManager mService;
public PowerManager(Context context, IPowerManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
public void reboot(String reason) {
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
//PowerManagerService.java处理流程
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if (PowerManager.REBOOT_RECOVERY.equals(reason)
|| PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
/*SPRD : add power debug log start*/
Log.d(TAG,
"reboot the device , UID : " + Binder.getCallingUid() + " , PID : "
+ Binder.getCallingPid() + " , reason : " + reason + " , confirm = " + confirm + " , wait = " + wait);
/*SPRD : add power debug log end*/
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
if (RescueParty.isAttemptingFactoryReset()) {
// If we're stuck in a really low-level reboot loop, and a
// rescue party is trying to prompt the user for a factory data
// reset, we must GET TO DA CHOPPA!
PowerManagerService.lowLevelReboot(reason);
} else {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
}
}
Runnable runnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
ShutdownThread.rebootSafeMode(getUiContext(), confirm);
} else if (haltMode == HALT_MODE_REBOOT) {
ShutdownThread.reboot(getUiContext(), reason, confirm);
} else {
ShutdownThread.shutdown(getUiContext(), reason, confirm);
}
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
Message msg = Message.obtain(UiThread.getHandler(), runnable);
msg.setAsynchronous(true);
UiThread.getHandler().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处理流程,这里是继承Thread
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
/**
* Request a clean shutdown, waiting for subsystems to clean up their
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
* @param context Context used to display the shutdown progress dialog. This must be a context
* suitable for displaying UI (aka Themable).
* @param reason code to pass to the kernel (e.g. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootHasProgressBar = false;
mReason = reason;
shutdownInner(context, confirm);
}
//关机对话框UI大小在这里处理
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();
Log.d("111", "shutdownInner: 11111111");
// 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
//SPRD:Bug714046 Add for reboot prompt
: (mReboot
? com.android.internal.R.string.reboot_device_confirm
//SPRD:Bug714046 Add for reboot prompt end
: (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
//SPRD:Bug714046 Add for reboot prompt
:(mReboot
? com.android.internal.R.string.reboot_device_title
//SPRD:Bug714046 Add for reboot prompt end
: 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();
LayoutInflater inflater = LayoutInflater.from(context) ;
View view = inflater.inflate(com.android.internal.R.layout.shoutdown_thread_dialog, null) ;
TextView tvTitle = (TextView) view.findViewById(com.android.internal.R.id.tv_dialog_title);
TextView tvContent = (TextView) view.findViewById(com.android.internal.R.id.tv_dialog_content);
ImageView ivYes = (ImageView) view.findViewById(com.android.internal.R.id.iv_dialog_yes);
ImageView ivNo = (ImageView) view.findViewById(com.android.internal.R.id.iv_dialog_no);
tvTitle.setText(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
//SPRD:Bug714046 Add for reboot prompt
:(mReboot
? com.android.internal.R.string.reboot_device_title
//SPRD:Bug714046 Add for reboot prompt end
: com.android.internal.R.string.power_off));
tvContent.setText(resourceId);
sConfirmDialog.setView(view);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
sConfirmDialog.getWindow().setBackgroundDrawableResource(com.android.internal.R.drawable.ic_shoutdown_thread_dialog_bg);
ivYes.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SystemProperties.set("persist.is.reboot","true");
beginShutdownSequence(context);
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
}
}});
ivNo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
}
}});
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.show();
if ("typeZhiMaKeJi2".equals(SystemProperties.get("persist.sys.ui.type","UI1"))) {
sConfirmDialog.getWindow().setLayout(480, 276);
}else if ("typeV9CardUI".equals(SystemProperties.get("persist.sys.ui.type","UI1"))) {
sConfirmDialog.getWindow().setLayout(480, 276);
//zqc linboqiang add end
}else if("typeP5UI".equals(SystemProperties.get("persist.sys.ui.type","UI1"))){
sConfirmDialog.getWindow().setLayout(480, 276);
} else {
sConfirmDialog.getWindow().setLayout(572, 276);
}
//modified text size
/*sConfirmDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextSize(22);
sConfirmDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextSize(22);
try {
Field mAlert = AlertDialog.class.getDeclaredField("mAlert");
mAlert.setAccessible(true);
Object mAlertController = mAlert.get(sConfirmDialog);
Field mTitle = mAlertController.getClass().getDeclaredField("mTitleView");
mTitle.setAccessible(true);
TextView mTitleView = (TextView) mTitle.get(mAlertController);
mTitleView.setTextSize(28);
mTitleView.setTextColor(Color.WHITE);
Field mMessage = mAlertController.getClass().getDeclaredField("mMessageView");
mMessage.setAccessible(true);
TextView mMessageView = (TextView) mMessage.get(mAlertController);
mMessageView.setTextSize(20);
mMessageView.setTextColor(Color.WHITE);
} catch (Exception e) {
e.printStackTrace();
}*/
} else {
beginShutdownSequence(context);
}
}