Android 6.0 PowerManagerService 一

SystemServer.java

startBootstrapServices 函数中

  mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);


SystemServer创建完PowerManagerService后,继续调用SystemReady方法,再做一些初始化的工作

            mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());

PowerManagerService.java

PowerManagerService构造函数

    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");//通过JNI调用底层的wakelock函数
               mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");  
               mDisplaySuspendBlocker.acquire();//持锁防止cpu睡眠  
               mHoldingDisplaySuspendBlocker = true;  
               mHalAutoSuspendModeEnabled = false;  
               mHalInteractiveModeEnabled = true;  
      
               mWakefulness = WAKEFULNESS_AWAKE;//系统正常运行状态  
      
               nativeInit();  
               nativeSetAutoSuspend(false);  
               nativeSetInteractive(true);  
               nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);  
           }  
       } 

systemReady

public void systemReady(IAppOpsService appOps) {
        synchronized (mLock) {
            mSystemReady = true;
            mAppOps = appOps;
            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 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);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.DOUBLE_TAP_TO_WAKE),
                    false, mSettingsObserver, UserHandle.USER_ALL);
            // Go.
            readConfigurationLocked();
            updateSettingsLocked();
            mDirty |= DIRTY_BATTERY_STATE;
            updatePowerStateLocked();
        }
    }

从在android5.1.1中,service一般都会继承一个虚类SystemService,在其中定义了两个接口onStart和onBootPhase,分别是PowerManagerService启动的时候会调用,而onBootPhase会在系统启动的各个阶段来调用,下面我们分别来看看在powerManagerService中这两个函数的实现:

@Override
    public void onStart() {
        publishBinderService(Context.POWER_SERVICE, new BinderService());//publish service
        publishLocalService(PowerManagerInternal.class, new LocalService());//publish local service

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


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,当距离传感器被遮挡,屏幕将被关闭。打电话时用这个功能


acquieWakeLock

在PowerManagerService中的acquieWakeLock先要检查权限然后调用acquireWakeLockInternal接口

@Override // Binder call
        public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
                WorkSource ws, String historyTag) {
            if (lock == null) {
                throw new IllegalArgumentException("lock must not be null");
            }
            if (packageName == null) {
                throw new IllegalArgumentException("packageName must not be null");
            }
            PowerManager.validateWakeLockParameters(flags, tag);

            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
            if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
                mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
            }
            if (ws != null && ws.size() != 0) {
                mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.UPDATE_DEVICE_STATS, null);
            } else {
                ws = null;
            }

            final int uid = Binder.getCallingUid();
            final int pid = Binder.getCallingPid();
            final long ident = Binder.clearCallingIdentity();
            try {
                acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

acquireWakeLockInternal

private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,  
               WorkSource ws, String historyTag, int uid, int pid) {  
           synchronized (mLock) {  
               if (DEBUG_SPEW) {  
                   Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)  
                           + ", flags=0x" + Integer.toHexString(flags)  
                           + ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);  
               }  
      
               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);  
                   setWakeLockDisabledStateLocked(wakeLock);  
                   notifyAcquire = true;  
               }  
      
               applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);//看是否需要点亮屏幕
               mDirty |= DIRTY_WAKE_LOCKS;//PowermanagerService用来记录各个状态变化的一个标志位 
               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

releaseWakeLockInternal

 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.mLock.unlinkToDeath(wakeLock, 0);
            removeWakeLockLocked(wakeLock, index);
        }
    }

PowerManagerService中最终各个接口都会调一个函数updatePowerStateLocked,主要用来更新power的各个状态 

updatePowerStateLocked

    /** 
        * Updates the global power state based on dirty bits recorded in mDirty. 
        * 
        * This is the main function that performs power state transitions. 
        * We centralize them here so that we can recompute the power state completely 
        * each time something important changes, and ensure that we do it the same 
        * way each time.  The point is to gather all of the transition logic here. 
        */  
       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;  
      
                   updateWakeLockSummaryLocked(dirtyPhase1);  
                   updateUserActivitySummaryLocked(now, dirtyPhase1);  
                   if (!updateWakefulnessLocked(dirtyPhase1)) {  
                       break;  
                   }  
               }  
      
               // Phase 2: Update display power state.  
               //更新display状态,在displaypowercontrol中会控制亮度,灭屏等
              boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);  
      
               // Phase 3: Update dream state (depends on display ready signal).  
               updateDreamLocked(dirtyPhase2, displayBecameReady);//更新梦的状态,用dreammanager控制梦,powermanagerservice中记录mWakefulness 
               // Phase 4: Send notifications, if needed.  
               finishWakefulnessChangeIfNeededLocked();  
      
               // 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);  
           }  
       }


