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

时间:2024-02-19 16:22:27
受不了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 (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> 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 (frameworks\base\services\input)
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 (frameworks\base\services\input)
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
        Thread(/*canCallJava*/ true), mReader(reader) {
}
 
InputDispatcher.cpp (frameworks\base\services\input)
InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& 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=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 (frameworks\base\services\input)
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& 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休眠】之休眠锁的获取和释放