第四章:Android灯光系统(4)-电池灯

通过前面几个小节,我们编写了灯光系统的驱动程序以及Hal文件,并且实现了我们想要的功能。 下面我们将对源码中的电池灯进行分析,然后编写我们的APP程序。当然在这之前我们先分析一下电池灯的使用过程:我们知道驱动程序是不会主动做任何事情的,所以肯定有一个应用程序去访问驱动程序,那么这个程序当然是我们的APP程序,他会通过open或者read获得电池状态。在我们使用手机的时候,如果电量过低,会出现电量不足请充电的提示框,如果我们没有及时充电,过一段时间之后,可能就会出现多少秒之后自动关机的提示框。假设这些操作都是另外一个APP实现的,那么他怎么知道电量过低呢?之前那个获取电量的APP通知他的。一般过程如下(假设有多个APP,其中APP0为能和硬件交互的程序):

1.  APP0:读取驱动,当检测到电池事件发生,唤醒APP0。
2.  APP1,2,3注册通知响应函数,表示他对电池事件感兴趣。
3.  当APP0检测到电池事件发生时,会发送通知给关注电池事件的APP
4.  APP1,2,3执行通知对应的函数

下面我们将对源码进行分析,看看是否如此

电池灯源码分析

在上一节中, 我们简单的分析了源码中BatteryService.java文件,我们知道对电池灯的操作,都集中在updateLightsLocked()函数中, 现在我们打开AS,使用Ctrl+Shift+N查找文件BatteryService.java,然后通过索引寻找到updateLightsLocked()函数,我们选中updateLightsLocked右击然后再选择Find Usage(快捷键Ctrl+Alt+F7)查看该方法在那些地方被引用了。我们可以看到,他只在mLed.updateLightsLocked()处被引用了,其引用他的方法为private void processValuesLocked(boolean force)
,该为一个私有方法,只能在本内中使用,使用快捷键(Ctrl+R),然后查找processValuesLocked,看该方法在那些地方被调用,通过从方法名筛选,我们可以找到update(BatteryProperties props)方法,然后我们再搜索
update方法,找到如下:

    private final class BatteryListener extends IBatteryPropertiesListener.Stub {
        @Override public void batteryPropertiesChanged(BatteryProperties props) {
            final long identity = Binder.clearCallingIdentity();
            try {
                BatteryService.this.update(props);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
       }
    }

从类名我们可以知道,这是一个电池监听器,我们继续搜索BatteryListener,看他在那些地方被使用,最终我们可以找到

 	batteryPropertiesRegistrar.registerListener(new BatteryListener());

这个方法应该就是我们前面提到过的注册函数,现在假设注册之后,肯定会导致BatteryListener类中的方法被调用,其中只有一个方法为batteryPropertiesChanged(),从方法名我们可以知道,当电池的属性改变时,应该就会调用该函数,然后该函数会调用update(props)方法,然后在该方法中调用processValuesLocked()处理force(电量),我们可以在processValuesLocked()方法中找到sendIntentLocked(),这个函数发送一个广播消息,应该发送给对这个事件关注的APP,即注册电池事件的APP。继续往查看,可以看到mLed.updateLightsLocked()代码,调用了更新灯光的方法。

我再到过来看看sendIntentLocked()方法:

    private void sendIntentLocked() {
        //  Pack up the values and broadcast them to everyone
        final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);

我们在源码中搜索ACTION_BATTERY_CHANGED,然后可以找到PowerManagerService.java 文件,从文件名名上看,电源管理服务,那么他应该对电池的状态肯定是感兴趣的:

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

当电池的电量改变的时候,会调用BatteryReceiver()方法,其内部调用过程如下

	BatteryReceiver()
		handleBatteryStateChangedLocked()
			updatePowerStateLocked()

最终的updatePowerStateLocked或许可能导致手机重启,当然也可能仅仅是个提示。通过以上分析,其电池灯的使用过程,大致如下所示:
在这里插入图片描述
前面的分析中,我们没有简介对硬件的操作部分,上小节我们提到过面对硬件的操作,都在BatteryService.java
文件中的updateLightsLocked()方法(已经进行删减):

    public void updateLightsLocked() {
		......
           mBatteryLight.setColor(mBatteryLowARGB);
           mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
                 	mBatteryLedOn, mBatteryLedOff);
           mBatteryLight.setColor(mBatteryFullARGB);
           mBatteryLight.setColor(mBatteryMediumARGB);
    	   tteryLight.turnOff();
	}

可以看到有一个重要的类- mBatteryLight,其定义为private final Light mBatteryLight,那么他是怎么获得一个Light类的呢?

	 mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);

在LightsManager.java文件中,我们看到 public abstract Light getLight(int id),则 getLight为一个抽象函数,既然要使用这个抽象方法,那么肯定有一个类继承了他,然后重写了该方法。在LightsService.java文件中

    private final LightsManager mService = new LightsManager() {
        @Override
        public Light getLight(int id) {
            if (id < LIGHT_ID_COUNT) {
                return mLights[id];
            } else {
                return null;
            }
        }
    };

然后我们在LightsService.java文件中,查看mService被怎么使用:

    @Override
    public void onStart() {
        publishLocalService(LightsManager.class, mService);
    }

注册了一个mService,那么肯定有其他方法在需要的地方获取了这个mService,那么获取这个Service就是前面的ights.getLight(LightsManager.LIGHT_ID_BATTERY)方法了。

小节结语

该小节,我们主要分析了电池灯的实现过程,已经APP之间是怎么实现通信的,下小节我们编写我们自己的APP,实现对灯灯光的控制。

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/87178806