转自: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, "Request
to 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, "Notifying
thread to start shutdown longPressBehavior=" + longPressBehavior);
if (confirm) {<br style="word-wrap:break-word">
final CloseDialogReceiver
closer = 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, "Shutdown
sequence 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, "No
permission 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, "No
permission 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" />
至此,全部修改完成,编译烧写即可。