转自:http://blog.chinaunix.net/uid-20729605-id-3779071.html
对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程。
首先关机的那个弹出菜单是在frameworks/base/policy/src/com/android/internal/policy/impl/GlobalActions.java这个文件中创建的:
/**
- 
Create the global actions dialog. 
- 
@return A new dialog. */ 
private GlobalActionsDialog createDialog() {
// Simple toggle style if there's no vibrator, otherwise use a tri-state<br style="word-wrap:break-word">
if (!mHasVibrator) {<br style="word-wrap:break-word">
    mSilentModeAction = new SilentModeToggleAction();<br style="word-wrap:break-word">
} else {<br style="word-wrap:break-word">
    mSilentModeAction = new SilentModeTriStateAction(mContext, mAudioManager, mHandler);<br style="word-wrap:break-word">
}<br style="word-wrap:break-word">
mAirplaneModeOn = new ToggleAction(<br style="word-wrap:break-word">
        R.drawable.ic_lock_airplane_mode,<br style="word-wrap:break-word">
        R.drawable.ic_lock_airplane_mode_off,<br style="word-wrap:break-word">
        R.string.global_actions_toggle_airplane_mode,<br style="word-wrap:break-word">
        R.string.global_actions_airplane_mode_on_status,<br style="word-wrap:break-word">
        R.string.global_actions_airplane_mode_off_status) {<br style="word-wrap:break-word">    void onToggle(boolean on) {<br style="word-wrap:break-word">
        if (mHasTelephony && Boolean.parseBoolean(<br style="word-wrap:break-word">
                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {<br style="word-wrap:break-word">
            mIsWaitingForEcmExit = true;<br style="word-wrap:break-word">
            // Launch ECM exit dialog<br style="word-wrap:break-word">
            Intent ecmDialogIntent =<br style="word-wrap:break-word">
                    new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);<br style="word-wrap:break-word">
            ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);<br style="word-wrap:break-word">
            mContext.startActivity(ecmDialogIntent);<br style="word-wrap:break-word">
        } else {<br style="word-wrap:break-word">
            changeAirplaneModeSystemSetting(on);<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">
    }<br style="word-wrap:break-word">    @Override<br style="word-wrap:break-word">
    protected void changeStateFromPress(boolean buttonOn) {<br style="word-wrap:break-word">
        if (!mHasTelephony) return;<br style="word-wrap:break-word">        // In ECM mode airplane state cannot be changed<br style="word-wrap:break-word">
        if (!(Boolean.parseBoolean(<br style="word-wrap:break-word">
                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {<br style="word-wrap:break-word">
            mState = buttonOn ? State.TurningOn : State.TurningOff;<br style="word-wrap:break-word">
            mAirplaneState = mState;<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">
    }<br style="word-wrap:break-word">    public boolean showDuringKeyguard() {<br style="word-wrap:break-word">
        return true;<br style="word-wrap:break-word">
    }<br style="word-wrap:break-word">    public boolean showBeforeProvisioning() {<br style="word-wrap:break-word">
        return false;<br style="word-wrap:break-word">
    }<br style="word-wrap:break-word">
};<br style="word-wrap:break-word">
onAirplaneModeChanged();<br style="word-wrap:break-word">mItems = new ArrayList<Action>();<br style="word-wrap:break-word">// first: power off<br style="word-wrap:break-word">
mItems.add(<br style="word-wrap:break-word">
    new SinglePressAction(<br style="word-wrap:break-word">
            com.android.internal.R.drawable.ic_lock_power_off,<br style="word-wrap:break-word">
            R.string.global_action_power_off) {<br style="word-wrap:break-word">        public void onPress() {<br style="word-wrap:break-word">
            // shutdown by making sure radio and power are handled accordingly.<br style="word-wrap:break-word">
            mWindowManagerFuncs.shutdown(true);<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">        public boolean onLongPress() {<br style="word-wrap:break-word">
            mWindowManagerFuncs.rebootSafeMode(true);<br style="word-wrap:break-word">
            return true;<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">        public boolean showDuringKeyguard() {<br style="word-wrap:break-word">
            return true;<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">        public boolean showBeforeProvisioning() {<br style="word-wrap:break-word">
            return true;<br style="word-wrap:break-word">
        }<br style="word-wrap:break-word">
    });我们可以看到mItems.add函数是添加一个选项,该菜单的第一个选项就是关机选项,我们可以在此之后添加重启选项,代码如下:
mItems.add(
new SinglePressAction(<br style="word-wrap:break-word">
    com.android.internal.R.drawable.ic_lock_power_off,<br style="word-wrap:break-word">
    R.string.global_action_reboot) { <br style="word-wrap:break-word">
 <br style="word-wrap:break-word">
    public void onPress() { <br style="word-wrap:break-word">
        // reboot <br style="word-wrap:break-word">
        mWindowManagerFuncs.reboot();<br style="word-wrap:break-word">
    } <br style="word-wrap:break-word">
     <br style="word-wrap:break-word">
    public boolean showDuringKeyguard() { <br style="word-wrap:break-word">
        return true;<br style="word-wrap:break-word">
    } <br style="word-wrap:break-word">
     <br style="word-wrap:break-word">
    public boolean showBeforeProvisioning() { <br style="word-wrap:break-word">
        return true; <br style="word-wrap:break-word">
    } <br style="word-wrap:break-word">
});上面的代码中使用了mWindowManagerFuncs.reboot函数和R.string.global_action_reboot资源,因此我们需要该资源并实现reboot函数。
首先在frameworks/base/core/java/android/view/WindowManagerPolicy.java中添加reboot接口:
/**
- 
Interface for calling back in to the window manager that is private 
- 
between it and the policy. */ 
public interface WindowManagerFuncs {
...<br style="word-wrap:break-word">/**<br style="word-wrap:break-word">
 * Switch the keyboard layout for the given device.<br style="word-wrap:break-word">
 * Direction should be +1 or -1 to go to the next or previous keyboard layout.<br style="word-wrap:break-word">
 */<br style="word-wrap:break-word">
public void switchKeyboardLayout(int deviceId, int direction);<br style="word-wrap:break-word">public void shutdown();<br style="word-wrap:break-word">
public void reboot(); <br style="word-wrap:break-word">
public void rebootSafeMode();<br style="word-wrap:break-word">}
然后在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java中实现该接口:
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown() {
ShutdownThread.shutdown(mContext, true);<br style="word-wrap:break-word">}
// Called by window manager policy. Not exposed externally.
@Override
public void reboot() {
ShutdownThread.reboot(mContext, null, true);<br style="word-wrap:break-word">}
// Called by window manager policy. Not exposed externally. 
@Override
public void rebootSafeMode() {
ShutdownThread.rebootSafeMode(mContext, true);<br style="word-wrap:break-word">}
接下来,为了在按下重启选项之后,能出现”重启“之类的提示,还需要修改frameworks/base/services/java/com/android/server/pm/ShutdownThread.java中的shutdownInner函数和beginShutdownSequence函数:
static void shutdownInner(final Context context, boolean confirm) {
// ensure that only one thread is trying to power down.<br style="word-wrap:break-word">
// any additional calls are just returned<br style="word-wrap:break-word">
synchronized (sIsStartedGuard) {<br style="word-wrap:break-word">
    if (sIsStarted) {<br style="word-wrap:break-word">
        Log.d(TAG, "Requestto shutdown already running, returning.");
        return;<br style="word-wrap:break-word">
    }<br style="word-wrap:break-word">
}<br style="word-wrap:break-word">final int longPressBehavior = context.getResources().getInteger(<br style="word-wrap:break-word">
                com.android.internal.R.integer.config_longPressOnPowerBehavior);<br style="word-wrap:break-word">
final int resourceId = mRebootSafeMode<br style="word-wrap:break-word">
        ? com.android.internal.R.string.reboot_safemode_confirm<br style="word-wrap:break-word">
        : (longPressBehavior == 2<br style="word-wrap:break-word">
                ? com.android.internal.R.string.shutdown_confirm_question<br style="word-wrap:break-word">
                : (mReboot ? com.android.internal.R.string.reboot_confirm :<br style="word-wrap:break-word">
                    com.android.internal.R.string.shutdown_confirm));<br style="word-wrap:break-word">Log.d(TAG, "Notifyingthread to start shutdown longPressBehavior=" + longPressBehavior);
if (confirm) {<br style="word-wrap:break-word">
    final CloseDialogReceivercloser = new CloseDialogReceiver(context);
    final AlertDialog dialog = new AlertDialog.Builder(context)<br style="word-wrap:break-word">
            .setTitle(mRebootSafeMode<br style="word-wrap:break-word">
                    ? com.android.internal.R.string.reboot_safemode_title<br style="word-wrap:break-word">
                    : (mReboot ? com.android.internal.R.string.reboot :<br style="word-wrap:break-word">
                        com.android.internal.R.string.power_off))<br style="word-wrap:break-word">
            .setMessage(resourceId)<br style="word-wrap:break-word">
            .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {<br style="word-wrap:break-word">
                public void onClick(DialogInterface dialog, int which) {<br style="word-wrap:break-word">
                    beginShutdownSequence(context);<br style="word-wrap:break-word">
                }<br style="word-wrap:break-word">
            })<br style="word-wrap:break-word">
            .setNegativeButton(com.android.internal.R.string.no, null)<br style="word-wrap:break-word">
            .create();<br style="word-wrap:break-word">
    closer.dialog = dialog;<br style="word-wrap:break-word">
    dialog.setOnDismissListener(closer);<br style="word-wrap:break-word">
    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);<br style="word-wrap:break-word">
    dialog.show();<br style="word-wrap:break-word">
} else {<br style="word-wrap:break-word">
    beginShutdownSequence(context);<br style="word-wrap:break-word">
}<br style="word-wrap:break-word">}
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
   if (sIsStarted) {<br style="word-wrap:break-word">
       Log.d(TAG, "Shutdownsequence already running, returning.");
       return;<br style="word-wrap:break-word">
   }<br style="word-wrap:break-word">
   sIsStarted = true;<br style="word-wrap:break-word">}
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
ProgressDialog pd = new ProgressDialog(context);
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
pd.show();
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
// make sure we never fall asleep again
sInstance.mCpuWakeLock = null;
try {
   sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(<br style="word-wrap:break-word">
           PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");<br style="word-wrap:break-word">
   sInstance.mCpuWakeLock.setReferenceCounted(false);<br style="word-wrap:break-word">
   sInstance.mCpuWakeLock.acquire();<br style="word-wrap:break-word">} catch (SecurityException e) {
   Log.w(TAG, "Nopermission to acquire wake lock", e);
   sInstance.mCpuWakeLock = null;<br style="word-wrap:break-word">}
// also make sure the screen stays on for better user experience
sInstance.mScreenWakeLock = null;
if (sInstance.mPowerManager.isScreenOn()) {
   try {<br style="word-wrap:break-word">
       sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(<br style="word-wrap:break-word">
               PowerManager.FULL_WAKE_LOCK, TAG + "-screen");<br style="word-wrap:break-word">
       sInstance.mScreenWakeLock.setReferenceCounted(false);<br style="word-wrap:break-word">
       sInstance.mScreenWakeLock.acquire();<br style="word-wrap:break-word">
   } catch (SecurityException e) {<br style="word-wrap:break-word">
       Log.w(TAG, "Nopermission to acquire wake lock", e);
       sInstance.mScreenWakeLock = null;<br style="word-wrap:break-word">
   }<br style="word-wrap:break-word">}
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start();
}
至此关于代码部分的改动全部完成,接下来就需要添加使用到的资源了,就是前面用到的字符串。首先需要在frameworks/base/core/res/res/values/strings.xml中添加一下字符串:
<string name="reboot">Reboot</string>
<string name="reboot_progress">Rebootu2026</string>
<string name="reboot_confirm" product="tablet">Your
tablet will reboot.</string>
<string name="reboot_confirm" product="default">Your
phone will reboot.</string>
<!-- label for item that reboot in phone options dialog -->
<string name="global_action_reboot">Reboot</string>
而后需要在frameworks/base/core/res/res/values/public.xml中声明这些资源,否则编译的时候会出现找不到该资源的错误。
<java-symbol type="string" name="reboot" />
<java-symbol type="string" name="reboot_confirm" />
<java-symbol type="string" name="reboot_progress" />
<java-symbol type="string" name="global_action_reboot" />
至此,全部修改完成,编译烧写即可。