Android 4.2 两个电池解决方案

         最近做个项目用到2个电池的系统,一个内部电池,一个外部电池。内部电池和普通Android系统没什么区别,外部电池实际上是作为AC的形式,但是用了一个CW2015的芯片来读取电量,并且要求能在系统中显示出来。

         由于Android原生只支持一个电池,因此需要修改系统才行。此项目选择在原有电池管理系统基础上修改来实现。下面先简单分析下Android电池管理的架构。

          Android电池管理分为服务端和客户端,下面做下简单分析。

          服务端通过JNI读取Linux 内核电池文件节点,然后更新电池信息,发送一个ACTION,ACTION里就带有电池信息的Intent,客户端注册接收此ACTION的广播接收器,接收处理并显示在状态栏(statusbar)上。

          服务端由如下2个文件组成:

                      JNI 部分:

                       frameworks/base/services/jni/com_android_server_BatteryService.cpp

                       Service部分:

                       frameworks/base/services/java/com/android/server/BatteryService.java
            此电池服务是作为系统服务运行的。

  

  

            客户端由如下文件组成:

             frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java

             客户端是SystemUI的一部分。


 

             PS:由于Android系统并不支持双电池系统,不过Linux内核支持UPS,所以在电池的驱动里把类型改为如下,其余的没有需要特别改的地方:

             cw_bat->rk_bat.type = POWER_SUPPLY_TYPE_UPS;
             这个在后面的Android系统修改中需要用到。
          

     

             

             ::::下面来一步步增加外部电池的部分。

                              1:把BatteryController.java文件复制一份,命名为ExtBatteryController.java ,然后按照java类的要去更改ExtBatteryController.java 为合法,不要问我改哪 里, 难道类名和构造函数名不改?

                              2:在/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ PhoneStatusBar.java文件 的

                                   BatteryController mBatteryController;

                                   这行下面增加一行:

                                   ExtBatteryController mExtBatteryController;

                                   实际就是在类里增加这个变量。

                                    然后在此文件里的protected PhoneStatusBarView makeStatusBarView()函数的下面3行后面

                                        mLocationController = new LocationController(mContext); // will post a notification
                                        mBatteryController = new BatteryController(mContext);
                                        mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));

                                        增加如下3行(位于636行左右)

                                        mExtBatteryController = new ExtBatteryController(mContext);
                                        mExtBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.extbattery));
                                        mExtBatteryController.addLabelView((TextView)mStatusBarView.findViewById(R.id.extbattery_label));

                                        这里的R.id.extbattery   R.id.extbattery_label 是下面第三步需要在布局文件里定义的。

                               3:更改布局文件

                                    在如下文件frameworks/base/packages/SystemUI/res/layout/status_bar.xml 的如下内如前面(位于98行左右)

                                         <ImageView
                                          android:id="@+id/battery"
                                          android:layout_height="wrap_content"
                                          android:layout_width="wrap_content"
                                          android:paddingLeft="4dip"
                                          />
                                     增加如下内容:

                                       <TextView
                                          xmlns:android="http://schemas.android.com/apk/res/android"    
                                          android:id="@+id/extbattery_label"
                                          android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network"
                                          android:layout_height="match_parent"
                                          android:layout_width="match_parent"
                                          android:layout_gravity="bottom"
                                          android:gravity="center"
                                         />
                                       <ImageView
                                          android:id="@+id/extbattery"
                                          android:layout_height="wrap_content"
                                          android:layout_width="wrap_content"
                                          android:paddingLeft="4dip"
                                          />

                                     看上面的id就是前面在PhoneStatusBar.java文件里用到的。

                                      这个时候保存,然后编译后应该可以看见2个电池图标,并在2个电池图标的左边会有一个显示电池百分比的位置,不过这时显示的还是内部电池的信息。

                               4:增加服务端

                                      JNI 部分=====================================:

                                     复制frameworks/base/services/jni/com_android_server_BatteryService.cpp 为com_android_server_ExtBatteryService.cpp 并作如下更改

                                     199行:------------------------

                                                  static void android_server_BatteryService_update(JNIEnv* env, jobject obj)

                                                  改为:static void android_server_ExtBatteryService_update(JNIEnv* env, jobject obj)

                                     228行:------------------------

                                                        {"native_ext_update", "()V", (void*)android_server_BatteryService_update},

                                                 改为:    {"native_ext_update", "()V", (void*)android_server_ExtBatteryService_update},

                                     231行:-------------------------

                                                         int register_android_server_BatteryService(JNIEnv* env)
                                                 改为:  int register_android_server_ExtBatteryService(JNIEnv* env)


                                     271行:--------------------------

                                                        else if (strcmp(buf, "battery") == 0) {

                                                   改为 : else if (strcmp(buf, "UPS") == 0) {

                                                   这里就是因为在Linux驱动里把电池类型定义为UPS的原因了。

                                    335行:---------------------------

                                                       jclass clazz = env->FindClass("com/android/server/BatteryService");

                                                  改为:jclass clazz = env->FindClass("com/android/server/ExtBatteryService");

                                                  PS:这里是为ExtBatteryService类服务的,不是,BatteryService,所以必须改。

                                 /*下面是JNI加载的时候调用的部分*/

                                 然后更改当前路径下的onload.cpp文件里的android命名空间里(25行左右)增加如下语句:

                                                    int register_android_server_ExtBatteryService(JNIEnv* env);
                                 再在extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {   函数里得初始化地方(64行左右)增加如下语句:
                                                  register_android_server_ExtBatteryService(env);

                                   最后在当前目录下的Android.mk文件里增加编译刚增加的文件的语句,不要告诉我不会,我也不会。

                                

                              JAVA 部分==================================

                              复制frameworks/base/services/java/com/android/server/BatteryService.java 文件为 ExtBatteryService.java,并更改类名。

                                    并更改如下:

                                     146行:---------------------------

                                                  private native void native_update();

                                                 改为:private native void native_ext_update();

                                    280行:---------------------------

                                                 native_update();

                                                 改为:native_ext_update();


                            更改当前目录下得SystemServer.java文件以注册此新服务:

                                    130行左右:----------------------------

                                                 增加:ExtBatteryService extbattery = null;

                                   292行左右:----------------------------

                                                增加:Slog.i(TAG, "extBattery Service");
                                                            extbattery = new ExtBatteryService(context, lights);
                                                           ServiceManager.addService("extbattery", extbattery);

                                  866行左右:------------------------------

                                               增加:final ExtBatteryService extbatteryF = extbattery;

                                                   

                              总结:到这里基本上的更改就已经完成了。  

                                

                                不过现在是不能正常工作的,因为内部电池和外部电池的服务端都发送的Intent.ACTION_BATTERY_CHANGED 这个广播,因此肯定会造成冲突,最后内部电池不做更改,外部电池我们新定义一个广播,取名为:"ACTION.EXTBATTERY_CHANGED",然后在外部电池服务里发送这个广播,在外部电池的客户端里接收这个广播,一切都好了,本项目在Android 4.2 Rockchip 3188项目上测试成功。


                                PS:至于在更改JAVA文件的时候需要导入相应的包的代码没有添加,请自行添加,不要告诉我不会,我也不会。


 

;