Android5.1 PowerManagerService深刻分析

PowerManagerService提供Android系統的電源管理服務,主要功能是控制系統的待機狀態,控制顯示屏的開關和亮度調節等。
PowerManagerService在systemserver中建立,加入到serviceManager中:
[java] view plain copy
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);  
先從構造函數分析,代碼以下:
   
public PowerManagerService(Context context) {  
       super(context);  
       mContext = context;  
  //建立處理消息的線程  
       mHandlerThread = new ServiceThread(TAG,  
               Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);  
       mHandlerThread.start();  
 //建立Handler,注意mHandlerThread.getLooper(),每個線程都只有一個looper,這樣消息的處理會放在這個線程中  
       mHandler = new PowerManagerHandler(mHandlerThread.getLooper());  
  
       synchronized (mLock) {  
           mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");  
           mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");  
  //防止cpu進入睡眠狀態  
           mDisplaySuspendBlocker.acquire();  
           mHoldingDisplaySuspendBlocker = true;  
           mHalAutoSuspendModeEnabled = false;  
           mHalInteractiveModeEnabled = true;  
  //當前系統狀態正常運行狀態  
           mWakefulness = WAKEFULNESS_AWAKE;  
  
           nativeInit();  
           nativeSetAutoSuspend(false);  
           nativeSetInteractive(true);  
       }  
   }  java

構造函數比較簡單,建立了一個接受消息處理的線程,cpu持鎖不讓手機睡眠,以及一些變量的初始化。
SystemServer建立完PowerManagerService後,繼續調用SystemReady方法,再作一些初始化的工做,代碼以下:
[java] view plain copy
public void systemReady(IAppOpsService appOps) {  
        synchronized (mLock) {  
            mSystemReady = true;  
            mAppOps = appOps;  
            //android5.0後的新方法,localService能夠直接取,在4.4中這樣service是在init中傳對象進來的  
            mDreamManager = getLocalService(DreamManagerInternal.class);  
            mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);  
            mPolicy = getLocalService(WindowManagerPolicy.class);  
            mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);  
  
            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);  
            //獲取缺省、最大、最小屏幕亮度  
            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();  
            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();  
            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();  
            //建立sensorManager和sersorservice交互  
            SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());  
  
            // The notifier runs on the system server's main looper so as not to interfere  
            // with the animations and other critical functions of the power manager.  
            mBatteryStats = BatteryStatsService.getService();  
            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 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);  
  
            // Register for settings changes.  
            final ContentResolver resolver = mContext.getContentResolver();  
            resolver.registerContentObserver(Settings.Secure.getUriFor(  
                    Settings.Secure.SCREENSAVER_ENABLED),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Secure.getUriFor(  
                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Secure.getUriFor(  
                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.System.getUriFor(  
                    Settings.System.SCREEN_OFF_TIMEOUT),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Secure.getUriFor(  
                    Settings.Secure.SLEEP_TIMEOUT),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Global.getUriFor(  
                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.System.getUriFor(  
                    Settings.System.SCREEN_BRIGHTNESS),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.System.getUriFor(  
                    Settings.System.SCREEN_BRIGHTNESS_MODE),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.System.getUriFor(  
                    Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Global.getUriFor(  
                    Settings.Global.LOW_POWER_MODE),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Global.getUriFor(  
                    Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            resolver.registerContentObserver(Settings.Global.getUriFor(  
                    Settings.Global.THEATER_MODE_ON),  
                    false, mSettingsObserver, UserHandle.USER_ALL);  
            // Go.  
            readConfigurationLocked();  
            updateSettingsLocked();  
            mDirty |= DIRTY_BATTERY_STATE;  
            updatePowerStateLocked();  
        }  
    }  android

從在android5.1.1中,service通常都會繼承一個虛類SystemService,在其中定義了兩個接口onStart和onBootPhase,分別是PowerManagerService啓動的時候會調用,而onBootPhase會在系統啓動的各個階段來調用,下面咱們分別來看看在powerManagerService中這兩個函數的實現:
[java] view plain copy
@Override  
public void onStart() {  
    publishBinderService(Context.POWER_SERVICE, new BinderService());  
    publishLocalService(PowerManagerInternal.class, new LocalService());  
  
    Watchdog.getInstance().addMonitor(this);  
    Watchdog.getInstance().addThread(mHandler);  
}  
在onstart函數中,必須把一些接口publish,像在以前Binder的接口,都是經過PowerManagerService extends IPowerManager.Stub形式在PowerManagerService中實現接口
而在android5.1.1中都是經過方式從新定義一個類,而後把這個類publish出去。
[java] view plain copy
private final class BinderService extends IPowerManager.Stub {  
    @Override // Binder call  
    public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,  
            String packageName, int uid) {  
        if (uid < 0) {  
            uid = Binder.getCallingUid();  
        }  
        acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);  
    }  
  
    @Override // Binder call  
    public void powerHint(int hintId, int data) {  
        if (!mSystemReady) {  
            // Service not ready yet, so who the heck cares about power hints, bah.  
            return;  
        }  
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);  
        powerHintInternal(hintId, data);  
    }  
  
    @Override // Binder call  
    public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,  
            WorkSource ws, String historyTag) {  
[java] view plain copy
。。。。。。。。。。。。。。  
而localservice都是一些本地的服務,不是經過Binder實現的。app

    咱們接下來從,powerManager中的wakeLock提及,在powerManager中調用newWakeLock接口會生成一個WakeLock對象,而調用器acqure方法,最終會調用PowerManagerService中的acquireWakeLock方法
而具體的WakeLock有幾種以下:
PARTIAL_WAKE_LOCK:只保持CPU運行,屏幕和鍵盤光關閉。
FULL_WAKE_LOCK:都不關閉
SCREEN_BRIGHT_WAKE_LOCK:屏幕背光不關閉,鍵盤光關閉
SCREEN_DIM_WAKE_LOCK:屏幕背光不關閉,鍵盤光關閉。可是屏幕背光能夠變暗
PROXIMITY_SCREEN_OFF_WAKE_LOCK當持有這種類型wakelock,當距離傳感器被遮擋,屏幕將被關閉。打電話時用這個功能
在PowerManagerService中的acquieWakeLock先要檢查權限而後調用acquireWakeLockInternal接口,代碼以下:
[java] view plain copy
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,  
          WorkSource ws, String historyTag, int uid, int pid) {  
      synchronized (mLock) {  
          WakeLock wakeLock;  
          //查找wakelock  
          int index = findWakeLockIndexLocked(lock);  
          boolean notifyAcquire;  
          if (index >= 0) {查找到  
              wakeLock = mWakeLocks.get(index);  
              if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {屬性不同,更新  
                  // Update existing wake lock.  This shouldn't happen but is harmless.  
                  notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,  
                          uid, pid, ws, historyTag);  
                  wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);  
              }  
              notifyAcquire = false;  
          } else {沒找到,從新創建,添加  
              wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);  
              try {  
                  lock.linkToDeath(wakeLock, 0);  
              } catch (RemoteException ex) {  
                  throw new IllegalArgumentException("Wake lock is already dead.");  
              }  
              mWakeLocks.add(wakeLock);  
              notifyAcquire = true;  
          }  
          //看是否須要點亮屏幕  
          applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);  
          //整個PowermanagerService用來記錄各個狀態變化的一個標誌位  
          mDirty |= DIRTY_WAKE_LOCKS;  
          //更新各個狀態  
          updatePowerStateLocked();  
          if (notifyAcquire) {  
              // This needs to be done last so we are sure we have acquired the  
              // kernel wake lock.  Otherwise we have a race where the system may  
              // go to sleep between the time we start the accounting in battery  
              // stats and when we actually get around to telling the kernel to  
              // stay awake.  
              notifyWakeLockAcquiredLocked(wakeLock);  
          }  
      }  
  }  
