Android8.1 PowerManager(電源服務)的使用

一、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);
        }
    }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章