由于项目需要,我们的android手机及上网本都需要做一个电池的电量检测与电池管理,所以,在开始动手做这一块之前,先整理一下电源管理方面的资料。

 

      首先,看看一下电源芯片驱动在内核的位置:kernel/driver/power/ 路径下,看了一下samsung I9000kernel用的是max17040+max8989max1740I2C接口,需要烧写一些寄存器和通过读写寄存器来获取电池的信息,max8998则是通过控制它的GPIO口来工作。两者相互协调完成底层电源管理的驱动,通过接口与android的中间层交互。里注册了充电器(ac) usb和电池(battery)三个power_supply。各个power_supply提供的属性和上述文件是对应的,从这些文件中可以读到充电器 (ac)usb和电池(battery)三个power_supply的相应状态。

 

BatteryService作为电池及充电相关的服务

 

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

 

实现了一个UEvent的观察者。ueventLinux内核用来向用户空间主动上报事件的机制,对于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_updatesysfs中读取相关状态(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"

 

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

 

BatteryService.java

 

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(BatteryManager.EXTRA_STATUS, mBatteryStatus);

 

        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);

 

        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent);

 

        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel);

 

        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);

 

        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);

 

        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);

 

        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage);

 

        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature);

 

        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);

 

 

        if (false) {

 

            Log.d(TAG, "updateBattery level:" + mBatteryLevel +

 

                    " scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +

 

                    " health:" + mBatteryHealth +  " present:" + mBatteryPresent +

 

                    " voltage: " + mBatteryVoltage +

 

                    " temperature: " + mBatteryTemperature +

 

                    " technology: " + mBatteryTechnology +

 

                    " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +

 

                    " icon:" + icon );

 

        }

 

        ActivityManagerNative.broadcastStickyIntent(intent, null);

    }

 

kernel将所得到的电池信息放到/sys/class/power_supply/Battery中,通过frameworks/base/services/jni文件夹下的com_android_server_BatteryService.cpp进行读取。

 

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

 

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

 

 下面我们看一下总路径的定义:

 

#define POWER_SUPPLY_PATH "/sys/class/power_supply"注意是与上面kernel路径相对应的。

 

int register_android_server_BatteryService(JNIEnv* env)中对每个特定路径赋值

 

如给定batteryCapacityPath的路径:

 

snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, name);

 

                if (access(path, R_OK) == 0)

 

                    gPaths.batteryCapacityPath = strdup(path);

 

最后在static void android_server_BatteryService_update(JNIEnv* env, jobject obj)中读取路径文件中的信息

 

setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);

 

关于ACTION_BATTERY_CHANGED的地方有好几个:

 

BatteryService.java

 

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

 else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

 

                updateBattery(intent);

 

            }

 

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

 

    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {

 

        @Override

 

        public void onReceive(Context context, Intent intent) {

 

            String action = intent.getAction();

 

 

 

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

 

                }

 

            } else if (action.equals(Intent.ACTION_UMS_CONNECTED)) {

 

                mUsbConnected = true;

 

                updateAdbNotification();

 

            } else if (action.equals(Intent.ACTION_UMS_DISCONNECTED)) {

 

                mUsbConnected = false;

 

                updateAdbNotification();

 

            } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)

 

                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {

 

                Uri uri = intent.getData();

 

                if (uri == null) {

 

                    return;

 

                }

 

                String pkgName = uri.getSchemeSpecificPart();

 

                if (pkgName == null) {

 

                    return;

 

                }

 

                cancelAllNotificationsInt(pkgName, 0, 0);

 

            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {

 

                mScreenOn = true;

 

                updateNotificationPulse();

 

            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {

 

                mScreenOn = false;

 

                updateNotificationPulse();

 

            }

 

        }

 

    };

 

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

    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) {

 

                        forceUserActivityLocked();

 

                    }

 

                }

 

            }

 

        }

WifiService.java 根据电源状态来决定是否需要定时唤醒

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;

 

            }

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

  /**

     * Handle {@link #MSG_BATTERY_UPDATE}

     */

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

            }

        }

    }

 

在我们的开发板上AC是由美信的max8677控制,而DC是由美信的DS2784控制。

 

更多相关文章

  1. Android(安卓)定位服务
  2. Android(安卓)仿2016版京东筛选
  3. android 4.4 电池电量管理底层分析(C\C++层)
  4. Android状态栏功能介绍
  5. Android托管c++的log
  6. Android获取内置sdcard跟外置sdcard路径
  7. Android(安卓)获取本机的mac和wifi的BSSID(mac)以及其他信息
  8. Android用户事件输入路径
  9. Eclipse Android(安卓)SDK content Loader一直显示为0%的问题

随机推荐

  1. Android(安卓)Asynctask与Handler的比较,
  2. helloPe的android项目实战之连连看—设计
  3. android ui事件处理分析
  4. 【Android语音合成TTS】国内主流引擎对比
  5. android实现登录,Login姿势对不对?
  6. android中使用startActivityForResult回
  7. Android(安卓)数据库更新 onupgrade
  8. android之AsyncTask异步加载的简介(一)
  9. SwitchButton 开关按钮 的多种实现方式 (
  10. Android(安卓)TextView标点符号换行问题(