整個PowermanagerService都是靠一個mDirty的各個標誌位來記錄各個狀態的變化,隨後會調用一個updatePowerStateLocked來更新各個狀態。
一樣解鎖會調用到releaseWakeLockInternal,代碼以下:
[java] view plain copy
 private void releaseWakeLockInternal(IBinder lock, int flags) {  
        synchronized (mLock) {  
            int index = findWakeLockIndexLocked(lock);  
            if (index < 0) {//沒有找到退出  
                if (DEBUG_SPEW) {  
                    Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)  
                            + " [not found], flags=0x" + Integer.toHexString(flags));  
                }  
                return;  
            }  
  
            WakeLock wakeLock = mWakeLocks.get(index);  
            if (DEBUG_SPEW) {  
                Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)  
                        + " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags));  
            }  
  
            if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {  
                mRequestWaitForNegativeProximity = true;  
            }  
            //去除wakelock  
            wakeLock.mLock.unlinkToDeath(wakeLock, 0);  
            removeWakeLockLocked(wakeLock, index);  
        }  
    }  
  
PowerManagerService中最終各個接口都會調一個函數updatePowerStateLocked,主要用來更新power的各個狀態  
  
private void updatePowerStateLocked() {  
        if (!mSystemReady || mDirty == 0) {各個狀態沒有變化  
            return;  
        }  
        if (!Thread.holdsLock(mLock)) {  
            Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");  
        }  
  
        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");  
        try {  
            // Phase 0: Basic state updates.  
            //更新充電的各個狀態(是否充電、電池電量、充電方式、是否低電量),以及更新低功耗模式(android5.0增長的)  
            updateIsPoweredLocked(mDirty);  
            //更新mStayOn狀態,爲true,屏幕常亮  
            updateStayOnLocked(mDirty);  
            //更新屏幕是否最亮的狀態是否持續  
            updateScreenBrightnessBoostLocked(mDirty);  
  
            // Phase 1: Update wakefulness.  
            // Loop because the wake lock and user activity computations are influenced  
            // by changes in wakefulness.  
            final long now = SystemClock.uptimeMillis();  
            int dirtyPhase2 = 0;  
            for (;;) {  
                int dirtyPhase1 = mDirty;  
                dirtyPhase2 |= dirtyPhase1;  
                mDirty = 0;  
                //更新mWakeLockSummary的狀態  
                updateWakeLockSummaryLocked(dirtyPhase1);  
                //更新mUserActivitySummary狀態  
                updateUserActivitySummaryLocked(now, dirtyPhase1);  
                if (!updateWakefulnessLocked(dirtyPhase1)) {  
                    break;  
                }  
            }  
  
            // Phase 2: Update display power state.  
            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);//更新display狀態,在displaypowercontrol中會控制亮度,滅屏等  
  
            // Phase 3: Update dream state (depends on display ready signal).  
            //更新夢的狀態,用dreammanager控制夢,powermanagerservice中記錄mWakefulness  
            updateDreamLocked(dirtyPhase2, displayBecameReady);  
  
            // Phase 4: Send notifications, if needed.  
            if (mDisplayReady) {  
                finishWakefulnessChangeLocked();  
            }  
  
            // Phase 5: Update suspend blocker.  
            // Because we might release the last suspend blocker here, we need to make sure  
            // we finished everything else first!  
            //更新睡眠鎖,以及是否持鎖和釋放鎖  
            updateSuspendBlockerLocked();  
        } finally {  
            Trace.traceEnd(Trace.TRACE_TAG_POWER);  
        }  
    }  less

updateIsPoweredLocked、updateStayOnLocked、updateScreenBrightnessBoostLocked、updateWakeLockSummaryLocked、updateUserActivitySummaryLocked都是比較簡單、在上面的函數註釋中都有介紹。下面咱們先看下updateWakefulnessLocked函數,代碼以下:
[java] view plain copy
private boolean updateWakefulnessLocked(int dirty) {  
    boolean changed = false;  
    if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED  
            | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE  
            | DIRTY_DOCK_STATE)) != 0) {  
        //當前狀態是醒着,而且準備開始睡眠了  
        if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {  
            if (DEBUG_SPEW) {  
                Slog.d(TAG, "updateWakefulnessLocked: Bed time...");  
            }  
            final long time = SystemClock.uptimeMillis();  
            //是應該開始作夢,仍是先睡眠  
            if (shouldNapAtBedTimeLocked()) {  
                //當前狀態設置爲睡眠狀態  
                changed = napNoUpdateLocked(time, Process.SYSTEM_UID);  
            } else {  
                //當前狀態設置爲假寐狀態  
                changed = goToSleepNoUpdateLocked(time,  
                        PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);  
            }  
        }  
    }  
    return changed;  
}  
[java] view plain copy
private boolean isBeingKeptAwakeLocked() {  
    return mStayOn  
            || mProximityPositive//距離傳感器  
            || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0//wakelock鎖  
            || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT  
                    | USER_ACTIVITY_SCREEN_DIM)) != 0//用戶行爲、和用戶點擊屏幕、自動滅屏時間等有關  
            || mScreenBrightnessBoostInProgress;\\是否要保持處於最亮狀態  
}  
  
  
private boolean isItBedTimeYetLocked() {  
//當啓動完成、而且設備沒必要保持喚醒狀態是的時候返回true  
    return mBootCompleted && !isBeingKeptAwakeLocked();  
}  ide

