长按power键的流程&&PhoneWindowManager的nullpointexception导致system_server crash 导致系统重启

本文详细解析了Android系统中,从InputDispatcher到PhoneWindowManager如何处理长按电源键的过程,包括按键监听、GlobalActions对话框的显示,以及如何进入安全模式。在PhoneWindowManager的interceptKeyBeforeQueueing方法中,对KeyEvent.KEYCODE_POWER的处理触发了GlobalActions显示,通过showGlobalActionsInternal展示全局操作对话框。当选择进入安全模式时,ShutdownThread被调用来执行安全重启。在修改系统相关代码时需谨慎,以避免引起系统服务崩溃导致的系统重启问题。
摘要由CSDN通过智能技术生成

前面的事件派发过程就跳过了,从PhoneWindowManager开始说起

 

 

 

安全模式简述

android平台,在长按power / menu键时会快速进入一个模式选择,部分定制的平台是直接进入安装模式,也可以定制成公司需要的一些特定功能模式,比如报警 ... 

power 也属于全局的特殊按键,同样在PhoneWindowManager.java中被捕获处理。

 

Power键(long)监听流程

InputDispatcher.cpp  中InputDispatcher::notifyKey分发按键

[cpp] view plain copy

  1. void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {  
  2. #if DEBUG_INBOUND_EVENT_DETAILS  
  3.     ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "  
  4.             "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",  
  5.             args->eventTime, args->deviceId, args->source, args->policyFlags,  
  6.             args->action, args->flags, args->keyCode, args->scanCode,  
  7.             args->metaState, args->downTime);  
  8. #endif  
  9.     if (!validateKeyEvent(args->action)) {  
  10.         return;  
  11.     }  
  12.   
  13.     uint32_t policyFlags = args->policyFlags;  
  14.     int32_t flags = args->flags;  
  15.     int32_t metaState = args->metaState;  
  16.     if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {  
  17.         policyFlags |= POLICY_FLAG_VIRTUAL;  
  18.         flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;  
  19.     }  
  20.     if (policyFlags & POLICY_FLAG_FUNCTION) {  
  21.         metaState |= AMETA_FUNCTION_ON;  
  22.     }  
  23.   
  24.     policyFlags |= POLICY_FLAG_TRUSTED;  
  25.   
  26.     int32_t keyCode = args->keyCode;  
  27.     if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {  
  28.         int32_t newKeyCode = AKEYCODE_UNKNOWN;  
  29.         if (keyCode == AKEYCODE_DEL) {  
  30.             newKeyCode = AKEYCODE_BACK;  
  31.         } else if (keyCode == AKEYCODE_ENTER) {  
  32.             newKeyCode = AKEYCODE_HOME;  
  33.         }  
  34.         if (newKeyCode != AKEYCODE_UNKNOWN) {  
  35.             AutoMutex _l(mLock);  
  36.             struct KeyReplacement replacement = {keyCode, args->deviceId};  
  37.             mReplacedKeys.add(replacement, newKeyCode);  
  38.             keyCode = newKeyCode;  
  39.             metaState &= ~AMETA_META_ON;  
  40.         }  
  41.     } else if (args->action == AKEY_EVENT_ACTION_UP) {  
  42.         // In order to maintain a consistent stream of up and down events, check to see if the key  
  43.         // going up is one we've replaced in a down event and haven't yet replaced in an up event,  
  44.         // even if the modifier was released between the down and the up events.  
  45.         AutoMutex _l(mLock);  
  46.         struct KeyReplacement replacement = {keyCode, args->deviceId};  
  47.         ssize_t index = mReplacedKeys.indexOfKey(replacement);  
  48.         if (index >= 0) {  
  49.             keyCode = mReplacedKeys.valueAt(index);  
  50.             mReplacedKeys.removeItemsAt(index);  
  51.             metaState &= ~AMETA_META_ON;  
  52.         }  
  53.     }  
  54.   
  55.     KeyEvent event;  
  56.     event.initialize(args->deviceId, args->source, args->action,  
  57.             flags, keyCode, args->scanCode, metaState, 0,  
  58.             args->downTime, args->eventTime);  
  59.   
  60.     mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);  
  61.   
  62.     bool needWake;  
  63.     { // acquire lock  
  64.         mLock.lock();  
  65.   
  66.         if (shouldSendKeyToInputFilterLocked(args)) {  
  67.             mLock.unlock();  
  68.   
  69.             policyFlags |= POLICY_FLAG_FILTERED;  
  70.             if (!mPolicy->filterInputEvent(&event, policyFlags)) {  
  71.                 return; // event was consumed by the filter  
  72.             }  
  73.   
  74.             mLock.lock();  
  75.         }  
  76.   
  77.         int32_t repeatCount = 0;  
  78.         KeyEntry* newEntry = new KeyEntry(args->eventTime,  
  79.                 args->deviceId, args->source, policyFlags,  
  80.                 args->action, flags, keyCode, args->scanCode,  
  81.                 metaState, repeatCount, args->downTime);  
  82.   
  83.         needWake = enqueueInboundEventLocked(newEntry);  
  84.         mLock.unlock();  
  85.     } // release lock  
  86.   
  87.     if (needWake) {  
  88.         mLooper->wake();  
  89.     }  
  90. }  

 

    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); 截获按键并处理,也即NativeInputManager::interceptKeyBeforeQueueing

