//创建电源锁
[cpp]
view plaincopy
PowerManagerService.java
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
return suspendBlocker;
}
//电源锁操作类的实现
[cpp]
view plaincopy
private final class SuspendBlockerImpl implements SuspendBlocker {
private final String mName;
private int mReferenceCount;
public SuspendBlockerImpl(String name) {
mName = name;
}
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker "" + mName + "".");
}
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker "" + mName + "".");
}
nativeReleaseSuspendBlocker(mName);
} else if (mReferenceCount < 0) {
Log.wtf(TAG, "Suspend blocker "" + mName
+ "" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
}
//JNI层函数实现电源锁的获取
[cpp]
view plaincopy
com_android_server_power_PowerManagerService.cpp
static void
nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
//将电源锁写入到相应的文件中,相当于获得了电源锁
power.c
[cpp]
view plaincopy
int acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
if (g_error) return g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return EINVAL;
}
return
write(fd, id, strlen(id));
}
//打开记录电源锁的文件
[cpp]
view plaincopy
static inline void
initialize_fds(void)
{
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
//记录电源锁的文件路径
[cpp]
view plaincopy
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",
};
到现在为止,我们的代码流程已经走了一大半了,我们一开始介绍的android的上面几层Framework层、JNI层、HAL层都已经介绍了。下面就应该是和kernel层进行交互了。
但是在android/hardware/libhardware_legacy/power/power.c中的acquire_wake_lock()函数似乎没法和kernel层进行通信啊?最后的返回语句return write(fd, id, strlen(id))是一个系统调用,这里就实现了与kernel的交互。
kernel/power/main.c中的power_attr宏很多地方用到:
[cpp]
view plaincopy
- #define power_attr(_name)
- static struct kobj_attribute _name##_attr = {
- .attr = {
- .name = __stringify(_name),
- .mode = 0644,
- },
- .show = _name##_show,
- .store = _name##_store,
- }
[cpp]
view plaincopy
- #ifdef CONFIG_USER_WAKELOCK
- power_attr(wake_lock);
- power_attr(wake_unlock);
- #endif
default y
User-space wake lock api. Write "lockname" or "lockname timeout"
to /sys/power/wake_lock lock and if needed create a wake lock.
Write "lockname" to /sys/power/wake_unlock to unlock a user wake
lock.
[cpp]
view plaincopy
- #ifdef CONFIG_PM_WAKELOCKS
- power_attr(wake_lock);
- power_attr(wake_unlock);
- #endif
default n
Allow user space to create, activate and deactivate wakeup source
objects with the help of a sysfs-based interface.
宏展开,等价于:
[cpp]
view plaincopy
- static struct kobj_attribute wake_lock_attr = {
- .attr = {
- .name = “wake_lock”,
- .mode = 0644,
- },
- .show = wake_lock_show,
- .store = wake_lock_store,
- }
[cpp]
view plaincopy
- static struct kobj_attribute wake_unlock_attr = {
- .attr = {
- .name = “wake_unlock”,
- .mode = 0644,
- },
- .show = wake_unlock_show,
- .store = wake_unlock_store,
- }
show和store函数的源码位于kernel/power/userwakelock.c。
[cpp]
view plaincopy
- static struct attribute * g[] = {
- &state_attr.attr,
- #ifdef CONFIG_PM_TRACE
- &pm_trace_attr.attr,
- &pm_trace_dev_match_attr.attr,
- #endif
- #ifdef CONFIG_PM_SLEEP
- &pm_async_attr.attr,
- &wakeup_count_attr.attr,
- #ifdef CONFIG_USER_WAKELOCK
- &wake_lock_attr.attr,
- &wake_unlock_attr.attr,
- #endif
- #ifdef CONFIG_PM_AUTOSLEEP
- &autosleep_attr.attr,
- #endif
- #ifdef CONFIG_PM_WAKELOCKS
- &wake_lock_attr.attr,
- &wake_unlock_attr.attr,
- #endif
- #ifdef CONFIG_PM_DEBUG
- &pm_test_attr.attr,
- #endif
- #ifdef CONFIG_PM_SLEEP_DEBUG
- &pm_print_times_attr.attr,
- #endif
- #endif
- #ifdef CONFIG_FREEZER
- &pm_freeze_timeout_attr.attr,
- #endif
- NULL,
- };
[cpp]
view plaincopy
- static struct attribute_group attr_group = {
- .attrs = g,
- };
pm_init()->
error = sysfs_create_group(power_kobj, &attr_group);
好了,我们该回到原来我们产生疑问的地方了这时我们还得关注其中的另一个函数acquire_wake_lock()->initialize_fds()。
[cpp]
view plaincopy
- initialize_fds(void)
- {
-
-
-
- if (g_initialized == 0) {
- if(open_file_descriptors(NEW_PATHS) < 0)
- open_file_descriptors(OLD_PATHS);
- g_initialized = 1;
- }
- }
其实这个函数中最核心的步骤就是open_file_descriptors(NEW_PATHS),顺序打开NEW_PATHS[ ]中的文件:
[cpp]
view plaincopy
- static int
- open_file_descriptors(const char * const paths[])
- {
- int i;
- for (i=0; i
- int fd = open(paths[i], O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "fatal error opening "%s"
", paths[i]);
- g_error = errno;
- return -1;
- }
- g_fds[i] = fd;
- }
-
- g_error = 0;
- return 0;
- }
[cpp]
view plaincopy
- const char * const NEW_PATHS[] = {
- "/sys/power/wake_lock",
- "/sys/power/wake_unlock",
- };
总之经过着一系列的步骤后,最终我们将在 return write(fd, id, strlen(id));时调用android/kernel/kernel/power/userwakelock.c 中的 wake_lock_store()函数。
[cpp]
view plaincopy
- ssize_t wake_lock_store(
- struct kobject *kobj, struct kobj_attribute *attr,
- const char *buf, size_t n)
- {
- long timeout;
- struct user_wake_lock *l;
-
- mutex_lock(&tree_lock);
- l = lookup_wake_lock_name(buf, 1, &timeout);
- if (IS_ERR(l)) {
- n = PTR_ERR(l);
- goto bad_name;
- }
-
- if (debug_mask & DEBUG_ACCESS)
- pr_info("wake_lock_store: %s, timeout %ld
", l->name, timeout);
-
- if (timeout)
- wake_lock_timeout(&l->wake_lock, timeout);
- else
- wake_lock(&l->wake_lock);
- bad_name:
- mutex_unlock(&tree_lock);
- return n;
- }
[cpp]
view plaincopy
- struct rb_root user_wake_locks;
- static struct user_wake_lock *lookup_wake_lock_name(
- const char *buf, int allocate, long *timeoutptr)
- {
- struct rb_node **p = &user_wake_locks.rb_node;
- struct rb_node *parent = NULL;
- struct user_wake_lock *l;
- int diff;
- u64 timeout;
- int name_len;
- const char *arg;
-
-
- arg = buf;
- while (*arg && !isspace(*arg))
- arg++;
-
- name_len = arg - buf;
- if (!name_len)
- goto bad_arg;
- while (isspace(*arg))
- arg++;
-
-
- if (timeoutptr && *arg) {
-
- timeout = simple_strtoull(arg, (char **)&arg, 0);
- while (isspace(*arg))
- arg++;