Android源码笔记--电量

Posted ljt2724960661

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android源码笔记--电量相关的知识,希望对你有一定的参考价值。

        这一节主要了解PowerManager,在android系统中,电源管理是基于Linux电源管理的轻量级Android电源管理。电源管理主要是通过锁和定时器来切换系统的状态,使系统的功耗降至最低。Android系统的Framework层是接口层,为上面的应用层提供拿来即用的接口。

  在Android Power Management系统中,Framework层涉及如下所示的文件:

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

/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java 

PowerManager类

          文件 PowerManager.java是提供给应用层调用的,最终的核心实现在文件 PowerManagerService中实现。在此文件PowerManager.java中定义了android.os.PowerManager,功能是控制设备的电源状态的切换。当通过函数 getSystemService(Context.POWER_SERVICE)获取PowerManager对象的时候,是通过构造函数 PowerManager(IPowerManagerservice,Handlerhandler)来创建并获取的,而此IPowerManager 则是创建PowerManager实例的核心,而IPowerManager则是由PowerManagerService实现,所以,从本质上说PowerManager的大部分方法是由PowerManager Service实现的。

(1)定义类PowerManager和接口函数,具体代码如下所示:

 /frameworks/base/core/java/android/os/PowerManager.java
  
@SystemService(Context.POWER_SERVICE)
public final class PowerManager 
  
     @Deprecated
 public static final int FULL_WAKE_LOCK = 0x0000001a;
 public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
 public static final int DOZE_WAKE_LOCK = 0x00000040;
  /**
     * Brightness value for fully on.
     * @hide
  */
 public static final int BRIGHTNESS_ON = 255;
 public static final int BRIGHTNESS_OFF = 0;
 public static final int BRIGHTNESS_DEFAULT = -1;

...

(2)定义对外接口函数,以实现对电源状态的控制管理。其中函数goToSleep的功能是强制设备进入Sleep状态,函数wakeUp的功能是强制设备进入wakeUp状态:

public void goToSleep(long time) 
        goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0);
    


   public void goToSleep(long time, int reason, int flags) 
        try 
            mService.goToSleep(time, reason, flags);
         catch (RemoteException e) 
            throw e.rethrowFromSystemServer();
        
    


 public void wakeUp(long time) 
        try 
            mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
         catch (RemoteException e) 
            throw e.rethrowFromSystemServer();
        
    

(3)定义函数userActivity,功能是当发生User activity 事件时,电源设备会被切换到Full on的状态,并同时Reset Screen offtimer,具体代码如下所示:

@SystemApi
    @RequiresPermission(anyOf = 
            android.Manifest.permission.DEVICE_POWER,
            android.Manifest.permission.USER_ACTIVITY
    )
    public void userActivity(long when, int event, int flags) 
        try 
            mService.userActivity(when, event, flags);
         catch (RemoteException e) 
            throw e.rethrowFromSystemServer();
        
    

提供PowerlManager功能

        文件 PowerManagerService.java 是Power Management 系统中整个Framework 层文件的核心,这个类的作用就是提供PowerManager 的功能,以及整个电源管理状态机的运行。PowerManagerService服务是Android系统的上层的电源管理服务,主要负责系统待机、屏幕背光、按键背光、键盘背光以及用户事件的处理。通过锁的申请与释放,以及默认的待机时间来控制系统的待机状态;通过系统默认关闭屏的时间,以及用户操作的事件状态控制背光的亮和暗。另外,PowerManagerService 服务还包括了光线、距离传感器上层查询与控制,LCD亮度的调节最终也是由该服务完成。来看一下PowerManagerService.java的具体实现过程。

 定义常量和变量
      /**
 * The power manager service is responsible for coordinating power management
 * functions on the device.
 */
