Android4.x 如何处理Power按键

1. 简介

        Android4.x在Framework的PhoneWindowManager对Power(KeyEvent.KEYCODE_POWER)和Home(KeyEvent.KEYCODE_HOME)键做了处理,不会把这些键传送上层应用程序。如需要把这些键发送给Activity和Service,需要在PhoneWindowManager处理这些键时“发送一个广播出去,然后在应用程序接收到广播后做处理”。

       如果应用程序只需要获取获取待机、唤醒、关机、网络状态变化消息,则可监听以下广播消息:
1) 待机:
广播消息:android.intent.action.SCREEN_OFF (代码)
2) 唤醒:
广播消息:android.intent.action.SCREEN_ON (代码)
3) 关机:
广播消息:android.intent.action.ACTION_SHUTDOWN (XML或代码)
4) 网络状态变化:
 广播消息:android.net.conn.CONNECTIVITY_CHANGE (XML或代码)
                  然后调用下面的isNetworkAvailable获取当前网络状态。
public static boolean isNetworkAvailable(Context context) { 

        ConnectivityManager mgr = (ConnectivityManager) context  
                .getSystemService(Context.CONNECTIVITY_SERVICE);  
        NetworkInfo[] info = mgr.getAllNetworkInfo();  
        if (info != null) {  
            for (int i = 0; i < info.length; i++) {  
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {  
                    return true;  
                }  
            }  
        }  
        return false;  
    } 

2. 短按Power键处理流程

    短按Power键处理流程如下图所示:

Android4.x 如何处理Power按键_第1张图片

 

3. 长按Power键处理流程

      长按Power键处理流程如下图所示:       

 Android4.x 如何处理Power按键_第2张图片

3.1 Message超时处理流程

      如果长按Power键(超过500ms),则此消息(Message.callback为mPowerLongPress)将被执行。mPowerLongPress (PhoneWindowManager.java)定义如下:

[cpp]  view plain copy
  1. private final Runnable mPowerLongPress = new Runnable() {  
  2.     public void run() {  
  3.         // The context isn't read  
  4.         if (mLongPressOnPowerBehavior < 0) {  
  5.             mLongPressOnPowerBehavior = mContext.getResources().getInteger(  
  6.                     com.android.internal.R.integer.config_longPressOnPowerBehavior);  
  7.         }  
  8.         switch (mLongPressOnPowerBehavior) {  
  9.         case LONG_PRESS_POWER_NOTHING:  
  10.             break;  
  11.         case LONG_PRESS_POWER_GLOBAL_ACTIONS:  
  12.             mPowerKeyHandled = true;  
  13.             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);  
  14.             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);  
  15.             showGlobalActionsDialog();  
  16.             break;  
  17.         case LONG_PRESS_POWER_SHUT_OFF:  
  18.             mPowerKeyHandled = true;  
  19.             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);  
  20.             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);  
  21.             ShutdownThread.shutdown(mContext, true);  
  22.             break;  
  23.         }  
  24.     }  
  25. };  

     它是一个匿名内部类,它是一个实现Runnable的类的对象引用,因此

     new Runnable() {

         public void run(){

         ...

         }

     };

     它包括了定义这个类(只不过这个类没有名字)和实例化这个类的对象。

      当超时时,其执行流程如下图所示:
Android4.x 如何处理Power按键_第3张图片
     

 3.2 reboot系统调用流程

 reboot系统调用流程如下图所示:

Android4.x 如何处理Power按键_第4张图片

 

 4. 如何处理短按和长按电源键

     长按电源键:弹出关机确认对话框(KeyDown之后,如果 500ms之内,没有收到KeyUp则弹出关机确认对话框)

     短按电源键:执行待机(KeyUp时执行<wmActions=4>)或唤醒(KeyDown时执行<wmActions=2>)

    

     对于长按电源键,在PhoneWindowManager.java的interceptKeyBeforeQueueing函数中进行处理,其相关代码如下 :

[java]  view plain copy
  1. case KeyEvent.KEYCODE_POWER: {  
  2.     result &= ~ACTION_PASS_TO_USER;  
  3.     if (down) {  
  4.         if (isScreenOn && !mPowerKeyTriggered  
  5.                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {  
  6.             mPowerKeyTriggered = true;  
  7.             mPowerKeyTime = event.getDownTime();  
  8.             interceptScreenshotChord();  
  9.         }  
  10.          
  11.         ...  
  12.         // Power Key down, set mPowerLongPress executing after 500ms  
  13.         interceptPowerKeyDown(!isScreenOn || hungUp  
  14.                 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);  
  15.     } else {  
  16.         mPowerKeyTriggered = false;  
  17.         cancelPendingScreenshotChordAction();  
  18.         if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {  
  19.             result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;  
  20.         }  
  21.         // Power key up, remove the mPowerLongPress, that is, if user release  
  22.         // power key during 500ms, mPowerLongPress will not be execute, then execute sleep  
  23.         mPendingPowerKeyUpCanceled = false;  
  24.     }  
  25.     break;  
  26. }  

[java]  view plain copy
  1. private void interceptPowerKeyDown(boolean handled) {  
  2.     mPowerKeyHandled = handled;  
  3.     if (!handled) {  
  4.         mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()/*500ms*/);  
  5.     }  
  6. }  
  7.   
  8. private boolean interceptPowerKeyUp(boolean canceled) {  
  9.     if (!mPowerKeyHandled) {  
  10.         mHandler.removeCallbacks(mPowerLongPress);  
  11.         return !canceled;  
  12.     }  
  13.     return false;  
  14. }  




  Android wakelock 学习总结第二篇  2014-01-24 17:24:28

分类: Android平台

如果看完第一篇的同学,是不是对大概上层睡眠流程有点小感了呢?如果你看过我说的几个代码,细心的你会发现上篇文章最后Native层只是对/sys/power/wakelock 和 /sys/power/unwakelock进行了操作,并没有对/sys/power/state进行操作,这个是在哪里进行的呢?调用的接口函数又写哪里呢?别着急,我们跟随updatePowerStateLocked()这个函数没见过?回头看我的第一篇,当时没有看得太明白,所以没有详细讲啊,哇哈哈!现在我们看下

1114     private void updatePowerStateLocked() {
1115         if (!mSystemReady || mDirty == 0) {
1116             return;
1117         }
1118 
1119         // Phase 0: Basic state updates.
1120         updateIsPoweredLocked(mDirty);
1121         updateStayOnLocked(mDirty);
1122 
1123         // Phase 1: Update wakefulness.
1124         // Loop because the wake lock and user activity computations are influenced
1125         // by changes in wakefulness.
1126         final long now = SystemClock.uptimeMillis();
1127         int dirtyPhase2 = 0;
1128         for (;;) {
1129             int dirtyPhase1 = mDirty;
1130             dirtyPhase2 |= dirtyPhase1;
1131             mDirty = 0;
1132 
1133             updateWakeLockSummaryLocked(dirtyPhase1);
1134             updateUserActivitySummaryLocked(now, dirtyPhase1);
1135             if (!updateWakefulnessLocked(dirtyPhase1)) {
1136                 break;
1137             }
1138         }
1139 
1140         // Phase 2: Update dreams and display power state.
1141         updateDreamLocked(dirtyPhase2);
1142         updateDisplayPowerStateLocked(dirtyPhase2);
1143 
1144         // Phase 3: Send notifications, if needed.
1145         if (mDisplayReady) {
1146             sendPendingNotificationsLocked();
1147         }
1148 
1149         // Phase 4: Update suspend blocker.
1150         // Because we might release the last suspend blocker here, we need to make sure
1151         // we finished everything else first!
1152         updateSuspendBlockerLocked();
1153     }

当程序跑到这里的时候,就是已经要执行睡眠了,我们主要看Phase 2这段的 updateDisplayPowerStateLocked(dirtyPhase2) 这个函数主要关注下:
1696             mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
1697                     mRequestWaitForNegativeProximity);

