android5.1添加android长按power键重启功能

当用户长按power键的时候,系统会在PhoneWindowManager中调用


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();//关机
    }
这样整个添加重启功能就结束了。



你可能感兴趣的:(android5.1添加android长按power键重启功能)