电池及充电相干的服务BatteryService的实现

来源:互联网 发布:自学编程的视频网站 编辑:程序博客网 时间:2024/05/22 05:17
电池及充电相关的服务BatteryService的实现
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),
"native_update"=>android_server_BatteryService_update:

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);
            }

一、BATTERY相关广播

1.Intent.ACTION_BATTERY_CHANGED  电量状态更新

包括下面的信息。

    “status”(int类型)…状态,定义值是BatteryManager.BATTERY_STATUS_XXX。

    “health”(int类型)…健康,定义值是BatteryManager.BATTERY_HEALTH_XXX。

    “present”(boolean类型)

    “level”(int类型)…电池剩余容量

    “scale”(int类型)…电池最大值。通常为100。

    “icon-small”(int类型)…图标ID。

    “plugged”(int类型)…连接的电源插座,定义值是BatteryManager.BATTERY_PLUGGED_XXX。

    “voltage”(int类型)…mV。

    “temperature”(int类型)…温度,0.1度单位。例如 表示197的时候,意思为19.7度。 

    “technology”(String类型)…电池类型,例如,Li-ion等等。



2.Intent.ACTION_BATTERY_LOW  //表示电池电量低

3.Intent.ACTION_BATTERY_OKAY  //表示电池电量充足,即从电池电量低变化到饱满时会发出广播



二、监听UEventObserver,读取sysfs里中的状态

private UEventObserver mUEventObserver = new UEventObserver() {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
           String strOnline = event.get("POWER_SUPPLY_ONLINE");   //电源连接状态
           String strBatteryState = event.get("POWER_SUPPLY_STATUS");  

                                        //电池状态,"Discharging","Charging","Not charging","Full","Unknown"
           String strBatteryLevel = event.get("POWER_SUPPLY_CAPACITY");   //电池剩余容量

           ...

        }

  }

1.BatteryService通过JNI(com_android_server_BatteryService.cpp)读取数据。BatteryService通过JNI注册的不仅有函数,还有变量。 如下:
  //##############在BatteryService.java中声明的变量################
  private boolean mAcOnline;
    private boolean mUsbOnline;
  private int mBatteryStatus;
  private int mBatteryHealth;
  private boolean mBatteryPresent;
  private int mBatteryLevel;
  private int mBatteryVoltage;
  private int mBatteryTemperature;
  private String mBatteryTechnology;

2.在BatteryService.java中声明的变量,在com_android_server_BatteryService.cpp 中共用,即在com_android_server_BatteryService.cpp中其实操作的也是BatteryService.java中声明的变量
  gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
  gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");
  gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");
  gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");
  gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");
  gFieldIds.mBatteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
  gFieldIds.mBatteryTechnology = env->GetFieldID(clazz, "mBatteryTechnology", "Ljava/lang/String;");
  gFieldIds.mBatteryVoltage = env->GetFieldID(clazz, "mBatteryVoltage", "I");
    gFieldIds.mBatteryTemperature = env->GetFieldID(clazz, "mBatteryTemperature", "I");

3.上面这些变量的值,对应是从下面的文件中读取的,一个文件存储一个数值。
    #define AC_ONLINE_PATH "/sys/class/power_supply/ac/online"     AC电源连接状态
    #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online"   USB电源连接状态
  #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"   电池level
  #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"   电池技术


android\kernel\kernel\drivers\power\88pm860x_battery.c
pm860x_changed_work
struct pm860x_battery_info *info = container_of(work,
  struct pm860x_battery_info, changed_work.work);

pm860x_update_charge_state(info);

power_supply_changed(&info->battery);
MONITOR_INTERVAL
原创粉丝点击