zoukankan      html  css  js  c++  java
  • Android中的BatteryService及相关组件

    转载时请注明出处和作者联系方式
    文章出处:http://www.limodev.cn/blog
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    BatteryService作为电池及充电相关的服务,它的实现非常简单:

    o 监听UEvent,读取sysfs里中的状态。

    实现了一个UEvent的观察者。uevent是Linux内核用来向用户空间主动上报事件的机制,对于JAVA程序来说,只实现UEventObserver的虚函数onUEvent,然后注册即可。

        private UEventObserver mUEventObserver = new UEventObserver() {
            @Override
            public void onUEvent(UEventObserver.UEvent event) {
                update();
            }
        };

    这里只关注power_supply的事件:

    mUEventObserver.startObserving("SUBSYSTEM=power_supply");

    当有power_supply相关的事件上报时,就会调用update函数。

    update先调用native_update从sysfs中读取相关状态(com_android_server_BatteryService.cpp):

    Linux驱动提供了下列文件,供应用程序获取电源相关状态:

    #define AC_ONLINE_PATH "/sys/class/power_supply/ac/online"
    #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online"
    #define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status"
    #define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health"
    #define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present"
    #define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity"
    #define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol"
    #define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp"
    #define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"

    在<DA9034驱动程序阅读笔记(6)>一文中,我已经提到drivers/power/micco_power.c里注册了充电器(ac)、 usb和电池(battery)三个power_supply。各个power_supply提供的属性和上述文件是对应的,从这些文件中可以读到充电器 (ac)、usb和电池(battery)三个power_supply的相应状态。

    update然后根据读到的状态更新BatteryService的成员变量,并广播一个Intent来通知其它关注电源状态的组件。

        private final void sendIntent() {
            //  Pack up the values and broadcast them to everyone
            Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            try {
                mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);
            } catch (RemoteException e) {
                // Should never happen.
            }
     
            int icon = getIcon(mBatteryLevel);
     
            intent.putExtra("status", mBatteryStatus);
            intent.putExtra("health", mBatteryHealth);
            intent.putExtra("present", mBatteryPresent);
            intent.putExtra("level", mBatteryLevel);
            intent.putExtra("scale", BATTERY_SCALE);
            intent.putExtra("icon-small", icon);
            intent.putExtra("plugged", mPlugType);
            intent.putExtra("voltage", mBatteryVoltage);
            intent.putExtra("temperature", mBatteryTemperature);
            intent.putExtra("technology", mBatteryTechnology);
     
            ActivityManagerNative.broadcastStickyIntent(intent, null);
        }

    关注ACTION_BATTERY_CHANGED的地方有好几个:

    o KeyguardUpdateMonitor 这里主要是用来更新锁屏界面下的电池状态。还有低电警告和关机也是在这里做的。

        private void handleBatteryUpdate(int pluggedInStatus, int batteryLevel) {
            if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
            final boolean pluggedIn = isPluggedIn(pluggedInStatus);
     
            if (isBatteryUpdateInteresting(pluggedIn, batteryLevel)) {
                mBatteryLevel = batteryLevel;
                mDevicePluggedIn = pluggedIn;
                for (int i = 0; i < mInfoCallbacks.size(); i++) {
                    mInfoCallbacks.get(i).onRefreshBatteryInfo(
                            shouldShowBatteryInfo(), pluggedIn, batteryLevel);
                }
            }
     
            // shut down gracefully if our battery is critically low and we are not powered
            if (batteryLevel == 0 &&
                    pluggedInStatus != BATTERY_STATUS_CHARGING &&
                    pluggedInStatus != BATTERY_STATUS_UNKNOWN) {
     
                ShutdownThread.shutdownAfterDisablingRadio(mContext, false);
     
            }
        }

    o NotificationManagerService 用来更新充电状态(LED)

                if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                    boolean batteryCharging = (intent.getIntExtra("plugged", 0) != 0);
                    int level = intent.getIntExtra("level", -1);
                    boolean batteryLow = (level >= 0 && level <= Power.LOW_BATTERY_THRESHOLD);
                    int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
                    boolean batteryFull = (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90);
     
                    if (batteryCharging != mBatteryCharging ||
                            batteryLow != mBatteryLow ||
                            batteryFull != mBatteryFull) {
                        mBatteryCharging = batteryCharging;
                        mBatteryLow = batteryLow;
                        mBatteryFull = batteryFull;
                        updateLights();
                    }
                }

    o PowerManagerService 这里主要是做两件事件,先是检查是否在充电时不允许睡眠,并采用相应的行动,其次是触发一个用户行为(会影响下一次睡眠的时间)。

        private final class BatteryReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                synchronized (mLocks) {
                    boolean wasPowered = mIsPowered;
                    mIsPowered = mBatteryService.isPowered();
     
                    if (mIsPowered != wasPowered) {
                        // update mStayOnWhilePluggedIn wake lock
                        updateWakeLockLocked();
     
                        // treat plugging and unplugging the devices as a user activity.
                        // users find it disconcerting when they unplug the device
                        // and it shuts off right away.
                        // temporarily set mUserActivityAllowed to true so this will work
                        // even when the keyguard is on.
                        synchronized (mLocks) {
                            boolean savedActivityAllowed = mUserActivityAllowed;
                            mUserActivityAllowed = true;
                            userActivity(SystemClock.uptimeMillis(), false);
                            mUserActivityAllowed = savedActivityAllowed;
                        }
                    }
                }
            }
        }

    o LocationManagerService 这里似乎没有什么用处,我没找到mCollector赋值的地方。

                 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                    log("PowerStateBroadcastReceiver: Battery changed");
                    synchronized (mLocationListeners) {
                        int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100);
                        int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0);
                        boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0;
     
                        // Notify collector battery state
                        if (mCollector != null) {
                            mCollector.updateBatteryState(scale, level, plugged);
                        }
                    }
                }

    o WifiService 根据电源状态来决定是否需要定时唤醒(没搞得太明白,看Wifi服务时再研究)。

    if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                    /*
                     * Set a timer to put Wi-Fi to sleep, but only if the screen is off
                     * AND we are transitioning from a state in which the device was supposed
                     * to stay awake to a state in which it is not supposed to stay awake.
                     * If "stay awake" state is not changing, we do nothing, to avoid resetting
                     * the already-set timer.
                     */
                    int pluggedType = intent.getIntExtra("plugged", 0);
                    if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
                            !shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
                        long triggerTime = System.currentTimeMillis() + idleMillis;
                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                        mPluggedType = pluggedType;
                        return;
                    }
                    mPluggedType = pluggedType;
                }

    o StatusBarPolicy用来更新状态栏上的充电图标。

    if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                    updateBattery(intent);
                }

  • 相关阅读:
    修复grub引导Centos8和Windows
    少儿编程到底学什么?
    Windows平台最方便最易用的法语输入法
    ServiceStack.OrmLite 入门(一)
    起步:Proteus 8 仿真 Arduino 1.8.2
    命令行方式登录PostgreSQL
    CentOS 7 安装 PostgreSQL
    Twitter开源的Heron快速安装部署教程
    centos7下使用yum安装mysql
    [转]centos7 下安装MongoDB
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167454.html
Copyright © 2011-2022 走看看