这个requestPowerState函数进入到PowerController这个类中,这个干什么用的?看得还不太明白,以后慢慢看吧,不过最重要的一个还是要说明下:
1350     private final class DisplayControllerHandler extends Handler {
1351         public DisplayControllerHandler(Looper looper) {
1352             super(looper, null, true /*async*/);
1353         }
1354                                                                                                                                           
1355         @Override
1356         public void handleMessage(Message msg) {
1357             switch (msg.what) {
1358                 case MSG_UPDATE_POWER_STATE:
1359                     updatePowerState();
1360                     break;
1361 
1362                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1363                     debounceProximitySensor();
1364                     break;
1365 
1366                 case MSG_LIGHT_SENSOR_DEBOUNCED:
1367                     debounceLightSensor();
1368                     break;
1369             }

这个Handler 是DisplayController自己重写的一个hangMessage的方法,具体干什么用呢?又有睡调用呢?接着上面往下看,刚才调用到了requestPowerState,这个函数设备状态进行了一大堆判断,主要是这两句话:
 529             if (changed && !mPendingRequestChangedLocked) {
 530                 mPendingRequestChangedLocked = true;
 531                 sendUpdatePowerStateLocked();
 532             }

条件为什么?自己看吧,我还没有弄明白呢,但是sendUpdatePowerStateLocked(); 这句话确实是进入到了
 544     private void sendUpdatePowerStateLocked() {
 545         if (!mPendingUpdatePowerStateLocked) {
 546             mPendingUpdatePowerStateLocked = true;
 547             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
 548             msg.setAsynchronous(true);
 549             mHandler.sendMessage(msg);
 550         }                                                                                                                                 
 551     }

这里呢,看到没有看到mHandler.sendMessage(msg); 这个函数就是刚才咱们看到的那个定义哦,哇哈哈是不是特别亲切啊?继续走啊~~~

当我们 进入updatePowerState(); 看到这个函数还真是他妈的长啊,不过仔细看看,无非就是对屏光亮有影响的一个设备的判断,比如L-sensor等,这个函数会调用setScreenOn(false); 

 829     private void setScreenOn(boolean on) {
 830         if (!mPowerState.isScreenOn() == on) {
 831             mPowerState.setScreenOn(on);                                                                                                  
 832             if (on) {
 833                 mNotifier.onScreenOn();
 834             } else {
 835                 mNotifier.onScreenOff();
 836             }
 837         }
 838     }

这个函数封装了DisplayPowerState类中实现的setScreenOn(boolean on)
124     /**
125      * Sets whether the screen is on or off.
126      */
127     public void setScreenOn(boolean on) {
128         if (mScreenOn != on) {
129             if (DEBUG) {
130                 Slog.d(TAG, "setScreenOn: on=" + on);                                                                                      
131             }
132 
133             mScreenOn = on;
134             mScreenReady = false;
135             scheduleScreenUpdate();
136         }
137     }

再次感叹JAVA封装的还真是牛逼哄哄啊,紧接着调用scheduleScreenUpdate(),接着调用postScreenUpdateThreadSafe(),
272     private void scheduleScreenUpdate() {
273         if (!mScreenUpdatePending) {
274             mScreenUpdatePending = true;
275             postScreenUpdateThreadSafe();                                                                                                  
276         }
277     }
278 
279     private void postScreenUpdateThreadSafe() {
280         mHandler.removeCallbacks(mScreenUpdateRunnable);
281         mHandler.post(mScreenUpdateRunnable);
282     }

如果你要是问我然后走到哪里了?呵呵,你肯定没有见过Handler.post这样的callback调用方法,没错,紧接着调用的就是mScreenUpdateRunnable这个类重写的run函数

300     private final Runnable mScreenUpdateRunnable = new Runnable() {
301         @Override
302         public void run() {
303             mScreenUpdatePending = false;
304 
305             int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
306             if (mPhotonicModulator.setState(mScreenOn, brightness)) {
307                 mScreenReady = true;
308                 invokeCleanListenerIfNeeded();                                                                                             
309             }
310         }
311     };
312 

不要着急,我们已经慢慢快接近真相了啊,下面主要看得是mPhotonicModulator.setState(mScreenOn, brightness)这个函数

342         public boolean setState(boolean on, int backlight) {
343             synchronized (mLock) {
344                 if (on != mPendingOn || backlight != mPendingBacklight) {
345                     if (DEBUG) {
346                         Slog.d(TAG, "Requesting new screen state: on=" + on
347                                 + ", backlight=" + backlight);
348                     }
349 
350                     mPendingOn = on;
351                     mPendingBacklight = backlight;
352 
353                     if (!mChangeInProgress) {
354                         mChangeInProgress = true;
355                         AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);                                                                     
356                     }
357                 }
358                 return mChangeInProgress;
359             }
360         }

到这里,调用一个mTask,这个在哪里定义呢?就在下面的函数中:

372         private final Runnable mTask = new Runnable() {
373             @Override
374             public void run() {
375                 // Apply pending changes until done.
376                 for (;;) {
377                     final boolean on;
378                     final boolean onChanged;
379                     final int backlight;
380                     final boolean backlightChanged;
381                     synchronized (mLock) {
382                         on = mPendingOn;
383                         onChanged = (on != mActualOn);
384                         backlight = mPendingBacklight;
385                         backlightChanged = (backlight != mActualBacklight);
386                         if (!onChanged && !backlightChanged) {
387                             mChangeInProgress = false;
388                             break;
389                         }
390                         mActualOn = on;
391                         mActualBacklight = backlight;
392                     }
393 
394                     if (DEBUG) {
395                         Slog.d(TAG, "Updating screen state: on=" + on
396                                 + ", backlight=" + backlight);
397                     }
398                     if (onChanged && on) {
399                         mDisplayBlanker.unblankAllDisplays();
400                     }
401                     if (backlightChanged) {
402                         mBacklight.setBrightness(backlight);
403                     }
404                     if (onChanged && !on) {
405                         mDisplayBlanker.blankAllDisplays();
406                     }
407                 }
408 
409                 // Let the outer class know that all changes have been applied.
410                 postScreenUpdateThreadSafe();
411             }
412         };

这个有点长,不过咱们就看mDisplayBlanker.blankAllDisplays(); 这个 与mDisplayBlanker.unblankAllDisplays(); 这两个函数一看就知道是相反的两个功能,继续跟随这个函数,我们终于回到了PowerManagerService了
2658         @Override
2659         public void blankAllDisplays() {                                                                                                  
2660             synchronized (this) {
2661                 mBlanked = true;
2662                 mDisplayManagerService.blankAllDisplaysFromPowerManager();
2663                 nativeSetInteractive(false);
2664                 nativeSetAutoSuspend(true);
2665             }
2666         }
2667 
2668         @Override
2669         public void unblankAllDisplays() {
2670             synchronized (this) {
2671                 nativeSetAutoSuspend(false);
2672                 nativeSetInteractive(true);
2673                 mDisplayManagerService.unblankAllDisplaysFromPowerManager();
2674                 mBlanked = false;
2675             }
2676         }

终于看到了亲切的native开头的函数了,马上就要到了啊,坚持住啊,其中 nativeSetInteractive(false);nativeSetAutoSuspend(true); 这两个函数都定义在
frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp 中,分别列举下:

170 static void nativeSetInteractive(JNIEnv *env, jclass clazz, jboolean enable) {
171     if (gPowerModule) {
172         if (enable) {
173             ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
174             gPowerModule->setInteractive(gPowerModule, true);
175         } else {
176             ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
177             gPowerModule->setInteractive(gPowerModule, false);
178         }
179     }
180 }
181 
182 static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) {                                                             
183     if (enable) {
184         ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");
185         autosuspend_enable();
186     } else {
187         ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");
188         autosuspend_disable();
189     }
190 }

第一个暂时没有找到实现,也不知道干什么用,第二个函数的autosuspend_enable()和autosuspend_disable这两个函数就是就是真正往/sys/power/state写mem和on的函数啦!但是他在哪里呢?这个我找了半天,没想到竟然实现在:system/core/libsuspend/  被编译成了一个库文件,一直不明白为什么同样的power曾的Native的庫文件,为什么不放在一起呢?奇怪

水平有限,就先这样吧,如果说不对的,请大牛帮忙指出,谢谢

现在大概的流程和接口都已经找到了,继续详细的看看代码了,就不再分析了!
下一篇会对kernel底层的earlysuspend的流程进行分析,走一遍!

你可能感兴趣的:(Android4.x 如何处理Power按键)