PowerManagerService(一)— 初始化

1. 简介

  PowerManagerServcie是android系统电源管理的核心服务,它在Framework层建立起一个策略控制方案,向下决策HAL层以及kernel层来控制设备待机状态,主要功能是控制系统待机状态,屏幕显示,亮度调节,光线/距离传感器的控制等。

  除了与应用程序交互之外,还要与系统中其它模块配合,在提供良好的能源管理同时提供友好的用户体验。比如听音乐时持续保持系统唤醒,应用通知来临唤醒手机屏幕等场景

  分析一个服务,首先要从它对应用层提供的api PowerManager入手,观察提供了哪些接口调用;

  • Wakeup():强制系统从睡眠状态唤醒,此接口对应用是不开放的,应用想唤醒系统必须通过设置亮屏标志(后面即将讲到);
  • gotoSleep():强制系统进入到睡眠状态,此接口也是应用不开放。
  • userActivity():向PowerManagerService报告影响系统休眠的用户活动,重计算灭屏时间,背光亮度等,例如触屏,划屏,power键等用户活动;
  • Wakelock:wakelock是PowerManager的一个内部类,提供了相关的接口来操作wakelock锁,比如newWakeLock()方法来创建wakelock锁,acquire()和release()方法来申请和释放锁。下面例子有介绍!
  • isDeviceIdleMode():返回设备当前的状态,如果处于Idle状态,则返回true,Idle状态是在手机长时间没有被使用以及没有运动的情况下,手机进入到一种Doze低功耗的模式下,这种状态下手机可能会关掉网络数据访问,可以通过监视DEVICE_IDLE_MODE_CHANGED这个广播信息,来监控手机状态的改变

1.1 系统层级图

在这里插入图片描述

1.2 电源管理架构

主要分为四个层次:

  • 应用接口层:PowerManager.java中开放给应用一系列接口,应用可以调用PM的接口申请wakelock,唤醒系统,使系统进入睡眠等操作;
  • Framework层:PowerManagerService.java计算系统中和Power相关的计算,是整个电源管理的决策系;
  • HAL层:该层只有一个power.c文件,该文件通过上层传下来的参数,向/sys/power/wake_lock或者/sys/power/wake_unlock文件节点写数据来与kernel进行通信,主要功能是申请/释放锁,维持屏幕亮灭。
  • Kernel层:内核层实现电源管理的方案主要包含三个部分:
    Kernel/power/:实现了系统电源管理框架机制。
    Arch/arm(ormips or powerpc)/mach-XXX/pm.c:实现对特定板的处理器电源管理。
    drivers/power:是设备电源管理的基础框架,为驱动提供了电源管理接口。

2. 初始化

  跟其他系统服务一样,PowerManagerService也是继承于SystemService并通过SystemServer启动。

2.1 SystemServer启动PowerManagerService服务

frameworks/base/services/java/com/android/server/SystemServer.java

private void startBootstrapServices() {
  ......
  mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
  ......
}

2.2 PowerManagerService构造

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

public final class PowerManagerService extends SystemService
        implements Watchdog.Monitor {
    public PowerManagerService(Context context) {
        super(context);
        mContext = context;
		//创建消息处理线程,并启动
        mHandlerThread = new ServiceThread(TAG,
                Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
        mHandlerThread.start();
		//创建Hanlder对象处理消息
        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
        mConstants = new Constants(mHandler);
        mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
        mBatterySaverPolicy = new BatterySaverPolicy(mHandler);

        synchronized (mLock) {
            //创建"PowerManagerService.WakeLocks"的SuspendBlocker
            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
            // 创建"PowerManagerService.Display"的SuspendBlocker
            mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
            // 请求DisplaySuspendBlocker,禁止系统进入休眠
            mDisplaySuspendBlocker.acquire();
            mHoldingDisplaySuspendBlocker = true;
            mHalAutoSuspendModeEnabled = false;
            mHalInteractiveModeEnabled = true;
            // 设置mWakefulness为唤醒状态
            mWakefulness = WAKEFULNESS_AWAKE;

            sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
            // 进入到native层初始化
            nativeInit();
            nativeSetAutoSuspend(false);
            nativeSetInteractive(true);
            nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
        }
    }
    ......
}

  PowerManagerService构造函数中首先创建了处理消息的进程及对应的handler对象以进行消息处理,然后创建SuspendBlocker对象,用于WakeLocks与Display,并设置mWakefulness的初始状态为WAKEFULNESS_AWAKE,最后进入到native层初始化。下面先看一下关于mWakefulness的定义。

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

/**
 * 设备处于休眠状态,只能被wakeUp()唤醒.
 */
public static final int WAKEFULNESS_ASLEEP = 0;

/**
 * 设备处于正常工作(fully awake)状态.
 */
public static final int WAKEFULNESS_AWAKE = 1;

/**
 * 设备处于播放屏保状态.
 */
public static final int WAKEFULNESS_DREAMING = 2;

/**
 * 设备处于doze状态,只有低耗电的屏保可以运行,其他应用被挂起.
 */
public static final int WAKEFULNESS_DOZING = 3;

  继续回到PowerManagerService构造函数的native初始化中,首先来看nativeInit的实现。

frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

static void nativeInit(JNIEnv* env, jobject obj) {
   // 创建一个全局对象,引用PMS
   gPowerManagerServiceObj = env->NewGlobalRef(obj);
   // 利用hw_get_module加载power模块
   status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
           (hw_module_t const**)&gPowerModule);
   if (!err) {
       gPowerModule->init(gPowerModule);
   } else {
       ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
   }
}

  nativeInit的主要任务时装载power模块,该模块由厂商实现,以高通为例,如下。

device/qcom/common/power/power.c

tatic struct hw_module_methods_t power_module_methods = {
    .open = NULL,
};

struct power_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = POWER_MODULE_API_VERSION_0_2,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = POWER_HARDWARE_MODULE_ID,
        .name = "QCOM Power HAL",
        .author = "Qualcomm",
        .methods = &power_module_methods,
    },

    .init = power_init,
    .powerHint = power_hint,
    .setInteractive = set_interactive,
};

  power_module中实现了init,powerHint,setInteractive,nativeInit最终调用到HAL power模块的power_init具体实现中。接着看native初始化nativeSetAutoSuspend的实现。

frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
    if (enable) {
        ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");
        autosuspend_enable();
    } else {
        ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");
        autosuspend_disable();
    }
}
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
    if (gPowerModule) {
        if (enable) {
            ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
            gPowerModule->setInteractive(gPowerModule, true);
        } else {
            ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
            gPowerModule->setInteractive(gPowerModule, false);
        }
    }
}

static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
    int data_param = data;

    if (gPowerModule && gPowerModule->setFeature) {
        gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);
    }
}

system/core/libsuspend/autosuspend.c

int autosuspend_disable(void)
{
    int ret;

    ret = autosuspend_init();
    if (ret) {
        return ret;
    }

    ALOGV("autosuspend_disable\n");

    if (!autosuspend_enabled) {
        return 0;
    }

    ret = autosuspend_ops->disable();
    if (ret) {
        return ret;
    }

    autosuspend_enabled = false;
    return 0;
}

  同nativeInit一样,最终都是调用到HAL power模块的具体实现中。

3. 启动

  下面继续看PowerManagerService在系统启动过程中回调onStart(),onBootPhase(),systemReady()的实现。

3.1 启动服务SystemServiceManager.onStart

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

public void onStart() {
    publishBinderService(Context.POWER_SERVICE, new BinderService());
    publishLocalService(PowerManagerInternal.class, new LocalService());

    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

private final class BinderService extends IPowerManager.Stub......private final class LocalService extends PowerManagerInternal {
    ......
}

  onStart()中发布了BinderServiceLocalService分别供其他进程,进程内其他服务调用,并将PowerManagerService加入到Watchdog监控中。

3.2 启动服务SystemServiceManager.onBootPhase

public void onBootPhase(int phase) {
    synchronized (mLock) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            ......
        } else if (phase == PHASE_BOOT_COMPLETED) {
            final long now = SystemClock.uptimeMillis();
            // 设置mBootCompleted状态
            mBootCompleted = true;
            mDirty |= DIRTY_BOOT_COMPLETED;
            // 更新userActivity及PowerState,后面分析
            userActivityNoUpdateLocked(
                    now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
            updatePowerStateLocked();
            // 执行mBootCompletedRunnables中的runnable方法
            if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
                Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
                for (Runnable r : mBootCompletedRunnables) {
                    BackgroundThread.getHandler().post(r);
                }
            }
            mBootCompletedRunnables = null;
        }
    }
}

  onBootPhase()中主要设置mBootCompleted状态,更新PowerState状态,并执行mBootCompletedRunnables中的runnables方法(低电量模式会设置)。

3.3 启动服务SystemServiceManager.systemReady

public void systemReady(IAppOpsService appOps) {
    synchronized (mLock) {
        mSystemReady = true;
        // 获取AppOpsService
        mAppOps = appOps;
        // 获取DreamManager 屏保
        mDreamManager = getLocalService(DreamManagerInternal.class);
        // 获取DisplayManagerService  屏幕显示
        mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
      //窗口策略
        mPolicy = getLocalService(WindowManagerPolicy.class);
        // 获取mBatteryService 电池电量
        mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);

        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        // 获取屏幕默认,最大,最小亮度
        mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
        mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
        mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
        // 获取SensorManager
        SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

        mBatteryStats = BatteryStatsService.getService();
        // 创建Notifier对象,用于广播power state的变化
        mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
                mPolicy);
        // 无线充电检测
        mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                mHandler);
        // 监听设置的变化
        mSettingsObserver = new SettingsObserver(mHandler);

        mLightsManager = getLocalService(LightsManager.class);
        mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);

        // Initialize display power management.
        mDisplayManagerInternal.initPowerManagement(
                mDisplayPowerCallbacks, mHandler, sensorManager);

        // Register for settings changes.
        final ContentResolver resolver = mContext.getContentResolver();
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                Settings.Secure.SCREENSAVER_ENABLED),
        ......
        IVrManager vrManager =
                (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
        try {
            vrManager.registerListener(mVrStateCallbacks);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register VR mode state listener: " + e);
        }
        // 读取配置
        readConfigurationLocked();
        updateSettingsLocked();
        mDirty |= DIRTY_BATTERY_STATE;
        updatePowerStateLocked();
    }

    // Register for broadcasts from other components of the system.
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);

    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_DREAMING_STARTED);
    filter.addAction(Intent.ACTION_DREAMING_STOPPED);
    mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);

    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_USER_SWITCHED);
    mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);

    filter = new IntentFilter();
    filter.addAction(Intent.ACTION_DOCK_EVENT);
    mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
}

  总而言之在SystemReady方法中完成的主要工作如下:

  • 1.获取与PowerManagerServcie相关的系统服务以及本地服务;
    获取屏幕最大,最小以及默认亮度值;
  • 2.创建SensorManager 对象,用于和SensorService交互;
  • 3.创建Notifier对象,用于通知系统中电源状态的改变;
  • 4.创建WirelessChargerDetector对象,用于检测无线充电的传感器(市面上支持的手机较少)
  • 5.调用DisplayManagerService的initPowerManagement()方法来初始化Power显示模块。
  • 6.注册SettingsObserver监听系统设置的变化

3.4 userActivity

  userActivity是定义在PowerManager中的SystemApi,用户向PowerManagerService报告用户活动,以更新PowerManagerService内部时间/状态值,推迟系统休眠的时间。
PowerManager中userActivity请求调用服务端PowerManagerService BinderService的userActivity,即调用内部方法userActivityNoUpdateLocked

private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
    // 如果发生时间是上一次休眠或唤醒前,或当前没有开机完成到systemReady,不采取操作直接返回
    if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    try {
        // 更新mLastInteractivePowerHintTime时间
        if (eventTime > mLastInteractivePowerHintTime) {
            powerHintInternal(POWER_HINT_INTERACTION, 0);
            mLastInteractivePowerHintTime = eventTime;
        }

        // 通过mNotifier通知BatteryStats UserActivity事件
        mNotifier.onUserActivity(event, uid);

        if (mUserInactiveOverrideFromWindowManager) {
            mUserInactiveOverrideFromWindowManager = false;
            mOverriddenTimeout = -1;
        }

        // 如果系统处于休眠状态,不进行处理
        if (mWakefulness == WAKEFULNESS_ASLEEP
                || mWakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
            return false;
        }

        // 根据flag是否在已变暗的情况下是否重启活动超时更新mLastUserActivityTimeNoChangeLights或mLastUserActivityTime
        // 并且设置mDirty DIRTY_USER_ACTIVITY
        if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
            if (eventTime > mLastUserActivityTimeNoChangeLights
                    && eventTime > mLastUserActivityTime) {
                mLastUserActivityTimeNoChangeLights = eventTime;
                mDirty |= DIRTY_USER_ACTIVITY;
                return true;
            }
        } else {
            if (eventTime > mLastUserActivityTime) {
                mLastUserActivityTime = eventTime;
                mDirty |= DIRTY_USER_ACTIVITY;
                return true;
            }
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return false;
}

4. 应用场景

  例如:长连接需要在后台服务需要持续在线;安卓系统底层优化策略会在系统休眠这段时间调整CPU的运作,我们需要将应用保持CPU一直运转。

mqtt或者websocket等长连接框架就需要如此!

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock w1 = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "MyTag");
w1.acquire();
//在这个过程,屏幕会保持光亮! 
//或者网络协议执行心跳包
w1.release();

  上述newWakeLock( )的第一个flag标记,这些标记不同程度的影响系统电源.
  这些标记都是独占的,并且每次只能指定其中一个。

  • PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
  • SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
  • SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
  • FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

5. 控制系统休眠

  Android设备的休眠和唤醒主要基于WakeLock机制。WakeLock是一种上锁机制,只要有进程获得了WakeLock锁系统就不会进 入休眠。例如,在下载文件或播放音乐时,即使休眠时间到了,系统也不能进行休眠。WakeLock可以设置超时,超时后会自动解锁,具体关于wake lock的介绍后面会另写一篇,此处仅作简单介绍。

  应用使用WakeLock功能前,需要先使用new WakeLock()接口创建一个WakeLock类对象,然后调用它的acquire()方法禁止系统休眠,应用完成工作后调用release()方法来恢复休眠机制,否则系统将无法休眠,直到耗光所有电量。

  WakeLock类中实现acquire()release()方法实际上是调用了PowerManagerServiceacquireWakeLock()releaseWakeLock()方法。

  updatePowerStateLocked()PowerManagerService的核心函数;在执行完申请锁,释放锁,用户事件,强制唤醒/睡眠等操作都需要调用updatePowerStateLocked()来更新电源状态

5.1 wakelock

  Wakelock是android系统上特有的电源管理机制,只要有应用拿着这个锁,系统就不能进入睡眠状态,在上层不同的应用程序可以持有多个不同的wakelock锁,但是反映到底层就只有三种:控制系统休眠PowerManagerService.WakeLock,控制屏幕显示的PowerManagerService.Display和控制电源状态改变通知的PowerManagerService.Broadcasts

  PowerManagerServiceacquire()加锁release()解锁两种状态,加锁有两种方式:

  • 第一种是永久的锁住,这样的锁除非显式的放开,否则是不会解锁的,所以这种锁用起来要非常的小心(默认)。
    acquire():申请wakelock永久锁(默认),需要手动release
  • 第二种锁是超时锁,这种锁会在锁住后一段时间解锁。
    acquire(long timeout):申请wakelock超时锁,timeout为设置的超时时间,超时自动release掉该wakelock。

  应用程序在使用wakelock前,必须在其manifest.xml文件中注册android.permission.WAKE_LOCK权限;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ʚ兔子的先森ɞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值