updateDreamLocked函數經過發送消息,最終會調用handleSandman:函數

[java] view plain copy
private void handleSandman() { // runs on handler thread  
    // Handle preconditions.  
    final boolean startDreaming;  
    final int wakefulness;  
    synchronized (mLock) {  
        mSandmanScheduled = false;  
        wakefulness = mWakefulness;  
        if (mSandmanSummoned && mDisplayReady) {  
            startDreaming = canDreamLocked() || canDozeLocked();  
            mSandmanSummoned = false;  
        } else {  
            startDreaming = false;  
        }  
    }  
  
    // Start dreaming if needed.  
    // We only control the dream on the handler thread, so we don't need to worry about  
    // concurrent attempts to start or stop the dream.  
    final boolean isDreaming;  
    if (mDreamManager != null) {  
        // Restart the dream whenever the sandman is summoned.  
        if (startDreaming) {  
            mDreamManager.stopDream(false /*immediate*/);  
            mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);  
        }  
        isDreaming = mDreamManager.isDreaming();  
    } else {  
        isDreaming = false;  
    }  
  
    // Update dream state.  
    synchronized (mLock) {  
        // Remember the initial battery level when the dream started.  
        if (startDreaming && isDreaming) {  
            mBatteryLevelWhenDreamStarted = mBatteryLevel;  
            if (wakefulness == WAKEFULNESS_DOZING) {  
                Slog.i(TAG, "Dozing...");  
            } else {  
                Slog.i(TAG, "Dreaming...");  
            }  
        }  
  
        // If preconditions changed, wait for the next iteration to determine  
        // whether the dream should continue (or be restarted).  
        if (mSandmanSummoned || mWakefulness != wakefulness) {  
            return; // wait for next cycle  
        }  
  
        // Determine whether the dream should continue.  
        if (wakefulness == WAKEFULNESS_DREAMING) {  
            if (isDreaming && canDreamLocked()) {  
                //在作夢中  
                if (mDreamsBatteryLevelDrainCutoffConfig >= 0  
                        && mBatteryLevel < mBatteryLevelWhenDreamStarted  
                                - mDreamsBatteryLevelDrainCutoffConfig  
                        && !isBeingKeptAwakeLocked()) {  
                    // If the user activity timeout expired and the battery appears  
                    // to be draining faster than it is charging then stop dreaming  
                    // and go to sleep.  
                    Slog.i(TAG, "Stopping dream because the battery appears to "  
                            + "be draining faster than it is charging.  "  
                            + "Battery level when dream started: "  
                            + mBatteryLevelWhenDreamStarted + "%.  "  
                            + "Battery level now: " + mBatteryLevel + "%.");  
                } else {  
                    //繼續作夢  
                    return; // continue dreaming  
                }  
            }  
  
            // Dream has ended or will be stopped.  Update the power state.  
            //結束作夢,要麼喚醒、要麼繼續goToSleep  
            if (isItBedTimeYetLocked()) {  
                goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),  
                        PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);  
                updatePowerStateLocked();  
            } else {  
                wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);  
                updatePowerStateLocked();  
            }  
        } else if (wakefulness == WAKEFULNESS_DOZING) {  
            if (isDreaming) {  
                return; // continue dozing  
            }  
            //直接睡眠,跳過作夢  
            // Doze has ended or will be stopped.  Update the power state.  
            reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);  
            updatePowerStateLocked();  
        }  
    }  
  
    // Stop dream.能走到這說明,確定結束作夢  
    if (isDreaming) {  
        mDreamManager.stopDream(false /*immediate*/);  
    }  
}  
updateSuspendBlockerLocked函數是是否要Cpu持鎖。oop

