转自:http://blog.chinaunix.net/uid-20729605-id-3779071.html


对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程。

首先关机的那个弹出菜单是在frameworks/base/policy/src/com/android/internal/policy/impl/GlobalActions.java这个文件中创建的:


  1. /**
  2. * Create the global actions dialog.
  3. * @return A new dialog.
  4. */
  5. privateGlobalActionsDialogcreateDialog(){
  6. // Simple toggle style if there's no vibrator, otherwise use a tri-state
  7. if(!mHasVibrator){
  8. mSilentModeAction=newSilentModeToggleAction();
  9. }else{
  10. mSilentModeAction=newSilentModeTriStateAction(mContext,mAudioManager,mHandler);
  11. }
  12. mAirplaneModeOn=newToggleAction(
  13. R.drawable.ic_lock_airplane_mode,
  14. R.drawable.ic_lock_airplane_mode_off,
  15. R.string.global_actions_toggle_airplane_mode,
  16. R.string.global_actions_airplane_mode_on_status,
  17. R.string.global_actions_airplane_mode_off_status){

  18. voidonToggle(booleanon){
  19. if(mHasTelephony&&Boolean.parseBoolean(
  20. SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))){
  21. mIsWaitingForEcmExit=true;
  22. // Launch ECM exit dialog
  23. Intent ecmDialogIntent=
  24. newIntent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS,null);
  25. ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  26. mContext.startActivity(ecmDialogIntent);
  27. }else{
  28. changeAirplaneModeSystemSetting(on);
  29. }
  30. }

  31. @Override
  32. protectedvoidchangeStateFromPress(booleanbuttonOn){
  33. if(!mHasTelephony)return;

  34. // In ECM mode airplane state cannot be changed
  35. if(!(Boolean.parseBoolean(
  36. SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))){
  37. mState=buttonOn?State.TurningOn:State.TurningOff;
  38. mAirplaneState=mState;
  39. }
  40. }

  41. publicbooleanshowDuringKeyguard(){
  42. returntrue;
  43. }

  44. publicbooleanshowBeforeProvisioning(){
  45. returnfalse;
  46. }
  47. };
  48. onAirplaneModeChanged();

  49. mItems=newArrayList<Action>();

  50. // first: power off
  51. mItems.add(
  52. newSinglePressAction(
  53. com.android.internal.R.drawable.ic_lock_power_off,
  54. R.string.global_action_power_off){

  55. publicvoidonPress(){
  56. // shutdown by making sure radio and power are handled accordingly.
  57. mWindowManagerFuncs.shutdown(true);
  58. }

  59. publicbooleanonLongPress(){
  60. mWindowManagerFuncs.rebootSafeMode(true);
  61. returntrue;
  62. }

  63. publicbooleanshowDuringKeyguard(){
  64. returntrue;
  65. }

  66. publicbooleanshowBeforeProvisioning(){
  67. returntrue;
  68. }
  69. });
我们可以看到mItems.add函数是添加一个选项,该菜单的第一个选项就是关机选项,我们可以在此之后添加重启选项,代码如下:

  1. mItems.add(
  2. newSinglePressAction(
  3. com.android.internal.R.drawable.ic_lock_power_off,
  4. R.string.global_action_reboot){

  5. publicvoidonPress(){
  6. // reboot
  7. mWindowManagerFuncs.reboot();
  8. }

  9. publicbooleanshowDuringKeyguard(){
  10. returntrue;
  11. }

  12. publicbooleanshowBeforeProvisioning(){
  13. returntrue;
  14. }
  15. });
上面的代码中使用了mWindowManagerFuncs.reboot函数和R.string.global_action_reboot资源,因此我们需要该资源并实现reboot函数。
首先在frameworks/base/core/java/android/view/WindowManagerPolicy.java中添加reboot接口:

  1. /**
  2. * Interface for calling back in to the window manager that is private
  3. * between it and the policy.
  4. */
  5. publicinterfaceWindowManagerFuncs{

  6. ...

  7. /**
  8. * Switch the keyboard layout for the given device.
  9. * Direction should be +1 or -1 to go to the next or previous keyboard layout.
  10. */
  11. publicvoidswitchKeyboardLayout(intdeviceId,intdirection);

  12. publicvoidshutdown();
  13. publicvoidreboot();
  14. publicvoidrebootSafeMode();
  15. }
然后在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java中实现该接口:

  1. // Called by window manager policy. Not exposed externally.
  2. @Override
  3. publicvoidshutdown(){
  4. ShutdownThread.shutdown(mContext,true);
  5. }

  6. // Called by window manager policy. Not exposed externally.
  7. @Override
  8. publicvoidreboot(){
  9. ShutdownThread.reboot(mContext,null,true);
  10. }

  11. // Called by window manager policy. Not exposed externally.
  12. @Override
  13. publicvoidrebootSafeMode(){
  14. ShutdownThread.rebootSafeMode(mContext,true);
  15. }
