一、Android系统重启的实现方式



1、广播方式



之前的博文介绍过这种方式《使用广播实现的Android关机及重启》,注意应用要在源码中编译,并且应用需要系统权限。



2、通过init.rc启动系统服务来运行sh文件



a.重启shell文件(system_reboot.sh),放在system/etc/目录下



1. #!/system/bin/sh    
2. reboot


b.init.rc中加入一个Service的定义


1. service system_reboot /system/etc/system_reboot.sh  
2.   oneshot  
3.   disabled


c.启动系统服务




1. SystemProperties.set("ctl.start", "system_reboot");



3、直接代码中执行命令行



需要取得root权限



1. Process proc = Runtime.getRuntime().exec(cmd);


    以上三种方法可以实现重启,但现在需要实现长按关机键提示对话框中有重启选项,这就设计修改系统源码,感觉修改源码,是个很难的工作,其实找到关机提示框的代码位置,一切都变得很简单。


 



二、修改源码定制重启功能



1、跟踪长按Power键相关代码



    首先要了解长按电源键弹出对话框的相关源码位置,通过跟踪找到PhoneWindowManager.java中有截断长按电源键的方法,继续跟踪代码找到Runnable mPowerLongPress = new Runnable(),在该runnable里边调用showGlobalActionsDialog()方法便是显示长按power键弹出的关机提示对话框,如果你的机器是原生态的,默认提示“飞行模式”,“静音”和“关机”选项。



     showGlobalActionsDialog创建关机对话框的代码在GlobalActions.java里边,主要代码如下:


1. private AlertDialog createDialog() {  
2. ……  
3. mItems = new ArrayList<Action>();  
4.   
5. // first: power off  
6.         mItems.add(  
7. new SinglePressAction(  
8.                     com.android.internal.R.drawable.ic_lock_power_off,  
9.                     R.string.global_action_power_off) {  
10.   
11. public void onPress() {  
12. // shutdown by making sure radio and power are handled accordingly.  
13. true);  
14.                 }  
15.   
16. public boolean showDuringKeyguard() {  
17. return true;  
18.                 }  
19.   
20. public boolean showBeforeProvisioning() {  
21. return true;  
22.                 }  
23.             });  
24.   
25. // next: airplane mode  
26.         mItems.add(mAirplaneModeOn);  
27.   
28. // last: silent mode  
29. if (SHOW_SILENT_TOGGLE) {  
30.             mItems.add(mSilentModeAction);  
31.         }  
32. ……  
33. }



2、重启方法



    跟踪源码到此处,需要加入重启部分的源码也是往AlertDialog 添加多一项,显示部分的代码直接造这power off即可,需要加入重启逻辑的代码直接修改回调方法onPress里边(上边代码粗体部分),一开始,我尝试了前文中提示的三种方法中的方法一和方法三均行不通,后来也没再进一步排查原因,估计权限问题。



    本打算使用方法二再尝试一下,突然想到为何不去看看关机的逻辑代码ShutdownThread.shutdown(),打开ShutdownThread.java,很快就发现源码里边也有reboot的实现方法,如下:



1. /**
2.      * Request a clean shutdown, waiting for subsystems to clean up their
3.      * state etc.  Must be called from a Looper thread in which its UI
4.      * is shown.
5.      *
6.      * @param context Context used to display the shutdown progress dialog.
7.      * @param reason code to pass to the kernel (e.g. "recovery"), or null.
8.      * @param confirm true if user confirmation is needed before shutting down.
9.      */  
10. public static void reboot(final Context context, String reason, boolean confirm){  
11.      ……  
12.      }



   该方法的使用直接看注释知道,reboot方法的后两个参数解释如下:



     reason  如果值为是null,正常重启;如果是recovery,系统重启进入recovery mode



     confirm true显示关机提示框,需要用户【确认】;false不显示提示框,直接关机



3、代码修改



a.在关机提示框中加入重启选项



    弄清楚关机相关的源码,直接在GlobalActions.java的createDialog方法中加入如下代码即可:

1. ...  
2. ext: reboot global_action_reboot  
3.   mItems.add(  
4. new SinglePressAction(  
5.               com.android.internal.R.drawable.ic_lock_power_off,  
6.               R.string.global_action_reboot) {  
7.   
8. public void onPress() {  
9. // reboot  
10. null,false);                
11.           }  
12.   
13. public boolean showDuringKeyguard() {  
14. return true;  
15.           }  
16.   
17. public boolean showBeforeProvisioning() {  
18. return true;  
19.           }  
20.       });


b.修改重启提示框,以区分关机提示框



  因为提示框默认是“关机”,在ShutdownThread.java的beginShutdownSequence(context)方法中代码修改如下:


1. /*/
2. //修改前:
3. ……
4.  pd.setTitle(context.getText(com.android.internal.R.string.power_off));
5.  pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
6. ……
7. /*/  
8. //修改后:  
9. ……  
10. if(mReboot){     // reboot progress  
11.          pd.setTitle(context.getText(com.android.internal.R.string.global_action_reboot));  
12.          pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress));  
13. else{          // shutdown progress  
14.          pd.setTitle(context.getText(com.android.internal.R.string.power_off));  
15.          pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));  
16.      }  
17. ……  
18. //*/



     重启功能实现了,但是不能到此结束,定制Android系统的重启功能,添加选项和修改重启提示框时加入了“重启”和“正在重启”的字符串,所以会涉及到在系统资源文件中添加新的字符串,源码中资源文件涉及到的多国语言直接忽略,我只在values/strings.xml和values-zh-rCN/strings.xml两个文件中加入对应的字符串:


1. <string name="global_action_reboot">重启</string>  
2. <string name="reboot_progress">"正在重启..."</string>



c.最后编译


因为修改涉及到系统资源文件又涉及到policy.jar包,经过多次尝试,正确的编译顺序如下:


步骤1.编译frameworks/base/res,在out/target/product/X设备名X/system/framework/目录下生成framework-res.apk


步骤2.编译frameworks/base/,在o同样目录下生成framework.jar包(不能忽略,不然步骤3编译报错)


步骤3.编译frameworks/base/policy,在同样目录下生成policy.jar包


附录:



本例源码以Android 4.0.4为准(2.3一样),关机相关的源码路径:


ics/frameworks/base/policy/src/com/android/internal/policy/impl/目录下:
 
  
PhoneWindowManager.java
 
  
GlobalActions.java
 
  
 
 
  
ics/frameworks/base/core/java/com/android/internal/app/目录下:


ShutdownThread.java



PS:4.1.1 关机相关方法位置有些变化



源码已经把关机的接口整合到:


public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs{...}中


不过可以直接使用:


import com.android.server.pm.ShutdownThread;
 
 
 
 
 
ShutdownThread.shutdown(mContext, true);
 
 
ShutdownThread.rebootSafeMode(mContext, true);


文件路径:


Android4.1.1/jb/frameworks/base/services/java/com/android/server/pm/
 
 
ShutdownThread.java
 
 

 
 
Android4.1.1/jb/frameworks/base/services/java/com/android/server/wm
 
 
WindowManagerService.java
 
 

 
 
...