public final class PowerManagerService extends SystemService
        implements Watchdog.Monitor 
		...
		
		  // Summarizes the state of all active wakelocks.
    private static final int WAKE_LOCK_CPU = 1 << 0;
    private static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
    private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
    private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
    private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
    private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
    private static final int WAKE_LOCK_DOZE = 1 << 6;
    private static final int WAKE_LOCK_DRAW = 1 << 7;
	
	 // Summarizes the user activity state.
    private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
    private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
    private static final int USER_ACTIVITY_SCREEN_DREAM = 1 << 2;
	
	    // Default timeout in milliseconds.  This is only used until the settings
    // provider populates the actual default value (R.integer.def_screen_off_timeout).
    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
    private static final int DEFAULT_SLEEP_TIMEOUT = -1;
		
	// A bitfield that indicates what parts of the power state have
    // changed and need to be recalculated.
    private int mDirty;	
	   // Indicates whether the device is awake or asleep or somewhere in between.
    // This is distinct from the screen power state, which is managed separately.
    private int mWakefulness;
		
		

mDirty:功能是表示power state的变化,在系统中一共定义了12个与之类似的变化,每一个state对应一个固定的数字,都是2的倍数。这样,当有若干个状态一起变化时就会按位取或,这样不但会得到一个唯一的结果,而且可以准确地标示出各个状态的变化。

mWakefulness:功能是标示device处于是醒着的、还是睡眠中的状态,或者处于两者之间的一种状态。这个状态是和 display的电源状态不同的,display 的电源状态是独立管理的。这个变量用来标示DIRTY_WAKEFULNESS这个power state 下的一个具体的内容。例如,当系统进入Draaming时,首先变化的是mDirty,在mDirty中监听DIRTY WAKEFULNESS的位置是否发生了变化,此时只是知道,DIRTY_WAKEFULNESS发生了变化,并不知道DIRTY_WAKEFULNESS发生了怎样的变化,并不知道 wakefulness 发生了怎样的变化。如果需要进一步了解系统wakefulness变成了什么,则需要查看mWakefulness的内容。

开机启动及处理

(1)当Android系统启动时,会调用文件SystemServer.java中的接口函数run,在此函数中将power服务加入到系统服务中,具体代码如下所示:

	  private void startBootstrapServices() 
	 mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
	 try 
            // TODO: use boot phase
            mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
         catch (Throwable e) 
            reportWtf("making Power Manager Service ready", e);
        
	

与系统其他模块之间的交互

BatteryReceiver->handleBatteryStateChangedLocked()   ACTION_BATTERY_CHANGED
	 DreamReceiver ->  scheduleSandmanLocked()        ACTION_DREAMING_STARTED  ACTION_DREAMING_STOPPED
	 UserSwitchedReceiver ->  handleSettingsChangedLocked()  ACTION_USER_SWITCHED
	 DockReceiver ->   updatePowerStateLocked();      ACTION_DOCK_EVENT 

在文件PowerManagerService.java 中除了注册上述4个Receiver 之外,还定义了一个SettingsObserver 以监视系统中以下属性的变化。

SCREENSAVER_ENABLED:屏保的功能开启。
SCREENSAVER_ACTIVATE_ON_SLEEP:在睡眠时屏保启动。
SCREENSAVER_ACTIVE_ON_DOCK:连接底座并且屏保启动。
SCREEN_OFF_TIMEOUT:休眠时间。
STAY_ON_WHILE_PLUGGED_IN:有硬件插入并且屏幕开启。
SCREEN_BRIGHTNESS:屏幕的亮度。
SCREEN_BRIGHTNESS_MODE:屏幕亮度的模式。

分析:SettingObserver会监视到上述属性发生的变化,并且会调用SettingObserver中的onChange方法:

       private final class SettingsObserver extends ContentObserver 
        public SettingsObserver(Handler handler) 
            super(handler);
        

        @Override
        public void onChange(boolean selfChange, Uri uri) 
            synchronized (mLock) 
                handleSettingsChangedLocked();
            
        
    

可见,PowerManagerService不但能够接收用户的请求,被动地去做一些操作,而且还要主动地监视系统中一些重要属性的变化和重要事件的发生。无论是处理主动还是被动的操作,都会有对应的处理函数。

以上是关于Android源码笔记--电量的主要内容,如果未能解决你的问题,请参考以下文章

Android源码笔记--电量

Android源码笔记--电量

Android源码笔记--电量

ChatGPT解答:安卓APP耗电量测试方案和源码,用Android代码实现

8.4 Android灯光系统_源码分析_电池灯

移动端手机 App 耗电量测试:Monkey 电量测试基本操作及 Android 性能优化