接下来,为了在按下重启选项之后,能出现”重启“之类的提示,还需要修改frameworks/base/services/java/com/android/server/pm/ShutdownThread.java中的shutdownInner函数和beginShutdownSequence函数:

  1. staticvoidshutdownInner(finalContextcontext,booleanconfirm){
  2. // ensure that only one thread is trying to power down.
  3. // any additional calls are just returned
  4. synchronized(sIsStartedGuard){
  5. if(sIsStarted){
  6. Log.d(TAG,"Request to shutdown already running, returning.");
  7. return;
  8. }
  9. }

  10. finalintlongPressBehavior=context.getResources().getInteger(
  11. com.android.internal.R.integer.config_longPressOnPowerBehavior);
  12. finalintresourceId=mRebootSafeMode
  13. ?com.android.internal.R.string.reboot_safemode_confirm
  14. :(longPressBehavior==2
  15. ?com.android.internal.R.string.shutdown_confirm_question
  16. :(mReboot?com.android.internal.R.string.reboot_confirm:
  17. com.android.internal.R.string.shutdown_confirm));

  18. Log.d(TAG,"Notifying thread to start shutdown longPressBehavior="+longPressBehavior);

  19. if(confirm){
  20. finalCloseDialogReceiver closer=newCloseDialogReceiver(context);
  21. finalAlertDialogdialog=newAlertDialog.Builder(context)
  22. .setTitle(mRebootSafeMode
  23. ?com.android.internal.R.string.reboot_safemode_title
  24. :(mReboot?com.android.internal.R.string.reboot:
  25. com.android.internal.R.string.power_off))
  26. .setMessage(resourceId)
  27. .setPositiveButton(com.android.internal.R.string.yes,newDialogInterface.OnClickListener(){
  28. publicvoidonClick(DialogInterfacedialog,intwhich){
  29. beginShutdownSequence(context);
  30. }
  31. })
  32. .setNegativeButton(com.android.internal.R.string.no,null)
  33. .create();
  34. closer.dialog=dialog;
  35. dialog.setOnDismissListener(closer);
  36. dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  37. dialog.show();
  38. }else{
  39. beginShutdownSequence(context);
  40. }
  41. }

  42. privatestaticvoidbeginShutdownSequence(Contextcontext){
  43. synchronized(sIsStartedGuard){
  44. if(sIsStarted){
  45. Log.d(TAG,"Shutdown sequence already running, returning.");
  46. return;
  47. }
  48. sIsStarted=true;
  49. }

  50. // throw up an indeterminate system dialog to indicate radio is
  51. // shutting down.
  52. ProgressDialog pd=newProgressDialog(context);
  53. pd.setTitle(context.getText(com.android.internal.R.string.power_off));
  54. pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
  55. pd.setIndeterminate(true);
  56. pd.setCancelable(false);
  57. pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);

  58. pd.show();

  59. sInstance.mContext=context;
  60. sInstance.mPowerManager=(PowerManager)context.getSystemService(Context.POWER_SERVICE);

  61. // make sure we never fall asleep again
  62. sInstance.mCpuWakeLock=null;
  63. try{
  64. sInstance.mCpuWakeLock=sInstance.mPowerManager.newWakeLock(
  65. PowerManager.PARTIAL_WAKE_LOCK,TAG+"-cpu");
  66. sInstance.mCpuWakeLock.setReferenceCounted(false);
  67. sInstance.mCpuWakeLock.acquire();
  68. }catch(SecurityExceptione){
  69. Log.w(TAG,"No permission to acquire wake lock",e);
  70. sInstance.mCpuWakeLock=null;
  71. }

  72. // also make sure the screen stays on for better user experience
  73. sInstance.mScreenWakeLock=null;
  74. if(sInstance.mPowerManager.isScreenOn()){
  75. try{
  76. sInstance.mScreenWakeLock=sInstance.mPowerManager.newWakeLock(
  77. PowerManager.FULL_WAKE_LOCK,TAG+"-screen");
  78. sInstance.mScreenWakeLock.setReferenceCounted(false);
  79. sInstance.mScreenWakeLock.acquire();
  80. }catch(SecurityExceptione){
  81. Log.w(TAG,"No permission to acquire wake lock",e);
  82. sInstance.mScreenWakeLock=null;
  83. }
  84. }

  85. // start the thread that initiates shutdown
  86. sInstance.mHandler=newHandler(){
  87. };
  88. sInstance.start();
  89. }
至此关于代码部分的改动全部完成,接下来就需要添加使用到的资源了,就是前面用到的字符串。首先需要在frameworks/base/core/res/res/values/strings.xml中添加一下字符串:

  1. <string name="reboot">Reboot</string>
  2. <string name="reboot_progress">Reboot\u2026</string>
  3. <string name="reboot_confirm"product="tablet">Your tablet will reboot.</string>
  4. <string name="reboot_confirm"product="default">Your phone will reboot.</string>
  5. <!-- label for item that reboot in phone options dialog -->
  6. <string name="global_action_reboot">Reboot</string>
而后需要在frameworks/base/core/res/res/values/public.xml中声明这些资源,否则编译的时候会出现找不到该资源的错误。

  1. <java-symbol type="string"name="reboot"/>
  2. <java-symbol type="string"name="reboot_confirm"/>
  3. <java-symbol type="string"name="reboot_progress"/>
  4. <java-symbol type="string"name="global_action_reboot"/>
至此,全部修改完成,编译烧写即可。

更多相关文章

  1. Android内核驱动——电源管理
  2. Android应用程序与SurfaceFlinger服务的连接过程分析
  3. [Android]电话拨号器开发
  4. 【Android】19.3 ContentProvider及安卓进一步封装后的相关类
  5. Android(安卓)中文 API ——对话框 AlertDialog.Builder
  6. android binder 讲解
  7. Android应用程序键盘(Keyboard)消息处理机制分析
  8. Android(安卓)Button控件 的简单使用(button监听和onClick触发函
  9. 箭头函数的基础使用

随机推荐

  1. MySQL Router实现MySQL的读写分离的方法
  2. MySQL通过binlog恢复数据
  3. MySQL 数据类型选择原则
  4. 图文详解MySQL中的主键与事务
  5. 跳槽必备之你设计索引的原则是什么?怎么
  6. 一看就懂的MySQL的聚簇索引及聚簇索引是
  7. MySQL之PXC集群搭建的方法步骤
  8. Mysql 用户权限管理实现
  9. MySQL 查询速度慢的原因
  10. MySQL 全文索引使用指南