Chinaunix首页 | 论坛 | 博客
  • 博客访问: 966729
  • 博文数量: 113
  • 博客积分: 7235
  • 博客等级: 少将
  • 技术积分: 2101
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 11:24
文章分类

全部博文(113)

文章存档

2013年(7)

2012年(5)

2011年(6)

2010年(8)

2009年(15)

2008年(72)

分类: Android平台

2013-06-28 11:12:11

对于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. private GlobalActionsDialog createDialog() {
  6.     // Simple toggle style if there's no vibrator, otherwise use a tri-state
  7.     if (!mHasVibrator) {
  8.         mSilentModeAction = new SilentModeToggleAction();
  9.     } else {
  10.         mSilentModeAction = new SilentModeTriStateAction(mContext, mAudioManager, mHandler);
  11.     }
  12.     mAirplaneModeOn = new ToggleAction(
  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.         void onToggle(boolean on) {
  19.             if (mHasTelephony && Boolean.parseBoolean(
  20.                     SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
  21.                 mIsWaitingForEcmExit = true;
  22.                 // Launch ECM exit dialog
  23.                 Intent ecmDialogIntent =
  24.                         new Intent(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.         protected void changeStateFromPress(boolean buttonOn) {
  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.         public boolean showDuringKeyguard() {
  42.             return true;
  43.         }

  44.         public boolean showBeforeProvisioning() {
  45.             return false;
  46.         }
  47.     };
  48.     onAirplaneModeChanged();

  49.     mItems = new ArrayList<Action>();

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

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

  59.             public boolean onLongPress() {
  60.                 mWindowManagerFuncs.rebootSafeMode(true);
  61.                 return true;
  62.             }

  63.             public boolean showDuringKeyguard() {
  64.                 return true;
  65.             }

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

  1. mItems.add(
  2.     new SinglePressAction(
  3.         com.android.internal.R.drawable.ic_lock_power_off,
  4.         R.string.global_action_reboot) {
  5.      
  6.         public void onPress() {
  7.             // reboot
  8.             mWindowManagerFuncs.reboot();
  9.         }
  10.          
  11.         public boolean showDuringKeyguard() {
  12.             return true;
  13.         }
  14.          
  15.         public boolean showBeforeProvisioning() {
  16.             return true;
  17.         }
  18.     });
上面的代码中使用了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. public interface WindowManagerFuncs {

  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.     public void switchKeyboardLayout(int deviceId, int direction);

  12.     public void shutdown();
  13.     public void reboot();
  14.     public void rebootSafeMode();
  15. }
然后在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java中实现该接口:

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

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

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

  1. static void shutdownInner(final Context context, boolean confirm) {
  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.     final int longPressBehavior = context.getResources().getInteger(
  11.                     com.android.internal.R.integer.config_longPressOnPowerBehavior);
  12.     final int resourceId = 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.         final CloseDialogReceiver closer = new CloseDialogReceiver(context);
  21.         final AlertDialog dialog = new AlertDialog.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, new DialogInterface.OnClickListener() {
  28.                     public void onClick(DialogInterface dialog, int which) {
  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. private static void beginShutdownSequence(Context context) {
  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 = new ProgressDialog(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 (SecurityException e) {
  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 (SecurityException e) {
  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 = new Handler() {
  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" />
至此,全部修改完成,编译烧写即可。

阅读(7033) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~