您的位置:首页 > 移动开发 > Android开发

Android wakelock 学习总结第一篇

2014-08-22 10:51 375 查看
转载自: http://slightsnow.blog.chinaunix.net/uid-29269256-id-4090529.html
最近好好学习看了看Android 关于睡眠的代码,从Framewake到Native到Kernel 学习了下,下面先对Framewake Native Kernel 做个简单总结: 按照自己看代码的理解和网上看得知识,如果不对,希望大牛们可以帮我指出来

以前从来没有看过上层的代码,最近看了之后,发现上层的代码结构复杂程度和KERNEL有一拼,但是封装的很好,学习了

言归正传:

我暂时把APP Framewake Native JNI看作成上层,底层包含kernel

需要先明白两个类的关系,第一个是PowerManager,还有一个是PowerManagerService,第一个是提供给上层APP调用的封装接口,第二个是具体的实现,

他们两个关联文件是 IPowerManager.aidl ,由于没有经验找了半天IPowerManager.cpp,后来发现跟IPowerManager.cpp半毛钱关系都没有,PowerManagerService继承了

IPowerManager类,并且实现了相关的方法,具体接口定义都存在IPowerManager.aidl中,看到这里是不是很迫不及待写个应用去尝试调用PowerManager去创建一个锁了,不让系统睡,哇哈哈

frameworks/base/services/java/com/android/server/power/PowerManagerService.cpp 这个目录下所有的文件都比较重要,这个会编译到 services 中

frameworks/base/core/java/android/os/IPowerManager.aidl

frameworks/base/core/java/android/os/IPowerManager.java

我们需要看看给APP提供那些接口呢? 这里不一一列举,就说几个,左边就是APP可以调用的接口,而右边是PowerManagerService对应的实现方法,这里有一个很重要的问题,

他们两个是通过什么通信呢?没错,是使用binder,我没有看过,还不太明白,以后再说。

PowerManager

PowerManagerService

goToSleep(long time)

goToSleep(long eventTime, int reason)

isScreenOn()

isScreenOn()

reboot(String reason)

reboot(boolean confirm, String reason, boolean wait)

userActivity(long when, boolean noChangeLights)

userActivity(long eventTime, int event, int flags)

wakeUp(long time)

wakeUp(long eventTime)

我们先跟随goToSleep函数吧,这个是在PowerManager.cpp中的

479 public void goToSleep(long time) {

480 try {

481 mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);

482 } catch (RemoteException e) {

483 }

484 }

其中的mService就是PowerManagerService类中的goToSleep方法,

988 public void goToSleep(long eventTime, int reason) {

989 if (eventTime > SystemClock.uptimeMillis()) {

990 throw new IllegalArgumentException("event time must not be in the future");

991 }

992

993 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

994

995 final long ident = Binder.clearCallingIdentity();

996 try {

997 goToSleepInternal(eventTime, reason);

998 } finally {

999 Binder.restoreCallingIdentity(ident);

1000 }

1001 }

这个函数主要权限检查,然后调用自己类中的goToSleepInternel方法,

1008 private void goToSleepInternal(long eventTime, int reason) {

1009 synchronized (mLock) {

1010 if (goToSleepNoUpdateLocked(eventTime, reason)) {

1011 updatePowerStateLocked();

1012 mDisplayPowerController.requestButtonLedState(false);

1013 }

1014 }

1015 }

goToSleepNoUpdateLocked()和updatePowerStateLocked(),而goToSleepNoUpdateLocked是goToSleep功能的计算者,来决定是否要休眠,而updatePowerStateLocked函数算是功能的执行者,而且这个执行者同时负责执行了很多其他的功能,这里就不都贴两段代码了,因为太长了,下面简单的介绍下,

goToSleepNoUpdateLocked函数的主要功能就是进行必要属性的赋值,在PowerManagerService代码可以看到各种NoUpdateLocked这样的后缀,都类似与goToSleepNoUpdateLocked方法,只不过进行必要属性更新/

updatePowerStateLocked函数

