一、 kernel部分
1.看TP驱动有没有事件上报
cat /dev/input/evnet1
或者看kernel log
[ 4036.282237] bt541_ts_device 5-0020: gesture wakeup input report //获得唤醒事件
[ 4036.486756] bt541_ts_device 5-0020: bt541_ts_resume start TP启动开始
[ 4036.550178] bt541_ts_device 5-0020: bt541_ts_resume end TP启动结束
Z:\HLOS\kernel\drivers\input\touchscreen\bt541\zinitix_bt541_ts.c
static irqreturn_t bt541_touch_work(int irq, void *data)
{
........
if(info->work_state == SUSPEND) //点击事件时才触发,触摸长按不触发
{
if(tpd_gesture == 1)
{
tpd_gesture = 0;
dev_err(&client->dev," gesture wakeup input report\r\n");
write_cmd(client, BT541_CLEAR_INT_STATUS_CMD);
input_report_key(info->input_dev, KEY_POWER, 1);
input_sync(info->input_dev);
input_report_key(info->input_dev, KEY_POWER, 0);
input_sync(info->input_dev);
}
goto out;
}
.....
}
Z:\HLOS\kernel\include\uapi\linux\input.h
#define BTN_TOUCH
0x14a
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
Z:\HLOS\kernel\drivers\input\input.c
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags;
if (is_event_supported(type, dev->evbit, EV_MAX)) { //判断是否是注册时的event类型,驱动 probe 时注册 input_dev 时设置了能响应的event类型
spin_lock_irqsave(&dev->event_lock, flags); //自旋锁枷锁
input_handle_event(dev, type, code, value); //进一步处理传上来的这个 event
spin_unlock_irqrestore(&dev->event_lock, flags); //解锁
}
}
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition;
disposition = input_get_disposition(dev, type, code, &value);
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
if (!dev->vals)
return;
if (disposition & INPUT_PASS_TO_HANDLERS) {
struct input_value *v;
if (disposition & INPUT_SLOT) {
v = &dev->vals[dev->num_vals++];
v->type = EV_ABS;
v->code = ABS_MT_SLOT;
v->value = dev->mt->slot;
}
v = &dev->vals[dev->num_vals++];
v->type = type;
v->code = code;
v->value = value;
}
if (disposition & INPUT_FLUSH) {
if (dev->num_vals >= 2)
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
} else if (dev->num_vals >= dev->max_vals - 2) {
dev->vals[dev->num_vals++] = input_value_sync;
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
}
}
static void input_pass_values(struct input_dev *dev,
struct input_value *vals, unsigned int count)
{
struct input_handle *handle;
struct input_value *v;
if (!count)
return;
rcu_read_lock();
handle = rcu_dereference(dev->grab);
if (handle) {
count = input_to_handler(handle, vals, count);
} else {
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
count = input_to_handler(handle, vals, count);
}
rcu_read_unlock();
add_input_randomness(vals->type, vals->code, vals->value);
/* trigger auto repeat for key events */
for (v = vals; v != vals + count; v++) {
if (v->type == EV_KEY && v->value != 2) {
if (v->value)
input_start_autorepeat(dev, v->code);
else
input_stop_autorepeat(dev);
}
}
}
static unsigned int input_to_handler(struct input_handle *handle,
struct input_value *vals, unsigned int count)
{
struct input_handler *handler = handle->handler;
struct input_value *end = vals;
struct input_value *v;
for (v = vals; v != vals + count; v++) {
if (handler->filter &&
handler->filter(handle, v->type, v->code, v->value))
continue;
if (end != v)
*end = *v;
end++;
}
count = end - vals;
if (!count)
return 0;
if (handler->events)
handler->events(handle, vals, count);
else if (handler->event)
for (v = vals; v != end; v++)
handler->event(handle, v->type, v->code, v->value);
return count;
}
Z:\HLOS\kernel\drivers\input\evdev.c
static struct input_handler evdev_handler = {
.event
= evdev_event,
.events
= evdev_events,
.connect
= evdev_connect,
.disconnect
= evdev_disconnect,
.legacy_minors
= true,
.minor
= EVDEV_MINOR_BASE,
.name
= "evdev",
.id_table
= evdev_ids,
};
static void evdev_events(struct input_handle *handle,
const struct input_value *vals, unsigned int count)
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
ktime_t time_mono, time_real;
time_mono = ktime_get();
time_real = ktime_mono_to_real(time_mono);
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_values(client, vals, count, time_mono, time_real);
else
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_values(client, vals, count,
time_mono, time_real);
rcu_read_unlock();
}
/*
* Pass incoming event to all connected clients.
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
{
struct input_value vals[] = { { type, code, value } };
evdev_events(handle, vals, 1);
}
static void evdev_pass_values(struct evdev_client *client,
const struct input_value *vals, unsigned int count,
ktime_t mono, ktime_t real)
{
struct evdev *evdev = client->evdev;
const struct input_value *v;
struct input_event event;
bool wakeup = false;
if (client->revoked)
return;
event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
mono : real);
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
for (v = vals; v != vals + count; v++) {
event.type = v->type;
event.code = v->code;
event.value = v->value;
__pass_event(client, &event);
if (v->type == EV_SYN && v->code == SYN_REPORT)
wakeup = true;
}
spin_unlock(&client->buffer_lock);
if (wakeup)
wake_up_interruptible(&evdev->wait);
}
static void __pass_event(struct evdev_client *client,
const struct input_event *event)
{
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
if (unlikely(client->head == client->tail)) {
/*
* This effectively "drops" all unconsumed events, leaving
* EV_SYN/SYN_DROPPED plus the newest event in the queue.
*/
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
client->packet_head = client->tail;
if (client->use_wake_lock)
wake_unlock(&client->wake_lock);
}
if (event->type == EV_SYN && event->code == SYN_REPORT) {
client->packet_head = client->head;
if (client->use_wake_lock)
wake_lock(&client->wake_lock);
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}
}
二、 native部分
Z:\HLOS\frameworks\native\services\inputflinger\InputReader.cpp
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector
inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1;
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count);
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
mQueuedListener->flush(); //做完一次事件后flush
}
Z:\HLOS\frameworks\native\services\inputflinger\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
AutoMutex _l(mLock);
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// Reopen input devices if needed.
if (mNeedToReopenDevices) {
mNeedToReopenDevices = false;
ALOGI("Reopening all input devices due to a configuration change.");
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
// Report any devices that had last been added/removed.
while (mClosingDevices) {
Device* device = mClosingDevices;
ALOGV("Reporting device closed: id=%d, name=%s\n",
device->id, device->path.string());
mClosingDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
event->type = DEVICE_REMOVED;
event += 1;
delete device;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
if (mNeedToScanDevices) { //这个在EventHub初始时为true
mNeedToScanDevices = false;
scanDevicesLocked(); //这个往里走就是通过EventHub::openDeviceLocked 打开*DEVICE_PATH = "/dev/input" 这个设备 ,最终用的open,实际到kernel层就是input设备注册的open
mNeedToSendFinishedDeviceScan = true;
}
while (mOpeningDevices != NULL) { //这个指针有指向,代表上面打开了某些input设备
Device* device = mOpeningDevices; // 初始化一个添加event,type 为DEVICE_ADDED
ALOGV("Reporting device opened: id=%d, name=%s\n",
device->id, device->path.string());
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED;
event += 1;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
event->when = now;
event->type = FINISHED_DEVICE_SCAN;
event += 1;
if (--capacity == 0) {
break;
}
}
// Grab the next input event.
bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) { //这个是为处理多个input event 做的一个epoll_event 类型数组
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
} else {
ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
}
continue;
}
if (eventItem.data.u32 == EPOLL_ID_WAKE) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
char buffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
eventItem.events);
}
continue;
}
ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
if (deviceIndex < 0) {
ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
eventItem.events, eventItem.data.u32);
continue;
}
Device* device = mDevices.valueAt(deviceIndex);
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer, //这里的device->fd就是/dev/input/event%d这个设备文件,就是从这里读取出event的buffer 最终会调用到evdev中的read
sizeof(struct input_event) * capacity);
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
ALOGW("could not get event, removed? (fd: %d size: %" PRId32
" bufferSize: %zu capacity: %zu errno: %d)\n",
device->fd, readSize, bufferSize, capacity, errno);
deviceChanged = true;
closeDeviceLocked(device);
} else if (readSize < 0) {
if (errno != EAGAIN && errno != EINTR) {
ALOGW("could not get event (errno=%d)", errno);
}
} else if ((readSize % sizeof(struct input_event)) != 0) {
ALOGE("could not get event (wrong size: %d)", readSize);
} else {
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i]; /这里把上面读到的input_event 转化过这里的RawEvent
ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
device->path.string(),
(int) iev.time.tv_sec, (int) iev.time.tv_usec,
iev.type, iev.code, iev.value);
// Some input devices may have a better concept of the time
// when an input event was actually generated than the kernel
// which simply timestamps all events on entry to evdev.
// This is a custom Android extension of the input protocol
// mainly intended for use with uinput based device drivers.
if (iev.type == EV_MSC) {
if (iev.code == MSC_ANDROID_TIME_SEC) {
device->timestampOverrideSec = iev.value;
continue;
} else if (iev.code == MSC_ANDROID_TIME_USEC) {
device->timestampOverrideUsec = iev.value;
continue;
}
}
if (device->timestampOverrideSec || device->timestampOverrideUsec) {
iev.time.tv_sec = device->timestampOverrideSec;
iev.time.tv_usec = device->timestampOverrideUsec;
if (iev.type == EV_SYN && iev.code == SYN_REPORT) {
device->timestampOverrideSec = 0;
device->timestampOverrideUsec = 0;
}
ALOGV("applied override time %d.%06d",
int(iev.time.tv_sec), int(iev.time.tv_usec));
}
// Use the time specified in the event instead of the current time
// so that downstream code can get more accurate estimates of
// event dispatch latency from the time the event is enqueued onto
// the evdev client buffer.
//
// The event's timestamp fortuitously uses the same monotonic clock
// time base as the rest of Android. The kernel event device driver
// (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
// The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
// calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
// system call that also queries ktime_get_ts().
event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
+ nsecs_t(iev.time.tv_usec) * 1000LL;
ALOGV("event time %" PRId64 ", now %" PRId64, event->when, now);
// Bug 7291243: Add a guard in case the kernel generates timestamps
// that appear to be far into the future because they were generated
// using the wrong clock source.
//
// This can happen because when the input device is initially opened
// it has a default clock source of CLOCK_REALTIME. Any input events
// enqueued right after the device is opened will have timestamps
// generated using CLOCK_REALTIME. We later set the clock source
// to CLOCK_MONOTONIC but it is already too late.
//
// Invalid input event timestamps can result in ANRs, crashes and
// and other issues that are hard to track down. We must not let them
// propagate through the system.
//
// Log a warning so that we notice the problem and recover gracefully.
if (event->when >= now + 10 * 1000000000LL) {
// Double-check. Time may have moved on.
nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
if (event->when > time) {
ALOGW("An input event from %s has a timestamp that appears to "
"have been generated using the wrong clock source "
"(expected CLOCK_MONOTONIC): "
"event time %" PRId64 ", current time %" PRId64
", call time %" PRId64 ". "
"Using current time instead.",
device->path.string(), event->when, time, now);
event->when = time;
} else {
ALOGV("Event time is ok but failed the fast path and required "
"an extra call to systemTime: "
"event time %" PRId64 ", current time %" PRId64
", call time %" PRId64 ".",
event->when, time, now);
}
}
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
if (capacity == 0) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
break;
}
}
} else if (eventItem.events & EPOLLHUP) {
ALOGI("Removing device %s due to epoll hang-up event.",
device->identifier.name.string());
deviceChanged = true;
closeDeviceLocked(device);
} else {
ALOGW("Received unexpected epoll event 0x%08x for device %s.",
eventItem.events, device->identifier.name.string());
}
}
// readNotify() will modify the list of devices so this must be done after
// processing all other events to ensure that we read all remaining events
// before closing the devices.
if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
mPendingINotify = false;
readNotifyLocked();
deviceChanged = true;
}
// Report added or removed devices immediately.
if (deviceChanged) {
continue;
}
// Return now if we have collected any events or if we were explicitly awoken.
if (event != buffer || awoken) {
break;
}
// Poll for events. Mind the wake lock dance!
// We hold a wake lock at all times except during epoll_wait(). This works due to some
// subtle choreography. When a device driver has pending (unread) events, it acquires
// a kernel wake lock. However, once the last pending event has been read, the device
// driver will release the kernel wake lock. To prevent the system from going to sleep
// when this happens, the EventHub holds onto its own user wake lock while the client
// is processing events. Thus the system can only sleep if there are no events
// pending or currently being processed.
//
// The timeout is advisory only. If the device is asleep, it will not wake just to
// service the timeout.
mPendingEventIndex = 0;
mLock.unlock(); // release lock before poll, must be before release_wake_lock
release_wake_lock(WAKE_LOCK_ID);
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); //用于等待监测是否有事件可读
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock
if (pollResult == 0) {
// Timed out.
mPendingEventCount = 0;
break;
}
if (pollResult < 0) {
// An error occurred.
mPendingEventCount = 0;
// Sleep after errors to avoid locking up the system.
// Hopefully the error is transient.
if (errno != EINTR) {
ALOGW("poll failed (errno=%d)\n", errno);
usleep(100000);
}
} else {
// Some events occurred.
mPendingEventCount = size_t(pollResult);
}
}
// All done, return the number of events we read.
return event - buffer; //指针相减,这个数组的元素个数
}
static const char *DEVICE_PATH = "/dev/input";
void EventHub::scanDevicesLocked() {
status_t res = scanDirLocked(DEVICE_PATH);
if(res < 0) {
ALOGE("scan dir failed for %s\n", DEVICE_PATH);
}
if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
createVirtualKeyboardLocked();
}
}
status_t EventHub::scanDirLocked(const char *dirname)
{
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
openDeviceLocked(devname);
}
closedir(dir);
return 0;
}
status_t EventHub::openDeviceLocked(const char *devicePath) {
char buffer[80];
ALOGV("Opening device: %s", devicePath);
int fd = open(devicePath, O_RDWR | O_CLOEXEC);
if(fd < 0) {
ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
}
InputDeviceIdentifier identifier;
// Get device name.
if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
//fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name.setTo(buffer);
}
// Check to see if the device is on our excluded list
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const String8& item = mExcludedDevices.itemAt(i);
if (identifier.name == item) {
ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
close(fd);
return -1;
}
}
// Get device driver version.
int driverVersion;
if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
close(fd);
return -1;
}
// Get device identifier.
struct input_id inputId;
if(ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
close(fd);
return -1;
}
identifier.bus = inputId.bustype;
identifier.product = inputId.product;
identifier.vendor = inputId.vendor;
identifier.version = inputId.version;
// Get device physical location.
if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
//fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.location.setTo(buffer);
}
// Get device unique id.
if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
//fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.uniqueId.setTo(buffer);
}
// Fill in the descriptor.
assignDescriptorLocked(identifier);
// Make file descriptor non-blocking for use with poll().
if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
ALOGE("Error %d making device file descriptor non-blocking.", errno);
close(fd);
return -1;
}
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, String8(devicePath), identifier); //这里根据前面获取的参数new成一个device,算是初步打开完成抽象成一个Device了
ALOGV("add device %d: %s\n", deviceId, devicePath);
ALOGV(" bus: %04x\n"
" vendor %04x\n"
" product %04x\n"
" version %04x\n",
identifier.bus, identifier.vendor, identifier.product, identifier.version);
ALOGV(" name: \"%s\"\n", identifier.name.string());
ALOGV(" location: \"%s\"\n", identifier.location.string());
ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string());
ALOGV(" driver: v%d.%d.%d\n",
driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
// Load the configuration file for the device.
loadConfigurationLocked(device); // 这个比较重要 ,加载这个device的配置信息,后面将会根据这个配置来定义规则
//又是一系列的判断初始化,其中比较重要的就是 device->classes 这个变量,代表了input 设备类型,是键盘,鼠标,触摸屏
// Figure out the kinds of events the device reports.
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
// See if this is a keyboard. Ignore everything in the button range except for
// joystick and gamepad buttons which are handled like keyboards for the most part.
bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
|| containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
sizeof_bit_array(KEY_MAX + 1));
bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
sizeof_bit_array(BTN_MOUSE))
|| containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
sizeof_bit_array(BTN_DIGI));
if (haveKeyboardKeys || haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this is a cursor device such as a trackball or mouse.
if (test_bit(BTN_MOUSE, device->keyBitmask)
&& test_bit(REL_X, device->relBitmask)
&& test_bit(REL_Y, device->relBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
// See if this is a rotary encoder type device.
String8 deviceType = String8();
if (device->configuration &&
device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
if (!deviceType.compare(String8("rotaryEncoder"))) {
device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
}
}
// See if this is a touch pad.
// Is this a new modern multi-touch driver?
if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
&& test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
// Some joysticks such as the PS3 controller report axes that conflict
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
}
// Is this an old style single-touch driver?
} else if (test_bit(BTN_TOUCH, device->keyBitmask)
&& test_bit(ABS_X, device->absBitmask)
&& test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH;
// Is this a BT stylus?
} else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
test_bit(BTN_TOUCH, device->keyBitmask))
&& !test_bit(ABS_X, device->absBitmask)
&& !test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
// Keyboard will try to claim some of the buttons but we really want to reserve those so we
// can fuse it with the touch screen data, so just take them back. Note this means an
// external stylus cannot also be a keyboard device.
device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this device is a joystick.
// Assumes that joysticks always have gamepad buttons in order to distinguish them
// from other devices such as accelerometers that also have absolute axes.
if (haveGamepadButtons) {
uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
if (test_bit(i, device->absBitmask)
&& (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
device->classes = assumedClasses;
break;
}
}
}
// Check whether this device has switches.
for (int i = 0; i <= SW_MAX; i++) {
if (test_bit(i, device->swBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_SWITCH;
break;
}
}
// Check whether this device supports the vibrator.
if (test_bit(FF_RUMBLE, device->ffBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
}
// Configure virtual keys.
if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
// Load the virtual keys for the touch screen, if any.
// We do this now so that we can make sure to load the keymap if necessary.
status_t status = loadVirtualKeyMapLocked(device);
if (!status) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
}
// Load the key map.
// We need to do this for joysticks too because the key layout may specify axes.
status_t keyMapStatus = NAME_NOT_FOUND;
if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
// Load the keymap for the device.
keyMapStatus = loadKeyMapLocked(device);
}
// Configure the keyboard, gamepad or virtual keyboard.
if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
// Register the keyboard as a built-in keyboard if it is eligible.
if (!keyMapStatus
&& mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD
&& isEligibleBuiltInKeyboard(device->identifier,
device->configuration, &device->keyMap)) {
mBuiltInKeyboardId = device->id;
}
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
if (hasKeycodeLocked(device, AKEYCODE_Q)) {
device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
}
// See if this device has a DPAD.
if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
device->classes |= INPUT_DEVICE_CLASS_DPAD;
}
// See if this device has a gamepad.
for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
break;
}
}
// Disable kernel key repeat since we handle it ourselves
unsigned int repeatRate[] = {0,0};
if (ioctl(fd, EVIOCSREP, repeatRate)) {
ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
}
}
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'",
deviceId, devicePath, device->identifier.name.string());
delete device;
return -1;
}
// Determine whether the device has a mic.
if (deviceHasMicLocked(device)) {
device->classes |= INPUT_DEVICE_CLASS_MIC;
}
// Determine whether the device is external or internal.
if (isExternalDeviceLocked(device)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
}
if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
&& device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
device->controllerNumber = getNextControllerNumberLocked(device);
setLedForController(device);
}
// Register with epoll.
struct epoll_event eventItem; //注册epoll
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
if (mUsingEpollWakeup) {
eventItem.events |= EPOLLWAKEUP;
}
eventItem.data.u32 = deviceId;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
delete device;
return -1;
}
String8 wakeMechanism("EPOLLWAKEUP");
if (!mUsingEpollWakeup) {
#ifndef EVIOCSSUSPENDBLOCK
// uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
// will use an epoll flag instead, so as long as we want to support
// this feature, we need to be prepared to define the ioctl ourselves.
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
#endif
if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
wakeMechanism = "";
} else {
wakeMechanism = "EVIOCSSUSPENDBLOCK";
}
}
// Tell the kernel that we want to use the monotonic clock for reporting timestamps
// associated with input events. This is important because the input system
// uses the timestamps extensively and assumes they were recorded using the monotonic
// clock.
//
// In older kernel, before Linux 3.4, there was no way to tell the kernel which
// clock to use to input event timestamps. The standard kernel behavior was to
// record a real time timestamp, which isn't what we want. Android kernels therefore
// contained a patch to the evdev_event() function in drivers/input/evdev.c to
// replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
// clock to be used instead of the real time clock.
//
// As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
// Therefore, we no longer require the Android-specific kernel patch described above
// as long as we make sure to set select the monotonic clock. We do that here.
int clockId = CLOCK_MONOTONIC;
bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
"wakeMechanism=%s, usingClockIoctl=%s",
deviceId, fd, devicePath, device->identifier.name.string(),
device->classes,
device->configurationFile.string(),
device->keyMap.keyLayoutFile.string(),
device->keyMap.keyCharacterMapFile.string(),
toString(mBuiltInKeyboardId == deviceId),
wakeMechanism.string(), toString(usingClockIoctl));
addDeviceLocked(device); //添加到 KeyedVector中
return 0;
}
void EventHub::loadConfigurationLocked(Device* device) {
device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier( //根据上面获取到的一些设备信息,进一步去找config文件
device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
if (device->configurationFile.isEmpty()) {
ALOGD("No input device configuration file found for device '%s'.",
device->identifier.name.string());
} else {
status_t status = PropertyMap::load(device->configurationFile, //找到之后 ,把这个device 的config file保存起来
&device->configuration);
if (status) {
ALOGE("Error loading input device configuration file for device '%s'. "
"Using default configuration.",
device->identifier.name.string());
}
}
}
Z:\HLOS\frameworks\native\libs\input\InputDevice.cpp
String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
const InputDeviceIdentifier& deviceIdentifier,
InputDeviceConfigurationFileType type) {
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
if (deviceIdentifier.version != 0) {
// Try vendor product version.
String8 versionPath(getInputDeviceConfigurationFilePathByName(
String8::format("Vendor_%04x_Product_%04x_Version_%04x", /用前面获取的input device 的相关VID PID 来找文件
deviceIdentifier.vendor, deviceIdentifier.product,
deviceIdentifier.version),
type));
if (!versionPath.isEmpty()) {
return versionPath;
}
}
// Try vendor product.
String8 productPath(getInputDeviceConfigurationFilePathByName(
String8::format("Vendor_%04x_Product_%04x",
deviceIdentifier.vendor, deviceIdentifier.product),
type));
if (!productPath.isEmpty()) {
return productPath;
}
}
// Try device name.
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); //这个函数也在同文件中,就是到 path.setTo(getenv("ANDROID_ROOT")); path.append("/usr/"); 也就是文件系统中/system/usr目录下去找
}
三、 framework部分
Z:\HLOS\frameworks\base\services\java\com\android\server\SystemServer.java
private void startOtherServices() {
......
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
.......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
private static native void nativeStart(long ptr);
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {
private:
sp mInputManager;
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
}
mInteractive = true;
sp eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
inline sp getInputManager() const { return mInputManager; }
.....
}
}
Z:\HLOS\frameworks\native\services\inputflinger\InputManager.cpp
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); //这个 mDispatcherThread 是在 InputManager 构造函数里调用 initialize 初始化,
//这里很明显启动了这个名为 InputDispatcher 的线程 分发给input事件给当前的activity的
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);//同上,开启线程 读取从下层发上来的input事件的
if (result) {
ALOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
}
Z:\HLOS\frameworks\native\services\inputflinger\InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) { //如果有缓存的命令就调用下面的runCommand去执行,没有的话这里去检查是否有新的input事件,这里定义一个唤醒时间控制
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis); //执行上面一次分发之后,就进入了loop,这个loop会持续的检测对应的管道中是否有内容可读,而另外一个线程InputReader 读取到input事件之后就会往这个管道写入
}
Z:\HLOS\frameworks\native\services\inputflinger\InputReader.cpp
InputReader类处理过程:
InputReader::loopOnce()--->EventHub::getEvents()--->InputReader::processEventsLocked()---
--->InputReader::processEventsForDeviceLocked()--->InputDevice::process()--->TouchInputMapper::process()--
--->TouchInputMapper::sync()--->TouchInputMapper::dispatchTouches()---->TouchInputMapper::dispatchMotion ---->getListener()->notifyMotion(&args);
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1;
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); //这里去获取event事件
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count); //如果获取到事件,就处理
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
mQueuedListener->flush();
}
getEvent中会一直read,直到get到event之后,通过 precessevent 处理,最终会唤醒上面介绍到的 InputDispatcherThread ,通知它有新的事件来了
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { //如果是常规的event事件
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize); 把这次获取到的event数组中属于同一批次的,进一步处理,判定条件就是:常规event以及是属于同一设备
} else {
switch (rawEvent->type) { //这里就是一些特殊的event类型了,上面有说到,打开设备的时候会有这个ADD事件
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize; //如果再上面没有处理完event数组中的成员,那么依次继续
rawEvent += batchSize;
}
}
static const int EVENT_BUFFER_SIZE = 256;
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
struct RawEvent {
nsecs_t when;
int32_t deviceId;
int32_t type;
int32_t code;
int32_t value;
};
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex < 0) {
ALOGW("Discarding event for unknown deviceId %d.", deviceId);
return;
}
InputDevice* device = mDevices.valueAt(deviceIndex); /这里根据id 取出上面添加进去的inputdevice
if (device->isIgnored()) {
//ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
// Process all of the events in order for each mapper.
// We cannot simply ask each mapper to process them in bulk because mappers may
// have side-effects that must be interleaved. For example, joystick movement events and
// gamepad button presses are handled by different mappers but they should be dispatched
// in the order received.
size_t numMappers = mMappers.size(); /这里有个map个数,这个也在上面提到过,在create时 会根据classes类型去匹配处理map,一般都是匹配一个
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { //遍历事件数组,依次去处理
#if DEBUG_RAW_EVENTS
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);
#endif
if(rawEvent->type == EV_KEY)
{
ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x",
rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value);
}
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
#if DEBUG_RAW_EVENTS
ALOGD("Recovered from input event buffer overrun.");
#endif
} else {
#if DEBUG_RAW_EVENTS
ALOGD("Dropped input event while waiting for next input sync.");
#endif
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
ALOGI("Detected input event buffer overrun for device %s.", getName().string());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent); //这里就是调用处理map的process 函数啦
}
}
}
}
EventHub 中 会创建多个Device ,这个是根据/dev/input下面的设备文件 一一对应的,也就是kernel中注册的input设备.
InputReader 中会create多个 InputDevice ,这个是由Device中的参数为基础创建的,所以与EventHub中的Device 一一对应.
InputDevice 在创建的时候会根据 classes 来添加需要的InputMap,每一个不同的InputMap 在InputReader中定义,有很多种处理方式.
InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, uint32_t classes) {
InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
controllerNumber, identifier, classes);
.......
// Touchscreens and touchpad devices.
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
device->addMapper(new MultiTouchInputMapper(device));
}
.....
return device;
}
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
TouchInputMapper::process(rawEvent);
mMultiTouchMotionAccumulator.process(rawEvent);
}
void TouchInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when);
}
}
void TouchInputMapper::sync(nsecs_t when) {
const RawState* last = mRawStatesPending.isEmpty() ?
&mCurrentRawState : &mRawStatesPending.top();
// Push a new state.
mRawStatesPending.push();
RawState* next = &mRawStatesPending.editTop();
next->clear();
next->when = when;
// Sync button state.
next->buttonState = mTouchButtonAccumulator.getButtonState()
| mCursorButtonAccumulator.getButtonState();
// Sync scroll
next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
mCursorScrollAccumulator.finishSync();
// Sync touch
syncTouch(when, next);
// Assign pointer ids.
if (!mHavePointerIds) {
assignPointerIds(last, next);
}
#if DEBUG_RAW_EVENTS
ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
"hovering ids 0x%08x -> 0x%08x",
last->rawPointerData.pointerCount,
next->rawPointerData.pointerCount,
last->rawPointerData.touchingIdBits.value,
next->rawPointerData.touchingIdBits.value,
last->rawPointerData.hoveringIdBits.value,
next->rawPointerData.hoveringIdBits.value);
#endif
processRawTouches(false /*timeout*/);
}
void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
size_t outCount = 0;
BitSet32 newPointerIdBits;
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
const MultiTouchMotionAccumulator::Slot* inSlot =
mMultiTouchMotionAccumulator.getSlot(inIndex);
if (!inSlot->isInUse()) {
continue;
}
if (outCount >= MAX_POINTERS) {
#if DEBUG_POINTERS
ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
"ignoring the rest.",
getDeviceName().string(), MAX_POINTERS);
#endif
break; // too many fingers!
}
RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
outPointer.x = inSlot->getX();
outPointer.y = inSlot->getY();
outPointer.pressure = inSlot->getPressure();
outPointer.touchMajor = inSlot->getTouchMajor();
outPointer.touchMinor = inSlot->getTouchMinor();
outPointer.toolMajor = inSlot->getToolMajor();
outPointer.toolMinor = inSlot->getToolMinor();
outPointer.orientation = inSlot->getOrientation();
outPointer.distance = inSlot->getDistance();
outPointer.tiltX = 0;
outPointer.tiltY = 0;
outPointer.toolType = inSlot->getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = mTouchButtonAccumulator.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
}
}
bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
&& (mTouchButtonAccumulator.isHovering()
|| (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
mHavePointerIds = true;
int32_t trackingId = inSlot->getTrackingId();
int32_t id = -1;
if (trackingId >= 0) {
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
uint32_t n = idBits.clearFirstMarkedBit();
if (mPointerTrackingIdMap[n] == trackingId) {
id = n;
}
}
if (id < 0 && !mPointerIdBits.isFull()) {
id = mPointerIdBits.markFirstUnmarkedBit();
mPointerTrackingIdMap[id] = trackingId;
}
}
if (id < 0) {
mHavePointerIds = false;
outState->rawPointerData.clearIdBits();
newPointerIdBits.clear();
} else {
outPointer.id = id;
outState->rawPointerData.idToIndex[id] = outCount;
outState->rawPointerData.markIdBit(id, isHovering);
newPointerIdBits.markBit(id);
}
outCount += 1;
}
outState->rawPointerData.pointerCount = outCount;
mPointerIdBits = newPointerIdBits;
mMultiTouchMotionAccumulator.finishSync();
}
void TouchInputMapper::processRawTouches(bool timeout) {
if (mDeviceMode == DEVICE_MODE_DISABLED) {
// Drop all input if the device is disabled.
mCurrentRawState.clear();
mRawStatesPending.clear();
return;
}
// Drain any pending touch states. The invariant here is that the mCurrentRawState is always
// valid and must go through the full cook and dispatch cycle. This ensures that anything
// touching the current state will only observe the events that have been dispatched to the
// rest of the pipeline.
const size_t N = mRawStatesPending.size();
size_t count;
for(count = 0; count < N; count++) {
const RawState& next = mRawStatesPending[count];
// A failure to assign the stylus id means that we're waiting on stylus data
// and so should defer the rest of the pipeline.
if (assignExternalStylusId(next, timeout)) {
break;
}
// All ready to go.
clearStylusDataPendingFlags();
mCurrentRawState.copyFrom(next);
if (mCurrentRawState.when < mLastRawState.when) {
mCurrentRawState.when = mLastRawState.when;
}
cookAndDispatch(mCurrentRawState.when);
}
if (count != 0) {
mRawStatesPending.removeItemsAt(0, count);
}
if (mExternalStylusDataPending) {
if (timeout) {
nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
clearStylusDataPendingFlags();
mCurrentRawState.copyFrom(mLastRawState);
#if DEBUG_STYLUS_FUSION
ALOGD("Timeout expired, synthesizing event with new stylus data");
#endif
cookAndDispatch(when);
} else if (mExternalStylusFusionTimeout == LLONG_MAX) {
mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
}
}
}
void TouchInputMapper::cookAndDispatch(nsecs_t when) {
// Always start with a clean state.
mCurrentCookedState.clear();
// Apply stylus buttons to current raw state.
applyExternalStylusButtonState(when);
// Handle policy on initial down or hover events.
bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
&& mCurrentRawState.rawPointerData.pointerCount != 0;
uint32_t policyFlags = 0;
bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
if (initialDown || buttonsPressed) {
// If this is a touch screen, hide the pointer on an initial down.
if (mDeviceMode == DEVICE_MODE_DIRECT) {
getContext()->fadePointer();
}
if (mParameters.wake) {
policyFlags |= POLICY_FLAG_WAKE;
}
}
// Consume raw off-screen touches before cooking pointer data.
// If touches are consumed, subsequent code will not receive any pointer data.
if (consumeRawTouches(when, policyFlags)) {
mCurrentRawState.rawPointerData.clear();
}
// Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
// with cooked pointer data that has the same ids and indices as the raw data.
// The following code can use either the raw or cooked data, as needed.
cookPointerData();
// Apply stylus pressure to current cooked state.
applyExternalStylusTouchState(when);
// Synthesize key down from raw buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
// Dispatch the touches either directly or by translation through a pointer on screen.
if (mDeviceMode == DEVICE_MODE_POINTER) {
for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
!idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
const RawPointerData::Pointer& pointer =
mCurrentRawState.rawPointerData.pointerForId(id);
if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
|| pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
mCurrentCookedState.stylusIdBits.markBit(id);
} else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
|| pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
mCurrentCookedState.fingerIdBits.markBit(id);
} else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
mCurrentCookedState.mouseIdBits.markBit(id);
}
}
for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
!idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
const RawPointerData::Pointer& pointer =
mCurrentRawState.rawPointerData.pointerForId(id);
if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
|| pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
mCurrentCookedState.stylusIdBits.markBit(id);
}
}
// Stylus takes precedence over all tools, then mouse, then finger.
PointerUsage pointerUsage = mPointerUsage;
if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
mCurrentCookedState.mouseIdBits.clear();
mCurrentCookedState.fingerIdBits.clear();
pointerUsage = POINTER_USAGE_STYLUS;
} else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
mCurrentCookedState.fingerIdBits.clear();
pointerUsage = POINTER_USAGE_MOUSE;
} else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
isPointerDown(mCurrentRawState.buttonState)) {
pointerUsage = POINTER_USAGE_GESTURES;
}
dispatchPointerUsage(when, policyFlags, pointerUsage);
} else {
if (mDeviceMode == DEVICE_MODE_DIRECT
&& mConfig.showTouches && mPointerController != NULL) {
mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
mPointerController->setButtonState(mCurrentRawState.buttonState);
mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
mCurrentCookedState.cookedPointerData.touchingIdBits);
}
if (!mCurrentMotionAborted) {
dispatchButtonRelease(when, policyFlags);
dispatchHoverExit(when, policyFlags);
dispatchTouches(when, policyFlags);
dispatchHoverEnterAndMove(when, policyFlags);
dispatchButtonPress(when, policyFlags);
}
if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
mCurrentMotionAborted = false;
}
}
// Synthesize key up from raw buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
// Clear some transient state.
mCurrentRawState.rawVScroll = 0;
mCurrentRawState.rawHScroll = 0;
// Copy current touch to last touch in preparation for the next cycle.
mLastRawState.copyFrom(mCurrentRawState);
mLastCookedState.copyFrom(mCurrentCookedState);
}
static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
nsecs_t when, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
lastButtonState, currentButtonState,
AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
lastButtonState, currentButtonState,
AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
}
static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
nsecs_t when, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
int32_t buttonState, int32_t keyCode) {
if (
(action == AKEY_EVENT_ACTION_DOWN
&& !(lastButtonState & buttonState)
&& (currentButtonState & buttonState))
|| (action == AKEY_EVENT_ACTION_UP
&& (lastButtonState & buttonState)
&& !(currentButtonState & buttonState))) {
NotifyKeyArgs args(when, deviceId, source, policyFlags,
action, 0, keyCode, 0, context->getGlobalMetaState(), when);
context->getListener()->notifyKey(&args);
}
}
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get();
}
//注意构造函数第三个参数const sp& listener
InputReader::InputReader(const sp& eventHub,
const sp& policy,
const sp& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy),
mGlobalMetaState(0), mGeneration(1),
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
Z:\HLOS\frameworks\native\services\inputflinger\InputManager.cpp
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher); //可以看到这里传入的是InputDispatcher ,但是上面直接用的 InputListenerInterface ,直接强制转换成了 父类指针! 这里注意一下
initialize();
}
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, //初始化
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast(im);
}
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
inline sp getInputManager() const { return mInputManager; }
class NativeInputManager : public virtual RefBase, //内部类继承了InputReaderPolicyInterface InputDispatcherPolicyInterface
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {
...........
NativeInputManager::NativeInputManager(jobject contextObj, //构造方法
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
}
mInteractive = true;
sp eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this); //this为 NativeInputManager 对象
}
}
Z:\HLOS\frameworks\native\services\inputflinger\InputListener.cpp
所以在InputReader中构造 QueuedInputListener 的时候保存的是 InputDispatcher 的父类指针,保存在私有成员 mInnerListener
QueuedInputListener::QueuedInputListener(const sp& innerListener) :
mInnerListener(innerListener) {
}
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
mArgsQueue.push(new NotifyKeyArgs(*args));
}
调用 QueuedInputListener::notifyKey ,将这个 notifyKey push进 mArgsQueue 链表队列,然后在 loopOnce() 中做完上述一次事件的获取以及分发处理之后将会调用 mQueuedListener->flush();
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener); //这里依次调用上面push进来的不同种类notify的notify函数,NotifyConfigurationChangedArgs / NotifyKeyArgs / NotifyMotionArgs / NotifySwitchArgs / NotifyDeviceResetArgs 这几种
delete args;
}
mArgsQueue.clear();
}
void NotifyKeyArgs::notify(const sp& listener) const {
listener->notifyKey(this);
}
就是这里。又来了一个 notifyKey 调用,这个纯虚函数 ,两个子类 QueuedInputListener InputDispatcher 中都有实现,就像上面分析到的,最终是调用到 InputDispatcher 中的 notifyKey !
Z:\HLOS\frameworks\native\services\inputflinger\InputDispatcher.cpp
listener->notifyKey(this);
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
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);
#endif
if (!validateKeyEvent(args->action)) {
return;
}
uint32_t policyFlags = args->policyFlags;
int32_t flags = args->flags;
int32_t metaState = args->metaState;
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
policyFlags |= POLICY_FLAG_VIRTUAL;
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
}
if (policyFlags & POLICY_FLAG_FUNCTION) {
metaState |= AMETA_FUNCTION_ON;
}
policyFlags |= POLICY_FLAG_TRUSTED;
int32_t keyCode = args->keyCode;
if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
int32_t newKeyCode = AKEYCODE_UNKNOWN;
if (keyCode == AKEYCODE_DEL) {
newKeyCode = AKEYCODE_BACK;
} else if (keyCode == AKEYCODE_ENTER) {
newKeyCode = AKEYCODE_HOME;
}
if (newKeyCode != AKEYCODE_UNKNOWN) {
AutoMutex _l(mLock);
struct KeyReplacement replacement = {keyCode, args->deviceId};
mReplacedKeys.add(replacement, newKeyCode);
keyCode = newKeyCode;
metaState &= ~AMETA_META_ON;
}
} else if (args->action == AKEY_EVENT_ACTION_UP) {
// In order to maintain a consistent stream of up and down events, check to see if the key
// going up is one we've replaced in a down event and haven't yet replaced in an up event,
// even if the modifier was released between the down and the up events.
AutoMutex _l(mLock);
struct KeyReplacement replacement = {keyCode, args->deviceId};
ssize_t index = mReplacedKeys.indexOfKey(replacement);
if (index >= 0) {
keyCode = mReplacedKeys.valueAt(index);
mReplacedKeys.removeItemsAt(index);
metaState &= ~AMETA_META_ON;
}
}
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); //接口方法,mPolicy为 InputDispatcherPolicyInterface 对象,具体实现在 com_android_server_input_InputManagerService.cpp 中
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
int32_t repeatCount = 0;
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();
}
}
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
bool interactive = mInteractive.load();
if (interactive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); //或者反射的方法名
jint wmActions;
if (keyEventObj) {
wmActions = env->CallIntMethod(mServiceObj, // 通过反射调用Java方法调用 InputManagerService.java 中的
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
wmActions = 0;
}
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
} else {
ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
wmActions = 0;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
if (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
}
#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
LOG_FATAL_IF(! var, "Unable to find method " methodName);
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I"); //获取反射的方法参数为Landroid/view/KeyEvent 方法名为interceptKeyBeforeQueueing
{ "nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
.......
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
.......
}
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
.....
mServiceObj = env->NewGlobalRef(serviceObj); //反射的Java类名为com/android/server/input/InputManagerService
.....
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
// Native callback. //JNI的反射调用
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags); //接口方法,具体实现在InputMonitor.java中
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\wm\InputMonitor.java
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
......
/* Provides an opportunity for the window manager policy to intercept early key
* processing as soon as the key has been read from the device. */
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
.....
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
final WindowManagerPolicy mPolicy = new PhoneWindowManager();
PowerManagerService.Java:以下简称PMS或者PowerMS,主要处理系统中与power相关的计算,然后决策系统该如何反应。同时协调power如何与系统其他模块的交互,比如没有用户活动时屏幕变暗等。
DisplayPowerController.java:以下简称DPC或者DisplayPC,管理display设备状态,在DisplayManagerService.java(简称DMS)中实例化一个对象,以DMS为桥梁与PMS进行交互。主要处理距离传感器,亮灭屏动画,以及计算屏幕目标亮度值。
通过异步回调机制来通知PMS那些事情发生了改变。同时也与WMS进行交互。
DisplayPowerState.java:以下简称DPS,power通过其与系统进行交互,如调用其它模块设置屏幕状态与亮度。仅在DPC中实例化一个对象,它算是DPC的一部分只不过将其独立出来了。
Notifier.java:将power状态的重要变化,通过广播发送出去,并且参与了与AMS,WMS,IMP的交互。
ColorFade.java:负责屏幕由关到开,由开到关的一些GL动画,由DPC进行控制。
AutomaticBrightnessController.java:主要处理光传感器,将底层上传的参数进行处理计算,将计算的新的亮度值传给DPC。
RampAnimator.java:处理屏幕亮度渐变动画
在点击power键亮屏过程中,主要流程就是input对按键事件的传输,传送到上层处理。之后就是在power中进行对亮屏状态的处理,计算一系列的数值,并且与AMS,WMS等模块进行交互,最后调用底层LCD进行最终的设备状态与亮度的设置
当触发power键,kernel会将该事件中断,然后InputReader通过EventHub获取事件,并且对输入事件进行处理,之后交由InputDispatcher进行分发。
如果该事件为key事件会先调用interceptKeyBeforeQueueing,提前对需要系统处理的事件进行处理。
最终调到 PhoneWindowManager 类中的 interceptKeyBeforeQueueing 函数对该事件优先处理,对power键以及屏幕状态进行判断,来决定亮屏还是灭屏等操作。当需要亮屏时,会调用 PowerMangerService 中的wakeup函数进行处理
从底层到上层的具体代码调用流程 InputReader.cpp->InputDispatcher.cpp->com_android_server_input_InputManagerService.cpp->InputManagerService.java->InputMonitor.java->WindowManagerPolicy.java->PhoneWindowManager.java
Z:\HLOS\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
public class PhoneWindowManager implements WindowManagerPolicy {
......
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (!mSystemBooted) { //系统还没有启动完成,不处理任何按键事件
// If we have not yet booted, don't let key events do anything.
return 0;
}
final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; //是否能与用户交互, 如果亮屏为true
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; //按键down事件
final boolean canceled = event.isCanceled(); //事件被取消
final int keyCode = event.getKeyCode(); //按键事件的code
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
// If screen is off then we treat the case where the keyguard is open but hidden
// the same as if it were open and in front.
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(interactive ?
isKeyguardShowingAndNotOccluded() :
mKeyguardDelegate.isShowing()));
Slog.d(TAG, "interceptKeyTq keycode=" + keyCode
+ " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags));
// Basic policy based on interactive state.
int result;
// policyFlags 有wake标记,或者按键为KEYCODE_BACK, KEYCODE_MENU, KEYCODE_WAKEUP, KEYCODE_PAIRING, KEYCODE_STEM_1, KEYCODE_STEM_2, KEYCODE_STEM_3设置 isWakeKey 为true. power ,home键属于systemKey
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
if (interactive || (isInjected && !isWakeKey)) {
// When the device is interactive or the key is injected pass the
// key to the application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
if (interactive) {
// If the screen is awake, but the button pressed was the one that woke the device
// then don't pass it to the application
if (keyCode == mPendingWakeKey && !down) {
result = 0;
}
// Reset the pending key
mPendingWakeKey = PENDING_KEY_NULL;
}
} else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
// interactive.
result = ACTION_PASS_TO_USER;
// Since we're dispatching the input, reset the pending key
mPendingWakeKey = PENDING_KEY_NULL;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
result = 0;
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
isWakeKey = false;
}
// Cache the wake key on down event so we can also avoid sending the up event to the app
if (isWakeKey && down) {
mPendingWakeKey = keyCode;
}
}
// If the key would be handled globally, just return the result, don't worry about special
// key processing.
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) { //如果按键时间有效, 并且在com.android.internal.R.xml.global_keys文件中配置了keycode. 如果是唤醒键就调用wakeUp唤醒屏幕
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
boolean useHapticFeedback = down
&& (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
&& event.getRepeatCount() == 0;
// Handle special keys. //处理特殊的按键事件 ,这里主要讲解power键事件
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: { //back键
if (down) {
mBackKeyHandled = false;
if (hasLongPressOnBackBehavior()) {
Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
} else {
boolean handled = mBackKeyHandled;
// Reset back key state
cancelPendingBackKeyAction();
// Don't pass back press to app if we've already handled it
if (handled) {
result &= ~ACTION_PASS_TO_USER;
}
}
break;
}
case KeyEvent.KEYCODE_VOLUME_DOWN: //音量下键
case KeyEvent.KEYCODE_VOLUME_UP: //音量上键
case KeyEvent.KEYCODE_VOLUME_MUTE: { //静音键
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeDownKeyTriggered = true;
mScreenshotChordVolumeDownKeyTime = event.getDownTime();
mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
mScreenshotChordVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (down) {
if (interactive && !mScreenshotChordVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
mScreenshotChordVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// If an incoming call is ringing, either VOLUME key means
// "silence ringer". We handle these keys here, rather than
// in the InCallScreen, to make sure we'll respond to them
// even if the InCallScreen hasn't come to the foreground yet.
// Look for the DOWN event here, to agree with the "fallback"
// behavior in the InCallScreen.
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " VOLUME key-down while ringing: Silence ringer!");
// Silence the ringer. (It's safe to call this
// even if the ringer has already been silenced.)
telecomManager.silenceRinger();
// And *don't* pass this key thru to the current activity
// (which is probably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
break;
}
if (telecomManager.isInCall()
&& (result & ACTION_PASS_TO_USER) == 0) {
// If we are in call but we decided not to pass the key to
// the application, just pass it to the session service.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, false);
break;
}
}
}
if (mUseTvRouting) {
// On TVs, defer special key handlings to
// {@link interceptKeyBeforeDispatching()}.
result |= ACTION_PASS_TO_USER;
} else if ((result & ACTION_PASS_TO_USER) == 0) {
// If we aren't passing to the user and no one else
// handled it send it to the session manager to
// figure out.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, true);
}
break;
}
case KeyEvent.KEYCODE_ENDCALL: { //挂断电话键
result &= ~ACTION_PASS_TO_USER;
if (down) {
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
hungUp = telecomManager.endCall();
}
if (interactive && !hungUp) {
mEndCallKeyHandled = false;
mHandler.postDelayed(mEndCallLongPress,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
} else {
mEndCallKeyHandled = true;
}
} else {
if (!mEndCallKeyHandled) {
mHandler.removeCallbacks(mEndCallLongPress);
if (!canceled) {
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
if (goHome()) {
break;
}
}
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
mPowerManager.goToSleep(event.getEventTime(),
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
isWakeKey = false;
}
}
}
}
break;
}
case KeyEvent.KEYCODE_POWER: { //电源键
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
// fall through
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
// fall through
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
// fall through
case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
result &= ~ACTION_PASS_TO_USER;
interceptSystemNavigationKey(event);
break;
}
case KeyEvent.KEYCODE_SLEEP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!mPowerManager.isInteractive()) {
useHapticFeedback = false; // suppress feedback if already non-interactive
}
if (down) {
sleepPress(event.getEventTime());
} else {
sleepRelease(event.getEventTime());
}
break;
}
case KeyEvent.KEYCODE_SOFT_SLEEP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!down) {
mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
}
break;
}
case KeyEvent.KEYCODE_WAKEUP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = true;
break;
}
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MUTE:
case KeyEvent.KEYCODE_MEDIA_STOP:
case KeyEvent.KEYCODE_MEDIA_NEXT:
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
// If the global session is active pass all media keys to it
// instead of the active window.
result &= ~ACTION_PASS_TO_USER;
}
if ((result & ACTION_PASS_TO_USER) == 0) {
// Only do this if we would otherwise not pass it to the user. In that
// case, the PhoneWindow class will do the same thing, except it will
// only do it if the showing app doesn't process the key on its own.
// Note that we need to make a copy of the key event here because the
// original key event will be recycled when we return.
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
new KeyEvent(event));
msg.setAsynchronous(true);
msg.sendToTarget();
}
break;
}
case KeyEvent.KEYCODE_CALL: {
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " CALL key-down while ringing: Answer the call!");
telecomManager.acceptRingingCall();
// And *don't* pass this key thru to the current activity
// (which is presumably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
}
}
}
break;
}
case KeyEvent.KEYCODE_VOICE_ASSIST: {
// Only do this if we would otherwise not pass it to the user. In that case,
// interceptKeyBeforeDispatching would apply a similar but different policy in
// order to invoke voice assist actions. Note that we need to make a copy of the
// key event here because the original key event will be recycled when we return.
if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
keyguardActive ? 1 : 0, 0);
msg.setAsynchronous(true);
msg.sendToTarget();
}
break;
}
case KeyEvent.KEYCODE_WINDOW: {
if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
if (mTvPictureInPictureVisible) {
// Consumes the key only if picture-in-picture is visible
// to show picture-in-picture control menu.
// This gives a chance to the foreground activity
// to customize PIP key behavior.
if (!down) {
showTvPictureInPictureMenu(event);
}
result &= ~ACTION_PASS_TO_USER;
}
}
break;
}
}
if (useHapticFeedback) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
if (isWakeKey) { //如果除了power键, 别的按键也需要亮屏,就调用WakeUp亮屏
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
......
}
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
Slog.v(TAG, "interceptPowerKeyDown start 1111111");
if (!mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.acquire(); //获取wakeLock,保持cpu唤醒状态 ,WakeLock为PowerManager的内部类---> mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,mHistoryTag);
// mService 为 PowerManagerService 的内部类 BinderService ,实际执行为下面的 BinderService 中的 acquireWakeLock 方法获取对应的唤醒锁
}
// Cancel multi-press detection timeout.
if (mPowerKeyPressCounter != 0) {
mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
}
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
isNavBarEmpty(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
}
// Latch power key state to detect screenshot chord.
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered = true;
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord(); //屏幕截屏
}
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
if (gestureService != null) {
gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
mTmpBoolean);
if (mTmpBoolean.value && mGoingToSleep) {
mCameraGestureTriggeredDuringGoingToSleep = true;
}
}
mPowerKeyHandled = mScreenshotChordVolumeDownKeyTriggered
|| mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) { //如果屏幕是亮这的,长按power键 ,就处理长按事件
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
} else {
wakeUpFromPowerKey(event.getDownTime()); //如果屏幕是休眠状态,就唤醒屏幕
if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, //如果还是长按power键, 就再处理长按事
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
mBeganFromNonInteractive = true;
} else {
final int maxCount = getMaxMultiPressPowerCount();
if (maxCount <= 1) {
mPowerKeyHandled = true;
} else {
mBeganFromNonInteractive = true;
}
}
}
}
Slog.v(TAG, "interceptPowerKeyDown end 1111111");
}
mPowerKeyWakeLock.acquire() 分析start
mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mPowerKeyWakeLock");
Z:\HLOS\frameworks\base\core\java\android\os\PowerManager.java
public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}
内部类
final IPowerManager mService;
public PowerManager(Context context, IPowerManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
public final class WakeLock {
.....
public void acquire() {
synchronized (mToken) {
acquireLocked();
}
}
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
// Do this even if the wake lock is already thought to be held (mHeld == true)
// because non-reference counted wake locks are not always properly released.
// For example, the keyguard's wake lock might be forcibly released by the
// power manager without the keyguard knowing. A subsequent call to acquire
// should immediately acquire the wake lock once again despite never having
// been explicitly released by the keyguard.
mHandler.removeCallbacks(mReleaser);
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource, ///mService 是PowerManagerService的内部类BinderService的对象
mHistoryTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
mHeld = true;
}
}
.....
}
Z:\HLOS\frameworks\base\core\java\android\app\SystemServiceRegistry.java
static {
.......
registerService(Context.POWER_SERVICE, PowerManager.class,
new CachedServiceFetcher() {
@Override
public PowerManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
if (service == null) {
Log.wtf(TAG, "Failed to get power manager service.");
}
return new PowerManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});
......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\SystemService.java
父类方法
public abstract class SystemService {
....
protected final void publishBinderService(String name, IBinder service) {
publishBinderService(name, service, false);
}
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
ServiceManager.addService(name, service, allowIsolated);
}
......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
public final class PowerManagerService extends SystemService
implements Watchdog.Monitor {
........
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService()); //父类SystemService的publishBinderService方法,new BinderService()为内部类
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
内部类
private final class BinderService extends IPowerManager.Stub {
......
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag); //验证锁申请
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); //检查申请唤醒锁的应用权限
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
.......
}
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag, int uid, int pid) {
synchronized (mLock) {
//if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
+ ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
// }
WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock); //查看这个唤醒锁是否已经申请过了
boolean notifyAcquire;
if (index >= 0) {
wakeLock = mWakeLocks.get(index);
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
// Update existing wake lock. This shouldn't happen but is harmless.
notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
uid, pid, ws, historyTag);
wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
}
notifyAcquire = false;
} else {
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
try {
lock.linkToDeath(wakeLock, 0); //linkToDeath():为Binder对象设置死亡代理。
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
mWakeLocks.add(wakeLock);
setWakeLockDisabledStateLocked(wakeLock);
qcNsrmPowExt.checkPmsBlockedWakelocks(uid, pid, flags, tag, wakeLock);
notifyAcquire = true;
}
applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked(); //更新power状态
if (notifyAcquire) {
// This needs to be done last so we are sure we have acquired the
// kernel wake lock. Otherwise we have a race where the system may
// go to sleep between the time we start the accounting in battery
// stats and when we actually get around to telling the kernel to
// stay awake.
notifyWakeLockAcquiredLocked(wakeLock); //通知更新
}
}
}
updatePowerStateLocked 分析start
当广播处理完毕后就会调用PMS的内部函数 updatePowerStateLocked 来更新全局电源状态。
其实在PMS中很多函数都只是对一些必须的属性进行赋值,大部分最终都会调用到 updatePowerStateLocked 函数中进行功能执行,其中更新电源状态主要依据就是变量 mDirty 。
mDirty就是用来记录power state的变化的标记位,这样的状态变化在系统中一共定义了12个,每一个状态对应一个固定的数字,都是2的倍数。这样,若有多个状态一块变化,进行按位取或这样结果既是唯一的,又能准确标记出各个状态的变化。
在 updatePowerStateLocked 中主要做了如下事情:
一.首先判断手机是否处于充电状态,如果标记位DIRTY_BATTERY_STATE发生改变时就证明电池状态发生了改变,然后通过对比判断(通过电池前后变化与充电状态的变化),确认手机是否处于充电状态。
如果手机处于充电状态会将表示充电的标记位记入mDirty中。
当有USB插拔时我们也可以通过配置信息来决定是否需要点亮屏幕。
并且是否在充电或者充电方式发生改变,系统都会认为发生了一次用户事件进行更新最后用户操作时间,以此来重新计算屏幕超时时间。
protected void updatePowerStateLocked() {
Slog.d(TAG, "updatePowerStateLocked() mSystemReady="+mSystemReady+" mDirty="+mDirty);
if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty); //更新电量状态,是否充电,电量是否发生变化
updateStayOnLocked(mDirty); //一般这个函数mStatyon为fasle,除非在资源中设置哪种充电状态下可以长亮
updateScreenBrightnessBoostLocked(mDirty); //更新屏幕是否保持最亮状态
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
//更新 wakefulness
for (;;) {
int dirtyPhase1 = mDirty; //这个循环中每次新的mDirty全部给dirtyPhase1,并且在这个循环中使用这个dirty
dirtyPhase2 |= dirtyPhase1; //dirtyPhase2 会把之前所有的mDirty状态全部或上,然后用这个状态继续下面的函数
mDirty = 0; //将mDirty清零,不影响下个循环
updateWakeLockSummaryLocked(dirtyPhase1); //更新mWakeLockSummary的值状态
updateUserActivitySummaryLocked(now, dirtyPhase1); //更新屏幕超时时间,根据最后一次的用户事件与屏幕超时时间与dim持续时间来计算屏幕超时的时间,然后与现在的时间进行对比,来决定屏幕要继续高亮,还是要变为dim状态
if (!updateWakefulnessLocked(dirtyPhase1)) { //当 updateWakefulnessLocked 返回false跳出循环
break;
}
}
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); //获取需要请求的设备电源状态是亮还是灭或者dim,判断是否开启了自动调节亮度开关,是否使用了距离传感器,
//并经过一系列的计算获取亮度值等,最终都记录到DisplayPowerRequest中,经过DMS传入DPC中,进行处理
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 4: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked(); //suspend blocker的更新
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
在 updateIsPoweredLocked 中主要做了如下事情:
首先判断手机是否处于充电状态,如果标记位 DIRTY_BATTERY_STATE 发生改变时就证明电池状态发生了改变,
然后通过对比判断(通过电池前后变化与充电状态的变化),确认手机是否处于充电状态。如果手机处于充电状态会将表示充电的标记位记入mDirty中。
当有USB插拔时我们也可以通过配置信息来决定是否需要点亮屏幕。并且是否在充电或者充电方式发生改变,系统都会认为发生了一次用户事件进行更新最后用户操作时间,以此来重新计算屏幕超时时间。
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) { //电量是否发生改变
final boolean wasPowered = mIsPowered; //是否在充电
final int oldPlugType = mPlugType; //充电类型
final boolean oldLevelLow = mBatteryLevelLow; //低电模式
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
mPlugType = mBatteryManagerInternal.getPlugType();
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
// if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
// }
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED; //如果充电中设置mDirty
// Update wireless dock detection state.
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
mIsPowered, mPlugType, mBatteryLevel); //无线充电
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
final long now = SystemClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) { //插拔USB是否要点亮屏幕
wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
}
/插拔USB算一次用户事件,重新设置最后一次用户事件的时间点
userActivityNoUpdateLocked(now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
// Tell the notifier whether wireless charging has started so that
// it can provide feedback to the user.
if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted();
}
}
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) { //低电模式
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
// if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
// }
mAutoLowPowerModeSnoozing = false;
}
updateLowPowerModeLocked(); //更新低电模式
}
}
}
首先systemReady函数最终会把mDirty置位为 DIRTY_BATTERY_STATE ,还有收BatterySevice发出来的广播,也会置这个标志位
private final class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
handleBatteryStateChangedLocked();
}
}
}
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
// Don't wake when powered unless configured to do so.
if (!mWakeUpWhenPluggedOrUnpluggedConfig) { //如果资源中没有配置这项,直接退出不唤醒设备
return false;
}
// Don't wake when undocked from wireless charger.
// See WirelessChargerDetector for justification. //这是一个 拔出的工作,然后之前的无线充电
if (wasPowered && !mIsPowered
&& oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
return false;
}
// Don't wake when docked on wireless charger unless we are certain of it.
// See WirelessChargerDetector for justification.
if (!wasPowered && mIsPowered
&& mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS //插入动作,现在是无线充电
&& !dockedOnWirelessCharger) {
return false;
}
// If already dreaming and becoming powered, then don't wake.
if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) { //正在充电,但是mWakefulness 是做梦状态
return false;
}
// Don't wake while theater mode is enabled.
if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {
return false;
}
// Otherwise wake up!
return true; //其他就唤醒设备
}
一般这个函数 mStatyon 为fasle,除非在资源中设置哪种充电状态下可以长亮
/**
* Updates the value of mStayOn.
* Sets DIRTY_STAY_ON if a change occurred.
*/
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) { //当dirty是电池状态和设置的状态改变时
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0 //这个值从资源中读取,一般设置的话代表哪种充电时可以常亮
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) { //看有没有设mMaximumScreenOffTimeoutFromDeviceAdmin屏幕最大亮屏时间,没设默认最大。那么这个函数返回是false
mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
mDirty |= DIRTY_STAY_ON;
}
}
}
//这个函数是更新屏幕是否保持最亮状态
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) { //这个状态是在 boostScreenBrightnessInternal 函数中设置最亮时置位,当然下面发送消息 MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT 也会将这个标志位置位
if (mScreenBrightnessBoostInProgress) { //当前正在最亮屏幕这个状态
final long now = SystemClock.uptimeMillis();
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
final long boostTimeout = mLastScreenBrightnessBoostTime +
SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
if (boostTimeout > now) { //看当前时间是否小于最亮屏幕结束的时间
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, boostTimeout); //发送一个延迟的消息,到最亮屏幕结束的时候接受到消息,将标志位置为 DIRTY_SCREEN_BRIGHTNESS_BOOST 后,重新再回到这个函数
return;
}
}
mScreenBrightnessBoostInProgress = false; //回到这个函数时,直接将这个屏幕最亮状态的标志位改成false
mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now, //触发一个userActivity
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
}
下面看看MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT消息的处理函数
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
break;
private void handleScreenBrightnessBoostTimeout() { // runs on handler thread
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleScreenBrightnessBoostTimeout");
}
mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
updatePowerStateLocked();
}
}
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 0;
final int numWakeLocks = mWakeLocks.size(); //获取所有的wakeLocks
for (int i = 0; i < numWakeLocks; i++) { //遍历所有的wakeLocks, 将wakeLocks记录在 mWakeLockSummary 中
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { //先根据 wakelock 的 mFlags, mWakeLockSummary 或上各种状态
case PowerManager.PARTIAL_WAKE_LOCK:
if (!wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
mWakeLockSummary |= WAKE_LOCK_CPU;
}
break;
case PowerManager.FULL_WAKE_LOCK: //屏幕键盘全部点亮
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: //点亮屏幕
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK: //dim锁 暗淡的
mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: //距离灭屏
mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
break;
case PowerManager.DOZE_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
case PowerManager.DRAW_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_DRAW;
break;
}
}
// Cancel wake locks that make no sense based on the current state.
//根据当前的屏幕状态, 取消不必要的wakeLocks 将上面或上的 mWakeLockSummary 有的减去
if (mWakefulness != WAKEFULNESS_DOZING) {
mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
if (mWakefulness == WAKEFULNESS_ASLEEP //如果屏幕为休眠,就将屏幕高亮,dim锁取消
|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
if (mWakefulness == WAKEFULNESS_ASLEEP) {
mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state. //只要有屏幕锁,cpu锁必须持有
if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) { //当WakeLock为亮屏锁或dim锁时,需要保持AWAKE状态。
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
//if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
// }
}
}
//之后 updateUserActivitySummaryLocked 就会更新屏幕超时时间,根据最后一次的用户事件与屏幕超时时间与dim持续时间来计算屏幕超时的时间,然后与现在的时间进行对比,来决定屏幕要继续高亮,还是要变为dim状态。
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT); //移除屏幕超时的Message
long nextTimeout = 0;
if (mWakefulness == WAKEFULNESS_AWAKE //状态为awake,dreaming,dozing,否则mUserActivitySummary为0
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
final int sleepTimeout = getSleepTimeoutLocked(); //睡眠timeout
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout); //灭屏的timeout
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); //屏幕由亮变暗的timeout
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
mUserActivitySummary = 0;
if (mLastUserActivityTime >= mLastWakeTime) { 最后一次的用户时间大于最后一次屏幕醒来的时间
nextTimeout = mLastUserActivityTime //计算下一次屏幕要变为dim的时间
+ screenOffTimeout - screenDimDuration;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; //现在还早于屏幕超时, 设置现在用户活动为屏幕高亮
} else {
nextTimeout = mLastUserActivityTime + screenOffTimeout; //重新设置屏幕超时时间,进入dim阶段
if (now < nextTimeout) { //进入dim阶段了
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout) {
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) { //根据请求的policy来判断屏幕是高亮,还是dim状态
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0) { /如果mUserActivitySummary还没赋值
if (sleepTimeout >= 0) {
final long anyUserActivity = Math.max(mLastUserActivityTime,
mLastUserActivityTimeNoChangeLights);
if (anyUserActivity >= mLastWakeTime) {
nextTimeout = anyUserActivity + sleepTimeout;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; //设置dream状态
}
}
} else {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
}
if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
if ((mUserActivitySummary &
(USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
// Device is being kept awake by recent user activity
if (nextTimeout >= now && mOverriddenTimeout == -1) {
// Save when the next timeout would have occurred
mOverriddenTimeout = nextTimeout;
}
}
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
if (mUserActivitySummary != 0 && nextTimeout >= 0 && mScreenOffTimeoutSetting > 0) {
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); //mUserActivitySummary 有值, 并且nextTimeout大于等于0, 发超时消息
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout); //到下个时间timeout结束的时候发送消息,重新进入这个函数
}
} else {
mUserActivitySummary = 0;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
}
}
PowerManagerHandler接收屏幕超时的消息, 并且调用 handleUserActivityTimeout 进行处理, 该函数之后就在Handler线程中运行.
MSG_USER_ACTIVITY_TIMEOUT 的消息处理
private final class PowerManagerHandler extends Handler {
.......
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
case MSG_SANDMAN:
handleSandman();
break;
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
break;
}
}
private void handleUserActivityTimeout() { // runs on handler thread
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleUserActivityTimeout");
}
mDirty |= DIRTY_USER_ACTIVITY; //设置有用户活动的mDirty值
updatePowerStateLocked(); //更新电源状态, 最后去判断是否要睡眠
}
}
.....
}
根据前面流程图可以看出更新 wakefulness 过程是通过一个死循环来执行的,只有调用函数 updateWakefulnessLocked 返回false时才会跳出循环。
在循环中对wakeLockSummary进行更新,并且更新自动灭屏时间后,进行判断系统是否该睡眠了,是否可以跳出循环
在 updateWakefulnessLocked 中主要根据是否存在wakeLock,用户活动进行判断设备是否需要进入睡眠状态。
从函数 isBeingKeptAwakeLocked 可以看出当device拿着一个wake lock,有用户事件,有距离传感器等都不会灭屏进行睡眠状态。如果需要睡眠就会往下面调用,最后跳出循环
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
| DIRTY_DOCK_STATE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) { //mWakefulness为AWAKE, 并且到了睡觉时间, 就去睡觉
// if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
// }
final long time = SystemClock.uptimeMillis();
if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time, Process.SYSTEM_UID); //睡觉前先小憩一会
} else {
changed = goToSleepNoUpdateLocked(time, //直接睡觉
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
}
}
}
return changed;
}
private boolean isItBedTimeYetLocked() {
return mBootCompleted && !isBeingKeptAwakeLocked(); // 对所有该唤醒的情况取反, 就是该休眠了
}
private boolean isBeingKeptAwakeLocked() {
return mStayOn //设置了stay on 持续亮屏
|| mProximityPositive //距离传感器返回一个positive结果,保持唤醒
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0 //当有wake lock时保持唤醒
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0 //有user activity时保持唤醒
|| mScreenBrightnessBoostInProgress;
}
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0); //从settings数据库获取对应值
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
private boolean shouldNapAtBedTimeLocked() { //当返回true, 设备自动nap
return mDreamsActivateOnSleepSetting
|| (mDreamsActivateOnDockSetting
&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
//睡觉前先小憩一会
private boolean napNoUpdateLocked(long eventTime, int uid) {
// if (DEBUG_SPEW) {
Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
// }
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
try {
Slog.i(TAG, "Nap time (uid " + uid +")...");
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DREAMING, 0); //设置WAKEFULNESS_DREAMING
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
//直接睡觉,当按power键灭屏是也会调用该函数
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
//if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
// }
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
} //判断设备是否应该睡眠
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
switch (reason) { //输出灭屏的原因
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy "
+ "(uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_HDMI:
Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
break;
default:
Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
break;
}
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) { //遍历所有的wakeLocks, 将FULL, BRIGHT, DIM Locks,计入 numWakeLocksCleared 中
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid); //如果没有doze流程,直接设置 WAKEFULNESS_ASLEEP
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
当第一个for循环中将所有的状态都设置好了, 并且此时也没有重要的mDirty发生变化, 在下一次循环中mDirty的值为0, updateWakefulnessLocked 返回false,就会跳出循环.
updateDisplayPowerStateLocked 分析 start
当跳出循环之后在函数 updateDisplayPowerStateLocked 中进行获取需要请求的设备电源状态是亮还是灭或者dim,判断是否开启了自动调节亮度开关,是否使用了距离传感器,
并经过一系列的计算获取亮度值等,最终都记录到DisplayPowerRequest中,经过DMS传入DPC中,进行处理。
private boolean updateDisplayPowerStateLocked(int dirty) {
final boolean oldDisplayReady = mDisplayReady;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); //根据mWakefulness与 mWakeLockSummary 获得,设备新状态是DIM, BRIGHT, OFF还是DOZE
// Determine appropriate screen brightness and auto-brightness adjustments.
boolean brightnessSetByUser = true;
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f; //自动亮度调节
boolean autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); /是否开启自动亮度
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
brightnessSetByUser = false;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
brightnessSetByUser = false;
} else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
} else if (isValidBrightness(mScreenBrightnessSetting)) {
screenBrightness = mScreenBrightnessSetting;
}
if (autoBrightness) { //自动亮度调节
screenBrightness = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
screenAutoBrightnessAdjustment =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSetting)) {
screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
}
}
screenBrightness = Math.max(Math.min(screenBrightness, //获得请求亮度
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
// Update display power request.
//将数据记录在 mDisplayPowerRequest 中
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
&& (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
} else {
mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity); //调用 requestPowerState 请求电源状态
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + mWakefulness
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ ", mScreenBrightnessBoostInProgress="
+ mScreenBrightnessBoostInProgress);
}
}
return mDisplayReady && !oldDisplayReady;
}
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
Z:\HLOS\frameworks\base\services\core\java\com\android\server\SystemService.java
protected final T getLocalService(Class type) {
return LocalServices.getService(type);
}
protected final void publishLocalService(Class type, T service) {
LocalServices.addService(type, service);
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
........
@Override
public void onStart() {
......
publishLocalService(DisplayManagerInternal.class, new LocalService());
.......
}
......
内部类
private final class LocalService extends DisplayManagerInternal {
......
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, //初始化函数在 PowerManagerService 的 systemReady 函数中调用
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = new DisplayBlanker() { //创建blanker对象
@Override
public void requestDisplayState(int state, int brightness) {
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
callbacks.onDisplayStateChange(state);
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
}
};
mDisplayPowerController = new DisplayPowerController( //创建DisplayPowerController对象
mContext, callbacks, handler, sensorManager, blanker);
}
}
@Override
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
return mDisplayPowerController.requestPowerState(request, //调用DisplayPowerController请求电源状态
waitForNegativeProximity);
}
........
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
......
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(mDisplayPowerCallbacks, mHandler, sensorManager);
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
if (DEBUG) {
Slog.d(TAG, "requestPowerState: "
+ request + ", waitForNegativeProximity=" + waitForNegativeProximity);
}
synchronized (mLock) {
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) {
mPendingRequestLocked.copyFrom(request);
changed = true;
}
if (changed) {
mDisplayReadyLocked = false;
}
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
return mDisplayReadyLocked;
}
}
在 DisplayPowerController 中通过Handler发送 MSG_UPDATE_POWER_STATE 消息调用 updatePowerState 来更新电源状态.
updatePowerState 也是一个非常核心的函数,在该函数中将PowerManagerService中传过来的参数获取出来根据policy获取设备的请求状态是ON, OFF还是DOZE, 应用距离传感器, 将最终的请求状态调用DisplayPowerState进行设置.
判断设备是否打开了自动亮度调节, 计算最终屏幕要达到的目标亮度并通过亮度渐变动画慢慢的点亮屏幕,最终变为高亮.
private void sendUpdatePowerStateLocked() {
if (!mPendingUpdatePowerStateLocked) {
mPendingUpdatePowerStateLocked = true;
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
private final class DisplayControllerHandler extends Handler {
........
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
Slog.d(TAG, "MSG_UPDATE_POWER_STATE");
updatePowerState();
break;
........
}
}
private void updatePowerState() {
// Update the power state request.
Slog.d(TAG, "updatePowerState");
final boolean mustNotify;
boolean mustInitialize = false;
boolean autoBrightnessAdjustmentChanged = false;
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) { //判断mPowerRequest是否为NULL,如果为空新创建一个, 否则直接将 mPendingRequestLocked 复制给他
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
mustNotify = !mDisplayReadyLocked;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
initialize(); //power state第一次发生变化时需要做一些初始化,如:创建DisplayPowerState, 亮灭屏动画,亮度渐变动画实例等
}
// Compute the basic display state using the policy.
// We might override this below based on other factors.
int state;
int brightness = PowerManager.BRIGHTNESS_DEFAULT; //设置屏幕默认亮度
boolean performScreenOffTransition = false;
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF: //设置设备状态为OFF
state = Display.STATE_OFF;
performScreenOffTransition = true; //灭屏有过渡动画
break;
case DisplayPowerRequest.POLICY_DOZE: //设置设备状态为DOZE
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
if (!mAllowAutoBrightnessWhileDozingConfig) { //如果在xml文件中配置了相关属性,就将dozeScreenBrightness赋给亮度值
brightness = mPowerRequest.dozeScreenBrightness;
}
break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON; //如果policy为DIM, BRIGHT的话,设备状态都为ON
break;
}
assert(state != Display.STATE_UNKNOWN);
// Apply the proximity sensor.
if (mProximitySensor != null) { //距离传感器相关处理
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = true;
sendOnProximityPositiveWithWakelock();
}
} else if (mWaitingForNegativeProximity
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
setProximitySensorEnabled(true);
} else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
}
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF; //如果因为距离传感器灭屏设置设备状态为OFF
}
// Animate the screen state change unless already animating.
// The transition may be deferred, so after this point we will use the
// actual state instead of the desired one.
animateScreenStateChange(state, performScreenOffTransition); //处理屏幕状态改变
state = mPowerState.getScreenState(); //获取新的屏幕状态
// Use zero brightness when screen is off.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF; //如果新的状态是灭屏的话设置brightness为0
}
// Configure auto-brightness.
boolean autoBrightnessEnabled = false;
if (mAutomaticBrightnessController != null) {
final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightness < 0;
final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
&& mPowerRequest.brightnessSetByUser;
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
userInitiatedChange, mPowerRequest.useTwilight); //配置控制自动亮度设置的对象
}
// Apply brightness boost.
// We do this here after configuring auto-brightness so that we don't
// disable the light sensor during this temporary state. That way when
// boost ends we will be able to resume normal auto-brightness behavior
// without any delay.
if (mPowerRequest.boostScreenBrightness
&& brightness != PowerManager.BRIGHTNESS_OFF) {
brightness = PowerManager.BRIGHTNESS_ON;
}
// Apply auto-brightness.
boolean slowChange = false;
if (brightness < 0) {
if (autoBrightnessEnabled) {
brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness(); //获取自动亮度值
}
if (brightness >= 0) {
// Use current auto-brightness value and slowly adjust to changes.
brightness = clampScreenBrightness(brightness); //保证亮度值的有效性,不能在0~255之外
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
slowChange = true; // slowly adapt to auto-brightness
}
mAppliedAutoBrightness = true; //使用了自动亮度
} else {
mAppliedAutoBrightness = false; //没有使用自动亮度
}
} else {
mAppliedAutoBrightness = false;
}
// Use default brightness when dozing unless overridden.
if (brightness < 0 && (state == Display.STATE_DOZE
|| state == Display.STATE_DOZE_SUSPEND)) {
brightness = mScreenBrightnessDozeConfig;
}
// Apply manual brightness.
// Use the current brightness setting from the request, which is expected
// provide a nominal default value for the case where auto-brightness
// is not ready yet.
if (brightness < 0) {
brightness = clampScreenBrightness(mPowerRequest.screenBrightness); //如果亮度值小于0的话,就是用setting中设置的亮度值
}
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightness > mScreenBrightnessRangeMinimum) {
brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
}
if (!mAppliedDimming) {
slowChange = false;
}
mAppliedDimming = true;
} else if (mAppliedDimming) {
slowChange = false;
mAppliedDimming = false;
}
// If low power mode is enabled, cut the brightness level by half
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
if (brightness > mScreenBrightnessRangeMinimum) {
brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum); //低电模式, 亮度是目标亮度的1/2
}
if (!mAppliedLowPower) {
slowChange = false;
}
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended.
if (!mPendingScreenOff) {
if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
animateScreenBrightness(brightness, 0);
//slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast); //使用亮度渐变动画设置亮度, 渐变速度依赖于rate
} else {
animateScreenBrightness(brightness, 0); //动画速率为0, 没有动画
}
}
// Determine whether the display is ready for use in the newly requested state.
// Note that we do not wait for the brightness ramp animation to complete before
// reporting the display is ready because we only need to ensure the screen is in the
// right power state even as it continues to converge on the desired brightness.
final boolean ready = mPendingScreenOnUnblocker == null
&& !mColorFadeOnAnimator.isStarted()
&& !mColorFadeOffAnimator.isStarted()
&& mPowerState.waitUntilClean(mCleanListener);
final boolean finished = ready
&& !mScreenBrightnessRampAnimator.isAnimating();
// Notify policy about screen turned on.
if (ready && state != Display.STATE_OFF
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON;
mWindowManagerPolicy.screenTurnedOn();
}
// Grab a wake lock if we have unfinished business.
if (!finished && !mUnfinishedBusiness) {
if (DEBUG) {
Slog.d(TAG, "Unfinished business...");
}
mCallbacks.acquireSuspendBlocker();
mUnfinishedBusiness = true;
}
// Notify the power manager when ready.
if (ready && mustNotify) {
// Send state change.
synchronized (mLock) {
if (!mPendingRequestChangedLocked) {
mDisplayReadyLocked = true;
if (DEBUG) {
Slog.d(TAG, "Display ready!");
}
}
}
sendOnStateChangedWithWakelock();
}
// Release the wake lock when we have no unfinished business.
if (finished && mUnfinishedBusiness) {
if (DEBUG) {
Slog.d(TAG, "Finished business...");
}
mUnfinishedBusiness = false;
mCallbacks.releaseSuspendBlocker();
}
}
根据上面代码分析在 updatePowerState 中主要做的事情主要有两件事:
1.调用 animateScreenStateChange 函数处理屏幕状态变化
2.调用 animateScreenBrightness 函数设置屏幕亮度
animateScreenStateChange(state, performScreenOffTransition) 分析 start
mPowerState = new DisplayPowerState(mBlanker,new ColorFade(Display.DEFAULT_DISPLAY));
private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
// If there is already an animation in progress, don't interfere with it.
Slog.d(TAG, "animateScreenStateChange target="+target+" performScreenOffTransition="+performScreenOffTransition);
if (mColorFadeOnAnimator.isStarted()
|| mColorFadeOffAnimator.isStarted()) {
if (target != Display.STATE_ON) {
return; //如果此时有亮灭屏动画, 并且目标状态不是ON,就返回.
}
// If display state changed to on, proceed and stop the color fade and turn screen on.
mPendingScreenOff = false;
}
// If we were in the process of turning off the screen but didn't quite
// finish. Then finish up now to prevent a jarring transition back
// to screen on if we skipped blocking screen on as usual.
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
}
if (target == Display.STATE_ON) { //亮屏
// Want screen on. The contents of the screen may not yet
// be visible if the color fade has not been dismissed because
// its last frame of animation is solid black.
if (!setScreenState(Display.STATE_ON)) { //设置屏幕状态,如果返回false就blocked亮屏, 不能往下执行
return; // screen on blocked
}
if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
// Perform screen on animation.
if (mPowerState.getColorFadeLevel() == 1.0f) { //执行亮屏动画, 将Color Fade level渐变为1.0f
mPowerState.dismissColorFade();
} else if (mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE :
ColorFade.MODE_WARM_UP)) {
mColorFadeOnAnimator.start();
} else {
mColorFadeOnAnimator.end();
}
} else {
// Skip screen on animation.
mPowerState.setColorFadeLevel(1.0f); //跳过亮屏, 直接设置Color Fade level为1.0f
mPowerState.dismissColorFade();
}
} else if (target == Display.STATE_DOZE) {
// Want screen dozing.
// Wait for brightness animation to complete beforehand when entering doze
// from screen on to prevent a perceptible jump because brightness may operate
// differently when the display is configured for dozing.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() == Display.STATE_ON) {
return;
}
// Set screen state.
if (!setScreenState(Display.STATE_DOZE)) {
return; // screen on blocked
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE_SUSPEND) {
// Want screen dozing and suspended.
// Wait for brightness animation to complete beforehand unless already
// suspended because we may not be able to change it after suspension.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
return;
}
// If not already suspending, temporarily set the state to doze until the
// screen on is unblocked, then suspend.
if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
if (!setScreenState(Display.STATE_DOZE)) {
return; // screen on blocked
}
setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else {
// Want screen off. //灭屏
mPendingScreenOff = true;
if (mPowerState.getColorFadeLevel() == 0.0f) {
// Turn the screen off.
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF); //如果Color Fade level为0.0f, 设置屏幕状态为OFF
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition //performScreenOffTransition为true, 有灭屏过渡动画
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
&& mPowerState.getScreenState() != Display.STATE_OFF) {
// Perform the screen off animation.
mColorFadeOffAnimator.start(); //灭屏动画,Color fade leve慢慢将1.0变为0.0f
} else {
// Skip the screen off animation and add a black surface to hide the
// contents of the screen.
mColorFadeOffAnimator.end(); //跳过灭屏动画
}
}
}
在上面函数中主要就是调用 setScreenState 设置屏幕状态, 只有设置好状态并且setScreenState返回true,之后才会判断是否有亮度渐变动画将Color Fade Level设置为1.0f. 否则一直会阻塞在setScreenState函数上.
private boolean setScreenState(int state) {
Slog.i(TAG, "setScreenState state" + state);
if (mPowerState.getScreenState() != state) {
final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
mPowerState.setScreenState(state); //调用DisplayPowerState设置屏幕状态
// Tell battery stats about the transition.
try {
mBatteryStats.noteScreenState(state);
} catch (RemoteException ex) {
// same process
}
}
// Tell the window manager policy when the screen is turned off or on unless it's due
// to the proximity sensor. We temporarily block turning the screen on until the
// window manager is ready by leaving a black surface covering the screen.
// This surface is essentially the final state of the color fade animation and
// it is only removed once the window manager tells us that the activity has
// finished drawing underneath.
final boolean isOff = (state == Display.STATE_OFF); //是否是灭屏状态
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff();
} else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
if (mPowerState.getColorFadeLevel() == 0.0f) { //亮屏处理, 此时Colorfade level为0.0f 为true
blockScreenOn(); //block亮屏, 创建一个mPendingScreenOnUnblocker对象
} else {
unblockScreenOn(); //将创建的mPendingScreenOnUnblocker对象销毁,设置NULL
}
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker); //调用 PhoneWindowManager 进行处理
}
// Return true if the screen isn't blocked.
return mPendingScreenOnUnblocker == null; //blockScreenOn时创建一个 mPendingScreenOnUnblocker 对象,所以返回false, block亮屏
}
private void blockScreenOn() {
if (mPendingScreenOnUnblocker == null) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
mPendingScreenOnUnblocker = new ScreenOnUnblocker();
mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); //开始blocked亮屏的时间
Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
}
}
private void unblockScreenOn() {
if (mPendingScreenOnUnblocker != null) {
mPendingScreenOnUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
Slog.i(TAG, "Unblocked screen on after " + delay + " ms"); //输出log,一共block亮屏多长时间
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
}
}
在 setScreenState 函数中主要做了两件事情:
1.调用 DisplayPowerState 对屏幕状态进行设置
2.通知 PhoneWindowManager 对 keyguard 和 windows 进行绘制.
当设置屏幕状态时,如果新状态与之前的状态不同时就会将新的状态值记录在成员变量 mScreenState 中,这样可以让其它类来获取当前的屏幕状态。
之后在一个Runnable对象的run函数中根据屏幕状态与ColorFade level来进行获取屏幕亮度,此时是亮屏操作但是windows尚未绘制完成level仍然是0.0,此时获取的亮度值为0,由此可知,只要windows绘制不完成亮度值会一直为0,即屏幕不会亮。
mPowerState.setScreenState(state) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerState.java
/**
* Sets whether the screen is on, off, or dozing.
*/
public void setScreenState(int state) {
if (mScreenState != state) {
if (DEBUG) {
Slog.d(TAG, "setScreenState: state=" + state);
}
mScreenState = state;
mScreenReady = false;
scheduleScreenUpdate();
}
}
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0; //根据屏幕状态设置亮度值, 亮屏时如果color Fade Level为0.0f, brightness一直为0,不会亮屏
if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
通过调用线程 PhotonicModulator 的 setState 函数来记录所请求的状态,如果线程此时处于wait状态,就调用 NotifyAll 函数将其唤醒。
在线程 PhotonicModulator 的run函数中为一个死循环,不停的进行判断屏幕亮度与屏幕状态是否发生了改变,如果两者都没有发生变化,为了减轻cpu负载线程就会wait。
由于此时屏幕状态发生变化,新的状态为 STATE_ON ,所以 suspending 为false。之后进行请求设备状态。
mPhotonicModulator = new PhotonicModulator();
private final class PhotonicModulator extends Thread {
......
public boolean setState(int state, int backlight) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
boolean backlightChanged = backlight != mPendingBacklight;
if (stateChanged || backlightChanged) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
mPendingState = state;
mPendingBacklight = backlight;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged;
mBacklightChangeInProgress = backlightChanged;
if (!changeInProgress) {
mLock.notifyAll();
}
}
return !mStateChangeInProgress;
}
}
@Override
public void run() {
for (;;) {
// Get pending change.
final int state;
final boolean stateChanged;
final int backlight;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
stateChanged = (state != mActualState);
backlight = mPendingBacklight;
backlightChanged = (backlight != mActualBacklight);
if (!stateChanged) { //判断状态是否变化
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
if (!stateChanged && !backlightChanged) { //如果亮度,状态都没有改变线程将wait
try {
mLock.wait();
} catch (InterruptedException ex) { }
continue;
}
mActualState = state; //获取确实的状态.亮度
mActualBacklight = backlight;
}
// Apply pending change.
if (DEBUG) {
Slog.d(TAG, "Updating screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
mBlanker.requestDisplayState(state, backlight); //mBlanker为DisplayManagerService中创建的对象,前面有提到.
}
}
......
}
在 DisplayManagerSerice 中的 LocalService 初始化函数 initPowerManagement 中创建的 mBlanker, 所以就调用他的 requestDisplayState 函数
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
private final class LocalService extends DisplayManagerInternal {
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = new DisplayBlanker() {
@Override
public void requestDisplayState(int state, int brightness) {
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness); //灭屏先调用该函数
}
callbacks.onDisplayStateChange(state); //callbacks为 PowerManagerService 中对象
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness); //亮屏调用该处函数
}
}
};
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker);
}
}
....
}
callbacks.onDisplayStateChange(state) 分析 start
在此处先讲解回调 PowerManagerServic e的 onDisplayStateChange 函数做了那些事情,耗时点在什么地方.
在该函数中会首先获取一个mLock的锁,这把锁是不是很熟悉,我们在前面讲绘制windows流程的时候window与power交互时需要获取mLock,如果该锁被别的线程持有,window绘制流程就会阻塞。
而根据上面流程可以看出,请求设备状态是在绘制window之前发生的,所以调用函数onDisplayStateChange没有结束的话,该锁就一直被持有,导致window绘制流程不能及时返回。
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
......
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
.....
}
}
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
new DisplayManagerInternal.DisplayPowerCallbacks() {
private int mDisplayState = Display.STATE_UNKNOWN;
.........
@Override
public void onDisplayStateChange(int state) {
// This method is only needed to support legacy display blanking behavior
// where the display's power state is coupled to suspend or to the power HAL.
// The order of operations matters here.
synchronized (mLock) { //获取mLock锁
if (mDisplayState != state) {
mDisplayState = state;
if (state == Display.STATE_OFF) { //灭屏
if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(false);
}
if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
} else { //亮屏
if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false); //设置自动suspend模式
}
if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(true); //设置hal交互模式
}
}
}
}
}
............
};
亮屏log:
PowerManagerService: Setting HAL auto-suspend mode to false
PowerManagerService: Setting HAL interactive mode to true
private void setHalAutoSuspendModeLocked(boolean enable) {
if (enable != mHalAutoSuspendModeEnabled) {
if (DEBUG) {
Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
}
mHalAutoSuspendModeEnabled = enable;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalAutoSuspend(" + enable + ")");
try {
nativeSetAutoSuspend(enable); //调用JNI设置
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
private void setHalInteractiveModeLocked(boolean enable) {
if (enable != mHalInteractiveModeEnabled) {
// if (DEBUG) {
Slog.d(TAG, "Setting HAL interactive mode to " + enable); //从log中可以看到 enable 为 true
// }
mHalInteractiveModeEnabled = enable;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalInteractive(" + enable + ")");
try {
nativeSetInteractive(enable); //调用JNI设置
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_power_PowerManagerService.cpp
static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (enable) {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off"); 灭屏执行超过100ms,会输出log
autosuspend_enable();
} else {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on"); 亮屏执行该函数超过100ms, 会输出该行log
autosuspend_disable();
}
}
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (gPowerModule) {
if (enable) {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on"); //如果setInteractive执行超过20ms,会输出log
gPowerModule->setInteractive(gPowerModule, true);
} else {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");// 如果setInteractive执行超过20ms,会输出log
gPowerModule->setInteractive(gPowerModule, false);
}
}
}
Z:\HLOS\system\core\libsuspend\autosuspend.c
int autosuspend_disable(void)
{
int ret;
ret = autosuspend_init();
if (ret) {
return ret;
}
ALOGV("autosuspend_disable\n");
if (!autosuspend_enabled) {
return 0;
}
ret = autosuspend_ops->disable();
if (ret) {
return ret;
}
autosuspend_enabled = false;
return 0;
}
Z:\HLOS\system\core\libsuspend\autosuspend_earlysuspend.c
#define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state"
struct autosuspend_ops autosuspend_earlysuspend_ops = {
.enable = autosuspend_earlysuspend_enable,
.disable = autosuspend_earlysuspend_disable,
};
static int autosuspend_earlysuspend_disable(void)
{
char buf[80];
int ret;
ALOGV("autosuspend_earlysuspend_disable\n");
ret = TEMP_FAILURE_RETRY(write(sPowerStatefd, pwr_state_on, strlen(pwr_state_on)));
if (ret < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error writing to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);
goto err;
}
if (wait_for_earlysuspend) {
pthread_mutex_lock(&earlysuspend_mutex);
while (earlysuspend_state != EARLYSUSPEND_ON) {
pthread_cond_wait(&earlysuspend_cond, &earlysuspend_mutex);
}
pthread_mutex_unlock(&earlysuspend_mutex);
}
ALOGV("autosuspend_earlysuspend_disable done\n");
return 0;
err:
return ret;
}
struct autosuspend_ops *autosuspend_earlysuspend_init(void)
{
char buf[80];
int ret;
sPowerStatefd = TEMP_FAILURE_RETRY(open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR));
......
}
在亮屏时调用autosuspend_disable()是往/sys/power/state写 on(亮屏)的函数。
在往节点写入状态后,调用late_resume将LCD resume,关于late_resume 阶段 “sprdfb_dispc_resume” 函数执行时间可能由于手机硬件信息的不同,导致执行时间相差较大。
callbacks.onDisplayStateChange(state) 分析 end
requestGlobalDisplayStateInternal 分析 start
private void requestGlobalDisplayStateInternal(int state, int brightness) {
if (state == Display.STATE_UNKNOWN) {
state = Display.STATE_ON;
}
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF; //灭屏设置屏幕亮度为0
} else if (brightness < 0) {
brightness = PowerManager.BRIGHTNESS_DEFAULT; //屏幕亮度小于0,设置为默认亮度
} else if (brightness > PowerManager.BRIGHTNESS_ON) {
brightness = PowerManager.BRIGHTNESS_ON; //屏幕亮度大于255设置最大亮度值255
}
synchronized (mTempDisplayStateWorkQueue) {
try {
// Update the display state within the lock.
// Note that we do not need to schedule traversals here although it
// may happen as a side-effect of displays changing state.
synchronized (mSyncRoot) {
if (mGlobalDisplayState == state
&& mGlobalDisplayBrightness == brightness) {
return; // no change 亮度与状态都没有改变就return
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
+ Display.stateToString(state)
+ ", brightness=" + brightness + ")");
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightness;
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); //应用全局状态
}
// Setting the display power state can take hundreds of milliseconds
// to complete so we defer the most expensive part of the work until
// after we have exited the critical section to avoid blocking other
// threads for a long time.
for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
mTempDisplayStateWorkQueue.get(i).run(); //运行mTempDisplayStateWorkQueue队列中的runnable
}
Trace.traceEnd(Trace.TRACE_TAG_POWER);
} finally {
mTempDisplayStateWorkQueue.clear();
}
}
}
在 applyGlobalDisplayStateLocked 函数中获取所有的 devices, 调用对应设备的 requestDisplayStateLocked 函数更新请求状态.
启动devices为 LocalDisplayAdapter , 就会调用到该类的 requestDisplayStateLocked 获得runnable.
private void applyGlobalDisplayStateLocked(List workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) { //遍历devices
DisplayDevice device = mDisplayDevices.get(i); //取出保存在mDisplayDevices的device
Runnable runnable = updateDisplayStateLocked(device); //获得devices中的runnable
if (runnable != null) {
workQueue.add(runnable); //将runnable加入workQueue队列, 即 mTempDisplayStateWorkQueue 队列
}
}
}
private Runnable updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); //获取devices信息
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); //调用 requestDisplayStateLocked 函数
}
return null;
}
在DMS中通过变量 mGlobalDisplayState 进行记录当前的设备状态,如果设备状态发生改变时就会重新记录,之后更新设备状态将device对应的Runnable放入队列。
然后就会将Runnable从队列中取出执行run函数。根据dumpsys信息可以知道,设备信息中只有一个设备“内置屏幕”,并且对应的Adapter为 LocalDisplayAdapter ,所以就会调用 LocalDisplayAdapter 中的 run 函数。
在run函数中会调用 SurfaceControl 中的 setDisplayPowerMode 函数处理。最终到JNI中,此处也有可能发生超时,也可从输出log中看出。
我们先来分析下device从哪来的
mDisplayDevices 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
@Override
public void onStart() {
// We need to pre-load the persistent data store so it's ready before the default display
// adapter is up so that we have it's configuration. We could load it lazily, but since
// we're going to have to read it in eventually we may as well do it here rather than after
// we've waited for the diplay to register itself with us.
........
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
......
}
private final class DisplayManagerHandler extends Handler {
......
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
registerDefaultDisplayAdapter();
break;
}
}
}
private void registerDefaultDisplayAdapter() {
// Register default display adapter.
synchronized (mSyncRoot) {
registerDisplayAdapterLocked(new LocalDisplayAdapter( // 默认用的是LocalDisplayAdapter
mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
}
}
private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
mDisplayAdapters.add(adapter);
adapter.registerLocked();
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
@Override
public void registerLocked() {
super.registerLocked();
mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
tryConnectDisplayLocked(builtInDisplayId);
}
}
private void tryConnectDisplayLocked(int builtInDisplayId) {
IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
if (displayToken != null) {
SurfaceControl.PhysicalDisplayInfo[] configs =
SurfaceControl.getDisplayConfigs(displayToken);
if (configs == null) {
// There are no valid configs for this device, so we can't use it
Slog.w(TAG, "No valid configs found for display device " +
builtInDisplayId);
return;
}
int activeConfig = SurfaceControl.getActiveConfig(displayToken);
if (activeConfig < 0) {
// There is no active config, and for now we don't have the
// policy to set one.
Slog.w(TAG, "No active config found for display device " +
builtInDisplayId);
return;
}
int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
if (activeColorMode < 0) {
// We failed to get the active color mode. We don't bail out here since on the next
// configuration pass we'll go ahead and set it to whatever it was set to last (or
// COLOR_MODE_NATIVE if this is the first configuration).
Slog.w(TAG, "Unable to get active color mode for display device " +
builtInDisplayId);
activeColorMode = Display.COLOR_MODE_INVALID;
}
int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
LocalDisplayDevice device = mDevices.get(builtInDisplayId);
if (device == null) {
// Display was added.
device = new LocalDisplayDevice(displayToken, builtInDisplayId,
configs, activeConfig, colorModes, activeColorMode);
mDevices.put(builtInDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); // 没有创建就new LocalDisplayDevice 然后发生 DISPLAY_DEVICE_EVENT_ADDED事件
} else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
colorModes, activeColorMode)) {
// Display properties changed.
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
} else {
// The display is no longer available. Ignore the attempt to add it.
// If it was connected but has already been disconnected, we'll get a
// disconnect event that will remove it from mDevices.
}
}
final class LocalDisplayAdapter extends DisplayAdapter {
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
super(syncRoot, context, handler, listener, TAG);
}
LocalDisplayAdapter 的内部类 LocalDisplayDevice
private final class LocalDisplayDevice extends DisplayDevice {
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayAdapter.java
public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener, String name) {
mSyncRoot = syncRoot;
mContext = context;
mHandler = handler;
mListener = listener;
mName = name;
}
/**
* Sends a display device event to the display adapter listener asynchronously.
*/
protected final void sendDisplayDeviceEventLocked(
final DisplayDevice device, final int event) {
mHandler.post(new Runnable() {
@Override
public void run() {
mListener.onDisplayDeviceEvent(device, event);
}
});
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
public DisplayManagerService(Context context) {
.....
mDisplayAdapterListener = new DisplayAdapterListener();
............
}
从之前的registerDefaultDisplayAdapter方法中可以看到 mDisplayAdapterListener 传到了 LocalDisplayAdapter的构造方法中, mListener 即为 mDisplayAdapterListener
new LocalDisplayAdapter( mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
private final class DisplayAdapterListener implements DisplayAdapter.Listener {
@Override
public void onDisplayDeviceEvent(DisplayDevice device, int event) {
switch (event) {
............
case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
handleDisplayDeviceAdded(device);
break;
..........
}
}
........
}
private void handleDisplayDeviceAdded(DisplayDevice device) {
synchronized (mSyncRoot) {
handleDisplayDeviceAddedLocked(device);
}
}
private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if (mDisplayDevices.contains(device)) {
Slog.w(TAG, "Attempted to add already added display device: " + info);
return;
}
Slog.i(TAG, "Display device added: " + info);
device.mDebugLastLoggedDeviceInfo = info;
mDisplayDevices.add(device); //把device增加到 mDisplayDevices 列表中
LogicalDisplay display = addLogicalDisplayLocked(device);
Runnable work = updateDisplayStateLocked(device);
if (work != null) {
work.run();
}
if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
int colorMode = mPersistentDataStore.getColorMode(device);
display.setRequestedColorModeLocked(colorMode);
}
scheduleTraversalLocked(false);
}
mDisplayDevices 分析 end
在 requestDisplayStateLocked 中主要的任务就是创建一个runnable返回到 DisplayManagerService 中,并且等待回调run函数.
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); //device为 LocalDisplayAdapter 的内部类 LocalDisplayDevice
private final class LocalDisplayDevice extends DisplayDevice {
.......
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
final boolean stateChanged = (mState != state); //状态是否改变
final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null; //亮度值是否改变
if (stateChanged || brightnessChanged) { //如果亮度值或者亮度状态发生改变就重新设置对应值
final int displayId = mBuiltInDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
if (stateChanged) { //设置亮度时.状态已经设置好,无变化
mState = state;
updateDeviceInfoLocked();
}
if (brightnessChanged) {
mBrightness = brightness; //设置mBrightness
}
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
return new Runnable() { //新建一个runnable返回
@Override
public void run() { //在DisplayManagerService中调用run函数
// Exit a suspended state before making any changes.
int currentState = oldState;
if (Display.isSuspendedState(oldState) //判断设置是否还是在suspend状态
|| oldState == Display.STATE_UNKNOWN) {
if (!Display.isSuspendedState(state)) {
setDisplayState(state);
currentState = state;
} else if (state == Display.STATE_DOZE_SUSPEND
|| oldState == Display.STATE_DOZE_SUSPEND) {
setDisplayState(Display.STATE_DOZE);
currentState = Display.STATE_DOZE;
} else {
return; // old state and new state is off
}
}
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged) {
setDisplayBrightness(brightness); //设置屏幕亮度
}
// Enter the final desired state, possibly suspended.
if (state != currentState) {
setDisplayState(state);
}
}
private void setDisplayState(int state) {
if (DEBUG) {
Slog.d(TAG, "setDisplayState("
+ "id=" + displayId
+ ", state=" + Display.stateToString(state) + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
+ "id=" + displayId
+ ", state=" + Display.stateToString(state) + ")");
try {
final int mode = getPowerModeForState(state);
SurfaceControl.setDisplayPowerMode(token, mode); //调用SurfaceControl中的setDisplayPowerMode函数处理
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
private void setDisplayBrightness(int brightness) {
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness); //调用LightService设置亮度
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
};
}
return null;
}
}
SurfaceControl.setDisplayPowerMode(token, mode) 分析 start
Z:\HLOS\frameworks\base\core\java\android\view\SurfaceControl.java
public static void setDisplayPowerMode(IBinder displayToken, int mode) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
nativeSetDisplayPowerMode(displayToken, mode);
}
Z:\HLOS\frameworks\base\core\jni\android_view_SurfaceControl.cpp
static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
sp token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()");
SurfaceComposerClient::setDisplayPowerMode(token, mode);
}
Z:\HLOS\frameworks\native\libs\gui\SurfaceComposerClient.cpp
void SurfaceComposerClient::setDisplayPowerMode(const sp& token, //属于GUI模块了
int mode) {
ComposerService::getComposerService()->setPowerMode(token, mode);
}
SurfaceControl.setDisplayPowerMode(token, mode) 分析 end
mBacklight.setBrightness(brightness) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java
private final Light mBacklight;
private final class LocalDisplayDevice extends DisplayDevice {
.......
public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
int[] colorModes, int activeColorMode) {
.........
if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
LightsManager lights = LocalServices.getService(LightsManager.class);
mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT); //LIGHT_ID_BACKLIGHT
} else {
mBacklight = null;
}
..........
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\lights\LightsService.java
final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
public LightsService(Context context) {
super(context);
mNativePointer = init_native();
for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
mLights[i] = new LightImpl(i);
}
}
public void onStart() {
publishLocalService(LightsManager.class, mService);
}
private final LightsManager mService = new LightsManager() {
@Override
public Light getLight(int id) {
if (id < LIGHT_ID_COUNT) { //LIGHT_ID_COUNT = 8
return mLights[id];
} else {
return null;
}
}
};
private final class LightImpl extends Light {
private LightImpl(int id) {
mId = id;
}
@Override
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER); //亮度模式默认为BRIGHTNESS_MODE_USER
}
@Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
int color = brightness & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color; //设置光颜色
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
mBrightnessMode != brightnessMode)) {
if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
mLastColor = mColor;
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
mLastBrightnessMode = mBrightnessMode;
mBrightnessMode = brightnessMode;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
+ Integer.toHexString(color) + ")");
try {
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode); //调用jni层设置亮度
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
..........
}
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_lights_LightsService.cpp
static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
{
int err;
hw_module_t* module;
Devices* devices;
devices = (Devices*)malloc(sizeof(Devices));
err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
devices->lights[LIGHT_INDEX_BACKLIGHT]
= get_device(module, LIGHT_ID_BACKLIGHT);
devices->lights[LIGHT_INDEX_KEYBOARD]
= get_device(module, LIGHT_ID_KEYBOARD);
devices->lights[LIGHT_INDEX_BUTTONS]
= get_device(module, LIGHT_ID_BUTTONS);
devices->lights[LIGHT_INDEX_BATTERY]
= get_device(module, LIGHT_ID_BATTERY);
devices->lights[LIGHT_INDEX_NOTIFICATIONS]
= get_device(module, LIGHT_ID_NOTIFICATIONS);
devices->lights[LIGHT_INDEX_ATTENTION]
= get_device(module, LIGHT_ID_ATTENTION);
devices->lights[LIGHT_INDEX_BLUETOOTH]
= get_device(module, LIGHT_ID_BLUETOOTH);
devices->lights[LIGHT_INDEX_WIFI]
= get_device(module, LIGHT_ID_WIFI);
} else {
memset(devices, 0, sizeof(Devices));
}
return (jlong)devices;
}
static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
Devices* devices = (Devices*)ptr;
light_state_t state;
if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
uint32_t version = devices->lights[light]->common.version;
memset(&state, 0, sizeof(light_state_t));
if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
if (light != LIGHT_INDEX_BACKLIGHT) {
ALOGE("Cannot set low-persistence mode for non-backlight device.");
return;
}
if (version < LIGHTS_DEVICE_API_VERSION_2_0) {
// HAL impl has not been upgraded to support this.
return;
}
} else {
// Only set non-brightness settings when not in low-persistence mode
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
}
state.brightnessMode = brightnessMode;
{
ALOGD_IF_SLOW(50, "Excessive delay setting light"); //当设置亮度耗时大于50ms,就会输出该行log.
devices->lights[light]->set_light(devices->lights[light], &state);
}
}
之后调用BSP向亮度节点写入亮度值. 从而点亮屏幕
mBacklight.setBrightness(brightness) 分析 end
当该流程结束后,设置设备状态就结束了
requestGlobalDisplayStateInternal 分析 end
mPowerState.setScreenState(state) 分析 end
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
public DisplayPowerController(Context context,
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker) {
......
mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
.......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
final WindowManagerPolicy mPolicy = new PhoneWindowManager();
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
.......
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
.......
}
private void initPolicy() {
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
}
private final class LocalService extends WindowManagerInternal {
.......
.............
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
@Override
public void screenTurningOn(final ScreenOnListener screenOnListener) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
updateScreenOffSleepToken(false);
synchronized (mLock) {
mScreenOnEarly = true;
mScreenOnFully = false;
mKeyguardDrawComplete = false;
mWindowManagerDrawComplete = false;
mScreenOnListener = screenOnListener; // 传回screenOnListener 以便回调onScreenOn事件
if (mKeyguardDelegate != null) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 350); //发送超时消息, 350ms keyguard还没有绘制完,就继续向下执行
mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); //调用keyguard中函数, 绘制完成后回调 mKeyguardDrawnCallback
} else {
if (DEBUG_WAKEUP) Slog.d(TAG,
"null mKeyguardDelegate: setting mKeyguardDrawComplete.");
finishKeyguardDrawn(); //如果没有keyguard就直接结束绘制
}
}
}
当绘制完keyguard或者keyguard绘制超时都会调用 finishKeyguardDrawn 结束绘制
final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
@Override
public void onDrawn() { //绘制完成调用onDrawn函数
if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE); //发送MSG_KEYGUARD_DRAWN_COMPLETE消息
}
};
private class PolicyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
.....
case MSG_KEYGUARD_DRAWN_COMPLETE:
if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
finishKeyguardDrawn(); //keyguard绘制完成, 结束
break;
case MSG_KEYGUARD_DRAWN_TIMEOUT:
Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
finishKeyguardDrawn(); //keyguard绘制超时, 结束
break;
.....
}
}
}
/** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
static final int WAITING_FOR_DRAWN_TIMEOUT = 100; //windows绘制超时时间1000ms
private void finishKeyguardDrawn() {
synchronized (mLock) {
if (!mScreenOnEarly || mKeyguardDrawComplete) {
return; // We are not awake yet or we have already informed of this event.
}
mKeyguardDrawComplete = true;
if (mKeyguardDelegate != null) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); //移除keyguard超时的message
}
mWindowManagerDrawComplete = false;
}
// ... eventually calls finishWindowsDrawn which will finalize our screen turn on
// as well as enabling the orientation change logic/sensor.
mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, //windows绘制完成后回调 mWindowManagerDrawCallback
WAITING_FOR_DRAWN_TIMEOUT);
}
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
......
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
private final class LocalService extends WindowManagerInternal {
.......
@Override
public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
boolean allWindowsDrawn = false;
synchronized (mWindowMap) {
mWaitingForDrawnCallback = callback;
final WindowList windows = getDefaultWindowListLocked(); //获取windows列表
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
if (win.isVisibleLw()
&& (win.mAppToken != null || isForceHiding || keyguard)) {
win.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
win.mLastContentInsets.set(-1, -1, -1, -1);
mWaitingForDrawn.add(win); //将所要绘制的windows加入 mWaitingForDrawn 中
// No need to wait for the windows below Keyguard.
if (isForceHiding) {
break;
}
}
}
mWindowPlacerLocked.requestTraversal();
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); //先将绘制windows超时的message移除, 以便重新计时
if (mWaitingForDrawn.isEmpty()) {
allWindowsDrawn = true;
} else {
mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); //发送绘制超时的延迟消息
checkDrawnWindowsLocked(); //检查windows是否绘制完成
}
}
if (allWindowsDrawn) {
callback.run(); /如果所有windows都绘制完成了就调用回调接口, 回到PhoneWindowManager中
}
}
.............
}
void checkDrawnWindowsLocked() {
if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { //如果没有要绘制的windows或者没有回调接口就直接返回了
return;
}
for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { //遍历要绘制的windows
WindowState win = mWaitingForDrawn.get(j);
if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
" mHasSurface=" + win.mHasSurface +
" drawState=" + win.mWinAnimator.mDrawState);
if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) { //如果window已经被移除或者隐藏 就不需要绘制了, 直接从等待列表中移除
// Window has been removed or hidden; no draw will now happen, so stop waiting.
if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
mWaitingForDrawn.remove(win);
} else if (win.hasDrawnLw()) { //如果window已经绘制完成,也从等待列表中移除
// Window is now drawn (and shown).
if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
mWaitingForDrawn.remove(win);
}
}
if (mWaitingForDrawn.isEmpty()) { //如果等待列表为空
if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); //移除超时消息
mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); //发送ALL_WINDOWS_DRAWN消息
}
}
Windows的绘制在 ViewRootImpl 的 draw 函数中,其中 ViewRoot 的 draw 是通过 vsync 进行同步绘制。在绘制完成之后就会调用到WMS中 DO_TRAVERSAL 流程进行调用函数 checkDrawnWindowsLocked 判断每个window是否绘制完成。
绘制完成后会发起ALL_WINDOWS_DRAWN的Message,回调回PhoneWindowManager。由于在调用函数 performLayoutAndPlaceSurfacesLockedInner 过程中需要与 Power 中的一些函数进行交互,而在 Power 中函数执行需要获得 mLock 锁,
如果该锁被别的线程所持有就会发生阻塞,就不会及时返回发出window绘制完成的信号,在该流程中具体 mLock 还会被那些线程获取, 在讲解设置设置状态时讲解过可能被power中线程获取.
当window绘制完成后通过接口回调到 PhoneWindowManager 中,发送Window准备好的Message进行结束window绘制,将变量 mWindowManagerDrawComplete 置为true。最后回到DPC中。
final class H extends Handler {
.....
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
}
switch (msg.what) {
..........
case ALL_WINDOWS_DRAWN: { //绘制windows完成
Runnable callback;
synchronized (mWindowMap) {
callback = mWaitingForDrawnCallback;
mWaitingForDrawnCallback = null;
}
if (callback != null) {
callback.run(); //回调回PhoneWindowManager
}
}
case WAITING_FOR_DRAWN_TIMEOUT: { //绘制Windows超时
Runnable callback = null;
synchronized (mWindowMap) {
Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); //输出超时log信息
mWaitingForDrawn.clear(); //将等待绘制列表清空
callback = mWaitingForDrawnCallback;
mWaitingForDrawnCallback = null;
}
if (callback != null) {
callback.run(); //回调回PhoneWindowManager
}
break;
}
........
}
}
}
.....
}
回调回 PhoneWindowManager 后发送所有 windows 绘制完成的 message
Z:\HLOS\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
final Runnable mWindowManagerDrawCallback = new Runnable() {
@Override
public void run() {
if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE); //发送Handler消息
}
};
private class PolicyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
.......
case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
finishWindowsDrawn(); //结束windows绘制
break;
......
}
}
}
private void finishWindowsDrawn() {
synchronized (mLock) {
if (!mScreenOnEarly || mWindowManagerDrawComplete) {
return; // Screen is not turned on or we did already handle this case earlier.
}
mWindowManagerDrawComplete = true; //设置windows绘制完成为true
}
finishScreenTurningOn(); //调用screenTurningOn就要结束了
}
private void finishScreenTurningOn() {
synchronized (mLock) {
// We have just finished drawing screen content. Since the orientation listener
// gets only installed when all windows are drawn, we try to install it again.
updateOrientationListenerLp(); /更新转向监听器
}
final ScreenOnListener listener;
final boolean enableScreen;
synchronized (mLock) {
if (DEBUG_WAKEUP) Slog.d(TAG,
"finishScreenTurningOn: mAwake=" + mAwake
+ ", mScreenOnEarly=" + mScreenOnEarly
+ ", mScreenOnFully=" + mScreenOnFully
+ ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+ ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
|| (mAwake && !mKeyguardDrawComplete)) {
return; // spurious or not ready yet
}
if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
listener = mScreenOnListener; // mScreenOnListener 为 mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker) 方法中传入的 mPendingScreenOnUnblocker
mScreenOnListener = null;
mScreenOnFully = true;
// Remember the first time we draw the keyguard so we know when we're done with
// the main part of booting and can enable the screen and hide boot messages.
if (!mKeyguardDrawnOnce && mAwake) {
mKeyguardDrawnOnce = true;
enableScreen = true;
if (mBootMessageNeedsHiding) {
mBootMessageNeedsHiding = false;
hideBootMessages();
}
} else {
enableScreen = false;
}
}
if (listener != null) {
listener.onScreenOn(); /回调回DisplayPowerController的onScreenOn函数
}
if (enableScreen) {
try {
mWindowManager.enableScreenIfNeeded();
} catch (RemoteException unhandled) {
}
}
}
Windows绘制完成回调回来之后,此时就不用 block screen了,将 mPendingScreenOnUnblocker 置为空,并计算screen一共block了多少毫秒。
之后进行更新power state,由于之前调用DisplayPS设置过状态为ON,现在状态没有发生改变,故不用进行设置直接返回,由于window已经绘制完成 mPendingScreenOnUnblocker 为空,故返回true。
如果没有亮屏动画直接将ColorFade level设置为1.0,如果有亮屏动画的话会有ColorFade level会从0.0逐渐变为1.0。
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
private void blockScreenOn() {
.......
mPendingScreenOnUnblocker = new ScreenOnUnblocker();
.....
}
private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
@Override
public void onScreenOn() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this); //发送unblock的消息
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
private final class DisplayControllerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
........
case MSG_SCREEN_ON_UNBLOCKED: //Handler收到unblock的消息后
if (mPendingScreenOnUnblocker == msg.obj) {
unblockScreenOn(); //将mPendingScreenOnUnblocker赋值NULL,并且输出unblock的时间, 之前有讲解
Slog.d(TAG, "MSG_SCREEN_ON_UNBLOCKED");
updatePowerState(); //重新更新power 状态. setPowerState返回true, 继续设置Color Fade Level为1.0f
}
break;
.........
}
}
}
private void unblockScreenOn() {
if (mPendingScreenOnUnblocker != null) {
mPendingScreenOnUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
Slog.i(TAG, "Unblocked screen on after " + delay + " ms"); //输出log,一共block亮屏多长时间
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
}
}
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker) 分析 end
animateScreenStateChange(state, performScreenOffTransition) 分析 end
之后就是通过 animateScreenBrightness 函数设置屏幕亮度,进而点亮屏幕,
animateScreenBrightness(brightness, 0) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
// Brightness animation ramp rate in brightness units per second.
private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; //亮度渐变动画较慢的速率, 每秒变化40个亮度单位
mBrightnessRampRateFast = resources.getInteger(
com.android.internal.R.integer.config_brightness_ramp_rate_fast); //从配置文件中获取较快的亮度速率
private void updatePowerState() {
.......
if (!mPendingScreenOff) {
if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
animateScreenBrightness(brightness, 0);
//slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast); //当亮屏或doze状态时有亮度渐变动画 ,已改动过
} else {
animateScreenBrightness(brightness, 0); //灭屏时没有亮度渐变动画,直接将亮度设置为0
}
}
.......
}
在 animateScreenBrightness 函数中调用动画 mScreenBrightnessRampAnimator 对亮度值处理, 而 mScreenBrightnessRampAnimator 是在 initialize() 函数中进行初始化的,
在构造函数中将 DisplayPowerState 和 DisplayPowerState.SCREEN_BRIGHTNESS 传输过去.
private void initialize() {
.........
mScreenBrightnessRampAnimator = new RampAnimator( //泛型为DisplayPowerState
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
.........
}
private void animateScreenBrightness(int target, int rate) {
if (DEBUG) {
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
}
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { //动画处理亮度值
try {
mBatteryStats.noteScreenBrightness(target);
} catch (RemoteException ex) {
// same process
}
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerState.java
public static final IntProperty SCREEN_BRIGHTNESS =
new IntProperty("screenBrightness") {
@Override
public void setValue(DisplayPowerState object, int value) {
object.setScreenBrightness(value);
}
@Override
public Integer get(DisplayPowerState object) {
return object.getScreenBrightness();
}
};
在 RampAnimator 的构造函数中将 DisplayPowerState 赋值给 mObject, DisplayPowerState.SCREEN_BRIGHTNESS 赋值给mProperty, 并且创建 mChoreographer 实例.
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\RampAnimator.java
public RampAnimator(T object, IntProperty property) {
mObject = object;
mProperty = property;
mChoreographer = Choreographer.getInstance();
}
public boolean animateTo(int target, int rate) {
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) { //当第一次调用animateTo, 或者rate小于等于0时直接设置目标亮度.
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false; //之后就不是第一次调用该函数
mRate = 0; //设置mRate为0
mTargetValue = target; //设置目标亮度为target
mCurrentValue = target;
mProperty.setValue(mObject, target); //调用 DisplayPowerState.setScreenBrightness()设置亮度值 DisplayPowerState.SCREEN_BRIGHTNESS
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd(); //动画结束
}
return true;
}
return false;
}
// Adjust the rate based on the closest target.
// If a faster rate is specified, then use the new rate so that we converge
// more rapidly based on the new request.
// If a slower rate is specified, then use the new rate only if the current
// value is somewhere in between the new and the old target meaning that
// we will be ramping in a different direction to get there.
// Otherwise, continue at the previous rate.
if (!mAnimating
|| rate > mRate
|| (target <= mCurrentValue && mCurrentValue <= mTargetValue)
|| (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
mRate = rate; //重新调节亮度速率
}
final boolean changed = (mTargetValue != target); //如果当前亮度值不等于目标亮度值,说明亮度改变了
mTargetValue = target; //重新设置mTargetValue
// Start animating. 开始动画
if (!mAnimating && target != mCurrentValue) {
mAnimating = true;
mAnimatedValue = mCurrentValue;
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
}
在 postAnimationCallback 中调用 Choreographer 的postCallback函数处理, 调用完成后回调回mAnimationCallback的run函数
private void postAnimationCallback() {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}
Z:\HLOS\frameworks\base\core\java\android\view\Choreographer.java
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
if (action == null) {
throw new IllegalArgumentException("action must not be null");
}
if (callbackType < 0 || callbackType > CALLBACK_LAST) {
throw new IllegalArgumentException("callbackType is invalid");
}
postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
if (DEBUG_FRAMES) {
Log.d(TAG, "PostCallback: type=" + callbackType
+ ", action=" + action + ", token=" + token
+ ", delayMillis=" + delayMillis);
}
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true); // 设置可异步
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
private Choreographer(Looper looper) {
mLooper = looper;
mHandler = new FrameHandler(looper);
.......
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
.....
}
private final class CallbackQueue {
private CallbackRecord mHead;
public boolean hasDueCallbacksLocked(long now) {
return mHead != null && mHead.dueTime <= now;
}
public CallbackRecord extractDueCallbacksLocked(long now) {
CallbackRecord callbacks = mHead;
if (callbacks == null || callbacks.dueTime > now) {
return null;
}
CallbackRecord last = callbacks;
CallbackRecord next = last.next;
while (next != null) {
if (next.dueTime > now) {
last.next = null;
break;
}
last = next;
next = next.next;
}
mHead = next;
return callbacks;
}
public void addCallbackLocked(long dueTime, Object action, Object token) {
CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
CallbackRecord entry = mHead;
if (entry == null) {
mHead = callback;
return;
}
if (dueTime < entry.dueTime) {
callback.next = entry;
mHead = callback;
return;
}
while (entry.next != null) {
if (dueTime < entry.next.dueTime) {
callback.next = entry.next;
break;
}
entry = entry.next;
}
entry.next = callback;
}
..........
}
private static final class CallbackRecord {
public CallbackRecord next;
public long dueTime;
public Object action; // Runnable or FrameCallback
public Object token;
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}
private CallbackRecord obtainCallbackLocked(long dueTime, Object action, Object token) {
CallbackRecord callback = mCallbackPool;
if (callback == null) {
callback = new CallbackRecord();
} else {
mCallbackPool = callback.next;
callback.next = null;
}
callback.dueTime = dueTime;
callback.action = action;
callback.token = token;
return callback;
}
private final class FrameHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}
void doScheduleCallback(int callbackType) {
synchronized (mLock) {
if (!mFrameScheduled) {
final long now = SystemClock.uptimeMillis();
if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
scheduleFrameLocked(now);
}
}
}
}
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME); // 执行到 doFrame(System.nanoTime(), 0);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
mDebugPrintNextFrameTimeDelta = false;
Log.d(TAG, "Frame time delta: "
+ ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
}
long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main thread.");
}
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
+ "which is more than the frame interval of "
+ (mFrameIntervalNanos * 0.000001f) + " ms! "
+ "Skipping " + skippedFrames + " frames and setting frame "
+ "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
}
frameTimeNanos = startNanos - lastFrameOffset;
}
if (frameTimeNanos < mLastFrameTimeNanos) {
if (DEBUG_JANK) {
Log.d(TAG, "Frame time appears to be going backwards. May be due to a "
+ "previously skipped frame. Waiting for next vsync.");
}
scheduleVsyncLocked();
return;
}
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
if (DEBUG_FRAMES) {
final long endNanos = System.nanoTime();
Log.d(TAG, "Frame " + frame + ": Finished, took "
+ (endNanos - startNanos) * 0.000001f + " ms, latency "
+ (startNanos - frameTimeNanos) * 0.000001f + " ms.");
}
}
void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;
synchronized (mLock) {
// We use "now" to determine when callbacks become due because it's possible
// for earlier processing phases in a frame to post callbacks that should run
// in a following phase, such as an input event that causes an animation to start.
final long now = System.nanoTime();
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
if (callbacks == null) {
return;
}
mCallbacksRunning = true;
// Update the frame time if necessary when committing the frame.
// We only update the frame time if we are more than 2 frames late reaching
// the commit phase. This ensures that the frame time which is observed by the
// callbacks will always increase from one frame to the next and never repeat.
// We never want the next frame's starting frame time to end up being less than
// or equal to the previous frame's commit frame time. Keep in mind that the
// next frame has most likely already been scheduled by now so we play it
// safe by ensuring the commit time is always at least one frame behind.
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
if (jitterNanos >= 2 * mFrameIntervalNanos) {
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
+ mFrameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
+ " ms which is more than twice the frame interval of "
+ (mFrameIntervalNanos * 0.000001f) + " ms! "
+ "Setting frame time to " + (lastFrameOffset * 0.000001f)
+ " ms in the past.");
mDebugPrintNextFrameTimeDelta = true;
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
}
}
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
c.run(frameTimeNanos); // 执行 CallbackRecord 的run(long frameTimeNanos) -> ((Runnable)action).run(); 即执行到 mAnimationCallback
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\RampAnimator.java
private final Runnable mAnimationCallback = new Runnable() {
@Override // Choreographer callback
public void run() {
final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
* 0.000000001f;
mLastFrameTimeNanos = frameTimeNanos; //记录最后一次的frameTimeNanos
// Advance the animated value towards the target at the specified rate
// and clamp to the target. This gives us the new current value but
// we keep the animated value around to allow for fractional increments
// towards the target.
final float scale = ValueAnimator.getDurationScale();
if (scale == 0) {
// Animation off.
mAnimatedValue = mTargetValue; //让scale为0时, 表示动画停止了, 将mAnimatedValue设置为目标亮度
} else {
final float amount = timeDelta * mRate / scale; //计算每一次需要变化的亮度值
if (mTargetValue > mCurrentValue) {
mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue); //亮屏,每次增加亮度amount,不超过目标亮度
} else {
mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue); //暗屏, 每次减少amount个亮度, 不超过目标亮度
}
}
final int oldCurrentValue = mCurrentValue;
mCurrentValue = Math.round(mAnimatedValue); //获取当前要达到的亮度值
if (oldCurrentValue != mCurrentValue) {
mProperty.setValue(mObject, mCurrentValue); //调用DisplayPowerState.SCREEN_BRIGHTNESS 设置亮度值
}
if (mTargetValue != mCurrentValue) {
postAnimationCallback(); //如果还没有达到目标亮度,就会继续调用postAnimationCallback循环设置亮度值
} else {
mAnimating = false;
if (mListener != null) {
mListener.onAnimationEnd(); //否则,亮度动画结束
}
}
}
};
Z:\HLOS\frameworks\base\services\core\java\com\android\server\display\DisplayPowerState.java
public static final IntProperty SCREEN_BRIGHTNESS =
new IntProperty("screenBrightness") {
@Override
public void setValue(DisplayPowerState object, int value) {
object.setScreenBrightness(value); //调用DisplayPowerState的setScreenBrightness函数,设置亮度值
}
@Override
public Integer get(DisplayPowerState object) {
return object.getScreenBrightness();
}
};
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
mScreenBrightness = brightness; //设置全局的亮度值
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate(); //如果不是灭屏状态,更新屏幕状态
}
}
}
scheduleScreenUpdate 函数最终通过Handler发送 mScreenUpdateRunnable 对象来更新亮度值. 从run函数中可以看出只有当 mColorFadeLevel > 0f 时才能给brightness设置亮度值,
所以说当windows没有绘制完成时就算mScreenBrightness有值不为0, 但是brightness仍然为0不能点亮屏幕.
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0; //判断设置亮度值
if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
之后的流程就与设置设置状态的流程相同了
animateScreenBrightness(brightness, 0) 分析 end
updateDisplayPowerStateLocked 分析 end
updateSuspendBlockerLocked 分析 start
private void updateSuspendBlockerLocked() { //suspend blocker的更新
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
final boolean autoSuspend = !needDisplaySuspendBlocker;
final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
// Disable auto-suspend if needed.
// FIXME We should consider just leaving auto-suspend enabled forever since
// we already hold the necessary wakelocks.
if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false);
}
// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Inform the power HAL about interactive mode.
// Although we could set interactive strictly based on the wakefulness
// as reported by isInteractive(), it is actually more desirable to track
// the display policy state instead so that the interactive state observed
// by the HAL more accurately tracks transitions between AWAKE and DOZING.
// Refer to getDesiredScreenPolicyLocked() for details.
if (mDecoupleHalInteractiveModeFromDisplayConfig) {
// When becoming non-interactive, we want to defer sending this signal
// until the display is actually ready so that all transitions have
// completed. This is probably a good sign that things have gotten
// too tangled over here...
if (interactive || mDisplayReady) {
setHalInteractiveModeLocked(interactive);
}
}
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
// Enable auto-suspend if needed.
if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
}
其中的 mWakeLockSuspendBlocker.acquire() 函数就是执行,加锁过程,
private final class SuspendBlockerImpl implements SuspendBlocker {
......
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
// if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
// }
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
nativeAcquireSuspendBlocker(mName);
}
}
}
......
}
调用的函数 nativeAcquireSuspendBlocker 就是JNI接口函数,函数位置在:
Z:\HLOS\frameworks\base\services\core\jni\com_android_server_power_PowerManagerService.cpp,这个统一编译成libandroid_servers.so供frameworks使用
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
Z:\HLOS\hardware\libhardware_legacy\power\power.c
const char * const OLD_PATHS[] = {
"/sys/android_power/acquire_partial_wake_lock",
"/sys/android_power/release_wake_lock",
};
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
int
acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
// ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
if (g_error) return g_error;
int fd;
size_t len;
ssize_t ret;
if (lock != PARTIAL_WAKE_LOCK) {
return -EINVAL;
}
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
ret = write(fd, id, strlen(id));
if (ret < 0) {
return -errno;
}
return ret;
}
static inline void initialize_fds(void)
{
// XXX: should be this:
//pthread_once(&g_initialized, open_file_descriptors);
// XXX: not this:
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
要往/sys/power/wake_lock 节点写值的函数了,走了这一大段路,终于走到了头?不是的,只能说上层已经把想要干什么活告诉了driver,现在要轮到driver干活了。
updateSuspendBlockerLocked 分析 end
updatePowerStateLocked 分析end
notifyWakeLockAcquiredLocked(wakeLock) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
//通知更新
protected void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
if (mSystemReady && !wakeLock.mDisabled) {
wakeLock.mNotifiedAcquired = true;
mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
wakeLock.mHistoryTag);
restartNofifyLongTimerLocked(wakeLock);
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
public void onWakeLockAcquired(int flags, String tag, String packageName,
int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
if (DEBUG) {
Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
+ "\", packageName=" + packageName
+ ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+ ", workSource=" + workSource);
}
final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
if (monitorType >= 0) {
try {
final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
&& (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
if (workSource != null) {
mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
historyTag, monitorType, unimportantForLogging);
} else {
mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
monitorType, unimportantForLogging);
// XXX need to deal with disabled operations.
mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
}
} catch (RemoteException ex) {
// Ignore
}
}
}
notifyWakeLockAcquiredLocked(wakeLock) 分析 end
mPowerKeyWakeLock.acquire() 分析end
wakeUpFromPowerKey(event.getDownTime()) 分析 start
private void wakeUpFromPowerKey(long eventTime) {
wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
}
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
Slog.v(TAG, "wakeUp wakeTime = "+wakeTime+" wakeInTheaterMode= "+" reason="+reason);
WAKE_UP_TIME = elapsedRealtime();
TelecomManager telecomManager = getTelecommService();
boolean isinCall = false;
if (telecomManager != null) {
isinCall = telecomManager.isInCall();
}
if((WAKE_UP_TIME - SLEEP_TIME)>=TIME_DISTANCE && !isinCall){
try {
mHomeIntent.putExtra("com.xtc.i3launcher.extra.LAUNCHER_TYPE",1);
int result = ActivityManagerNative.getDefault()
.startActivityAsUser(null, null, mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
null, null, UserHandle.USER_CURRENT);
if (DEBUG_WAKEUP) Slog.v(TAG, "result==================="+result);
} catch (RemoteException ex) {
// bummer, the activity manager, which is in this process, is dead
}
}
final boolean theaterModeEnabled = isTheaterModeEnabled();
if (!wakeInTheaterMode && theaterModeEnabled) {
return false;
}
if (theaterModeEnabled) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0);
}
mPowerManager.wakeUp(wakeTime, reason);//调用PowerManagerService唤醒屏幕
return true;
}
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Z:\HLOS\frameworks\base\core\java\android\os\PowerManager.java
final IPowerManager mService;
public void wakeUp(long time, String reason) {
try {
mService.wakeUp(time, reason, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Z:\HLOS\frameworks\base\core\java\android\app\SystemServiceRegistry.java
static {
.......
registerService(Context.POWER_SERVICE, PowerManager.class,
new CachedServiceFetcher() {
@Override
public PowerManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
if (service == null) {
Log.wtf(TAG, "Failed to get power manager service.");
}
return new PowerManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});
......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
父类方法
public abstract class SystemService {
....
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
ServiceManager.addService(name, service, allowIsolated);
}
......
}
内部类
private final class BinderService extends IPowerManager.Stub {
......
@Override // Binder call
public void wakeUp(long eventTime, String reason, String opPackageName) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
.......
}
private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
int opUid) {
synchronized (mLock) {
if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
updatePowerStateLocked(); // 之前已经分析过,更新power状态
}
}
}
wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) 分析 start
private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
String opPackageName, int opUid) {
// if (DEBUG_SPEW) {
Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
// }
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false; //判断是否要去亮屏
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
try {
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");
break;
case WAKEFULNESS_DREAMING:
Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");
break;
case WAKEFULNESS_DOZING:
Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");
break;
}
mLastWakeTime = eventTime; //设置最后一次唤醒的时间
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); //Notifier调用onWakefulnessChangeStarted发送亮屏广播
mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid); //调用Notifier通知battery处理
userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid); //更新最后一次用户事件的时间
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
当power接收到亮灭屏调用后,会先进行设置手机wakefullness状态,之后发送亮灭屏广播通知其他应用手机处于亮屏还是灭屏状态。并且在发送广播过程中power也与AMS,window,input进行交互,通知各模块手机状态发生了改变,
根据屏幕状态各自进行处理。其中发送亮灭屏广播的主要实现在Notifier.java中。
当wakefulness状态发生改变,AMS收到通知。如果亮屏操作,AMS就会通过函数comeOutOfSleepIfNeedLocked调用到ActivityStackSupervisor中,将sleep超时消息移除,如果抓的有partial锁,就将其释放,最后将在栈顶的activity显示出来。
power是通过 WindowManagerPolicy 与 PhoneWindowManager 进行交互,当屏幕在wakingup时需要通知window进行更新手势监听,更新方向监听,更新锁屏超时时间。
最后通知keyguard屏幕点亮了,进行刷新锁屏界面时间,之后通过回调接口,回调回PhoneWindowManager的onShown函数,通知window keyguard准备完成。
当亮屏时通过 InputManagerService 将当前屏幕状态传入JNI中进行记录,当再次发生power键事件可以方便确认该事件是需要亮屏还是灭屏。
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0)分析start
private void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
mBatteryStats = BatteryStatsService.getService();
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
在Notifier.java中与AMS,window,input进行交互,通知各模块手机状态发生了改变,根据屏幕状态各自进行处理, 最后发送亮灭屏广播, 通知关心的模块.
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); //获取交互模式,亮屏为true, 灭屏为false
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
+ ", reason=" + reason + ", interactive=" + interactive);
}
// Tell the activity manager about changes in wakefulness, not just interactivity.
// It needs more granularity than other components.
mHandler.post(new Runnable() {
@Override
public void run() {
mActivityManagerInternal.onWakefulnessChanged(wakefulness); //与AMS交互处理
}
});
// Handle any early interactive state changes.
// Finish pending incomplete ones from a previous cycle.
if (mInteractive != interactive) {
// Finish up late behaviors if needed.
if (mInteractiveChanging) {
handleLateInteractiveChange();
}
// Start input as soon as we start waking up or going to sleep.
if(mInputManagerInternal != null) {
mInputManagerInternal.setInteractive(interactive); //在input中记录现在的屏幕状态
}
if(mInputMethodManagerInternal != null) {
mInputMethodManagerInternal.setInteractive(interactive);
}
// Notify battery stats.
try {
mBatteryStats.noteInteractive(interactive); //唤醒battery状态
} catch (RemoteException ex) { }
// Handle early behaviors.
mInteractive = interactive;
mInteractiveChangeReason = reason;
mInteractiveChanging = true;
handleEarlyInteractiveChange(); //初期处理交互模式改变
}
}
mActivityManagerInternal.onWakefulnessChanged(wakefulness) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
private void start() {
Process.removeAllProcessGroups();
mProcessCpuThread.start();
mBatteryStatsService.publish(mContext);
mAppOpsService.publish(mContext);
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, new LocalService());
}
private final class LocalService extends ActivityManagerInternal {
........
@Override
public void onWakefulnessChanged(int wakefulness) {
ActivityManagerService.this.onWakefulnessChanged(wakefulness);
}
......
}
void onWakefulnessChanged(int wakefulness) {
synchronized(this) {
mWakefulness = wakefulness;
updateSleepIfNeededLocked();
}
}
void updateSleepIfNeededLocked() {
if (mSleeping && !shouldSleepLocked()) {
mSleeping = false;
startTimeTrackingFocusedActivityLocked();
mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
mStackSupervisor.comeOutOfSleepIfNeededLocked();
updateOomAdjLocked();
} else if (!mSleeping && shouldSleepLocked()) {
mSleeping = true;
if (mCurAppTimeTracker != null) {
mCurAppTimeTracker.stop();
}
mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
mStackSupervisor.goingToSleepLocked();
updateOomAdjLocked();
// Initialize the wake times of all processes.
checkExcessivePowerUsageLocked(false);
mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
}
mActivityManagerInternal.onWakefulnessChanged(wakefulness) 分析 end
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
//初期处理交互模式改变
private void handleEarlyInteractiveChange() {
Slog.d(TAG, "handleEarlyInteractiveChange");
synchronized (mLock) {
if (mInteractive) {
// Waking up...
mHandler.post(new Runnable() {
@Override
public void run() {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
Slog.d(TAG, " mPolicy.startedWakingUp()");
mPolicy.startedWakingUp(); //通过PhoneWindowManager系统开始亮屏, 更新转向监听器,手势监听器等
}
});
// Send interactive broadcast.
mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
mPendingWakeUpBroadcast = true;
updatePendingBroadcastLocked(); //更新亮屏广播
} else {
// Going to sleep... //灭屏
// Tell the policy that we started going to sleep.
final int why = translateOffReason(mInteractiveChangeReason);
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedGoingToSleep(why);
}
});
}
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
{
mPolicy = getLocalService(WindowManagerPolicy.class);
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
IAppOpsService appOps, SuspendBlocker suspendBlocker,
WindowManagerPolicy policy) {
.......
mSuspendBlocker = suspendBlocker;
........
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
public class PhoneWindowManager implements WindowManagerPolicy {
.....
public void startedWakingUp() {
EventLog.writeEvent(70000, 1);
if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
// Since goToSleep performs these functions synchronously, we must
// do the same here. We cannot post this work to a handler because
// that might cause it to become reordered with respect to what
// may happen in a future call to goToSleep.
synchronized (mLock) {
mAwake = true;
updateWakeGestureListenerLp();
updateOrientationListenerLp();
updateLockScreenTimeout();
}
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedWakingUp();
}
}
....
}
void updateOrientationListenerLp() {
if (!mOrientationListener.canDetectOrientation()) {
// If sensor is turned off or nonexistent for some reason
return;
}
// Could have been invoked due to screen turning on or off or
// change of the currently visible window's orientation.
if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
+ ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
+ ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
+ ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+ ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
boolean disable = true;
// Note: We postpone the rotating of the screen until the keyguard as well as the
// window manager have reported a draw complete.
if (mScreenOnEarly && mAwake &&
mKeyguardDrawComplete && mWindowManagerDrawComplete) {
if (needSensorRunningLp()) {
disable = false;
//enable listener if not already enabled
if (!mOrientationSensorEnabled) {
mOrientationListener.enable();
if(localLOGV) Slog.v(TAG, "Enabling listeners");
mOrientationSensorEnabled = true;
}
}
}
//check if sensors need to be disabled
if (disable && mOrientationSensorEnabled) {
mOrientationListener.disable();
if(localLOGV) Slog.v(TAG, "Disabling listeners");
mOrientationSensorEnabled = false;
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
private void updatePendingBroadcastLocked() {
if (!mBroadcastInProgress
&& mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
&& (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
|| mPendingInteractiveState != mBroadcastedInteractiveState)) {
mBroadcastInProgress = true;
mSuspendBlocker.acquire();
Message msg = mHandler.obtainMessage(MSG_BROADCAST);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
private final class NotifierHandler extends Handler {
.......
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case MSG_BROADCAST:
sendNextBroadcast();
break;
......
}
}
private void sendNextBroadcast() {
final int powerState;
synchronized (mLock) {
if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
// Broadcasted power state is unknown. Send wake up.
mPendingWakeUpBroadcast = false;
mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE; //亮屏状态
} else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
// Broadcasted power state is awake. Send asleep if needed.
if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
|| mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
mPendingGoToSleepBroadcast = false;
mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP; //灭屏状态
} else {
finishPendingBroadcastLocked(); //结束发送广播
return;
}
} else {
// Broadcasted power state is asleep. Send awake if needed.
if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
|| mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
mPendingWakeUpBroadcast = false;
mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
} else {
finishPendingBroadcastLocked();
return;
}
}
mBroadcastStartTime = SystemClock.uptimeMillis();
powerState = mBroadcastedInteractiveState;
}
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
if (powerState == INTERACTIVE_STATE_AWAKE) {
sendWakeUpBroadcast(); //发送亮屏广播
} else {
sendGoToSleepBroadcast();
}
}
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); //亮屏广播intent
mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); //前台广播
private void sendWakeUpBroadcast() {
if (DEBUG) {
Slog.d(TAG, "Sending wake up broadcast.");
}
if (ActivityManagerNative.isSystemReady()) {
mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, //发送亮屏广播,并且其它模块全部处理完后, 自身接收亮屏广播
mWakeUpBroadcastDone, mHandler, 0, null, null);
} else {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
sendNextBroadcast();
}
}
private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
sendNextBroadcast(); //自身接收到亮屏广播后, 之后会调用 finishPendingBroadcastLocked ,释放wakeLock
}
};
Z:\HLOS\frameworks\base\core\java\android\app\ActivityManagerNative.java
static public boolean isSystemReady() {
if (!sSystemReady) {
sSystemReady = getDefault().testIsSystemReady();
}
return sSystemReady;
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public boolean testIsSystemReady() {
// no need to synchronize(this) just to read & return the value
return mSystemReady;
}
Z:\HLOS\frameworks\base\core\java\android\app\ContextImpl.java
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(),
scheduler, null, false).getIIntentReceiver();
}
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermissions,
appOp, options, true, false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// If we have not finished booting, don't allow this to launch new processes.
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
(sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
+ " ordered=" + ordered + " userid=" + userId);
if ((resultTo != null) && !ordered) {
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_NON_FULL, "broadcast", callerPackage);
// Make sure that the user who is receiving this broadcast is running.
// If not, we will just skip it. Make an exception for shutdown broadcasts
// and upgrade steps.
if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
if ((callingUid != Process.SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
Slog.w(TAG, "Skipping broadcast of " + intent
+ ": user " + userId + " is stopped");
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
BroadcastOptions brOptions = null;
if (bOptions != null) {
brOptions = new BroadcastOptions(bOptions);
if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
// See if the caller is allowed to do this. Note we are checking against
// the actual real caller (not whoever provided the operation as say a
// PendingIntent), because that who is actually supplied the arguments.
if (checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
}
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
final String action = intent.getAction();
final boolean isProtectedBroadcast;
try {
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
return ActivityManager.BROADCAST_SUCCESS;
}
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
case Process.ROOT_UID:
case Process.SYSTEM_UID:
case Process.PHONE_UID:
case Process.BLUETOOTH_UID:
case Process.NFC_UID:
isCallerSystem = true;
break;
default:
isCallerSystem = (callerApp != null) && callerApp.persistent;
break;
}
// First line security check before anything else: stop non-system apps from
// sending protected broadcasts.
if (!isCallerSystem) {
if (isProtectedBroadcast) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from pid="
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
// Special case for compatibility: we don't want apps to send this,
// but historically it has not been protected and apps may be using it
// to poke their own app widget. So, instead of making it protected,
// just limit it to the caller.
if (callerPackage == null) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from unknown caller.";
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (intent.getComponent() != null) {
// They are good enough to send to an explicit component... verify
// it is being sent to the calling app.
if (!intent.getComponent().getPackageName().equals(
callerPackage)) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " to "
+ intent.getComponent().getPackageName() + " from "
+ callerPackage;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// Limit broadcast to their own package.
intent.setPackage(callerPackage);
}
}
}
if (action != null) {
switch (action) {
case Intent.ACTION_UID_REMOVED:
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
case Intent.ACTION_PACKAGES_SUSPENDED:
case Intent.ACTION_PACKAGES_UNSUSPENDED:
// Handle special intents: if this broadcast is from the package
// manager about a package being removed, we need to remove all of
// its activities from the history stack.
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
callingPid, callingUid, -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
switch (action) {
case Intent.ACTION_UID_REMOVED:
final Bundle intentExtras = intent.getExtras();
final int uid = intentExtras != null
? intentExtras.getInt(Intent.EXTRA_UID) : -1;
if (uid >= 0) {
mBatteryStatsService.removeUid(uid);
mAppOpsService.uidRemoved(uid);
}
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
// If resources are unavailable just force stop all those packages
// and flush the attribute cache as well.
String list[] =
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && list.length > 0) {
for (int i = 0; i < list.length; i++) {
forceStopPackageLocked(list[i], -1, false, true, true,
false, false, userId, "storage unmount");
}
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
userId);
}
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
break;
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
Uri data = intent.getData();
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
final boolean replacing =
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final boolean killProcess =
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
final boolean fullUninstall = removed && !replacing;
if (removed) {
if (killProcess) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
false, true, true, false, fullUninstall, userId,
removed ? "pkg removed" : "pkg changed");
}
final int cmd = killProcess
? IApplicationThread.PACKAGE_REMOVED
: IApplicationThread.PACKAGE_REMOVED_DONT_KILL;
sendPackageBroadcastLocked(cmd,
new String[] {ssp}, userId);
if (fullUninstall) {
mAppOpsService.packageRemoved(
intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
// Hide the "unsupported display" dialog if necessary.
if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
mUnsupportedDisplaySizeDialog.getPackageName())) {
mUnsupportedDisplaySizeDialog.dismiss();
mUnsupportedDisplaySizeDialog = null;
}
mCompatModePackages.handlePackageUninstalledLocked(ssp);
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
if (killProcess) {
killPackageProcessesLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
userId, ProcessList.INVALID_ADJ,
false, true, true, false, "change " + ssp);
}
cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
}
}
break;
case Intent.ACTION_PACKAGES_SUSPENDED:
case Intent.ACTION_PACKAGES_UNSUSPENDED:
final boolean suspended = Intent.ACTION_PACKAGES_SUSPENDED.equals(
intent.getAction());
final String[] packageNames = intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_PACKAGE_LIST);
final int userHandle = intent.getIntExtra(
Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
synchronized(ActivityManagerService.this) {
mRecentTasks.onPackagesSuspendedChanged(
packageNames, suspended, userHandle);
}
break;
}
break;
case Intent.ACTION_PACKAGE_REPLACED:
{
final Uri data = intent.getData();
final String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
final ApplicationInfo aInfo =
getPackageManagerInternalLocked().getApplicationInfo(
ssp,
userId);
if (aInfo == null) {
Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
+ " ssp=" + ssp + " data=" + data);
return ActivityManager.BROADCAST_SUCCESS;
}
mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REPLACED,
new String[] {ssp}, userId);
}
break;
}
case Intent.ACTION_PACKAGE_ADDED:
{
// Special case for adding a package: by default turn on compatibility mode.
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
final boolean replacing =
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
try {
ApplicationInfo ai = AppGlobals.getPackageManager().
getApplicationInfo(ssp, 0, 0);
mBatteryStatsService.notePackageInstalled(ssp,
ai != null ? ai.versionCode : 0);
} catch (RemoteException e) {
}
}
break;
}
case Intent.ACTION_PACKAGE_DATA_CLEARED:
{
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
// Hide the "unsupported display" dialog if necessary.
if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
mUnsupportedDisplaySizeDialog.getPackageName())) {
mUnsupportedDisplaySizeDialog.dismiss();
mUnsupportedDisplaySizeDialog = null;
}
mCompatModePackages.handlePackageDataClearedLocked(ssp);
}
break;
}
case Intent.ACTION_TIMEZONE_CHANGED:
// If this is the time zone changed action, queue up a message that will reset
// the timezone of all currently running processes. This message will get
// queued up before the broadcast happens.
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
break;
case Intent.ACTION_TIME_CHANGED:
// If the user set the time, let all running processes know.
final int is24Hour =
intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
: 0;
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
stats.noteCurrentTimeChangedLocked();
}
break;
case Intent.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
break;
case Proxy.PROXY_CHANGE_ACTION:
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
break;
case android.hardware.Camera.ACTION_NEW_PICTURE:
case android.hardware.Camera.ACTION_NEW_VIDEO:
// These broadcasts are no longer allowed by the system, since they can
// cause significant thrashing at a crictical point (using the camera).
// Apps should use JobScehduler to monitor for media provider changes.
Slog.w(TAG, action + " no longer allowed; dropping from "
+ UserHandle.formatUid(callingUid));
if (resultTo != null) {
final BroadcastQueue queue = broadcastQueueForIntent(intent);
try {
queue.performReceiveLocked(callerApp, resultTo, intent,
Activity.RESULT_CANCELED, null, null,
false, false, userId);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
+ intent, e);
}
}
// Lie; we don't want to crash the app.
return ActivityManager.BROADCAST_SUCCESS;
}
}
// Add to the sticky list if requested.
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
callingPid, callingUid)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
+ callingPid + ", uid=" + callingUid
+ " requires " + android.Manifest.permission.BROADCAST_STICKY;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
if (requiredPermissions != null && requiredPermissions.length > 0) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
+ " and enforce permissions " + Arrays.toString(requiredPermissions));
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
if (intent.getComponent() != null) {
throw new SecurityException(
"Sticky broadcasts can't target a specific component");
}
// We use userId directly here, since the "all" target is maintained
// as a separate set of sticky broadcasts.
if (userId != UserHandle.USER_ALL) {
// But first, if this is not a broadcast to all users, then
// make sure it doesn't conflict with an existing broadcast to
// all users.
ArrayMap> stickies = mStickyBroadcasts.get(
UserHandle.USER_ALL);
if (stickies != null) {
ArrayList list = stickies.get(intent.getAction());
if (list != null) {
int N = list.size();
int i;
for (i=0; i if (intent.filterEquals(list.get(i))) {
throw new IllegalArgumentException(
"Sticky broadcast " + intent + " for user "
+ userId + " conflicts with existing global broadcast");
}
}
}
}
}
ArrayMap> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
ArrayList list = stickies.get(intent.getAction());
if (list == null) {
list = new ArrayList<>();
stickies.put(intent.getAction(), list);
}
final int stickiesCount = list.size();
int i;
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
// This sticky already exists, replace it.
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
list.add(new Intent(intent));
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {
// Caller wants broadcast to go to all started users.
users = mUserController.getStartedUserArrayLocked();
} else {
// Caller wants broadcast to go to one specific user.
users = new int[] {userId};
}
// Figure out who all will receive this broadcast.
List receivers = null;
List registeredReceivers = null;
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
List registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
}
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueing broadcast: " + intent.getAction()
+ " replacePending=" + replacePending);
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
if (isCallerSystem) {
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, registeredReceivers);
}
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// Merge into one list.
int ir = 0;
if (receivers != null) {
// A special case for PACKAGE_ADDED: do not allow the package
// being added to see this broadcast. This prevents them from
// using this as a back door to get run as soon as they are
// installed. Maybe in the future we want to have a special install
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
String skipPackages[] = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null) {
String pkgName = data.getSchemeSpecificPart();
if (pkgName != null) {
skipPackages = new String[] { pkgName };
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if (skipPackages != null && (skipPackages.length > 0)) {
for (String skipPackage : skipPackages) {
if (skipPackage != null) {
int NT = receivers.size();
for (int it=0; it ResolveInfo curt = (ResolveInfo)receivers.get(it);
if (curt.activityInfo.packageName.equals(skipPackage)) {
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
while (it < NT && ir < NR) {
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
if (curr.getPriority() >= curt.priority) {
// Insert this broadcast record into the final list.
receivers.add(it, curr);
ir++;
curr = null;
it++;
NT++;
} else {
// Skip to the next ResolveInfo in the final list.
it++;
curt = null;
}
}
}
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
if (isCallerSystem) {
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, receivers);
}
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
+ ": prev had " + queue.mOrderedBroadcasts.size());
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Enqueueing broadcast " + r.intent.getAction());
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
} else {
// There was nobody interested in the broadcast, but we still want to record
// that it happened.
if (intent.getComponent() == null && intent.getPackage() == null
&& (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
// This was an implicit broadcast... let's record it for posterity.
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0)分析end
mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid) 分析 start
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
/**
* Called when the screen has turned on.
*/
public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) {
if (DEBUG) {
Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid
+ " opPackageName=" + opPackageName + " opUid=" + opUid);
}
try {
mBatteryStats.noteWakeUp(reason, reasonUid);
if (opPackageName != null) {
mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
}
} catch (RemoteException ex) {
// Ignore
}
}
mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid) 分析 end
userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid) 分析 start
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
//if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime
+ ", event=" + event + ", flags=0x" + Integer.toHexString(flags)
+ ", uid=" + uid);
// }
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
try {
if (eventTime > mLastInteractivePowerHintTime) {
powerHintInternal(POWER_HINT_INTERACTION, 0);
mLastInteractivePowerHintTime = eventTime;
}
mNotifier.onUserActivity(event, uid); //通知用户更新
if (mUserInactiveOverrideFromWindowManager) {
mUserInactiveOverrideFromWindowManager = false;
mOverriddenTimeout = -1;
}
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;
}
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return false;
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\power\Notifier.java
public void onUserActivity(int event, int uid) {
if (DEBUG) {
Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
}
try {
mBatteryStats.noteUserActivity(uid, event);
} catch (RemoteException ex) {
// Ignore
}
synchronized (mLock) {
if (!mUserActivityPending) {
mUserActivityPending = true;
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
}
userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid) 分析 end
wakeUpFromPowerKey(event.getDownTime()) 分析 end
wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) 分析 end
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;
Slog.v(TAG, "interceptPowerKeyUp start 1111111 handled="+handled);
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
if (!handled) { //power键还没被处理
// Figure out how to handle the key now that it has been released.
mPowerKeyPressCounter += 1;
final int maxCount = getMaxMultiPressPowerCount(); //多按的次数
final long eventTime = event.getDownTime();
Slog.v(TAG, "interceptPowerKeyUp maxCount="+maxCount+" mPowerKeyPressCounter="+mPowerKeyPressCounter);
if (mPowerKeyPressCounter < maxCount) {
// This could be a multi-press. Wait a little bit longer to confirm.
// Continue holding the wake lock.
//等待一会调用powerPress处理
Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
Slog.v(TAG, "interceptPowerKeyUp sendMessageDelayed ViewConfiguration.getDoubleTapTimeout()="+ViewConfiguration.getDoubleTapTimeout());
return;
}
// No other actions. Handle it immediately.
powerPress(eventTime, interactive, mPowerKeyPressCounter); //没有的的处理, 立即处理power down事件
}
// Done. Reset our state.
finishPowerKeyPress(); //power键处理结束
Slog.v(TAG, "interceptPowerKeyUp end 1111111");
}
private void finishPowerKeyPress() {
mBeganFromNonInteractive = false;
mPowerKeyPressCounter = 0;
if (mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.release(); //释放wakLock
}
}
threadLoop ----> mDispatcher->dispatchOnce();----> dispatchOnceInnerLocked(&nextWakeupTime);
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
// Reset the key repeat timer whenever normal dispatch is suspended while the
// device is in a non-interactive state. This is to ensure that we abort a key
// repeat if the device is just coming out of sleep.
if (!mDispatchEnabled) {
resetKeyRepeatLocked();
}
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
if (mDispatchFrozen) {
#if DEBUG_FOCUS
ALOGD("Dispatch frozen. Waiting some more.");
#endif
return;
}
// Optimize latency of app switches.
// Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
// been pressed. When it expires, we preempt dispatch and drop all other pending events.
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
// Ready to start a new event.
// If we don't already have a pending event, go grab one.
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
resetPendingAppSwitchLocked(false);
isAppSwitchDue = false;
}
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}
// Nothing to do if there is no pending event.
if (!mPendingEvent) {
return;
}
} else {
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
resetANRTimeoutsLocked();
}
// Now we have an event to dispatch.
// All events are eventually dequeued and processed this way, even if we intend to drop them.
ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
dropReason = DROP_REASON_POLICY;
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
case EventEntry::TYPE_DEVICE_RESET: {
DeviceResetEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
default:
ALOG_ASSERT(false);
break;
}
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
if (! entry->dispatchInProgress) {
if (entry->repeatCount == 0
&& entry->action == AKEY_EVENT_ACTION_DOWN
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
&& (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
// We have seen two identical key downs in a row which indicates that the device
// driver is automatically generating key repeats itself. We take note of the
// repeat here, but we disable our own next key repeat timer since it is clear that
// we will not need to synthesize key repeats ourselves.
entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
} else {
// Not a repeat. Save key down state in case we do see a repeat later.
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;
entry->refCount += 1;
} else if (! entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
if (entry->repeatCount == 1) {
entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
} else {
entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
}
entry->dispatchInProgress = true;
logOutboundKeyDetailsLocked("dispatchKey - ", entry);
}
// Handle case where the policy asked us to try again later last time.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
// Give the policy a chance to intercept the key.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
if (*dropReason == DROP_REASON_NOT_DROPPED) {
*dropReason = DROP_REASON_POLICY;
}
}
// Clean up if dropping the event.
if (*dropReason != DROP_REASON_NOT_DROPPED) {
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
return true;
}
// Identify targets.
Vector inputTargets;
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
addMonitoringTargetsLocked(inputTargets);
// Dispatch the key.
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
mPowerManager.wakeUp(wakeTime, reason);//调用PowerManagerService唤醒屏幕