[java] view plain copy
private void updateSuspendBlockerLocked() {  
    final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//是否要cpu持鎖  
    final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();//是否display要持鎖  
    final boolean autoSuspend = !needDisplaySuspendBlocker;  
    final boolean interactive = mDisplayPowerRequest.isBrightOrDim();  
  
    // Disable auto-suspend if needed.  
    // FIXME We should consider just leaving auto-suspend enabled forever since  
    // we already hold the necessary wakelocks.  
    if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {  
        setHalAutoSuspendModeLocked(false);  
    }  
  
    // First acquire suspend blockers if needed.  
    if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {  
        mWakeLockSuspendBlocker.acquire();  
        mHoldingWakeLockSuspendBlocker = true;  
    }  
    if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {  
        mDisplaySuspendBlocker.acquire();  
        mHoldingDisplaySuspendBlocker = true;  
    }  
  
    // Inform the power HAL about interactive mode.  
    // Although we could set interactive strictly based on the wakefulness  
    // as reported by isInteractive(), it is actually more desirable to track  
    // the display policy state instead so that the interactive state observed  
    // by the HAL more accurately tracks transitions between AWAKE and DOZING.  
    // Refer to getDesiredScreenPolicyLocked() for details.  
    if (mDecoupleHalInteractiveModeFromDisplayConfig) {  
        // When becoming non-interactive, we want to defer sending this signal  
        // until the display is actually ready so that all transitions have  
        // completed.  This is probably a good sign that things have gotten  
        // too tangled over here...  
        if (interactive || mDisplayReady) {//當屏幕亮着|| 當屏幕暗着,displayPowerControl準備好了,進入該條件設置  
            setHalInteractiveModeLocked(interactive);  
        }  
    }  
  
    // Then release suspend blockers if needed.  
    if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {  
        mWakeLockSuspendBlocker.release();  
        mHoldingWakeLockSuspendBlocker = false;  
    }  
    if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {  
        mDisplaySuspendBlocker.release();  
        mHoldingDisplaySuspendBlocker = false;  
    }  
  
    // Enable auto-suspend if needed.  
    if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {  
        setHalAutoSuspendModeLocked(true);  
    }  
}  ui

下來介紹下powermanager中其餘的接口,
一、gotosleep,讓設備睡眠,按power鍵會調用這個函數
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {  
       synchronized (mLock) {  
           //返回true,才更新狀態  
           if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {  
               updatePowerStateLocked();  
           }  
       }  
   }  
  
   @SuppressWarnings("deprecation")  
   private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {  
       if (DEBUG_SPEW) {  
           Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime  
                   + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);  
       }  
  
       if (eventTime < mLastWakeTime  
               || mWakefulness == WAKEFULNESS_ASLEEP  
               || mWakefulness == WAKEFULNESS_DOZING  
               || !mBootCompleted || !mSystemReady) {  
           return false;  
       }  
  
       Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");  
       try {  
           switch (reason) {//說明緣由  
               case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:  
                   Slog.i(TAG, "Going to sleep due to device administration policy "  
                           + "(uid " + uid +")...");  
                   break;  
。。。。。。。。。。。。  
           }  
  
           mLastSleepTime = eventTime;  
           mSandmanSummoned = true;  
           setWakefulnessLocked(WAKEFULNESS_DOZING, reason);  
  
           // Report the number of wake locks that will be cleared by going to sleep.  
           //統計wakelock的數量  
           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.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;  
   }  
二、useractivity是當用戶點擊屏幕等行爲,會從新計算自動滅屏的時間等,而後回去updatepowerstate
三、wakeup喚醒設備,與gotosleep對應。
四、nap,使設備處於一種假寐的狀態
五、boostScreenBrightness,是屏幕達到最亮持續一段時間
這其中每一個函數都會調用updatepowerstatethis

相關文章
相關標籤/搜索