为什么移动4G/A1手机一不小心转生了按中了电源键太久然后就好像关机了开机开不

手机关机以后开不了机,长按按电源键手机会震动一下,但是不能开机。可能是什么原因造成的,应该怎么办?_百度知道为什么4G手机耗电量大的惊人!1招搞定
4G无线网络显然有更高的网络带宽及更好的上网体验,并且现在也是热炒4G也确实给用户带来了很多的好处,但是你可能不知道的是4G手机耗电量大的惊人,甚至很多4G手机在开着4G网络之后坚
4G无线网络显然有更高的网络带宽及更好的上网体验,并且现在也是热炒4G也确实给用户带来了很多的好处,但是你可能不知道的是4G手机耗电量大的惊人,甚至很多4G手机在开着4G网络之后坚持不到一上午,到底是什么原因呢?诺基亚曾经有报告说,4GG手机至少比3G手机多耗电5%至20%。注意这个至少。1、多天线所有的LTE终端设备都采用一种叫MIMO的技术,这种技术支持多路并行传输。这种MIMO技术需要在你的LTE手机里内置两根天线(或多根天线),而每一根天线都有自己的功率放大器。而以前的手机只支持单发单收,夸张一点解释,这就好比一块电池同时要支持两台手机,所以耗电就会更多。2、频繁工作关掉手机屏幕,但你的手机并没有停下来,它们一直都很忙。它们要不断的扫描无线电波,决定应该接受哪个通信塔发出的信号。目前的移动通信网络不仅仅只有LTE网络,还有GSM、WCDMA、TD-SCDMA、CDMA2000多种制式的网络。而这些不同制式的网络使用的是不同的频段,这就意味着,你的手机不但要不停的扫描LTE网络的无线电波,还是在不同的频段跳来跳去扫描其它制式的网络信号。手机的工作内容越多,功耗当然也就越大。3、高的数据传输必将高耗能为什么LTE能提供更高速的数据传输?简单点说,是在无线电波中加入了更多的bit,当然这就导致了无线电波的波形越来越复杂。波形越复杂,手机的处理器对调制解调的处理也越复杂,随之而来的就会更耗电了。什么64QAM、OFDM,这些运用于LTE制式的技术听起来就复杂。所以,更快的速率,更高的频谱利用率,是需要牺牲手机的耗电量的。4、网络覆盖率低目前,4G网络建设还不到2年,覆盖不足这是事实,这也是影响手机功耗的原因之一。因为覆盖率低,如果你的手机首选的网络是4G,它就会频繁的搜素信号,加速电量的消耗。5、电池容量未升级现在的手机配置已经越来越高,特别是4G手机。8核64位处理器,2K高分辨率高亮度屏幕,系统越来越臃肿,服务越来越多,功耗越来越大,电池性能却没有明显提升。那么如何一招解决呢?相信小编说出来很多人会打小编的脸,但是小编还是要说,就是当你觉得你不必要在进行网络连接的时候,关闭4G网络。别拍砖虽然说这个方法可能你也知道,但是确实是非常简单有效的方法。————————————————————栗子老师推荐大家关注我的微信公众号(创新孵化平台)!微信公众号ID:ideebank提创意变产品,你的一个创意可能就是千元现金!
猜你感兴趣
最新图文推荐
大家感兴趣的内容
网友热评的文章苹果4S手机突然关机了,然后按开机键都开不了,是怎么回事?_百度知道android源码解析(二十八)--)电源开关机按键事件流程
前面我们讲解了系统截屏按键处理流程,HOME按键处理流程,今天再来讲解一下电源开关机按键事件流程,当然这也是系统按键处理流程方面的最后一篇博客了。
和截屏按键、HOME按键的处理流程类似,电源按键由于也是系统级别的按键,所以对其的事件处理逻辑是和截屏按键、HOME按键类似,不在某一个App中,而是在PhoneWindowManager的dispatchUnhandledKey方法中。所以和前面两篇类似,这里我们也是从PhoneWindowManager的dispatchUnhandledKey方法开始我们今天电源开关机按键的事件流程分析。
下面首先看一下dispatchUnhandledKey方法的实现逻辑:
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
KeyEvent fallbackEvent =
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
final KeyCharacterMap kcm = event.getKeyCharacterMap();
final int keyCode = event.getKeyCode();
final int metaState = event.getMetaState();
final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0;
// Check for fallback actions specified by the key character map.
final FallbackAction fallbackA
if (initialDown) {
fallbackAction = kcm.getFallbackAction(keyCode, metaState);
fallbackAction = mFallbackActions.get(keyCode);
if (fallbackAction != null) {
if (DEBUG_INPUT) {
Slog.d(TAG, &Fallback: keyCode=& + fallbackAction.keyCode
+ & metaState=& + Integer.toHexString(fallbackAction.metaState));
final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
fallbackEvent = KeyEvent.obtain(
event.getDownTime(), event.getEventTime(),
event.getAction(), fallbackAction.keyCode,
event.getRepeatCount(), fallbackAction.metaState,
event.getDeviceId(), event.getScanCode(),
flags, event.getSource(), null);
if (!interceptFallback(win, fallbackEvent, policyFlags)) {
fallbackEvent.recycle();
fallbackEvent =
if (initialDown) {
mFallbackActions.put(keyCode, fallbackAction);
} else if (event.getAction() == KeyEvent.ACTION_UP) {
mFallbackActions.remove(keyCode);
fallbackAction.recycle();
return fallbackE
我们知道关于系统按键的处理逻辑被下放到了interceptFallback方法中,所以我们继续看一下interceptFallback方法的实现逻辑。
private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
if ((actions & ACTION_PASS_TO_USER) != 0) {
long delayMillis = interceptKeyBeforeDispatching(
win, fallbackEvent, policyFlags);
if (delayMillis == 0) {
通过分析interceptFallback方法的源码,我们知道关于电源按键的处理逻辑在interceptKeyBeforeQueueing方法中,所以我们需要继续看一下interceptKeyBeforeQueueing方法中关于电源按键的处理逻辑。
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
interceptPowerKeyUp(event, interactive, canceled);
这里我们重点看一下电源按键的处理事件,可以发现当电源按键按下的时候我们调用了interceptPowerKeyDown方法,可以看出,这个方法就是处理电源事件的了,既然如此,我们继续看一下interceptPowerKeyDown方法的执行逻辑。
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Latch power key state to detect screenshot chord.
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered =
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
// Stop ringing or end call if configured to do so when power is pressed.
TelecomManager telecomManager = getTelecommService();
boolean hungUp =
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telecomManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telecomManager.isInCall() && interactive) {
// Otherwise, if &Power button ends call& is enabled,
// the Power button will hang up any current active call.
hungUp = telecomManager.endCall();
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
|| mScreenshotChordVolumeUpKeyT
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
wakeUpFromPowerKey(event.getDownTime());
if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
mBeganFromNonInteractive =
final int maxCount = getMaxMultiPressPowerCount();
if (maxCount &= 1) {
mPowerKeyHandled =
mBeganFromNonInteractive =
这里我们重点看一下if(interactive)分支,在这里我们发送一个一个异步消息,并且msg的what为MSG_POWER_LONG_PRESS,即长按电源事件的异步消息,所以我们看一下mHandler的handleMessage方法对该what消息的处理逻辑。
case MSG_POWER_LONG_PRESS:
powerLongPress();
我们可以发现在mHandler的handleMessage方法中当msg的what为MSG_POWER_LONG_PRESS时我们调用了powerLongPress方法,这个方法应该就是处理电源按键长按的逻辑,下面我们来看一下powerLongPress方法的实现。
private void powerLongPress() {
final int behavior = getResolvedLongPressOnPowerBehavior();
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled =
if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
performAuditoryFeedbackForAccessibilityIfNeed();
showGlobalActionsInternal();
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled =
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
可以发现这里有四个switch分之,其中第一个什么都不做直接break掉,第二个case则需要弹出选择操作界面,比如:飞行模式,开关机,静音模式,重新启动等,这里可以参看一下小米手机的关机界面:
然后第三第四个case分之则是直接调用关机方法,这里我们先看第二个case,看看系统是如何显示出关机操作界面的。那我们看一下showGlobalActionsInternal方法的实现逻辑。
void showGlobalActionsInternal() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
if (keyguardShowing) {
// since it took two seconds of long press to bring this up,
// poke the wake lock so they have some time to see the dialog.
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
可以发现我们首先调用了sendCloseSystemWindows方法,前面我们分析HOME按键流程的时候知道该方法用于关机系统弹窗,比如输入法,壁纸等。然后我们创建了一个GlobalActions对象,并调用了其showDialog方法,通过分析源码,我们发现该方法就是用于显示长按电源按键弹出操作界面的,我们首先看一下GlobalActions的构造方法:
public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
mContext =
mWindowManagerFuncs = windowManagerF
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.getService(DreamService.DREAM_SERVICE));
// receive broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mBroadcastReceiver, filter);
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
// get notified of phone state changes
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
mAirplaneModeObserver);
Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = vibrator != null && vibrator.hasVibrator();
mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
可以看到在GlobalActions对象的构造方法中我们主要用于初始化其成员变量,由于我们的电源长按操作界面是一个全局页面,所以这里自定义了一个Window对象,下面我们看一下GlobalActions的showDialog方法。
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
mKeyguardShowing = keyguardS
mDeviceProvisioned = isDeviceP
if (mDialog != null) {
mDialog.dismiss();
// Show delayed, so that the dismiss of the previous dialog completes
mHandler.sendEmptyMessage(MESSAGE_SHOW);
handleShow();
可以看到在showDialog方法中我们首先判断mDialog是否为空,若为空则发送msg的what为MESSAGE_SHOW的异步消息,否则调用handleShow方法,而这里的mDialog是一个类型为GlobalActionsDialog的变量,由于我们的mDialog为空,所以下面我们看一下handleShow方法。
private void handleShow() {
awakenIfNecessary();
mDialog = createDialog();
prepareDialog();
// If we only have 1 item and it's a simple press action, just do this action.
if (mAdapter.getCount() == 1
&& mAdapter.getItem(0) instanceof SinglePressAction
&& !(mAdapter.getItem(0) instanceof LongPressAction)) {
((SinglePressAction) mAdapter.getItem(0)).onPress();
WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();
attrs.setTitle(&GlobalActions&);
mDialog.getWindow().setAttributes(attrs);
mDialog.show();
mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
在方法体中我们调用了createDialog方法,创建了GlobalActionsDialog类型的mDialog,这里我们看一下createDialog的实现方法。
private GlobalActionsDialog createDialog() {
mAirplaneModeOn = new ToggleAction(
R.drawable.ic_lock_airplane_mode,
R.drawable.ic_lock_airplane_mode_off,
R.string.global_actions_toggle_airplane_mode,
R.string.global_actions_airplane_mode_on_status,
R.string.global_actions_airplane_mode_off_status) {
void onToggle(boolean on) {
if (mHasTelephony && Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
mIsWaitingForEcmExit =
// Launch ECM exit dialog
Intent ecmDialogIntent =
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(ecmDialogIntent);
changeAirplaneModeSystemSetting(on);
protected void changeStateFromPress(boolean buttonOn) {
if (!mHasTelephony)
// In ECM mode airplane state cannot be changed
if (!(Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {
mState = buttonOn ? State.TurningOn : State.TurningO
mAirplaneState = mS
public boolean showDuringKeyguard() {
public boolean showBeforeProvisioning() {
onAirplaneModeChanged();
mItems = new ArrayList();
String[] defaultActions = mContext.getResources().getStringArray(
com.android.internal.R.array.config_globalActionsList);
ArraySet addedKeys = new ArraySet();
for (int i = 0; i & defaultActions. i++) {
String actionKey = defaultActions[i];
if (addedKeys.contains(actionKey)) {
// If we already have added this, don't add it again.
if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
mItems.add(new PowerAction());
} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
mItems.add(mAirplaneModeOn);
} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
mItems.add(getBugReportAction());
} else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
if (mShowSilentToggle) {
mItems.add(mSilentModeAction);
} else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
if (SystemProperties.getBoolean(&fw.power_user_switcher&, false)) {
addUsersToMenu(mItems);
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
mItems.add(getLockdownAction());
} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
mItems.add(getVoiceAssistAction());
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
mItems.add(getAssistAction());
Log.e(TAG, &Invalid global action key & + actionKey);
// Add here so we don't add more than one.
addedKeys.add(actionKey);
mAdapter = new MyAdapter();
AlertParams params = new AlertParams(mContext);
params.mAdapter = mA
params.mOnClickListener =
params.mForceInverseBackground =
GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.getListView().setItemsCanFocus(true);
dialog.getListView().setLongClickable(true);
dialog.getListView().setOnItemLongClickListener(
new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView parent, View view, int position,
long id) {
final Action action = mAdapter.getItem(position);
if (action instanceof LongPressAction) {
return ((LongPressAction) action).onLongPress();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.setOnDismissListener(this);
方法体的内容比较长,我们看重点的内容,首先我们通过调用mContext.getResources().getStringArray(com.android.internal.R.array.config_globalActionsList)获得操作列表,这里可能包含:飞行模式、开关机、静音模式、重启等等,然后我们轮训操作列表,并添加相应的Action最后我们将这个操作列表保存到Dialog的adapter中并返回该dialog,然后我们回到我们刚刚的handleShow方法,在得到返回的dialog之后我们调用了dialog的show方法,这样我们就显示出了电源长按操作界面,比如小米的界面:
好吧,继续我们的分析,当我们长按电源按键弹出操作弹窗之后,这时候点击关机是怎么样的流程呢?我们发现在createDialog方法中关机操作adapter的item,我们添加了:
mItems.add(new PowerAction());
这样不难发现我们对关机按钮的操作封装在了PowerAction中,所以我们继续看一下PowerAction的实现。
private final class PowerAction extends SinglePressAction implements LongPressAction {
private PowerAction() {
super(com.android.internal.R.drawable.ic_lock_power_off,
R.string.global_action_power_off);
public boolean onLongPress() {
UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
mWindowManagerFuncs.rebootSafeMode(true);
public boolean showDuringKeyguard() {
public boolean showBeforeProvisioning() {
public void onPress() {
// shutdown by making sure radio and power are handled accordingly.
mWindowManagerFuncs.shutdown(false /* confirm */);
可以发现在PowerAction类的成员函数onPress方法中我们调用了mWindowManagerFuncs.showdown方法,而这个方法也就是开始执行我们的关机操作了,那么这里的mWindowManagerFuncs又是什么呢?它是在什么时候赋值的呢?通过分析我们发现这里的mWindowManagerFuncs成员变量是在GlobalActions的构造方法中赋值的。
public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
mWindowManagerFuncs = windowManagerF
好吧,回到我们的PhoneWindowManager,早构造GlobalActions时,直接传递的是PhoneWindowManager的成员变量mWindowManagerFuncs,那么PhoneWindowManager的mWindowManagerFuncs成员变量又是何时被赋值的呢?通过分析源码我们能够看到PhoneWindowManager的mWindowManagerFuncs变量是在PhoneWindowManager的init方法中初始化的,好吧,再次查找PhoneWindowManager的init方法是何时被调用的。
经过查找终于在WindowManagerService中我们找到了PhoneWindowManager的init方法的调用。
private void initPolicy() {
UiThread.getHandler().runWithScissors(new Runnable() {
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
这里的mPolicy就是一个PhoneWindowManager的实力,可以发现这里的init方法中mWindowManagerFuncs传递的就是一个WindowManagerService的实例,O(&_&)O哈哈~,让我们好找。
然么在PowerAction的onPress方法中调用的mWindowManagerFuncs.shutdown(false /* confirm */);方法,实际上调用的就是WindowManagerService的shutdown方法,这样我们继续看一下WindowManagerService的shutdown方法的实现。
public void shutdown(boolean confirm) {
ShutdownThread.shutdown(mContext, confirm);
好吧,这里很简单就是直接调用了ShutdownThread的shutdown方法,看样子这里就是执行关机操作的封装了,继续看一下ShutdownThread的shutdown方法。
public static void shutdown(final Context context, boolean confirm) {
mRebootSafeMode =
shutdownInner(context, confirm);
可以看到在ShutdownThread的shutdown方法中代码很简单,具体的操作下发到了shutdownInner方法中,那么我们继续看一下shutdownInner方法的实现。
static void shutdownInner(final Context context, boolean confirm) {
// ensure that only one thread is trying to power down.
// any additional calls are just returned
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, &Request to shutdown already running, returning.&);
final int longPressBehavior = context.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
final int resourceId = mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_confirm
: (longPressBehavior == 2
? com.android.internal.R.string.shutdown_confirm_question
: com.android.internal.R.string.shutdown_confirm);
Log.d(TAG, &Notifying thread to start shutdown longPressBehavior=& + longPressBehavior);
if (confirm) {
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
sConfirmDialog = new AlertDialog.Builder(context)
.setTitle(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
: com.android.internal.R.string.power_off)
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
beginShutdownSequence(context);
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
closer.dialog = sConfirmD
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
sConfirmDialog.show();
beginShutdownSequence(context);
可以看到方法体中,首先判断若用户点击了关机按键是否弹出确认框,若弹出则弹出关机确认框,若不需要确认,则直接调用beginShutdownSequence方法,执行关机操作。而在关机确认框中我们的确认按钮也是执行了beginShutdownSequence方法,所以我们继续看一下关机方法beginShutdownSequence。
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, &Shutdown sequence already running, returning.&);
sIsStarted =
if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();
if (mRebootUpdate) {
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_prepare));
pd.setMax(100);
pd.setProgressNumberFormat(null);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgress(0);
pd.setIndeterminate(false);
// Factory reset path. Set the dialog message accordingly.
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
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.mProgressDialog =
sInstance.mContext =
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
// make sure we never fall asleep again
sInstance.mCpuWakeLock =
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG + &-cpu&);
sInstance.mCpuWakeLock.setReferenceCounted(false);
sInstance.mCpuWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, &No permission to acquire wake lock&, e);
sInstance.mCpuWakeLock =
// also make sure the screen stays on for better user experience
sInstance.mScreenWakeLock =
if (sInstance.mPowerManager.isScreenOn()) {
sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, TAG + &-screen&);
sInstance.mScreenWakeLock.setReferenceCounted(false);
sInstance.mScreenWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, &No permission to acquire wake lock&, e);
sInstance.mScreenWakeLock =
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
sInstance.start();
在方法beginShutdownSequence中我们首先初始化了一个Process的dialog,该dialog用于显示关机界面,然后我们调用了sInstance.start方法,再往下的方法中就是真正的shutdown方法的实现,同时也是native方法,我们这里就不做过得解读了。。。
电源按键是系统按键,所以对电源按键的处理逻辑也是在PhoneWindowManager的dispatchUnhandledKey方法中;
在PhoneWindowManager的dispatchUnhandleKey方法处理Power按键之后会首先显示系统操作弹窗,一般包括但不限于:飞行模式,静音模式,重新启动,关机等;
当用户点击关机按钮是调用的是WindowManagerService.shutdown方法,而内部调用的是ShutdownThread.shutdown方法;
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'}

我要回帖

更多关于 ninebot a1 怎么关机 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信