版本信息:Linux 3.10Android 4.4
http://blog.csdn.net/u013686019/article/details/53691879

Android休眠在framework的处理涉及两个系统服务,InputManagerServicePowerManagerServiceInputManagerService负责处理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();}

它们之间关系如下图:

【Android休眠】之Android对PowerKey事件的处理(1)代码流程_第1张图片


由于这两个服务涉及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;}}

至于锁释放是如何和内核交互的,参见:



更多相关文章

  1. Android热插拔事件处理流程
  2. android 软键盘 返回键 消失事件 监听
  3. Android中callback(接口回调)机制
  4. Android事件分发之总结(三)
  5. Android调用相机接口
  6. Android adb 模拟滑动 按键 点击事件
  7. Android framework 源码分析一Activity启动流程(android 8.0)
  8. 重点核心☆☆☆☆☆按钮点击事件的四种类型
  9. 关于android 的触摸事件

随机推荐

  1. Android 支持多屏幕机制
  2. android 开发中java.net.UnknownServiceE
  3. Android 实现聊天-smack4.19
  4. android简单计算器源码
  5. android - Animation prevents click eve
  6. about android screen
  7. android ndk 开发
  8. Android消息推送MQTT
  9. Android(安卓)工程的创建
  10. android bug fix