提示:本文是基于海思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为例,大致流程如下:
四、数据库详解
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
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为例
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文件的流程