省电模式

updateLowPowerModeLocked

    void updateLowPowerModeLocked() {
        if (mIsPowered && mLowPowerModeSetting) {//如果当前插着电源,并且mLowPowerModeSetting为true。也是不能开启低功耗的,将其改为fasle,存入setting
            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateLowPowerModeLocked: powered, turning setting off");
            }
            // Turn setting off if powered
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.LOW_POWER_MODE, 0);
            mLowPowerModeSetting = false;
        }
        final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured//自动模式开启需要四个。没有充电、开启自动配置、mAutoLowPowerModeSnoozing为false、低电量
                && !mAutoLowPowerModeSnoozing && mBatteryLevelLow;
        final boolean lowPowerModeEnabled = mLowPowerModeSetting || autoLowPowerModeEnabled;//主动的低电量模式只要开启,不在充电就可以了;主动模式和自动模式两者满足其一,就开启低电量模式

        if (mLowPowerModeEnabled != lowPowerModeEnabled) {
            mLowPowerModeEnabled = lowPowerModeEnabled;
            powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);//将低功耗模式,以及是否开启通过JNI,到hardware的power模块,但是我们hardware的power模块好像还不支持低功耗模式
            BackgroundThread.getHandler().post(new Runnable() {//在消息线程里面处理
                @Override
                public void run() {
                    Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)//发送正在处理低功耗的广播
                            .putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, mLowPowerModeEnabled)
                            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                    mContext.sendBroadcast(intent);
                    ArrayList listeners;
                    synchronized (mLock) {
                        listeners = new ArrayList(
                                mLowPowerModeListeners);
                    }
                    for (int i=0; i

通过binder接口setPowerSaveMode设置低功耗模式

        @Override // Binder call
        public boolean setPowerSaveMode(boolean mode) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            final long ident = Binder.clearCallingIdentity();
            try {
                return setLowPowerModeInternal(mode);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

    private boolean setLowPowerModeInternal(boolean mode) {
        synchronized (mLock) {
            if (DEBUG) Slog.d(TAG, "setLowPowerModeInternal " + mode + " mIsPowered=" + mIsPowered);
            if (mIsPowered) {
                return false;
            }
            Settings.Global.putInt(mContext.getContentResolver(),//将手动模式保存
                    Settings.Global.LOW_POWER_MODE, mode ? 1 : 0);
            mLowPowerModeSetting = mode;

            if (mAutoLowPowerModeConfigured && mBatteryLevelLow) {//如果自动模式开启,并且低电量的时候
                if (mode && mAutoLowPowerModeSnoozing) {
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "setLowPowerModeInternal: clearing low power mode snooze");
                    }
                    mAutoLowPowerModeSnoozing = false; //这个参数为false,是自动低功耗模式开启的必要条件
                } else if (!mode && !mAutoLowPowerModeSnoozing) {
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "setLowPowerModeInternal: snoozing low power mode");
                    }
                    mAutoLowPowerModeSnoozing = true;
                }
            }

            updateLowPowerModeLocked();//更新低功耗模式
            return true;
        }
    }

低功耗模式可以通过setPowerSaveMode接口设置,也可以通过Setting中的数据库监听来设置。


而当省电模式改变时,又有两种模式通知,一种是发广播,另一种的通知回调。上面在updateLowPowerModeLocked已经有描述。

注册回调的接口

        @Override
        public void registerLowPowerModeObserver(LowPowerModeListener listener) {
            synchronized (mLock) {
                mLowPowerModeListeners.add(listener);
            }
        }

因为是LocalService的接口只能是SystemServer注册的。

下面我们来看看到底会通知那些服务或者应用。

1.回调通知

在NetworkPolicyManagerService会监听,进入省电模式后,网络切断。

BatteryStatsService、VibratorService、WindowManagerService(不放动画)也会处理。

2.广播通知

而广播的是GpsLocationProvider(关闭Gps),PowerUI(显示通知栏等)、声音处理等。

你可能感兴趣的:(Android,电源管理)