海思android随笔之hippo数据交互

提示:本文是基于海思android 9.0 tv系统进行分析的


前言

海思的代码结构很清晰,db相关操作基本都在device/hisilicon/bigfish/hippo/vendor/common/db目录里,结构如下图
在这里插入图片描述
主要用到的是hi_mw_dbo和hi_mw_db_def


一、上层调用方法

Set:调用相关命令,返回该命令的执行结果(成功或失败)
HitvManager.getInstance().excuteCommandSet();

    /**
     * Excute command set int.
     *
     * @param cmd_id the cmd id
     * @return 1(success) or 0(failure)
     */
    public int excuteCommandSet(int cmd_id) {
    
    
        Parcel request = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        request.writeInt(cmd_id);
        int ret = invoke(request, reply);
        request.recycle();
        reply.recycle();

        return ret;
    }

Get:调用相关命令,返回命令中replay里的数据
HitvManager.getInstance().excuteCommandGet();

    /**
     * Excute command get int.
     *
     * @param cmd_id the cmd id
     * @param arg1   the arg 1
     * @return the int
     */
    public int excuteCommandGet(int cmd_id, int arg1) {
    
    
        Parcel request = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        request.writeInt(cmd_id);
        request.writeInt(arg1);
        invoke(request, reply);
        int ret = reply.readInt();
        request.recycle();
        reply.recycle();

        return ret;
    }

函数实体都在device/hisilicon/bigfish/hippo/api/java/com/hisilicon/android/tvapi/HitvManager.java

二、上层可调用命令列表

static LocalAtomicInfo g_astSystemModuleLocalAtomicInfo[] = {
    
    
    /* int */ /* method */
    {
    
     CMD_SERVICE_INIT,                   Init },
    {
    
     CMD_SERVICE_DEINIT,                 Deinit },
    {
    
     CMD_SYSTEM_RESTOREDEFAULT,          RestoreDefault },
    {
    
     CMD_SYSTEM_SETSCREENBLUE,           MuteScreen },
    {
    
     CMD_SYSTEM_GETSCREENBLUE,           GetScreenStatus },
    {
    
     CMD_SYSTEM_SHUTDOWN,                Shutdown },
    {
    
     CMD_SYSTEM_SUSPEND,                 Suspend },
    {
    
     CMD_SYSTEM_RESUME,                  Resume },
    {
    
     CMD_SYSTEM_SETPOWERONPANEL,         SetPowerOnPanel },
    {
    
     CMD_SYSTEM_GETPOWERONPANEL,         GetPowerOnPanel },
    {
    
     CMD_SYSTEM_SETLSADCKEY,             SetLSADCKey },
    {
    
     CMD_SYSTEM_GETLSADCKEY,             GetLSADCKey },
    {
    
     CMD_SYSTEM_GETBOOTVERSION,          GetBootVersion },
    {
    
     CMD_SYSTEM_SETPANELFIXOUTRATE,      SetPanelFixOutRate },
    {
    
     CMD_SYSTEM_SETRESUMETIMER,          SetResumeTimer },
    {
    
     CMD_SYSTEM_SETHDMIEDIDTYPE,         SetHdmirxEdidType },
    {
    
     CMD_SYSTEM_GETHDMIEDIDTYPE,         GetHdmirxEdidType },
    {
    
     CMD_SYSTEM_GETHDMIEDIDCAP,          GetHdmirxEdidCap },
    {
    
     CMD_SYSTEM_SETCOUNTRY,              SetCountry },
    {
    
     CMD_SYSTEM_GETCOUNTRY,              GetCountry },
    {
    
     CMD_SYSTEM_GETWAKEUP,               GetWakeup },
    {
    
     CMD_SYSTEM_GETCURRENTLOCK,          IsCurrentLocked },
    {
    
     CMD_SYSTEM_SETLOCKENABLE,           SetLockEnable },
    {
    
     CMD_SYSTEM_GETLOCKENABLE,           GetLockEnable },
    {
    
     CMD_SYSTEM_SETLOCKPWD,              SetPwdStatus },
    {
    
     CMD_SYSTEM_GETLOCKPWD,              GetPwdStatus },
......
}

