当用户长按power键的时候,系统会在PhoneWindowManager中调用
mGlobalActions.showDialog,来显示关机、飞行、重启等界面选项。
而我们需要在GlobalActions.Java中创建一个重启的选项。下面我们从GlobalActions中的createDialog节选一段代码:
[java] view plain copy
- 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,我们看下代码:
[java] view plain copy
- 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中添加如下:
[html] view plain copy
- <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中
[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();//关机
- }
这样整个添加重启功能就结束了。