Android FrameWork

这里是测试内容

文章目录

本文再次分析Android lights模块,此次分析处于以下目的原因:
1.Android8.1 新引入HIDL接口,HAL lights模块有变动
2.新增自定义服务,同时进一步深入理解Android系统服务板块

note:本文此次分析主要以HIDL接口分析为依托,旧方式可以移步msm8953 Android7.1.2 lights模块分析

1.Linux kernel 驱动层

关于Linux kernel驱动层这里就不多费口舌,直接上图和传送门:Android(Linux) led子系统分析
//TODO,此处缺图,后面补上

2.hardware层

2.1 hardware hal 硬件具体实现 (这里会根据硬件的不同而不同)

hardware/rockchip/liblights:此处以rockchip px30作为分析对象

因为这里的cpp实现是紧紧依赖硬件的,所以关于liblights/lights.cpp这里就不分析了,感兴趣的和可以结合我上面的传送门(以前的分析文章)自行阅读源码。

2.2 hardware/libhardware/include/hardware/lights.h

在hardware/libhardware/Android.bp中定义了cc_library_shared的生成规则,最终生成libhardware.so。
另外,lights.h内容如下,主要定义了针对lights的HAL的标准ID–LIGHTS_HARDWARE_MODULE_ID,还有两个重要的结构体light_state_tlight_device_t

2.3 hardware/interfaces/light

HIDL接口服务端实现处,这部分是Android8以后新增的一个架构,目的是将HAL里面在进行一次分层,促成依赖于binder的CS架构,即原来是直接通过jni的方式调用本地hal的硬件动态库变成依赖于binder的CS架构,什么意思呢?就是慢慢抛弃直接调用so的库的形式,jni调用binder的客户端,然后通过客户端与binder的服务端进行通信,实现对硬件的操作,这样做的好处是从原来的systemserver进程中将每个HAL模块独立在独立进程中,咱们先理解到这,后面结合分析深入理解。
目录结构如下:

light/
|-- 2.0
|   |-- Android.bp
|   |-- Android.mk
|   |-- ILight.hal
|   |-- default
|   |   |-- Android.mk
|   |   |-- Light.cpp
|   |   |-- Light.h
|   |   |-- android.hardware.light@2.0-service.rc
|   |   `-- service.cpp
|   |-- types.hal
|   `-- vts
|       |-- Android.mk
|       `-- functional
|           |-- Android.bp
|           `-- VtsHalLightV2_0TargetTest.cpp
`-- Android.bp
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这里可以看到hardware/interface下的lights目录下即是HIDL的实现处,在旧版本这里是没有的,其中ILight.hal 即是HIDL接口的定义,(这里用白话解释下HIDL,熟悉AIDL接口的朋友可以以H换A来理解,AIDL是跨进程通信的,那HIDL也是可以这样理解,只不过它是处于HAL层的,好,就此打住!)
其他文件后续一一分析。
ILight.hal 内容如下:

package android.hardware.light@2.0;

interface ILight {
    setLight(Type type, LightState state) generates (Status status);
    getSupportedTypes() generates (vec<Type> types);
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这个接口就提供了两个方法,它们用于对指定的light进行设置和获取支持的type;关于支持的type我们可以从前面提到的lights.h中得到,比如有BACKLIGHT,KEYBOARD等;
那这两个接口定义都是需要我们在hal服务层去实现的,最终调用到了hal硬件实现处,即light.cpp里。
**hal服务层实现在哪?**可以注意到在default目录下有Light.cpp,就是它了~
关于HIDL这部分都是可以自动生成,生成后我们进行具体化的实现,以及部分根据需要修改即可,这里重要的就是Light.cpp了,这里我们看看头文件Light.h的定义:

#ifndef ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
#define ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H

#include <android/hardware/light/2.0/ILight.h>
#include <hardware/hardware.h>
#include <hardware/lights.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
#include <map>

namespace android {
namespace hardware {
namespace light {
namespace V2_0 {
namespace implementation {

using ::android::hardware::light::V2_0::ILight;
using ::android::hardware::light::V2_0::LightState;
using ::android::hardware::light::V2_0::Status;
using ::android::hardware::light::V2_0::Type;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct Light : public ILight {
    Light(std::map<Type, light_device_t*> &&lights);

    // Methods from ::android::hardware::light::V2_0::ILight follow.
    Return<Status> setLight(Type type, const LightState& state)  override;
    Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;

private:
    std::map<Type, light_device_t*> mLights;
};

extern "C" ILight* HIDL_FETCH_ILight(const char* name);

}  // namespace implementation
}  // namespace V2_0
}  // namespace light
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

上述代码可以看到:
实现了我们在ILight.hal中看到的两个方法,setLightgetSupportedTypes
note:这里注意一个点,关于HIDL_FETCH_ILight方法,这个就是谷歌为了以前的就HAL方式的实现向前兼容的一个处理,可以看到现在很多厂商为了沿用之前的代码将这部分进行实现,也就可以直接沿用之前的一个hal直接调用so的实现了,而非现在的binder HIDL;
这里主要针对的是HIDL,看看实现,CPP文件内容比较长,这里就只留了部分重要的地方以供参考:

#define LOG_TAG "light"

#include <log/log.h>

#include "Light.h"

namespace android {
namespace hardware {
namespace light {
namespace V2_0 {
namespace implementation {

Light::Light(std::map<Type, light_device_t*> &&lights)
  : mLights(std::move(lights)) {}

// Methods from ::android::hardware::light::V2_0::ILight follow.
Return<Status> Light::setLight(Type type, const LightState& state)  {
    auto it = mLights.find(type);
    ......
    light_device_t* hwLight = it->second;
	......
    int ret = hwLight->set_light(hwLight, &legacyState);
    ......
}

Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb)  {
	......
}

const static std::map<Type, const char*> kLogicalLights = {
    {Type::BACKLIGHT,     LIGHT_ID_BACKLIGHT},
	......
};

light_device_t* getLightDevice(const char* name) {
    light_device_t* lightDevice;
    const hw_module_t* hwModule = NULL;

    int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule);
    if (ret == 0) {
        ret = hwModule->methods->open(hwModule, name,
            reinterpret_cast<hw_device_t**>(&lightDevice));
            ......
    } 
	......
}

ILight* HIDL_FETCH_ILight(const char* /* name */) {
    std::map<Type, light_device_t*> lights;
	......
    light_device_t* light = getLightDevice(name);
	......
    return new Light(std::move(lights));
}

} // namespace implementation
}  // namespace V2_0
}  // namespace light
}  // namespace hardware
}  // namespace android
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

这部分的实现也是挺简单的,这里简单分析下:
1.先把不相干但挺重要的说了吧,看到HIDL_FETCH_ILight的实现,它是这么个流程,HIDL_FETCH_ILight->getLightDevice,在getLightDevice中有用到了以前很重要的一些东西–hw_get_module 和hwModule->methods->open,这种方式就是HIDL方式出来之前的。那意思就是说只要实现了这部分,我们就可以不用binder C/S的方式,直接调用so到lights.cpp中。
2.再看getSupportedTypes函数,这个就是HIDL的方式,这里的实现内容比较简单,就是将type进行归纳整理就不进行分析了,上述代码我也去掉了,感兴趣的可以自行查看源码。
3.setLight函数,这个就是lights模块HIDL服务端的重头戏了,它就是对客户端的一个实际实现,但实现具体是在硬件实现层的lights.cpp。setlight通过hwLight调用到了对应的set_light,这个set_light最终也到了lights.cpp中。hwLight是一个light_device_t类型的指针,它指向了一个每一个type,因此只要传入的type不一样,那么最终实现的set_light也就不一样。

这里还有一个比较的重要文件–service.cpp,暂且理解成HIDL的HAL服务提供吧,理解成用来解决为啥HIDL客户端能够找到链接到这个服务端,这里由于笔者学艺不精,讲不太清,由大佬可以指教一二也就感激之至了!

#define LOG_TAG "android.hardware.light@2.0-service"

#include <android/hardware/light/2.0/ILight.h>
#include <hidl/LegacySupport.h>

using android::hardware::light::V2_0::ILight;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    return defaultPassthroughServiceImplementation<ILight>();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到service.cpp的代码实现是很简单的,但里面涉及的知识量应该很大吧,所谓不知道就很神奇~

最后一个文件:android.hardware.light@2.0-service.rc,它也可以是由工具生成,先看看内容,如下:

service light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service
    class hal
    user system
    group system
  • 1
  • 2
  • 3
  • 4

有没有感觉很熟悉,没错就是由init.rc,init进程进行处理,因此这也就解释了为啥HIDL的模式会使得原来的HAL层代码脱离systemserver进程而可以独立有自己的进程空间。其实这里也可以想到,以独立服务运行了,一定会涉及到selinux的问题,这里关于新增的hal服务,新增的selinux机制咱们后面再谈。
最终运行效果如下图所示:

关于Android.bp,Android.mk文件,这里不做过多说明,感兴趣的不明白的可以移步:

关于type.hal这个文件它是HIDL语法的文件,可以移步:

3.frameworks services层:frameworks/base/services

3.1 客户端jni调用

frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

namespace android {
class LightHal {
private:
    static sp<ILight> sLight;
    static bool sLightInit;

    LightHal() {}

public:
    static void disassociate() {
    } // 断开ILight服务

    static sp<ILight> associate() {
            sLight = ILight::getService(); //取得ILight服务
        return sLight;
    }
};

sp<ILight> LightHal::sLight = nullptr;
bool LightHal::sLightInit = false;

//对参数进行检查
static bool validate(jint light, jint flash, jint brightness) {
    return valid;
}

//构造LightState 类型参数
static LightState constructState(
        jint colorARGB,
        jint flashMode,
        jint onMS,
        jint offMS,
        jint brightnessMode){
    Flash flash = static_cast<Flash>(flashMode);
    Brightness brightness = static_cast<Brightness>(brightnessMode);

    LightState state{};
    state.brightnessMode = brightness;

    return state;
}

//处理返回结果
static void processReturn(
        const Return<Status> &ret,
        Type type,
        const LightState &state) {
}

// jni本地方法 setLight
static void setLight_native(
        JNIEnv* /* env */,
        jobject /* clazz */,
        jint light,
        jint colorARGB,
        jint flashMode,
        jint onMS,
        jint offMS,
        jint brightnessMode) {

    if (!validate(light, flashMode, brightnessMode)) {
        return;
    }

    sp<ILight> hal = LightHal::associate(); //取得Light服务
    LightState state = constructState(
        colorARGB, flashMode, onMS, offMS, brightnessMode); //构造setLight需要的LightState类型参数

    {
        android::base::Timer t;
        Return<Status> ret = hal->setLight(type, state); //调用hal的setLight函数实际是调用了HIDL里的setLight,最终调到lights里的对应setLight
        processReturn(ret, type, state);//处理执行结果
    }
}

//本地方法集合
static const JNINativeMethod method_table[] = {
    { "setLight_native", "(IIIIII)V", (void*)setLight_native },
};

//注册本地方法
int register_android_server_LightsService(JNIEnv *env) {
    return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
            method_table, NELEM(method_table));
}

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

以上代码我去除了一些部分,并且对重要部分做了些注释,应该还算容易理解,完整的大家自行查阅源码;

3.2 客户端frameworks java服务:执行本地jni调用

frameworks/base/services/core/java/com/android/server/lights/LightsService.java
那么谁会调到setLight_native 呢,肯定就是jni的java文件了–LightsService.java
LightsService java块集中在frameworks/base/services/core/java/com/android/server/lights,如下:

这里代码就不一一分析了,可以参考前面提到的传送门。
另外,这里提下之前没有讲到的关于Android系统服务之publishLocalServicepublishBinderService,它们被定义在Systemservice里,前者所发布的服务非同进程的是不可以获取该服务的,也就是说它只能同进程内使用,这也就意味着,其他app无法使用该服务;那么后者所发布的服务(binder),这种显而易见就是跨进程通信的,因此它是能够被其他app所获取并使用的。
从另一方面来讲,我想之所以存在这两种类型的服务,大多是效率和需求所致,如果只有Local,那就不能实现跨进程通信,如果只有Binder,虽然同进程和非同进程的都能使用,但是对于同进程来说,就有点杀鸡用牛刀且效率不够高的那味了~。
LightsService 服务发布如下所示:

这也就意味着我们其他APP不能使用这个服务了,只能systemserver进程自己使用了,经过代码调用查找,也确实如此。关于light服务下的turnoff方法的使用,也只有很少的系统进程使用了,如下所示:

4.systemserver进程调用

现在看看如何对于使用publishLocalService发布的服务,系统进程是如何使用的,就以电池服务作为例子吧。
frameworks/base/services/core/java/com/android/server/BatteryService.java

这里不明白的朋友可能会疑惑为啥这里有两种本地服务的调用方式,看下面方框的ActivityManagerInternal也是本地服务,它怎么是以LocalServices.getService的方式调用的,我们看看getLocalService的实现,如下:

可以知道getLocalService的实现就是LocalServices.getService,这样就清晰了。
结合上面将的lights模块,最终它是怎么调用到硬件lights的驱动呢?
看看led的构造,如下:

可以看到lights是一个LightsManager的对象,它通过getLight方法取得了电池的type id,这样通过前面的分析,jni java到cpp然后到HIDL接口再到服务端最终到达硬件实际实现地方lights.cpp。

至此,基于android8.1. 新特性HIDL的lights模块分析至此结束,后面讲讲如何新增自己的HAL层HIDL接口,以GPIO操控为例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值