三、流程图

下图以CMD_SYSTEM_GETSCREENBLUE为例,大致流程如下:

app HitvManager.java hi_mw_logic_system_module.cpp hi_mw_logic_system.cpp hi_mw_dbo.cpp excuteCommandGet() GetScreenStatus(in, out) GetScreenStatus(*penScreenColor) db Query(HI_MW_ATTR_SYSTEM) out out *penScreenColor *pData.enScreenColor app HitvManager.java hi_mw_logic_system_module.cpp hi_mw_logic_system.cpp hi_mw_dbo.cpp

四、数据库详解

1、配置文件

a、ini路径

device/hisilicon/bigfish/hippo/include/hi_mw_common.h

static const HI_CHAR* ATV_INI_CFG_INI_PATH  = "atv/ini/cfg.ini";
static const HI_CHAR* ATV_INI_DB_INI_PATH  = "atv/ini/db.ini";
static const HI_CHAR* ATV_INI_AQ_INI_PATH  = "atv/ini/aq.ini";
static const HI_CHAR* ATV_INI_DIR_PATH  = "atv/ini";

b、db路径

device/hisilicon/bigfish/hippo/vendor/custom/客户名/ini/项目名/cfg.ini

......
[databasepath]
databaseusr = /atv/db/user.db;
databasefac = /atv/db/factory.db;
databaseatv = /atv/db/atv.db;
......

2、db分类

device/hisilicon/bigfish/hippo/vendor/common/db/hi_mw_dbo.h

enum HI_MW_DB_E {
    
    
    HI_MW_DB_FAC = HI_MW_ATTR_FAC,
    HI_MW_DB_USR = HI_MW_ATTR_USR,
    HI_MW_DB_CHN = HI_MW_ATTR_ATV,
    HI_MW_DB_BUTT = HI_MW_ATTR_BUTT
};

这里的分类要与上面db路径一一对应,BUTT相当于bufffer用来中转,没有实体

3、db形成过程

a. ini配置的初始化

主要实现在hi_mw_ini_provider.cpp

Created with Raphaël 2.3.0 INIProvider LoadIniFile hi_get_one_cfg_file(ini path) InitCacheMap AddCacheMap CacheMapLoad ini所有数据就都记录在了m_Cache里

b. ini配置数据的读取方法

方法主要在hi_mw_ini_provider.cpp,实际都是去操作m_Cache

    HI_S32 ParseInt(const string &fil);
    Array<HI_S32> ParseIntArray(const string &fil);

    HI_DOUBLE ParseDouble(const string &fil);
    Array<HI_DOUBLE> ParseDoubleArray(const string &fil);

    HI_BOOL ParseBoolean(const string &fil);
    Array<HI_BOOL> ParseBooleanArray(const string &fil);

    string ParseString(const string &fil);
    Array<string> ParseStringArray(const string &fil);

c. ini数据转db

主要实现在hi_mw_dbo.cpp

  • ini数据字段归类
   enum HI_MW_ATTR_E {
    
    
       HI_MW_ATTR_FAC = 0x0,
       .....
       HI_MW_ATTR_FAC_END,
       
       HI_MW_ATTR_USR = 0x100,
       ......
       HI_MW_ATTR_USR_END,
       
       HI_MW_ATTR_ATV = 0x200,
       ......
       HI_MW_ATTR_ATV_END,
   }
  • user.db: LoadUsrSetting()
    • HI_MW_ATTR_USR ~ HI_MW_ATTR_USR_END
  • factory.db: LoadFacSetting()
    • HI_MW_ATTR_FAC ~ HI_MW_ATTR_FAC_END
  • atv.db: LoadChnSetting()
    • HI_MW_ATTR_ATV ~ HI_MW_ATTR_ATV_END
  • 过程大致如下:
    这里以atv.db为例
Created with Raphaël 2.3.0 获取db文件路径:HiCfgFact::Get()->ParseString("databasepath:databaseatv") 创建db文件:CreateFile 获取ini数据库版本:HiCfgFact::Get()->ParseInt("databasedef:DatabaseChannelVersion") 查询db里版本是否与ini版本一致:QueryVersion 是否需要还原数据? 把db所有数据还原成ini里的配置值:InsertChnDefault 最终形成的数据都记录在m_mapAttrDB里 插入对应范围的ini里的配置值:pDbo->Attach() yes no

d. db数据的读取方法

都在hi_mw_dbo.cpp里,实际都是操作m_mapAttrDB

class HiDBO {
    
    
public:
    /* ±ê×¼²Ù×÷½Ó¿Ú:²åÈëÊý¾Ý */
    HI_S32 Insert(HI_MW_ATTR_E enAttr, const HI_U8 *pData, HI_U32 u32Length, HI_U32 u32Num = 1);

    /* ±ê×¼²Ù×÷½Ó¿Ú:ɾ³ýÊý¾Ý */
    HI_S32 Erase(HI_MW_ATTR_E enAttr, HI_U32 u32Row);
    HI_S32 Erase(HI_MW_ATTR_E enAttr);

    /* ±ê×¼²Ù×÷½Ó¿Ú:¸üÐÂÊý¾Ý */
    HI_S32 Update(HI_MW_ATTR_E enAttr, const HI_U8 *pData, HI_U32 u32Length, HI_U32 u32Row = 0);

    /* ±ê×¼²Ù×÷½Ó¿Ú:²éѯÊý¾Ý */
    HI_S32 Query(HI_MW_ATTR_E enAttr, HI_U8 *pData, HI_U32 u32Length, HI_U32 u32Row = 0);

    /* ²éѯij¸öÊý¾ÝÏîµÄ[u32StartRow,u32EndRow]Çø¼äÄÚµÄËùÓмǼ,
    u32LengthÊÇÒ»Ìõ¼Ç¼µÄÊý¾Ý´óС£¬·Ç²éѯµÄËùÓÐÊý¾ÝµÄ´óС */
    HI_S32 Query(HI_MW_ATTR_E enAttr, HI_U8 *pData, HI_U32 u32Length, HI_U32 u32StartRow, HI_U32 u32EndRow);
    /* Çå¿ÕÖ¸¶¨Êý¾Ý¿â */
    HI_S32 Clear(HI_MW_DB_E enDBType);
    ......
}

五、案例分享

例1:查询ini里user.db的路径

上文配置路径可知,user.db路径是保存在ini文件databasepath组下databaseusr字段。
那么获取的方法如下:
HiCfgFact::Get()->ParseString(“databasepath:databaseusr”);
这里海思用了一个HiCfgFact类作为中转,这个类就是获取INIProvider实例,INIProvider实例就在hi_mw_ini_provider里

例2:查询aq.ini文件里audiodrc组下DrcLimit字段当前在db中的实时数据

aq.ini:
......
[audiodrc]
DrcAttackTime    = 50;
DrcReleaseTime   = 100;
DrcThrhd         = -40000;
DrcLimit         = -10000;
DrcRefMode       = 1;
DrcSpeedCtrlMode = 1;
.......

大致思路如下:

  • 先查询DrcLimit字段在code里对应的枚举,搜索下,
    在hi_mw_db_def.cpp里有
HI_VOID UpdateAudDrcDef(HI_MW_DRC_ATTR_S(&stDrcAttrData)[HI_MW_AUDIO_CHANNEL_BUTT])
{
    
    
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].u32AttackTime = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt("audiodrc:DrcAttackTime"));
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].u32ReleaseTime = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt("audiodrc:DrcReleaseTime"));
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].s32Thrhd = HiCfgFact::Get()->ParseInt("audiodrc:DrcThrhd");
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].s32Limit = HiCfgFact::Get()->ParseInt("audiodrc:DrcLimit");
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].u32RefMode = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt("audiodrc:DrcRefMode"));
    stDrcAttrData[HI_MW_AUDIO_CHANNEL_SPEAKER].u32SpeedCtrlMode =
        static_cast<HI_U32>(HiCfgFact::Get()->ParseInt("audiodrc:DrcSpeedCtrlMode"));

    for (HI_U8 i = 1; (HI_MW_AUDIO_CHANNEL_E)i < HI_MW_AUDIO_CHANNEL_BUTT; i++) {
    
    
        std::string drcPortName = "drc" + GetPortNameFromIni((HI_MW_AUDIO_CHANNEL_E)i, HI_TRUE);
        if ("drc" == drcPortName) {
    
    
            continue;
        }

        stDrcAttrData[i].u32AttackTime = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt(drcPortName + ":DrcAttackTime"));
        stDrcAttrData[i].u32ReleaseTime = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt(drcPortName + ":DrcReleaseTime"));
        stDrcAttrData[i].s32Thrhd = HiCfgFact::Get()->ParseInt(drcPortName + ":DrcThrhd");
        stDrcAttrData[i].s32Limit = HiCfgFact::Get()->ParseInt(drcPortName + ":DrcLimit");
        stDrcAttrData[i].u32RefMode = static_cast<HI_U32>(HiCfgFact::Get()->ParseInt(drcPortName + ":DrcRefMode"));
        stDrcAttrData[i].u32SpeedCtrlMode =
            static_cast<HI_U32>(HiCfgFact::Get()->ParseInt(drcPortName + ":DrcSpeedCtrlMode"));
    }
}

这里可以看出DrcLimit数据是保存在一个HI_MW_DRC_ATTR_S结构体s32Limit成员里

HI_VOID RestoreDbAttrSubSixPartA(HI_U32 u32Id, HI_U8 *pData, HI_MW_SRC_E &enSource)
{
    
    
    if (pData == HI_NULL) {
    
    
        LOGE("null pointer..");
        return;
    }
    errno_t rc;
    switch (u32Id >> ATTR_BW) {
    
    
        case HI_MW_ATTR_AUDIO_DRC:
            HI_MW_DRC_ATTR_S stAudioDrcData[HI_MW_AUDIO_CHANNEL_BUTT];
            UpdateAudDrcDef(stAudioDrcData);
            rc = memcpy_s(pData, sizeof(stAudioDrcData), &stAudioDrcData, sizeof(stAudioDrcData));
            if (rc != EOK) {
    
    
                LOGE("memcpy_s_func failed rc = %d", rc);
                return;
            }
            break;
......
}

得到HI_MW_ATTR_AUDIO_DRC
这里后面用的上,另外这里也可以看出是把HI_MW_DRC_ATTR_S结构体存储起来,而不是单个变量

  • 查询db里的值
    HiDBOFact::GetDBO()->Query(HI_MW_ATTR_AUDIO_DRC, (HI_U8 *)&stDrcData, sizeof(HI_MW_DRC_ATTR_S))
    这里的data是HI_MW_DRC_ATTR_S结构体, 所以这里得到的是结构体,stDrcData.s32Limit就是我们想要的值. 值得注意的是,这个Query方法只能在hippo用,没有暴露给上层app,那么怎么办呢?细心的小伙伴可能已经联想到了第三章的流程图了。没错,结合第三章的流程,可以自定义个方法获取这个值,再添加对应的CMD_***命令就暴露给上层app了

总结

在分析的过程中能看出海思的code结构整洁,逻辑清晰,阅读起来如沐春风,让我受益匪浅。也学到了很多写code的技巧。建议有兴趣的伙伴们有空的话多阅读下海思的源代码,能收获很多东西。
下一篇打算写hippo客制化db文件的流程

猜你喜欢

转载自blog.csdn.net/hmz0303hf/article/details/125936341