[cpp] view plain copy

  1. void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,  
  2.         uint32_t& policyFlags) {  
  3.     // Policy:  
  4.     // - Ignore untrusted events and pass them along.  
  5.     // - Ask the window manager what to do with normal events and trusted injected events.  
  6.     // - For normal events wake and brighten the screen if currently off or dim.  
  7.     if (mInteractive) {  
  8.         policyFlags |= POLICY_FLAG_INTERACTIVE;  
  9.     }  
  10.     if ((policyFlags & POLICY_FLAG_TRUSTED)) {  
  11.         nsecs_t when = keyEvent->getEventTime();  
  12.         JNIEnv* env = jniEnv();  
  13.         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);  
  14.         jint wmActions;  
  15.         if (keyEventObj) {  
  16.             wmActions = env->CallIntMethod(mServiceObj,  
  17.                     gServiceClassInfo.interceptKeyBeforeQueueing,  
  18.                     keyEventObj, policyFlags);  
  19.             if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {  
  20.                 wmActions = 0;  
  21.             }  
  22.             android_view_KeyEvent_recycle(env, keyEventObj);  
  23.             env->DeleteLocalRef(keyEventObj);  
  24.         } else {  
  25.             ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");  
  26.             wmActions = 0;  
  27.         }  
  28.   
  29.         handleInterceptActions(wmActions, when, /*byref*/ policyFlags);  
  30.     } else {  
  31.         if (mInteractive) {  
  32.             policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  33.         }  
  34.     }  
  35. }  


wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing,keyEventObj, policyFlags);则会call 到

InputManagerService.java中的interceptKeyBeforeQueueing

[cpp] view plain copy

  1. private long interceptKeyBeforeQueueing(InputWindowHandle focus,  
  2.         KeyEvent event, int policyFlags) {  
  3.     return mWindowManagerCallbacks.interceptKeyBeforeQueueing(focus, event, policyFlags);  
  4. }  


mWindowManagerCallbacks实际为InputMonitor

SystemServer.java 文件中startOtherServices调用inputManager.setWindowManagerCallbacks(wm.getInputMonitor()),给mWindowManagerCallbacks

赋值,而wm.getInputMonitor()获取的是InputMonitor, 所以mWindowManagerCallbacks.interceptKeyBeforeQueueing最后调用到InputMonitor:interceptKeyBeforeQueueing

InputMonitor.java文件中:

[cpp] v

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值