美文网首页
android PMS

android PMS

作者: superme_ | 来源:发表于2020-09-15 21:06 被阅读0次

    安卓电源状态

    首先安卓将电源分为以下几种情况:

    1.sleep:休眠

    从代码看,安卓将系统的休眠原因分为以下几种:

    goToSleepNoUpdateLocked

        GO_TO_SLEEP_REASON_DEVICE_ADMIN//Going to sleep due to device administration policy

        GO_TO_SLEEP_REASON_TIMEOUT //Going to sleep due to screen timeout

        GO_TO_SLEEP_REASON_LID_SWITCH //Going to sleep due to lid switch 滑盖

        GO_TO_SLEEP_REASON_POWER_BUTTON //Going to sleep due to power button

        GO_TO_SLEEP_REASON_SLEEP_BUTTON //Going to sleep due to sleep button 头显的远近

        GO_TO_SLEEP_REASON_HDMI //Going to sleep due to HDMI standby

        GO_TO_SLEEP_REASON_ACCESSIBILITY//Going to sleep by an accessibility service request

        如果不是以上几种情况,则默认为应用导致的休眠:

        GO_TO_SLEEP_REASON_APPLICATION//Going to sleep by application request

    2.nap:进入屏保

    默认屏幕超时后进入休眠,如果希望进入的是屏保模式

    则需要在overlay/frameworks/base/core/res/res/values/config.xml中将屏保模式打开

    <bool name="config_dreamsActivatedOnSleepByDefault">true</bool>   

    3.wakeup:唤醒

    wakeUpNoUpdateLocked

    从以下状态中唤醒,reason不固定:

        WAKEFULNESS_ASLEEP:

        WAKEFULNESS_DREAMING:

        WAKEFULNESS_DOZING:

    4.shutdown:关机

    5.reboot:重启

    在此前的内核篇,我们讲到了用户层会去轮询查看是否有唤醒事件需要处理,如果没有则echo mem > /sys/power/state,从而进入内核的休眠唤醒流程;所以在本篇我们主要将这两个流程是怎么衔接上的~

    由于通过调用api进行休眠唤醒的流程更为简单,所以我们看下老化apk是如何进行调用休眠唤醒的api,然后进行老化休眠唤醒实验的;

    老化休眠唤醒代码demo

    休眠动作:

    单点击开始后,设置闹钟和走休眠流程:

    runSleepWakeUpTest()

    mAlarmMgr.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()

    + (mSleepTime * 1000),

    pendIntent);

    standby();

    pm.goToSleep(SystemClock.uptimeMillis());

    唤醒动作:

    onReceive

    PowerManager pm = (PowerManager) this

      .getSystemService(Context.POWER_SERVICE);

    if (getAndroidSDKVersion() >= 17) {

          pm.wakeUp(SystemClock.uptimeMillis());

    } else {

      pm.userActivity(SystemClock.uptimeMillis(), false);

    }

    从调用流程可以看到就是不断的调用goToSleep,然后设置一个闹钟,当闹钟来临的时候唤醒系统;

    framework相关代码

    core/java/android/os/PowerManager.java

    public void goToSleep(long time) {

        goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0);   

    }

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

    public void goToSleep(long eventTime, int reason, int flags) {

        if (eventTime > SystemClock.uptimeMillis()) {

            throw new IllegalArgumentException("event time must not be in the future");

        }

    goToSleepInternal(eventTime, reason, flags, uid);

    }

    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {

        synchronized (mLock) {

            if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {

                updatePowerStateLocked();

            }

        } 

    }

    sleep流程

    当屏幕超时,按power键休眠,和应用主动调goToSleep;无论是哪种方式,如果系统启动没有异常,都会走到PowerManagerService的核心函数,updatePowerStateLocked;按照安卓注释,将updatePowerStateLocked 分为五个阶段,我们也按照五个阶段对该函数的功能进行讲解;

    Phase 0: Basic state updates

    1.USB插播亮屏入口点

    //如果需要插拔事件不影响到屏幕的亮灭,在overlay/frameworks/base/core/res/res/values/config.xml下

    //修改<bool name="config_unplugTurnsOnScreen">true</bool>从字面意思貌似是拔出的时候不亮屏;

    //mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(                                                                                                                                             

                com.android.internal.R.bool.config_unplugTurnsOnScreen);//从这里就能完整看到这个配置的用途,插拔都会影响到屏幕

    2.更新低电量模式       

    当电池电量状态发生变化的时候,才能调到该方法

    updateIsPoweredLocked(mDirty);

    判断系统是否在setting中设置了充电时保持屏幕亮屏

    updateStayOnLocked(mDirty);

    updateScreenBrightnessBoostLocked(mDirty); 

    Phase 1: Update wakefulness

    wakefulness,安卓将休眠唤醒的电源状态分为四个:

    类型状态介绍

    WAKEFULNESS_ASLEEP设备处于sleep状态,只能被wakeUp函数唤醒,屏幕会被关闭,设备先进入doze状态

    WAKEFULNESS_AWAKE设备处于awake状态,可通过goToSleep的接口将设备置于休眠状态,当用户超时时间到了设备将开始dreaming或者进入休眠流程

    WAKEFULNESS_DREAMING设备处于dreaming状态,会被wakeUp唤醒,当dreaming时间结束或者

    WAKEFULNESS_DOZING打盹

    // Loop because the wake lock and user activity computations are influenced

    // by changes in wakefulness.

    //此循环只会循环两次,然后就退出;

    for (;;) {

        updateWakeLockSummaryLocked(dirtyPhase1);

            getWakeLockSummaryFlags(wakeLock);

            adjustWakeLockSummaryLocked(mWakeLockSummary);

        updateUserActivitySummaryLocked(now, dirtyPhase1);

        if (!updateWakefulnessLocked(dirtyPhase1)) {

                    break; 

        }         

    }

    1.updateWakeLockSummaryLocked(dirtyPhase1); ;

    简单先介绍安卓的锁:

    类型属性功能介绍

    PARTIAL_WAKE_LOCKWAKE_LOCK_CPU保持CPU运行,屏幕和键盘灯允许关闭。用户按power键之后,屏幕和键盘灯会关闭,CPU keep on,直到所有该类型所被释放

    FULL_WAKE_LOCKWAKE_LOCK_SCREEN_BRIGHT WAKE_LOCK_BUTTON_BRIGH保证屏幕和键盘灯亮(at full brightness)。用户按power键之后,CPU和屏幕键盘灯都会被关闭

    SCREEN_BRIGHT_WAKE_LOCKWAKE_LOCK_SCREEN_BRIGHT保证屏幕亮(full brightness),键盘灯允许关闭。用户按power键之后,CPU和屏幕都会被关闭

    SCREEN_DIM_WAKE_LOCKWAKE_LOCK_SCREEN_BRIGHT保证屏幕亮(full brightness),键盘灯允许关闭。用户按power键之后,CPU和屏幕都会被关闭

    PROXIMITY_SCREEN_OFFPROXIMITY_SCREEN_OFFpSensor导致的灭屏情况下系统不会进入休眠,正常情况下不影响系统休眠

    DOZE_WAKE_LOCKWAKE_LOCK_DOZE使屏幕进入low power状态,允许cpu挂起。只有在电源管理进入doze模式时生效

    DRAW_WAKE_LOCKWAKE_LOCK_DRAW 保持设备awake状态已完成绘制事件,只在doze模式下生效

    该函数的主要作用为,遍历申请的所有锁,根据当前mWakefulness的状态(asleep,dozing,wake,dream),过滤不需要的锁,如DOZE模式下过滤WAKE_LOCK_SCREEN_BRIGHTWAKE_LOCK_SCREEN_DIMWAKE_LOCK_BUTTON_BRIGHT,而ASLEEP模式下在基础上过滤WAKE_LOCK_PROXIMITY_SCREEN_OFF,在Dream模式下会添加WAKE_LOCK_CPU.

    2.updateUserActivitySummaryLocked(now, dirtyPhase1);

    mUserActivitySummary的种类如下:

    类型类型介绍

    USER_ACTIVITY_SCREEN_BRIGHT点亮屏幕

    USER_ACTIVITY_SCREEN_DIM屏幕变暗

    USER_ACTIVITY_SCREEN_DREAM屏保模式

    这里有三个时间参数:

    sleepTimeout:设备完全休眠的时间,该值可以理解为保持唤醒或屏保的最大值或者上限,并且该值要大

                Settings.System.SCREEN_OFF_TIMEOUT,默认为-1;表示禁用此功能项;

    screenOffTimeoutSetting:表示设备在一段不活动进入睡眠或者屏保的时间,也称为用户超时时间,但屏幕不一定关闭,可能进入屏保

    screenDimDuration 亮屏后不操作,多久变暗;

    根据这三个时间参数计算nextTimeout的时间:

            scheduleUserInactivityTimeout(nextTimeout);

    故该函数的主要作用为,更新用户活动时间,当设备和用户有交互的时,都会根据当前时间和休眠时长,dim时长,所处状态而计算下次休眠的时间,从而完成活动超时时的操作,如由亮屏进入Dim的时长,Dim到灭屏的时长,亮屏到屏保的时长;

    3.updateWakefulnessLocked

    if (shouldNapAtBedTimeLocked()) {                                           

    changed = napNoUpdateLocked(time, Process.SYSTEM_UID);

        -->mSandmanSummoned = true;

          setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);

          -->mNotifier.onWakefulnessChangeStarted(wakefulness, reason);                   

    } else {                                                                     

    changed = goToSleepNoUpdateLocked(time,                                 

            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); 

          --> mSandmanSummoned = true;

              setWakefulnessLocked(WAKEFULNESS_DOZING, reason);

              -->mNotifier.onWakefulnessChangeStarted(wakefulness, reason);

    }                                                                           

    该函数的主要作用在与更新电源状态;

    Phase2:Lock profiles that became inactive/not kept awake.

    updateProfilesLocked(now); //估计是cts的时候使用,这个不再赘述

    Phase 3: Update display power state.

    updateDisplayPowerStateLocked(dirtyPhase2);

    -->mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();

    -->requestPowerState

        -->return mDisplayPowerController.requestPowerState(request,waitForNegativeProximity);

            -->requestPowerState

                -->sendUpdatePowerStateLocked

                    -->Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);

                        mHandler.sendMessage(msg);

    handleMessage(Message msg)

      -->updatePowerState();

          -->animateScreenStateChange

            -->setScreenState

            -->mPowerState.setScreenState(state);(DPC)

                -->scheduleScreenUpdate-->postScreenUpdateThreadSafe-->setState->mLock.notifyAll

                    -->mBlanker.requestDisplayState(DPS)

                -->callbacks.onDisplayStateChange(state)  -->根据亮灭屏走PowerManagerService enable/disable autosuspend

                -->requestGlobalDisplayStateInternal(state, brightness=0) -->mTempDisplayStateWorkQueue.get(i).run()(DMS)

                -->SurfaceControl.setDisplayPowerMode(LDA)

            -->blockScreenOn 在亮屏的流程里面监听窗口是否绘制完成,

              是的话重新发起updatePowerState,设置mColorFadeLevel为1;此时才会去设置背光,这时候对于用户来说屏幕才是最终的亮了

              否的话此时的背光值一直会为0;

            -->mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker)

            在灭屏的同时还发起了activity的pause流程

            -->updateScreenOffSleepToken

            -->acquireSleepToken

            -->updateSleepIfNeededLocked

            -->goingToSleepLocked

            -->checkReadyForSleepLocked

            -->putStacksToSleepLocked

            -->goToSleepIfPossible

            -->startPausingLocked

            -->schedulePauseAcvity --> sendMessage

            -->handleMessage -->handlePauseActivity-->performPauseActivity-->performPauseActivityIfNeed

            -->callActivityOnPause -->activity.performPause--> onPause

            唤醒的时候应用resume的流程

            ActivityStackSupervisor.java

            SleepTokenImpl.release

            -->removeSleepTokenLocked

            -->updateSleepIfNeededLocked

            -->applySleepTokensLocked

            -->resumeFocusedStackTopActivityLockedi

            -->resumeTopActivityUncheckedLocked

            -->resumeTopActivityInnerLocked

    函数作用:决策屏幕的量灭状态

    如果当前是WAKEFULNESS_ASLEEP状态,直接设置屏幕为POLICY_OFF

    如果包含以下一种状态,就设置屏幕为POLICY_BRIGHT

    1.mWakeLockSummary 如果有 WAKE_LOCK_SCREEN_BRIGHT类型的wakeLock

    2.mUserActivitySummary 屏幕状态为USER_ACTIVITY_SCREEN_BRIGHT

    3.当前系统未启动完成

    4.当前处于最大屏幕亮度

    可以看出屏幕的状态和前面设置的wakeLock,stayon,userActivity,screenBrightness等有关

    Phase 4: Update dream state (depends on display ready signal).

    updateDreamLocked(dirtyPhase2, displayBecameReady);

    -->scheduleSandmanLocked();

        -->if (!mSandmanScheduled) {

            Message msg = mHandler.obtainMessage(MSG_SANDMAN);

          }

    函数作用:决定是否进入屏保状态

    Phase 5: Send notifications, if needed.

    finishWakefulnessChangeIfNeededLocked();

    函数作用:发出wakefulness发生改变的通知

    Phase 6: Update suspend blocker.

    // Because we might release the last suspend blocker here, we need to make sure

    // we finished everything else first! 

    updateSuspendBlockerLocked();

        -->needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//根据是否有CPU的wakelock,来决定cpu是否保持唤醒

        -->needDisplaySuspendBlockerLocked//根据前面屏幕的状态,屏幕是否需要亮屏,来决定是否需要持持有屏幕的锁           

    函数作用:进行锁的申请和释放

    分析完整个函数的调用流程,依然找不到怎么跟内核休眠的流程衔接起来;那么安卓是什么是否才会去调用内核休眠流程对接起来的?原来安卓在上面的函数调到灭屏的接口时候,才会去使能autosuspend的流程;想想也没有什么毛病,毕竟对于用户来说灭屏时标识着系统要走到休眠的标志;

    代码流程如下:

    onDisplayStateChange

    -->if (state == Display.STATE_OFF) {

        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {

              setHalInteractiveModeLocked(true);

        }

        }

    nativeSetAutoSuspend(enable);

        enabelAutosuspend

            suspendControl->enableAutoSuspend 使能autoSuspend进程,进程会一直检测系统是否无锁

            gSuspendBlocker->release释放锁

    对应的灭屏disable的流程

        disableAutoSuspend

        suspendHal->acquireWakeLock(WakeLockType:PARTIAL,"PowerManager.SuspendLockout");所以一旦亮屏我们都会在内核的wake_lock节点看到这个锁,当然等到安卓把这个锁放在上层申请

        的话就看不到了

    为了呼应上次内核篇上讲的安卓等待的时机,我们在这里把读写wakeup count内核的的相关操作也po出来;

    ReadFdToString(wakeup_count_fd, &wakeup_count)

    bool pm_get_wakeup_count(unsigned int *count, bool block)   

    {                                                           

        unsigned int cnt, inpr;                                 

        if (block) {                                           

            DEFINE_WAIT(wait);                                 

            for (;;) {                                         

                prepare_to_wait(&wakeup_count_wait_queue, &wait,

                        TASK_INTERRUPTIBLE);                   

                split_counters(&cnt, &inpr);                   

                if (inpr == 0 || signal_pending(current))       

                    break;                                     

                schedule();                                     

            }                                                   

            finish_wait(&wakeup_count_wait_queue, &wait);       

        }                                                       

        split_counters(&cnt, &inpr);                           

        *count = cnt;                                           

        return !inpr;                                           

    }

    可以看到在读函数里面也会去判断是否有唤醒事件在处理,如果有唤醒事件那么就会不断的阻塞在获取进程当中;

    WriteStringToFd(wakeup_count, wakeup_count_fd)

    bool pm_save_wakeup_count(unsigned int count)   

    {                                               

        unsigned int cnt, inpr;                     

        unsigned long flags;                         

        events_check_enabled = false;               

        spin_lock_irqsave(&events_lock, flags);     

        split_counters(&cnt, &inpr);                 

        if (cnt == count && inpr == 0) {             

            saved_count = count;                     

            events_check_enabled = true;             

        }                                           

        spin_unlock_irqrestore(&events_lock, flags); 

        return events_check_enabled;                 

    }

    可以看到在写函数中,呼应到了我们内核篇中,当判断是否save_count == wakeup_count && inpr==0这两个判断为没有唤醒事件,之后就开始写相关的节点,

    success = WriteStringToFd(sleep_state, state_fd);//echo mem > /sys/power/state 发起内核进入休眠流程;

    总之,当安卓灭屏后,才会使能autosuspend不断轮询是否有锁也即唤醒事件,没有才会下发mem到写到内核节点state中;

    安卓按键亮灭屏唤醒流程

    亮屏:

    InputManagerService interceptKeyBeforeQueueing

    InputManagerCallback        interceptKeyBeforeQueueing

    PhoneWindowManager  interceptKeyBeforeQueueing

        inputceptPowerKeyDown

        wakeUpFromPowerKey

        wakeUp

    PowerManager     wakeUp

    PowerManagerService wakeUp

    灭屏:

    InputManagerService        interceptKeyBeforeQueueing

    InputManagerCallback        interceptKeyBeforeQueueing

    PhoneWindowManager  interceptKeyBeforeQueueing

        inputceptPowerKeyUp

        powerPress

        goToSleepFromPowerButton

        goToSleep

    PowerManager        goToSleep

    PowerManagerService goToSleep

    安卓的持锁流程

    PhoneWindowManager mPowerKeyWakeLock.acquire   

    PowerManager      acquireLocked  -->mService.acquireWakeLock     

    PowerManarService  acquireWakeLockInternal

                      -->new WakeLock ,mWakeLock.add将申请的锁放到PowerManager统计,这一步并不会真正申请锁

                      -->updatePowerState

                          -->updateWakeLockSummaryLocked adjustWakeLockSummary 汇总所有申请到的锁,根据睡眠状态,决定后续是否申请锁,信息保存在mWakeLockSummary

                          -->updateSuspendBlockerLocked-->mWakeLockSuspendBlocker.acquire -->nativeAcquireSuspendBlocker

    jni                acquire_wake_lock

    hal power.cpp      suspendService->acquireWakeLock

    system SystemSuspend  new WakeLock --> mSystemSuspend->incSuspendCounter -->WriteStringToFd(name, mWakeLockFd) 往内核wakeLocks写锁

      mSuspendCounter++ 这个是另外一套,安卓后续计划通过suspendCounter而不是写内核节点持锁的方式

    autospend 流程

    androidR上,谷歌说要弃用/sys/power/wake_lock节点;安卓此前申请锁的流程在hardware/libhardware_legacy/power.cpp;原理就是去往wake_lock节点写值;

    现在的话想将这个流程放在system/hardware/interfaces/suspend中进行实现;

    在这里只能说谷歌终于想通了要把这套放在用户层,毕竟曾经为了wake_lock,一直在争吵,最后还是被谷歌给干进内核,现在的话又抽出来放在用户层里面;具体细节可以参照这篇文章Linux电源管理

    谷歌列举这样的好处是:

    减少对内核的依赖

    在没有debugfs的时候用户层仍有能力去debug和log suspend blocks

    当进程消亡的时候可以进行锁通过binder的管理进行释放 dangling wake locks

    通过mSuspendCounter去统计当前持锁的数量,当mSuspendCounter为0的时候,说明上层持锁为0

    void SystemSuspend::initAutosuspend() {                                                           

        std::thread autosuspendThread([this] {                                                         

            while (true) {                                                                             

                std::this_thread::sleep_for(mSleepTime);  //如果失败了,会更改autosuspend的时间,100ms~1min                                           

                lseek(mWakeupCountFd, 0, SEEK_SET);                                                   

                const string wakeupCount = readFd(mWakeupCountFd);                                     

                if (wakeupCount.empty()) {                                                             

                    PLOG(ERROR) << "error reading from /sys/power/wakeup_count";                       

                    continue;                                                                         

                }                                                                                     

                auto counterLock = std::unique_lock(mCounterLock);                                     

                mCounterCondVar.wait(counterLock, [this] { return mSuspendCounter == 0; });//申请锁的时候mSuspendCounter会增加;释放的时候mSuspendCounter会减少           

                // The mutex is locked and *MUST* remain locked until we write to /sys/power/state.   

                // Otherwise, a WakeLock might be acquired after we check mSuspendCounter and before we

                // write to /sys/power/state.                                                         

                if (!WriteStringToFd(wakeupCount, mWakeupCountFd)) {                                   

                    PLOG(VERBOSE) << "error writing from /sys/power/wakeup_count";                     

                    continue;                                                                         

                }                                                                                     

                bool success = WriteStringToFd(kSleepState, mStateFd);                                 

                counterLock.unlock();                                                                 

                if (!success) {                                                                       

                    PLOG(VERBOSE) << "error writing to /sys/power/state";                             

                }                                                                                     

                mControlService->notifyWakeup(success);                                               

                updateSleepTime(success);                                                             

            }                                                                                         

        });                                                                                           

        autosuspendThread.detach();                                                                   

        LOG(INFO) << "automatic system suspend enabled";                                               

    }

    关机充电判断休眠唤醒原理大同小异

    system/core/libsuspend/autosuspend.c

    int autosuspend_enable(void)

    {

        autosuspend_init();

    autosuspend_ops = autosuspend_wakeup_count_init();

        autosuspend_ops->enable(); 

    autosuspend_wakeup_count_enable()

    }

    system/core/libsuspend/autosuspend_wakeup_count.cpp

    autosuspend_wakeup_count_enable()

    autosuspend_init();

    创建一个进程:suspend_thread_func 这个进程主要就是用来做轮询的动作

    sem_post(&suspend_lockout);

    suspend_thread_func

    while (true) {

    if (!ReadFdToString(wakeup_count_fd, &wakeup_count)) { //读取wakeup count值,如果成功,将读取的值回写,否则说明正在处理wakeup events,continue

    continue;

    }

    int ret = sem_wait(&suspend_lockout);//通过信号量来控制这个流程是否要继续走下去,当disable的时候信号量为0,进程会阻塞在这里等待;

    if (WriteStringToFd(wakeup_count, wakeup_count_fd)) { //回写后,判断返回值是否成功,如果不成功(说明读写过程中产生了wakeup events),继续读,写,直到成功。成功后,可以触发电源状态切换

      success = WriteStringToFd(sleep_state, state_fd);                   

    }

    ret = sem_post(&suspend_lockout);

    }

    其他

    如何设置安卓休眠超时时间?

    settings get system screen_off_timeout

    settings put system screen_off_timeout 2147483647 //设置永不休眠

    设置屏保命令

    settings put secure screensaver_activate_on_sleep 1 打开屏保

    设置插入适配器后不休眠

    settings put global stay_on_while_plugged_in 1

    安卓系统不休眠debug

    查看上层有没有释放锁

        dumpsys power | grep -Hrsn 'LOCK'

    PARTIAL_WAKE_LOCK              'messaging_service_start_wakelock'

    查看active_since这一项,看哪个锁不为0

          cat /sys/kernel/debug/wakeup_sources

    上层传向底层的锁

    cat /sys/power/wake_lock

    当这几步查找后都没有对应的锁时,可以通过/sys/power/pm_test结点,操作设备进入对应的休眠阶段,详见linux休眠篇章

    进入深度休眠后被唤醒问题debug

    一般而言,平台会提供深度休眠后如何查看系统唤醒源,如全志平台的查看方式为

        一:休眠的时候不关闭终端

        echo N > /sys/module/printk/parameters/console_suspend

        二:唤醒后查看对应的唤醒源

        查看唤醒时候打印:

            platform wakeup, standby wakesource is:0x10000

        在allwinner对应的pm.h里面就可以看到对应的唤醒源编号,如linux4.9的在driver/soc/sunxi/pm.h

        其他版本可以直接搜索关键字找到对应的唤醒源编号;

            #define CPUS_WAKEUP_DESCEND    (1<<16)

        而CPUS的GPIO一般是WIFI中断管脚在连接,故此时可以断开wifi连接查看系统唤醒是否依然异常

    另外如果当log出现为闹钟唤醒:

        platform wakeup, standby wakesource is:0x100000

        查看对应唤醒源编号

        #define CPUS_WAKEUP_ALM0        (1<<20)

    这种情况下我们一般需要通过去查看到底是哪个应用去唤醒系统的:这个时候我们可以借助这个应用 BetterBatteryStats2.0

        1.下载地址:

        http://cn.apkhere.com/app/com.asksven.betterbatterystats

        安装该软件:

        2.adb install com.asksven.betterbatterystats_2.2.2.0_paid-www.apkhere.com.apk

        3.获取权限:

        adb -d shell pm grant com.asksven.betterbatterystats android.permission.BATTERY_STATS

        4.若依然不可以:

        setenforce 0:取消selinux

        getenforce 查看是否为安全模式 Permissive 则是非安全;

        观察各项参数:

    rtc闹钟设置与查看

    venus-a3:/ # cat /proc/driver/rtc

    rtc_time        : 05:44:49

    rtc_date        : 2019-04-26

    alrm_time      : 00:00:00

    alrm_date      : 1970-01-01

    alarm_IRQ      : no

    alrm_pending    : no

    update IRQ enabled      : no

    periodic IRQ enabled    : no

    periodic IRQ frequency  : 1

    max user IRQ frequency  : 64

    24hr            : yes

    设置当前时间+100000后唤醒

    venus-a3:/ # echo +100000 > /sys/devices/platform/soc/rtc/rtc/rtc0/wakealarm

    venus-a3:/ # cat /proc/driver/rtc

    rtc_time        : 05:47:15

    rtc_date        : 2019-04-26

    alrm_time      : 09:33:52

    alrm_date      : 2019-04-27

    alarm_IRQ      : yes

    alrm_pending    : no

    update IRQ enabled      : no

    periodic IRQ enabled    : no

    periodic IRQ frequency  : 1

    max user IRQ frequency  : 64

    24hr            : yes

    echo 0取消

    查看闹钟应用设置闹钟:

    venus-a3:/ # settings list system | grep  next

          next_alarm_formatted=Wed 11:50 AM

    怎么捕捉休眠唤醒的systrace

    休眠前

    atrace –async_start -b 8192 -o /data/trace2.dat gfx view wm am power

    唤醒后

    atrace –async_stop

    https://dongka.github.io/2018/12/13/standby/android_standby/

    相关文章

      网友评论

          本文标题:android PMS

          本文链接:https://www.haomeiwen.com/subject/tovbektx.html