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

四、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

};

const char * const NEW_PATHS[] = {

"/sys/power/wake_lock",

"/sys/power/wake_unlock",

"/sys/power/state"

};

static int g_initialized = 0;

static int g_fds[OUR_FD_COUNT];

static const char *off_state = "mem";

static const char *on_state = "on";

static intopen_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/"/n", paths[i]);

g_error = errno;

return -1;

}

g_fds[i] = fd;

}

g_error = 0;

return 0;

}

static inline voidinitialize_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));

}

intrelease_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;

}

int set_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,代码片段如下:

static voidacquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj)

{

if (idObj == NULL) {

throw_NullPointerException(env, "id is null");

return ;

}

const char *id = env->GetStringUTFChars(idObj, NULL);

acquire_wake_lock(lock, id);

env->ReleaseStringUTFChars(idObj, id);

}//对wakelock加锁函数

static void releaseWakeLock(JNIEnv *env, jobject clazz, jstring idObj)

{

if (idObj == NULL) {

throw_NullPointerException(env, "id is null");

return ;

}

const char *id = env->GetStringUTFChars(idObj, NULL);

release_wake_lock(id);

env->ReleaseStringUTFChars(idObj, id);

}//对wakelock解锁函数

static intsetScreenState(JNIEnv *env, jobject clazz, jboolean on)

{

return set_screen_state(on);

}//休眠唤醒的函数

Jni的方法需要注册到上层才可以使用,同时也需要在上层的对应java类中声明了native才可以使用。那么这里的方法在java中对应的声明在哪里呢?frameworks/base/core/java/android/os/Power.java,该文件定义一个java类,如下:

public class Power

{

// can't instantiate this class

private Power()

{

}

/**

* Wake lock that ensures that the CPU is running.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接口应该是被java server在使用,这里就是专门的电源管理服务: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 is running.The screen might

* not be on.

*/

public static final intPARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;

/**

* Wake lock that ensures that the screen and keyboard are 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 full brightness;

* 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 (but may 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 the proximity sensor activates.

* Since not all devices have proximity sensors, use

* {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if

* this wake lock mode is supported.

*

* {@hide}

*/

public static 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);

}

}

}

}

public WakeLock 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) {

}

}

public PowerManager(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层的代码分析得不是很详细,这里只关注框架和流程。下图是网上的一个框架,可以参考一下:

uid-21074389-id-3029858.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值