Android5.0 framework 灯光系统 -- 电池灯源码分析

本文详细解析了Android系统中电池灯的控制流程,从启动SystemService到调用JNI、HAL直至控制Linux驱动,实现电池灯的不同状态显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文章分析Android系统中,灯光系统如何调用灯光服务、JNI、HAL等从而操控底层Linux驱动控制的led电池灯去闪烁或者亮不同颜色的灯来通知用户。

不扯别的,直接上图,简单描述整个调用过程:
这里写图片描述

以下是详细调用过程:
1. 首先Android系统加载后会执行init进程,然后加载SystemService.java系统服务
SystemService.java

private void startCoreServices() {
    // Manages LEDs and display backlight.
    mSystemServiceManager.startService(LightsService.class);

    // Tracks the battery level.  Requires LightService.
    mSystemServiceManager.startService(BatteryService.class);
}

private void startBootstrapServices() {
    /* 加载电源管理服务,灯光系统属于电源管理的一部分 */
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
}

2 . mSystemServiceManager.startService(LightsService.class);
调用LightsService.java的onStart方法,开启一个LightsManager服务。
LightsManager服务用来管理所有的灯光,包括电池灯、通知灯、背光灯。当需要控制这些灯的时候就需要getLocalService获取这个服务,然后调用这个服务的getLight方法,传入对应的灯的id(参考lighs.h)就可以获取对应的灯的实例化对象,从而可以通过这个对象获取对象里面的操作各种灯的方法。
LightsService.java

//实例化多个LightImpl对象,分别对应电池灯、通知灯、背光灯,通过getLight方法传入不同的id就可以获取对应的对象
final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
public void onStart() {
    publishBinderService("hardware", mLegacyFlashlightHack);
    publishLocalService(LightsManager.class, mService);
}

private final LightsManager mService = new LightsManager() {
    @Override
    public com.android.server.lights.Light getLight(int id) {
        if (id < LIGHT_ID_COUNT) {
            return mLights[id];
        } 
    }
};

LightImpl继承了Light这个抽象类,并实现了抽象类的setBrightness  setColor  setFlashing等抽象方法,这些方法最终都调用了setLightLocked方法,而setLightLocked方法最终有调用了JNI提供的接口setLight_native
private final class LightImpl extends Light {
        private LightImpl(int id) {
            mId = id;
        }

        @Override
        public void setBrightness(int brightness) {
            setBrightness(brightness, BRIGHTNESS_MODE_USER);
        }

        @Override
        public void setBrightness(int brightness, int brightnessMode) {
            setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
        }

        @Override
        public void setColor(int color) {
            setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
        }

        @Override
        public void setFlashing(int color, int mode, int onMS, int offMS) {
            setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
        }

        @Override
        public void turnOff() {
            setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
        }

        private void stopFlashing() {
            setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
        }

        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
            setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
        }
}

2.1 JNI:
关于JNI调用HAL再调用Linux驱动的细节请参考我的博客:http://blog.youkuaiyun.com/hanp_linux/article/details/76590527
com_android_server_lights_LightsService.cpp

static JNINativeMethod method_table[] = {
    { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
};

/* 从HAL获取hw_module_t结构体,在根据hw_module_t结构体获取一个battery对应的light_device_t结构体 */
hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
devices->lights[LIGHT_INDEX_BATTERY] = get_device(module, LIGHT_ID_BATTERY);
static void setLight_native(JNIEnv *env, jobject clazz, jlong ptr, jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
    devices->lights[light]->set_light(devices->lights[light], &state);

}

2.2. HAL:
lights.c

if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
    /* 当充电时,低电量,中电量,和满分别让不同颜色的灯亮或者闪烁 */
    set_light = set_light_battery;
}
static int set_light_battery (struct light_device_t *dev, struct light_state_t const* state) {                   
     write_int (const char *path, int value) {       //调用Linux底层驱动
         fd = open(path, O_RDWR);
         write (fd, buffer, bytes);
   }
}

3 . mSystemServiceManager.startService(BatteryService.class);
此时,会调用BatteryService.java的onStart方法。
BatteryService.java

BatteryService的构造方法:
public BatteryService(Context context) {
    mHandler = new Handler(true /*async*/);
    /* 获取第2章分析注册的publishLocalService(LightsManager.class, mService);服务 */
    mLed = new Led(context, getLocalService(LightsManager.class));     
}

public Led(Context context, LightsManager lights) {
    /* 获取一个电池灯,后面对电池灯的所以操作都是通过mBatteryLight来进行的 */
    mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
}
public void onStart() {
    IBinder b = ServiceManager.getService("batteryproperties");
    final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =  
    IBatteryPropertiesRegistrar.Stub.asInterface(b);

    /* 注册一个监听器监听电量的变化,电池的Linux驱动上报电池事件时调用batteryPropertiesChanged更新电池灯 */
    batteryPropertiesRegistrar.registerListener(new BatteryListener());

    publishBinderService("battery", new BinderService());
    publishLocalService(BatteryManagerInternal.class, new LocalService());
}

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

private void update(BatteryProperties props) {
    processValuesLocked(false);
}

private void processValuesLocked(boolean force) {
    /* 发送广播ACTION_BATTERY_CHANGED,通知关心电池状态的进程,低电量提示,关机提示,状态栏图标等
     * 接收广播请看 PowerManagerService.java的BatteryReceiver方法
     */
    sendIntentLocked();

    /* 同时更新电池灯的状态  --  根据电量和是否在充电状态从而使闪灯或者红灯亮或黄灯亮等 */
    mLed.updateLightsLocked();
}

private void sendIntentLocked() {
    //  Pack up the values and broadcast them to everyone
    final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
        }
    });
}

public void updateLightsLocked() {
    final int level = mBatteryProps.batteryLevel;
    final int status = mBatteryProps.batteryStatus;
    /* 如果电量低于警告值的话 */
    if (level < mLowBatteryWarningLevel) {
          /* 如果电量低于警告值,并且正在充电,则将电池灯设置为让低电量颜色的灯亮起,
             如果没有在充电,则让低电量的灯闪烁 */
        if (status == BatteryManager.BATTERY_STATUS_CHARGING) { 
              mBatteryLight.setColor(mBatteryLowARGB);
        } else {
             mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED, 
             mBatteryLedOn, mBatteryLedOff);
        }
    /* 如何电量高于警告值,而且正在充电或者是满电状态,则根据电量选择让不同电量颜色的灯亮起 */
    } else if (status == BatteryManager.BATTERY_STATUS_CHARGING || status == 
            BatteryManager.BATTERY_STATUS_FULL) {
           if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
               mBatteryLight.setColor(mBatteryFullARGB);
           } else {
               mBatteryLight.setColor(mBatteryMediumARGB);
           }
    /* 如果以上状态都不是,则关闭电池灯 */
    } else {
         mBatteryLight.turnOff();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值