1114 private void updatePowerStateLocked() {

1115 if (!mSystemReady || mDirty == 0) { //检查系统是否准备好了

1116 return;

1117 }

1118

1119 // Phase 0: Basic state updates. //基本状态更新,检查是否插着充电器

1120 updateIsPoweredLocked(mDirty);

1121 updateStayOnLocked(mDirty);

1122

1123 // Phase 1: Update wakefulness.

1124 // Loop because the wake lock and user activity computations are influenced

1125 // by changes in wakefulness.

1126 final long now = SystemClock.uptimeMillis();

1127 int dirtyPhase2 = 0;

1128 for (;;) {

1129 int dirtyPhase1 = mDirty;

1130 dirtyPhase2 |= dirtyPhase1;

1131 mDirty = 0;

1132

1133 updateWakeLockSummaryLocked(dirtyPhase1);

1134 updateUserActivitySummaryLocked(now, dirtyPhase1);

1135 if (!updateWakefulnessLocked(dirtyPhase1)) {

1136 break;

1137 }

1138 }

1139

1140 // Phase 2: Update dreams and display power state. //dream和display状态的更新

1141 updateDreamLocked(dirtyPhase2);

1142 updateDisplayPowerStateLocked(dirtyPhase2);

1143

1144 // Phase 3: Send notifications, if needed.

1145 if (mDisplayReady) {

1146 sendPendingNotificationsLocked();

1147 }

1148

1149 // Phase 4: Update suspend blocker. //suspend blocker的更新

1150 // Because we might release the last suspend blocker here, we need to make sure

1151 // we finished everything else first!

1152 updateSuspendBlockerLocked(); //真正的执行者

1153 }

这段函数看得不仔细,大概可以看出来的都表明出来了,最后updateSuspendBlockerLocked是继续往下调用

1768 private void updateSuspendBlockerLocked() {

1769 boolean wantCpu = isCpuNeededLocked();

1770 if (wantCpu != mHoldingWakeLockSuspendBlocker) {

1771 mHoldingWakeLockSuspendBlocker = wantCpu;

1772 if (wantCpu) {

1773 if (DEBUG) {

1774 Slog.d(TAG, "updateSuspendBlockerLocked: Acquiring suspend blocker.");

1775 }

1776 mWakeLockSuspendBlocker.acquire();

1777 } else {

1778 if (DEBUG) {

1779 Slog.d(TAG, "updateSuspendBlockerLocked: Releasing suspend blocker.");

1780 }

1781 mWakeLockSuspendBlocker.release();

1782 }

1783 }

1784 }

其中的mWakeLockSuspendBlocker.acquire() 函数就是执行,加锁过程,

2579 public void acquire() {

2580 synchronized (this) {

2581 mReferenceCount += 1;

2582 if (mReferenceCount == 1) {

2583 nativeAcquireSuspendBlocker(mName);

2584 }

2585 }

2586 }

这个时候调用的函数nativeAcquireSuspendBlocker就是JNI接口函数,函数位置在:

frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp,这个统一编译成libandroid_servers.so供FarmeWork使用,JNI真是个牛叉的玩意。

还没有结束呢,早着呢,系统刚刚走了一半的路,我们继续跟随:

JNI里面的实现

160 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {

161 ScopedUtfChars name(env, nameStr);

162 acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());

163 }

这个函数调用的acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str())是真正干活的吗?不是的,它调用了power.c中的acquire_wake_lock(),话说我看到这个函数,好熟悉啊,终于到了底层了,这个文件存在:

hardware/libhardware_legacy/power/power.c 这个文件会被编译成libpower.so。

现在我们再看看power.c中的acquire_wake_lock()实现,

93 int

94 acquire_wake_lock(int lock, const char* id)

95 {

96 initialize_fds();

97

98 // ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);

99

100 if (g_error) return g_error;

101

102 int fd;

103

104 if (lock == PARTIAL_WAKE_LOCK) {

105 fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];

106 }

107 else {

108 return EINVAL;

109 }

110

111 return write(fd, id, strlen(id));

112 }

^_^,没错,这个就是真正要往/sys/power/wake_lock 节点写值的函数了,走了这一大段路,终于走到了头?不是的,只能说上层已经把想要干什么活告诉了driver,现在要轮到driver干活了。

我们只是简单的分析了下,APP调用的过程,当然也有可能和系统别的模块交互,PowerManagerService不仅可以被动接受用户的操作请求,也可以主动的去监听一些重要的属性变化和重要的时间发生,在PowerManagerService主要注册这几个Reciver,看下

BatteryReceiverACTION_BATTERY_CHANGEDhandleBatterStateChangeLocked()
BootCompleteReceiverACTION_BOOT_COMPLETEDstartWatchingForBootAnimationFinished()
userSwitchReceiverACTION_USER_SWITCHEDhandleSettingsChangedLocked
DockReceiverACTION_DOCK_EVENTupdatePowerStateLocked
DreamReceiverACTION_DREAMING_STARTED

ACTION_DREAMING_STOPPED
scheduleSandmanLocked

不管什么接口调用最终都会是用以接口updatePowerStateLocked这个是不会变化的,因为对于JNI都是统一的,不管什么请求,都是调用JNI提供的标准接口



上面的图盗用网络。

下面一篇我介绍下学习的updatePowerStateLocked() 的这个函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: