Android Framework 电源子系统(01)PowerManagerService启动分析

198 篇文章 98 订阅

该系列文章总纲链接:专题总纲目录 Android Framework 总纲


本章关键点总结 & 说明:

本章节主要关注➕ 以上思维导图即可。该章节 主要是 对 PMS 启动的分析,从systemServer启动 到 构造器、systemReady、、接口userActicity、接口gotoSleep的 一个简要的整体分析。

1 PowerManagerService启动

PowerManagerService负责Andorid系统中电源管理方面的工作。作为系统核心服务之一,PowerManagerService与其他服务及HAL层等都有交互关系,同时 因为很多服务都会涉及它,因此启动会比较早一些,在SystemServer的startBootstrapServices中就启动了,代码如下:

	private void startBootstrapServices() {
		//...
		anager needs to be started early because other services need it.
		// Native daemons may be watching for it to be registered so it must be ready
		// to handle incoming binder calls immediately (including being able to verify
		// the permissions for those calls).
		mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
		//...
	}

因此 整个分析就基于此,接下来看PowerManagerService的构造器,代码实现如下:

public PowerManagerService(Context context) {
    super(context);
    mContext = context;
    //创建处理消息的线程和Handler对象
    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new PowerManagerHandler(mHandlerThread.getLooper());

    synchronized (mLock) {
        //创建对象mWakeLockSuspendBlocker和mDisplaySuspendBlocker
        mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
        mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
        mDisplaySuspendBlocker.acquire();
        mHoldingDisplaySuspendBlocker = true;
        mHalAutoSuspendModeEnabled = false;
        mHalInteractiveModeEnabled = true;

        //注意:这里共有4种状态
        //    WAKEFULNESS_AWAKE 正常运行状态
        //    WAKEFULNESS_DREAMING 正在播放屏保状态
        //    WAKEFULNESS_DOZING 处于doze状态,此时只有“低耗电”的屏保可以运行,其他进程均被挂起
        //    WAKEFULNESS_ASLEEP 休眠状态,只能被wakeup唤醒
        mWakefulness = WAKEFULNESS_AWAKE;//设置PowerManagerService的状态

        nativeInit();//进入PMS的native层调用
        nativeSetAutoSuspend(false);
        nativeSetInteractive(true);
    }
}

@1 createSuspendBlockerLocked分析

这里创建对象mWakeLockSuspendBlocker和mDisplaySuspendBlocker的createSuspendBlockerLocked方法实现如下:

private SuspendBlocker createSuspendBlockerLocked(String name) {
    SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
    mSuspendBlockers.add(suspendBlocker);
    return suspendBlocker;
}

这里创建了SuspendBlockerImpl类型的对象,接下来主要是SuspendBlockerImpl的acquire方法和release方法的实现,核心代码实现如下:

@Override
public void acquire() {
    synchronized (this) {
        mReferenceCount += 1;
        if (mReferenceCount == 1) {
            nativeAcquireSuspendBlocker(mName);
        }
    }
}

@Override
public void release() {
    synchronized (this) {
        mReferenceCount -= 1;
        if (mReferenceCount == 0) {
            nativeReleaseSuspendBlocker(mName);
        } else if (mReferenceCount < 0) {
            mReferenceCount = 0;
        }
    }
}

这里两个关键方法nativeAcquireSuspendBlocker和 nativeReleaseSuspendBlocker在native层的实现,代码如下:

static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
    ScopedUtfChars name(env, nameStr);
    acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}

static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
    ScopedUtfChars name(env, nameStr);
    release_wake_lock(name.c_str());
}

继续分析acquire_wake_lock 和 release_wake_lock的实现,代码如下:

int acquire_wake_lock(int lock, const char* id)
{
    initialize_fds();
    if (g_error) return g_error;
    int fd;
    if (lock == PARTIAL_WAKE_LOCK) {
        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();
    if (g_error) return g_error;
    ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
    return len >= 0;
}

这里实际上是通过向驱动中写入数据来实现功能的,所写的数据就是创建变量时传递的PowerManagerService.WakeLocks和PowerManagerService.Display,同时 文件句柄的创建是通过方法initialize_fds来实现的,代码如下:

const char * const OLD_PATHS[] = {
    "/sys/android_power/acquire_partial_wake_lock",
    "/sys/android_power/release_wake_lock",
};

const char * const NEW_PATHS[] = {
    "/sys/power/wake_lock",
    "/sys/power/wake_unlock",
};
//...
static inline void initialize_fds(void)
{
    //pthread_once(&g_initialized, open_file_descriptors);
    if (g_initialized == 0) {
        //文件操作open 相关
        if(open_file_descriptors(NEW_PATHS) < 0)
            open_file_descriptors(OLD_PATHS);
        g_initialized = 1;
    }
}

说明:

Android防止系统休眠的方式是通过向设备节点"/sys/power/wake_lock"写入数据

  1. 如果写的是PowerManagerService.WakeLocks,系统将不能休眠,但屏幕会关闭
  2. 如果写的是PowerManagerService.Display,系统将不能休眠,同时屏幕也不会关闭

如果系统要恢复休眠,则向"/sys/power/wake_unlock"写入同样的字符串就可以了。

@2 nativeInit分析

native层的代码实现如下:

static void nativeInit(JNIEnv* env, jobject obj) {
    gPowerManagerServiceObj = env->NewGlobalRef(obj);
    status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
            (hw_module_t const**)&gPowerModule);
    if (!err) {
        gPowerModule->init(gPowerModule);
    }
    //...
}

这里主要是装载Power模块,然后执行它的init方法。

2 PowerManagerService的systemReady方法

同时在startOtherServices中执行 最后的systemReady方法,代码如下:

	private void startOtherServices() {
		final Context context = mSystemContext;
		//...
		try {
			// TODO: use boot phase
			mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
		} catch (Throwable e) {
			reportWtf("making Power Manager Service ready", e);
		}
		//...
	}

继续看systemReady的代码实现,如下:

public void systemReady(IAppOpsService appOps) {
    synchronized (mLock) {
        mSystemReady = true;
        mAppOps = appOps;

        //获得DreamManager的引用
        mDreamManager = getLocalService(DreamManagerInternal.class);
        //获得DisplayManager的引用
        mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
        mPolicy = getLocalService(WindowManagerPolicy.class);
        //获得BatteryManager的引用
        mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);

        //获取最大、最小、默认的屏幕亮度值
        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
        mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
        mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
        //获取sensorManager引用,用于和SensorService(native服务,管理 传感器设备)交互
        SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
        
        //获取BatteryStatsService引用
        mBatteryStats = BatteryStatsService.getService();
        //创建Notifier,广播和Power相关的变化,屏幕的打开和关闭
        mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
                mPolicy);
        //获取 检测无线充电的对象
        mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                mHandler);
        //监听系统设置变化的对象
        mSettingsObserver = new SettingsObserver(mHandler);
        //获取LightsService的引用
        mLightsManager = getLocalService(LightsManager.class);
        mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);

        //初始化显示模块电源管理模块
        mDisplayManagerInternal.initPowerManagement(
                mDisplayPowerCallbacks, mHandler, sensorManager);

        // Register for broadcasts from other components of the system.
        //监听其他广播的intent,很多都和电源管理有关
        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);//Dock插拔事件通知
        mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);

        //监听系统设置Setting的变化
        final ContentResolver resolver = mContext.getContentResolver();
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                Settings.Secure.SCREENSAVER_ENABLED),
                false, mSettingsObserver, UserHandle.USER_ALL);
        //监听更多setting的变化...
        resolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.THEATER_MODE_ON),
                false, mSettingsObserver, UserHandle.USER_ALL);
        
        readConfigurationLocked();
        updateSettingsLocked();
        mDirty |= DIRTY_BATTERY_STATE;
        updatePowerStateLocked();
    }
}

3 接口userActivity分析

PowerManager(简称PM)是PowerManagerService(后简称PMS)的代理类,这里接口userActivity用于用户进程向PMS报告用户影响系统休眠的活动,比如:用户点击屏幕时,系统会调用该方法userActivity告诉PMS用户点击的时间,这样PMS将更新内部保存的时间值,从而推迟系统休眠的时间,userActivity实现如下:

@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
    final long now = SystemClock.uptimeMillis();
    //权限检测 & 异常处理
    final int uid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    try {
        userActivityInternal(eventTime, event, flags, uid);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

继续分析userActivityInternal,内部实现如下:

private void userActivityInternal(long eventTime, int event, int flags, int uid) {
    synchronized (mLock) {
        if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
            updatePowerStateLocked();
        }
    }
}

这里关键两行代码:userActivityNoUpdateLocked的判定和执行updatePowerStateLocked,其中userActivityNoUpdateLocked只是将参数保存在内部变量中,并不采取任何操作,代码实现如下:

private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
    //...
    try {
        if (eventTime > mLastInteractivePowerHintTime) {
            powerHintInternal(POWER_HINT_INTERACTION, 0);
            mLastInteractivePowerHintTime = eventTime;
        }

        mNotifier.onUserActivity(event, uid);//发出通知
        if (mWakefulness == WAKEFULNESS_ASLEEP
                || mWakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
            return false;//如果系统处于休眠或doze模式,返回
        }

        /*关键变量
            mLastUserActivityTimeNoChangeLights
            mLastUserActivityTime
            mDirty
          将会作为是否执行睡眠/唤醒操作的依据
            */
        if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
            if (eventTime > mLastUserActivityTimeNoChangeLights
                    && eventTime > mLastUserActivityTime) {
                //记录userActivity方法的时间
                mLastUserActivityTimeNoChangeLights = eventTime;
                mDirty |= DIRTY_USER_ACTIVITY;
                return true;
            }
        } else {
            if (eventTime > mLastUserActivityTime) {
                //记录userActivity方法的时间
                mLastUserActivityTime = eventTime;
                //记录用户的操作类型
                mDirty |= DIRTY_USER_ACTIVITY;
                return true;
            }
        }
    } 
    //...
    return false;
}

接下来 调用 updatePowerStateLocked开始更新 休眠 or 唤醒状态我们会在下一节中专门分析该方法此处先略过。

4 接口gotoSleep分析

gotoSleep接口是用来强制系统进入休眠模式。当系统一段时间无操作时,将调用gotoSleep接口来进入该模式,PMS的接口gotoSleep实现如下:

@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
    //...
    final int uid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    try {
        goToSleepInternal(eventTime, reason, flags, uid);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

这里主要调用了方法goToSleepInternal,代码实现如下:

private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
    synchronized (mLock) {
        if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
            updatePowerStateLocked();
        }
    }
}

继续分析关键方法goToSleepNoUpdateLocked的实现,代码如下:

// This method is called goToSleep for historical reasons but we actually start
// dozing before really going to sleep.
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
    if (eventTime < mLastWakeTime
            || mWakefulness == WAKEFULNESS_ASLEEP
            || mWakefulness == WAKEFULNESS_DOZING
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
    try {
        //打印日志...
        //更新成员变量 值
        mLastSleepTime = eventTime;
        mSandmanSummoned = true;
        setWakefulnessLocked(WAKEFULNESS_DOZING, reason);

        // Report the number of wake locks that will be cleared by going to sleep.
        int numWakeLocksCleared = 0;
        final int numWakeLocks = mWakeLocks.size();
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                case PowerManager.FULL_WAKE_LOCK:
                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                case PowerManager.SCREEN_DIM_WAKE_LOCK:
                    numWakeLocksCleared += 1;
                    break;
            }
        }
        //打印EventLog 日志
        EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);

        // Skip dozing if requested.
        if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
            reallyGoToSleepNoUpdateLocked(eventTime, uid);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

这里执行了setWakefulnessLocked,代码如下:

private void setWakefulnessLocked(int wakefulness, int reason) {
    if (mWakefulness != wakefulness) {
        finishWakefulnessChangeLocked();

        mWakefulness = wakefulness;
        mWakefulnessChanging = true;
        mDirty |= DIRTY_WAKEFULNESS;
        mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
    }
}

这里的核心操作是修改了成员变量的值,在这之后发送了休眠的通知。接下来 调用 updatePowerStateLocked开始更新 休眠 or 唤醒状态我们会在 本模块 第3 4 5 节中专门分析该方法,因此 此处先略过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

图王大胜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值