四、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 int  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;
}
 
static inline 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;
}
 
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 void  acquireWakeLock(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 int 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类,如下:

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
       
    /**
     * Wake lock that ensures that the screen is on.
     */
    public static final int FULL_WAKE_LOCK
       
    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 int PARTIAL_WAKE_LOCK
 
    /**
     * Wake lock that ensures that the screen and keyboard are on at
     * full brightness.
     */
    public static final int FULL_WAKE_LOCK
       
    /**
     * 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层的代码分析得不是很详细,这里只关注框架和流程。下图是网上的一个框架,可以参考一下: