mGlobalActions.showDialog,来显示关机、飞行、重启等界面选项。
而我们需要在GlobalActions.java中创建一个重启的选项。下面我们从GlobalActions中的createDialog节选一段代码:
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,我们看下代码:
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; } }
还有需要在资源文件中添加一些内容:
需要在core/res/res/values-zh-rCN/strings.xml中添加如下:
<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中
<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中
<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" />
还需要添加一个图标的图片
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中增加几个选项来打开重启等功能
<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新增接口
public void shutdown(boolean confirm); public void rebootSafeMode(boolean confirm); public void reboot(boolean confirm);//新增的接口
并且最总在WindowManagerService中实现:
@Override public void reboot(boolean confirm) { Log.d(TAG,"reboot confirm:" + confirm); ShutdownThread.reboot(mContext, null, confirm); }
最后调用ShutdownThread的reboot函数。
public static void reboot(final Context context, String reason, boolean confirm) { mReboot = true;//这个参数最后决定是重启还是关机 mRebootSafeMode = false; mRebootReason = reason; shutdownInner(context, confirm); }
下面主要看下ShutdownThread的shutdownInner这个函数,主要是创建弹出框,以及开启线程执行关机或重启。
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();//关机 }这样整个添加重启功能就结束了。