Android 6.0 PowerManagerService 一

来源:互联网 发布:java实验fan 编辑:程序博客网 时间:2024/05/16 19:01

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();            <span><span class="comment">//创建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<PowerManagerInternal.LowPowerModeListener> listeners;                    synchronized (mLock) {                        listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(                                mLowPowerModeListeners);                    }                    for (int i=0; i<listeners.size(); i++) {                        listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);//这里也是像MountService中一样是注册的各个回调,后续去看看都有谁注册了这些回调。                    }                    intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);//发送低功耗处理完了的广播                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);                    mContext.sendBroadcast(intent);                }            });        }    }

通过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(显示通知栏等)、声音处理等。

0 0
原创粉丝点击