您的位置:首页 > 运维架构 > Linux

Android在标准linux基础上对休眠唤醒的实现(三)

2011-12-08 16:53 507 查看
四、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层的代码分析得不是很详细,这里只关注框架和流程。下图是网上的一个框架,可以参考一下:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: