zoukankan      html  css  js  c++  java
  • 【Android休眠】之Android对PowerKey事件的处理(1)代码流程

    受不了xxxx恶心人的行为,遂搬迁至博客园。
    始发:2016-12-16 13:08:47
    
    
    版本信息:
    Linux:3.10
    Android: 4.4
    

    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 (frameworksaseservicesjavacomandroidserver)
    InputManagerService inputManager = null;
    inputManager = new InputManagerService(context, wmHandler);
    inputManager.start();
    

    2、InputManagerService Java:

    InputManagerService.java (frameworksaseservicesjavacomandroidserverinput)
    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 (frameworksaseservicesjni)
    static jint nativeInit(JNIEnv* env, jclass clazz,
            jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
        sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
        
        NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
                messageQueue->getLooper());
        im->incStrong(0);
        return reinterpret_cast<jint>(im);
    }
     
    NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :
            mLooper(looper) {
        mInputManager = new InputManager(eventHub, this, this);
    }
    

    4、Input事件的Manager:

    InputManager.cpp (frameworksaseservicesinput)
    InputManager::InputManager(
            const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& 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 (frameworksaseservicesinput)
    InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
            Thread(/*canCallJava*/ true), mReader(reader) {
    }
     
    InputDispatcher.cpp (frameworksaseservicesinput)
    InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
            Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
    }
    

    6、PowerKey事件上报:

    InputReader.cpp (frameworksaseservicesinput)
    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=1
    	ALOGI("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 (frameworksaseservicesinput)
    void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
        ALOGD("notify");
        listener->notifyKey(this);
    }
    

      

    7、构建KeyEvent:

    InputDispatcher.cpp (frameworksaseservicesinput)
    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 (frameworksaseservicesjni)
    void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
    	ALOGD("interceptKeyBeforeQueueing: policyFlags = %d
    ", 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 (frameworksaseservicesjni)
    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 (frameworksaseservicesjavacomandroidserverpower)
    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休眠】之休眠锁的获取和释放

  • 相关阅读:
    socket 中文man页面函数
    指针和数组(上)
    char和unsigned char--数据类型区别
    自己的总结
    warning C4305:“初始化”:从“double”到“float”截断
    指针数组和数组指针区别
    Python模块常用的几种安装方式
    Jenkins环境搭建
    wxPython:事件
    wx.ListCtrl简单使用例子
  • 原文地址:https://www.cnblogs.com/rockyching2009/p/13282388.html
Copyright © 2011-2022 走看看