【Android休眠】之Android对PowerKey事件的处理(1)代码流程
16lz
2021-01-23
版本信息:Linux 3.10Android 4.4
http://blog.csdn.net/u013686019/article/details/53691879 Android休眠在framework的处理涉及两个系统服务,InputManagerService和PowerManagerService。InputManagerService负责处理PowerKey产生的Input事件,根据事件类型调用PowerManagerService的休眠、唤醒接口:
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags) { if (wmActions & WM_ACTION_GO_TO_SLEEP) { ALOGD("handleInterceptActions: Going to sleep."); android_server_PowerManagerService_goToSleep(when); } if (wmActions & WM_ACTION_WAKE_UP) { ALOGD("handleInterceptActions: Waking up."); android_server_PowerManagerService_wakeUp(when); } if (wmActions & WM_ACTION_PASS_TO_USER) { policyFlags |= POLICY_FLAG_PASS_TO_USER; }}
PowerManagerService执行具体的休眠、唤醒动作:
private void goToSleepInternal(long eventTime, int reason) {Slog.i(TAG, "goToSleepInternal, reason: " + reason); synchronized (mLock) { if (goToSleepNoUpdateLocked(eventTime, reason)) { updatePowerStateLocked(); } } }}private void updatePowerStateLocked() {// Phase 0: Basic state updates.// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.// Phase 2: Update dreams and display power state.// Phase 3: Send notifications, if needed.// Phase 4: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();}
它们之间关系如下图:
由于这两个服务涉及framework最核心的功能且其代码实现繁复,这里只贴出其处理流程,具体细节其他篇幅再续。本篇目的:始知此事要躬行,如果有意弄清流程,提供一个参照。
1、InputManagerService服务加载:
SystemServer.java (frameworks\base\services\java\com\android\server)InputManagerService inputManager = null;inputManager = new InputManagerService(context, wmHandler);inputManager.start();
2、 InputManagerService Java:
InputManagerService.java (frameworks\base\services\java\com\android\server\input)public class InputManagerService { public InputManagerService(Context context, Handler handler) { mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); }}
3、 InputManagerService的JNI:
com_android_server_input_InputManagerService.cpp (frameworks\base\services\jni)static jint nativeInit(JNIEnv* env, jclass clazz, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(0); return reinterpret_cast(im);}NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp& looper) : mLooper(looper) { mInputManager = new InputManager(eventHub, this, this);}
4、Input事件的Manager:
InputManager.cpp (frameworks\base\services\input)InputManager::InputManager( const sp& eventHub, const sp& readerPolicy, const sp& dispatcherPolicy) { mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize();}// InputReaderThread:事件读取// InputDispatcherThread:事件分发void InputManager::initialize() { mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher);}status_t InputManager::start() { status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); return OK;}
5 ,事件读取、分发:
InputReader.cpp (frameworks\base\services\input)InputReaderThread::InputReaderThread(const sp& reader) : Thread(/*canCallJava*/ true), mReader(reader) {}InputDispatcher.cpp (frameworks\base\services\input)InputDispatcherThread::InputDispatcherThread(const sp& dispatcher) : Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {}
6、PowerKey事件上报:
InputReader.cpp (frameworks\base\services\input)void InputReader::loopOnce() { size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); { // acquire lock AutoMutex _l(mLock); if (count) { processEventsLocked(mEventBuffer, count); } } // release lock}void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {int32_t type = rawEvent->type; size_t batchSize = 1;if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {ALOGD("BatchSize: %d Count: %d", batchSize, count);processEventsForDeviceLocked(deviceId, rawEvent, batchSize);}}void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count) { InputDevice* device = mDevices.valueAt(deviceIndex); device->process(rawEvents, count);}void InputDevice::process(const RawEvent* rawEvents, size_t count) { ALOGD("InputDevice::process"); size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld", rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);if (mDropUntilNextSync) { } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) { } else { ALOGD("InputDevice::process else"); for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); } }}}void KeyboardInputMapper::process(const RawEvent* rawEvent) {ALOGI("KeyboardInputMapper::process"); switch (rawEvent->type) { case EV_KEY: {// #define EV_KEY 0x01 int32_t scanCode = rawEvent->code; int32_t usageCode = mCurrentHidUsage; mCurrentHidUsage = 0; if (isKeyboardOrGamepadKey(scanCode)) { int32_t keyCode; uint32_t flags; processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags); } break; } }}void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {// processkey, down=1, keyCode=26, policyFlags=1ALOGI("processkey, down=%d, keyCode=%d, policyFlags=%d, ", down, keyCode, policyFlags); if (down) { // Rotate key codes according to orientation if needed. } NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); getListener()->notifyKey(&args);}InputListener.cpp (frameworks\base\services\input)void NotifyKeyArgs::notify(const sp& listener) const { ALOGD("notify"); listener->notifyKey(this);}
7、构建KeyEvent:
InputDispatcher.cpp (frameworks\base\services\input)void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, " "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld", args->eventTime, args->deviceId, args->source, args->policyFlags, args->action, args->flags, args->keyCode, args->scanCode, args->metaState, args->downTime); if (!validateKeyEvent(args->action)) { return; } uint32_t policyFlags = args->policyFlags; int32_t flags = args->flags; int32_t metaState = args->metaState; KeyEvent event; event.initialize(args->deviceId, args->source, args->action, flags, args->keyCode, args->scanCode, metaState, 0, args->downTime, args->eventTime); mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);}
8、KeyEvent处理并调用PowerManagerService的休眠接口:
com_android_server_input_InputManagerService.cpp (frameworks\base\services\jni)void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {ALOGD("interceptKeyBeforeQueueing: policyFlags = %d\n", policyFlags); if ((policyFlags & POLICY_FLAG_TRUSTED)) { nsecs_t when = keyEvent->getEventTime(); bool isScreenOn = this->isScreenOn(); bool isScreenBright = this->isScreenBright(); JNIEnv* env = jniEnv(); jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); jint wmActions; if (keyEventObj) { wmActions = env->CallIntMethod(mServiceObj, gServiceClassInfo.interceptKeyBeforeQueueing, keyEventObj, policyFlags, isScreenOn); if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { wmActions = 0; } android_view_KeyEvent_recycle(env, keyEventObj); env->DeleteLocalRef(keyEventObj); }handleInterceptActions(wmActions, when, /*byref*/ policyFlags);}}void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags) { if (wmActions & WM_ACTION_GO_TO_SLEEP) { ALOGD("handleInterceptActions: Going to sleep."); android_server_PowerManagerService_goToSleep(when); } if (wmActions & WM_ACTION_WAKE_UP) { ALOGD("handleInterceptActions: Waking up."); android_server_PowerManagerService_wakeUp(when); } if (wmActions & WM_ACTION_PASS_TO_USER) { policyFlags |= POLICY_FLAG_PASS_TO_USER; } else { ALOGD("handleInterceptActions: Not passing key to user."); }}com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) { if (gPowerManagerServiceObj) { JNIEnv* env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleepFromNative, nanoseconds_to_milliseconds(eventTime), 0); checkAndClearExceptionFromCallback(env, "goToSleepFromNative"); }}
9、由于是从PowerKey发起休眠/唤醒动作,所以使用的是goToSleepFromNative:
PowerManagerService.java (frameworks\base\services\java\com\android\server\power)private void goToSleepFromNative(long eventTime, int reason) { Slog.i(TAG, "goToSleepFromNative, reason: " + reason); if (reason != PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN && reason != PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { if (mDisplayManager.isWfdConnect()) {mHandler.sendEmptyMessage(MSG_DISABLE_WIFI_FOR_WIFIP2P);return; }} goToSleepInternal(eventTime, reason);}private void goToSleepInternal(long eventTime, int reason) {Slog.i(TAG, "goToSleepInternal, reason: " + reason); synchronized (mLock) { if (goToSleepNoUpdateLocked(eventTime, reason)) { updatePowerStateLocked(); } } }}/** * This is the main function that performs power state transitions. * We centralize them here so that we can recompute the power state completely * each time something important changes, and ensure that we do it the same * way each time. The point is to gather all of the transition logic here. */private void updatePowerStateLocked() {// Phase 0: Basic state updates.// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.// Phase 2: Update dreams and display power state.// Phase 3: Send notifications, if needed.// Phase 4: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();}
10、 PowerManagerService执行休眠,对了, 就是释放锁:
/** * Updates the suspend blocker that keeps the CPU alive. */private void updateSuspendBlockerLocked() {final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();// First acquire suspend blockers if needed.if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {mWakeLockSuspendBlocker.acquire();mHoldingWakeLockSuspendBlocker = true;}if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {mDisplaySuspendBlocker.acquire();mHoldingDisplaySuspendBlocker = true;}// Then release suspend blockers if needed.if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {mWakeLockSuspendBlocker.release();mHoldingWakeLockSuspendBlocker = false;}if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {mDisplaySuspendBlocker.release();mHoldingDisplaySuspendBlocker = false;}}
至于锁释放是如何和内核交互的,参见:
更多相关文章
- Android热插拔事件处理流程
- android 软键盘 返回键 消失事件 监听
- Android中callback(接口回调)机制
- Android事件分发之总结(三)
- Android调用相机接口
- Android adb 模拟滑动 按键 点击事件
- Android framework 源码分析一Activity启动流程(android 8.0)
- 重点核心☆☆☆☆☆按钮点击事件的四种类型
- 关于android 的触摸事件