例子: 打开收,并解锁进入桌面,如果在规定时间内不操作手机,那么屏幕将变暗,最后关闭。在此过程中,如果触动屏幕,屏幕又会重新变亮。这个触动屏幕的操作将触发userActivity函数的调用。
上例中涉及两方面
1. 不操作手机,屏幕将变暗,最后关闭。在PowerManagerService中,这是一个状态切换过程;
2. 操作手机,将触发userActivity,此后屏幕变亮;
源代码:
public void userActivity(long time, boolean noChangeLights, int eventType) {
userActivity(time, -1, noChangeLights, eventType, false);
}
另外一个同名函数:
该函数的eventType共有三种,分别为:
1. OTHER_EVENT: 除按键,触屏外的事件
2. BUTTON_EVENT: 按键事件
3. TOUCH_EVENT: 触屏事件
private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
int eventType, boolean force) {
if (((mPokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0) && (eventType == TOUCH_EVENT)) {
if (false) {
Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
}
return;
}
synchronized (mLocks) {
if (mSpew) {
Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
+ " mUserActivityAllowed=" + mUserActivityAllowed
+ " mUserState=0x" + Integer.toHexString(mUserState)
+ " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
+ " mProximitySensorActive=" + mProximitySensorActive
+ " timeoutOverride=" + timeoutOverride
+ " force=" + force);
}
// ignore user activity if we are in the process of turning off the screen
if (isScreenTurningOffLocked()) {
Slog.d(TAG, "ignoring user activity while turning off screen");
return;
}
// Disable proximity sensor if if user presses power key while we are in the
// "waiting for proximity sensor to go negative" state.
if (mProximitySensorActive && mProximityWakeLockCount == 0) {
mProximitySensorActive = false;
}
if (mLastEventTime <= time || force) {
mLastEventTime = time;
if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
// Only turn on button backlights if a button was pressed
// and auto brightness is disabled
if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
} else {
// don't clear button/keyboard backlights when the screen is touched.
mUserState |= SCREEN_BRIGHT;
}
int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
mBatteryStats.noteUserActivity(uid, eventType);
} catch (RemoteException e) {
// Ignore
} finally {
Binder.restoreCallingIdentity(ident);
}
mWakeLockState = mLocks.reactivateScreenLocksLocked();
setPowerState(mUserState | mWakeLockState, noChangeLights,
WindowManagerPolicy.OFF_BECAUSE_OF_USER);
setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
}
}
}
if (mPolicy != null) {
mPolicy.userActivity();
}
}
在该函数中调用setTimeoutLocked重新计算超时时间
private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
long timeoutOverride = originalTimeoutOverride;
if (mBootCompleted) {
synchronized (mLocks) {
long when = 0;
if (timeoutOverride <= 0) {
switch (nextState)
{
case SCREEN_BRIGHT:
when = now + mKeylightDelay;
break;
case SCREEN_DIM:
if (mDimDelay >= 0) {
when = now + mDimDelay;
break;
} else {
Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
}
case SCREEN_OFF:
synchronized (mLocks) {
when = now + mScreenOffDelay;
}
break;
default:
when = now;
break;
}
} else {
override: {
if (timeoutOverride <= mScreenOffDelay) {
when = now + timeoutOverride;
nextState = SCREEN_OFF;
break override;
}
timeoutOverride -= mScreenOffDelay;
if (mDimDelay >= 0) {
if (timeoutOverride <= mDimDelay) {
when = now + timeoutOverride;
nextState = SCREEN_DIM;
break override;
}
timeoutOverride -= mDimDelay;
}
when = now + timeoutOverride;
nextState = SCREEN_BRIGHT;
}
}
if (mSpew) {
Slog.d(TAG, "setTimeoutLocked now=" + now
+ " timeoutOverride=" + timeoutOverride
+ " nextState=" + nextState + " when=" + when);
}
mHandler.removeCallbacks(mTimeoutTask);
mTimeoutTask.nextState = nextState;
mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
? (originalTimeoutOverride - timeoutOverride)
: -1;
mHandler.postAtTime(mTimeoutTask, when);
mNextTimeout = when; // for debugging
}
}
}
向Handler中添加mTimeoutTask任务,mTimeoutTask为TimeoutTask的对象
private class TimeoutTask implements Runnable
{
int nextState; // access should be synchronized on mLocks
long remainingTimeoutOverride;
public void run()
{
synchronized (mLocks) {
if (mSpew) {
Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
}
if (nextState == -1) {
return;
}
mUserState = this.nextState;
setPowerState(this.nextState | mWakeLockState);
long now = SystemClock.uptimeMillis();
switch (this.nextState)
{
case SCREEN_BRIGHT:
if (mDimDelay >= 0) {
setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
break;
}
case SCREEN_DIM:
setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
break;
}
}
}
}
TimeoutTask就是用来切换屏幕状态的。