當用戶長按power鍵的時候,系統會在PhoneWindowManager中調用html
mGlobalActions.showDialog,來顯示關機、飛行、重啓等界面選項。java
而咱們須要在GlobalActions.Java中建立一個重啓的選項。下面咱們從GlobalActions中的createDialog節選一段代碼:android
[java] view plain copygit
- mItems = new ArrayList<Action>();
- String[] defaultActions = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_globalActionsList);//讀取配置文件中config_globalActionsList內容,下面詳細介紹
-
- ArraySet<String> addedKeys = new ArraySet<String>();
- for (int i = 0; i < defaultActions.length; i++) {
- String actionKey = defaultActions[i];
- if (addedKeys.contains(actionKey)) {
- // If we already have added this, don't add it again.
- continue;
- }
- if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
- mItems.add(new PowerAction());
- } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
- mItems.add(mAirplaneModeOn);
- else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) {//咱們本身添加了一個重啓功能,在config文件中找到reboot這一項就添加這個reboot
- mItems.add(new RebootAction());
- } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
- if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
- mItems.add(getBugReportAction());
- }
- } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
- if (mShowSilentToggle) {
- mItems.add(mSilentModeAction);
- }
- } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
- if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
- addUsersToMenu(mItems);
- }
- } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
- mItems.add(getSettingsAction());
- } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
- mItems.add(getLockdownAction());
- } else {
- Log.e(TAG, "Invalid global action key " + actionKey);
- }
- // Add here so we don't add more than one.
- addedKeys.add(actionKey);
- }
咱們本身還須要新建一個RebootAction,咱們看下代碼:app
[java] view plain copyasync
- private final class RebootAction extends SinglePressAction {
- private RebootAction() {
- super(com.android.internal.R.drawable.ic_lock_restart,//界面圖片和內容
- R.string.global_action_restart);
- }
-
- public void onPress() {
- mWindowManagerFuncs.reboot(true);//長按重啓
- }
-
- public boolean showDuringKeyguard() {
- return true;
- }
-
- public boolean showBeforeProvisioning() {
- return true;
- }
- }
還有須要在資源文件中添加一些內容:ide
須要在core/res/res/values-zh-rCN/strings.xml中添加以下:函數
[html] view plain copyui
- <string name="global_action_restart">"從新啓動"</string>
- <string name="restart_confirm_question">"您要從新啓動手機嗎?"</string>
- <string name="restart_confirm">"您的手機會從新啓動。"</string>
- <string name="restart">"從新啓動"</string>
在core/res/res/values/strings.xml中this
[html] view plain copy
- <string name="global_action_restart">Restart</string>
- <string name="restart_confirm_question">"Would you like to restart?"</string>
- <string name="restart_confirm">"Your phone will restart."</string>
- <string name="restart">"Restart"</string>
在core/res/res/values/symbols.xml中
[html] view plain copy
- <java-symbol type="string" name="global_action_restart"/>
- <java-symbol type="string" name="restart_confirm_question"/>
- <java-symbol type="string" name="restart_confirm"/>
- <java-symbol type="string" name="restart"/>
- <java-symbol type="drawable" name="ic_lock_restart" />
還須要添加一個圖標的圖片
[html] view plain copy
- diff --git a/core/res/res/drawable-hdpi/ic_lock_restart.png b/core/res/res/drawable-hdpi/ic_lock_restart.png
-
- diff --git a/core/res/res/drawable-ldpi/ic_lock_restart.png b/core/res/res/drawable-ldpi/ic_lock_restart.png
-
- diff --git a/core/res/res/drawable-mdpi/ic_lock_restart.png b/core/res/res/drawable-mdpi/ic_lock_restart.png
-
- diff --git a/core/res/res/drawable-xhdpi/ic_lock_restart.png b/core/res/res/drawable-xhdpi/ic_lock_restart.png
最後咱們須要在core/res/res/values/config.xml中增長几個選項來打開重啓等功能
[html] view plain copy
- <string-array translatable="false" name="config_globalActionsList">
- <item>power</item>
- <item>bugreport</item>
- <item>users</item>
- <item>airplane</item>//飛行模式
- <item>reboot</item>//新增重啓功能
- </string-array>
而上面再GlobalActions中添加的reboot,須要在WindowManagerPolicy新增接口
[java] view plain copy
- public void shutdown(boolean confirm);
- public void rebootSafeMode(boolean confirm);
- public void reboot(boolean confirm);//新增的接口
而且最總在WindowManagerService中實現:
[java] view plain copy
- @Override
- public void reboot(boolean confirm) {
- Log.d(TAG,"reboot confirm:" + confirm);
- ShutdownThread.reboot(mContext, null, confirm);
- }
最後調用ShutdownThread的reboot函數。
[java] view plain copy
- public static void reboot(final Context context, String reason, boolean confirm) {
- mReboot = true;//這個參數最後決定是重啓仍是關機
- mRebootSafeMode = false;
- mRebootReason = reason;
- shutdownInner(context, confirm);
- }
下面主要看下ShutdownThread的shutdownInner這個函數,主要是建立彈出框,以及開啓線程執行關機或重啓。
[java] view plain copy
- static void shutdownInner(final Context context, boolean confirm) {
- 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 int resourceIdMsg;
- final int resourceIdTitle;
- if(mReboot){//這段是咱們添加的,根據不一樣選項建立不一樣的界面
- resourceIdTitle = com.android.internal.R.string.restart;
- resourceIdMsg = longPressBehavior == 2
- ? com.android.internal.R.string.restart_confirm_question
- : com.android.internal.R.string.restart_confirm;
- }
- else if(mRebootSafeMode){
- resourceIdTitle = com.android.internal.R.string.reboot_safemode_title;
- resourceIdMsg = com.android.internal.R.string.reboot_safemode_confirm;
- }
- else {
- resourceIdTitle = com.android.internal.R.string.power_off;
- resourceIdMsg = longPressBehavior == 2
- ? com.android.internal.R.string.shutdown_confirm_question
- : com.android.internal.R.string.shutdown_confirm;
- }
-
- if (confirm) {//這個參數決定是否須要彈出對話框
- final CloseDialogReceiver closer = new CloseDialogReceiver(context);
- if (sConfirmDialog != null) {
- sConfirmDialog.dismiss();
- }
- sConfirmDialog = new AlertDialog.Builder(context)//這邊彈出一個對話框也將其進行了修改,主要是顯示
- .setTitle(resourceIdTitle)
- .setMessage(resourceIdMsg)
- .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- beginShutdownSequence(context);//當確認了調用beginShutdownSequence函數,執行關機或重啓。
- }
- })
- .setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- //set the mReboot to default value for next time.
- mReboot = false;//不確認就直接結束了,不調用beginShutdownSequence
- }
- })
- .create();
- closer.dialog = sConfirmDialog;
- sConfirmDialog.setOnDismissListener(closer);
- sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- sConfirmDialog.show();
- } else {//當不須要確認框彈出,直接調用beginShutdownSequence函數,執行關機或重啓。
- beginShutdownSequence(context);
- }
- }
beginShutdownSequence最後會調用sInstance.start();開啓線程
所以會到run接口,而run接口最後又會調用rebootOrShutdown,根據reboot是重啓仍是關機。
- public static void rebootOrShutdown(boolean reboot, String reason) {
- if (reboot) {
- Log.i(TAG, "Rebooting, reason: " + reason);
- 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, 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) {
- }
- }
-
- // Shutdown power
- Log.i(TAG, "Performing low-level shutdown...");
- PowerManagerService.lowLevelShutdown();//關機
- }
這樣整個添加劇啓功能就結束了。