四、android层源码解析 在linux之上经过android的软件堆层层封装,最终在上层的java应用程序中使用。休眠唤醒也是从最上层发出的命令,然后一层一层地将参数解析,往最底层传,最后走上标准linux的休眠唤醒之路。 这一部分将会初略分析休眠唤醒机制上linux之上所走的路线。
在linux之上,存在一个hal层,专门做和linux内核设备打交道的事情,这里也不例外。休眠唤醒机制的hal层源码位于:@hardware/libhardware_legacy/power/power.c 该文件源码比较简单,下面列举重点片段: enum { ACQUIRE_PARTIAL_WAKE_LOCK = 0, RELEASE_WAKE_LOCK, REQUEST_STATE, OUR_FD_COUNT }; constchar * const NEW_PATHS[] = { "/sys/power/wake_lock", "/sys/power/wake_unlock", "/sys/power/state" }; staticint g_initialized = 0; staticint g_fds[OUR_FD_COUNT]; staticconst char *off_state = "mem"; staticconst char *on_state = "on";
staticint open_file_descriptors(const char * const paths[]) { int i; for (i=0; i<OUR_FD_COUNT; i++) { int fd = open(paths[i], O_RDWR); if (fd < 0) { fprintf(stderr, "fatal error opening/"%s/"/n", paths[i]); g_error = errno; return -1; } g_fds[i] = fd; }
g_error = 0; return 0; }
staticinline void initialize_fds(void) { if (g_initialized == 0) { if(open_file_descriptors(NEW_PATHS) < 0) { open_file_descriptors(OLD_PATHS); on_state = "wake"; off_state = "standby"; } g_initialized = 1; } }
int acquire_wake_lock(int lock, const char* id) { initialize_fds(); if(g_error) return g_error; int fd;
if (lock == PARTIAL_WAKE_LOCK) { // 上层传下来的lock type fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK]; } else { return EINVAL; }
return write(fd,id, strlen(id)); }
int release_wake_lock(const char* id) { initialize_fds();
// LOGI("release_wake_lock id='%s'/n", id);
if (g_error) return g_error;
ssize_t len = write(g_fds[RELEASE_WAKE_LOCK],id, strlen(id)); return len >= 0; }
intset_screen_state(int on) { QEMU_FALLBACK(set_screen_state(on)); LOGI("*** set_screen_state %d", on);
initialize_fds(); if (g_error) return g_error;
char buf[32]; int len; if(on) len = sprintf(buf, on_state); else len = sprintf(buf, off_state); len = write(g_fds[REQUEST_STATE],buf, len); if(len < 0) { LOGE("Failed setting last user activity:g_error=%d/n", g_error); } return 0; }
Hal层的代码在jni层中被使用,源码位于:frameworks/base/core/jni/android_os_Power.cpp,代码片段如下: staticvoid acquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj) { if (idObj == NULL) { throw_NullPointerException(env, "id isnull"); return ; }
const char *id = env->GetStringUTFChars(idObj,NULL);
acquire_wake_lock(lock, id);
env->ReleaseStringUTFChars(idObj, id); }// 对wakelock加锁函数 staticvoid releaseWakeLock(JNIEnv*env, jobject clazz, jstring idObj) { if (idObj == NULL) { throw_NullPointerException(env, "id isnull"); return ; }
const char *id = env->GetStringUTFChars(idObj,NULL);
release_wake_lock(id);
env->ReleaseStringUTFChars(idObj, id);
}// 对wakelock解锁函数 staticint setScreenState(JNIEnv *env, jobject clazz, jboolean on) { return set_screen_state(on); }// 休眠唤醒的函数
Jni的方法需要注册到上层才可以使用,同时也需要在上层的对应java类中声明了native才可以使用。那么这里的方法在java中对应的声明在哪里呢?frameworks/base/core/java/android/os/Power.java,该文件定义一个java类,如下: publicclass Power { // can't instantiate this class private Power() { }
/** * Wake lock that ensures that the CPU isrunning. The screen might * not be on. */ public static final int PARTIAL_WAKE_LOCK = 1;
/** * Wake lock that ensures that the screen is on. */ public static final int FULL_WAKE_LOCK = 2;
public static native void acquireWakeLock(int lock, String id); public static native void releaseWakeLock(String id); … /** * Turn the screen on or off * * @param on Whether you want the screen on or off */ public static native int setScreenState(boolean on);
… }
声明的jni接口应该是被javaserver在使用,这里就是专门的电源管理服务:PowerManagerService使用,具体源码位置在:frameworks/base/services/java/com/android/server/PowerManagerService.java。android在最上层还提供了现场的android.os.PowerManager类 (frameworks/base/core/java/android/os/PowerManager.java)来供app使用,PowerManager类会调用java服务PowerManagerService的方法来完成与wakelock相关的工作。
@frameworks/base/core/java/android/os/PowerManager.java 类PowerManager中内嵌了一个WakeLock类,另外还定义了wakelock的类型,下面是代码片段: public class PowerManager { private static final String TAG = "PowerManager"; … /** * Wake lock that ensures that the CPU isrunning. The screen might * not be on. */ public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
/** * Wake lock that ensures that the screen and keyboardare on at * full brightness. */ public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK| WAKE_BIT_SCREEN_BRIGHT | WAKE_BIT_KEYBOARD_BRIGHT;
/** * Wake lock that ensures that the screen is on at fullbrightness; * the keyboard backlight will be allowed to go off. */ public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK| WAKE_BIT_SCREEN_BRIGHT;
/** * Wake lock that ensures that the screen is on (butmay be dimmed); * the keyboard backlight will be allowed to go off. */ public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK| WAKE_BIT_SCREEN_DIM;
/** * Wake lock that turns the screen off when theproximity sensor activates. * Since not all devices have proximity sensors, use * {@link #getSupportedWakeLockFlags()getSupportedWakeLockFlags()} to determine if * this wake lock mode is supported. * * {@hide} */ publicstatic final int PROXIMITY_SCREEN_OFF_WAKE_LOCK =WAKE_BIT_PROXIMITY_SCREEN_OFF; … public class WakeLock { … WakeLock(int flags, String tag) { switch (flags & LOCK_MASK) { case PARTIAL_WAKE_LOCK: case SCREEN_DIM_WAKE_LOCK: case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: case PROXIMITY_SCREEN_OFF_WAKE_LOCK: break; default: throw new IllegalArgumentException(); }
mFlags = flags; mTag = tag; mToken = new Binder(); } public void acquire() { synchronized (mToken) { if (!mRefCounted || mCount++ == 0) { try { mService.acquireWakeLock(mFlags, mToken, mTag); } catch (RemoteException e) { } mHeld = true; } } } public void release(int flags) { synchronized (mToken) { if (!mRefCounted || --mCount == 0) { try { mService.releaseWakeLock(mToken, flags); } catch (RemoteException e) { } mHeld = false; } if (mCount < 0) { throw new RuntimeException("WakeLock under-locked" + mTag); } } } … } … publicWakeLock newWakeLock(int flags, String tag) { if (tag == null) { throw new NullPointerException("tag is null in PowerManager.newWakeLock"); } return new WakeLock(flags, tag); } public void goToSleep(long time) { try { mService.goToSleep(time); } catch (RemoteException e) { } } … publicPowerManager(IPowerManager service, Handler handler) { mService = service; mHandler = handler; }
IPowerManager mService; Handler mHandler; } 应用实例: PowerManager pm =(PowerManager)getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,“Tag”); wl.acquire(); //申请锁这个里面会调用PowerManagerService里面acquireWakeLock() … wl.release(); //释放锁,显示的释放,如果申请的锁不在此释放系统就不会进入休眠。
接下来就会调用到java服务PowerManagerService中: public void acquireWakeLock(int flags, IBinder lock, String tag) { int uid = Binder.getCallingUid(); if (uid != Process.myUid()) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK,null); } long ident = Binder.clearCallingIdentity(); try { synchronized (mLocks) { acquireWakeLockLocked(flags, lock, uid,tag); // 内部方法 } } finally { Binder.restoreCallingIdentity(ident); } }
acquireWakeLockLocked(flags,lock, uid, tag)会调用函数power类的方法: Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME)。
public void releaseWakeLock(IBinder lock, int flags) { int uid = Binder.getCallingUid(); if (uid != Process.myUid()) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK,null); }
synchronized (mLocks) { releaseWakeLockLocked(lock, flags, false); } } releaseWakeLockLocked(lock,flags, false)函数会调用power类的方法: Power.releaseWakeLock(PARTIAL_NAME);
上层休眠唤醒都是调用PowerManagerService类的方法: goToSleep() à goToSleepWithReason() à goToSleepLocked() à setPowerState() à setScreenStateLocked() à Power.setScreenState() à jni方法 Android层的代码分析得不是很详细,这里只关注框架和流程。下图是网上的一个框架,可以参考一下:
|
|