OpenHarmony 源码解析之帐号子系统

2022年01月13日 阅读数:5
这篇文章主要向大家介绍OpenHarmony 源码解析之帐号子系统,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

做者:严明舟c++

1 简介

在标准系统上,帐号子系统主要提供分布式账号登陆状态管理能力,支持在端侧对接厂商云账号应用,提供云账号登陆状态查询和更新的管理能力shell

1.1 OpenHarmony架构图

OpenHarmonyOS_architecture.png

1.2 帐号子系统架构图

zhcn_image_account_struct.png

1.3 帐号子系统目录结构

/base/account/os_account
├── frameworks                          
│   ├── appaccount                                          # 应用帐号kit代码
│   ├── ohosaccount                                         # 云帐号kit代码
│   ├── common                                              # 共通基础代码
│   │   ├── account_error                                   # 错误码
│   │   ├── database                                        # 数据库基础代码
│   │   ├── log                                             # 打印日志代码
│   │   └── perf_stat                                       # 性能统计
├── interfaces                          
│   ├── innerkits                       
│   │   ├── appaccount                                      # 应用帐号内部接口
│   │   ├── ohosaccount                                     # 云帐号内部接口
│   └── kits                            
│       └── napi                        
│           ├── appaccount                                  # 应用帐号对外接口
│           └── distributedaccount                          # 分布式帐号对外接口
├── sa_profile                                              # 账号SA配置文件定义目录
└── services                            
    └── accountmgr                                          # 账号管理服务                

2 帐号管理服务的启动

2.1 rc启动服务

```c++
#base\account\os_account\services\accountmgr\accountmgr.rc
on post-fs-data
start accountmgr数据库

service accountmgr /system/bin/sa_main /system/profile/accountmgr.xml
class z_core
user system
group system shell
seclabel u:r:accountmgr:s0
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks /dev/blkio/foreground/tasksjson


#### 2.1.1 rc文件结构解析

rc文件是以模块为单位的,模块分为3种类型:**on**、**service**、**import**

- **import:** 导入其它的`rc`文件
- **on:** 执行`chown、mkdir、write、export、symlink`等简单的shell指令,如:

```c++
on post-fs-data
    start accountmgr

post-fs-data将一个section里的全部命令加入到一个执行队列,在将来的某个时候会顺序执行队列里的命令api

  • service: 执行可执行程序,如:

```c++
service accountmgr /system/bin/sa_main /system/profile/accountmgr.xml
class z_core
user system
group system shell
seclabel u:r:accountmgr:s0
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks /dev/blkio/foreground/tasks缓存


`accountmgr`为可执行程序名

`/system/bin/sa_main /system/profile/accountmgr.xml`为可执行文件的路径

`class、user、group、seclabel、writepid`这些关键字所对应的行是用来描述`service`一些特色,不一样的`service`有着不一样的特色

**service**何时被执行?

在某个**on**模块的指令里会存在`“class_start”`,例如:

```c++
class_start core
class_start main
on nonencrypted
class_start late_start

当执行到这里是service模块就会被调用markdown

2.2 AccountMgrService的启动流程

Dingtalk_20211129165757.jpg

2.2.1 AccountMgrService经过OnStart调用Init

  • AccountMgrService继承自SystemAbility,当应用启动时首先应用程序框架会调用AccountMgrService的生命周期函数OnStart()
  • OnStart()首先判断服务运行状态是否已经开启,若是没有开启,则调用Init()进行初始化操做
  • 初始化操做完成并返回trueOnStart()后,服务运行状态则更新为开启状态

```c++
//base\account\os_account\services\accountmgr\src\account_mgrservice.cpp
void AccountMgrService::OnStart()
{
//判断服务运行状态是否已经开启
if (state
== ServiceRunningState::STATE_RUNNING) {
ACCOUNT_LOGI("AccountMgrService has already started.");
return;
}架构

PerfStat::GetInstance().SetInstanceStartTime(GetTickCount());
ACCOUNT_LOGI("start is triggered");
//若是服务运行状态没有开启,则调用Init()进行初始化操做
if (!Init()) {
    ACCOUNT_LOGE("failed to init AccountMgrService");
    return;
}
//初始化操做完成并返回true给OnStart()后,服务运行状态则更新为开启状态
state_ = ServiceRunningState::STATE_RUNNING;
ACCOUNT_LOGI("AccountMgrService::OnStart start service success.");

}app


#### 2.2.2 AccountMgrService的Init()实现

- `Init()`被调用后,依然要先判断服务运行状态是否已经开启
- 随后,检查`DEVICE_OWNER_DIR`是否存在,若是不存在就强制建立
- 若是服务尚未被注册,则调用`Publish()`来注册服务,`Publish()`执行成功后,标记服务已经被注册
- 建立`OhosAccountManager`对象,并调用它的`OnInitialize`方法

```c++
//base\account\os_account\services\accountmgr\src\account_mgr_service.cpp
bool AccountMgrService::Init()
{
    //判断服务运行状态是否已经开启
    if (state_ == ServiceRunningState::STATE_RUNNING) {
        ACCOUNT_LOGW("Service is already running!");
        return false;
    }

    //检查DEVICE_OWNER_DIR是否存在,若是不存在就强制建立
    if (!OHOS::FileExists(DEVICE_OWNER_DIR)) {
        ACCOUNT_LOGI("Device owner dir not exist, create!");
        if (!OHOS::ForceCreateDirectory(DEVICE_OWNER_DIR)) {
            ACCOUNT_LOGW("Create device owner dir failure!");
        }
    }

    bool ret = false;
    //若是服务尚未被注册,则调用Publish()来注册服务,Publish()执行成功后,标记服务已经被注册
    if (!registerToService_) {
        ret = Publish(&DelayedRefSingleton<AccountMgrService>::GetInstance());
        if (!ret) {
            HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStartFailed",
                HiviewDFX::HiSysEvent::EventType::FAULT, "ERROR_TYPE", ERR_ACCOUNT_MGR_ADD_TO_SA_ERROR);
            ACCOUNT_LOGE("AccountMgrService::Init Publish failed!");
            return false;
        }
        registerToService_ = true;
    }

    PerfStat::GetInstance().SetInstanceInitTime(GetTickCount());

    //建立OhosAccountManager对象
    ohosAccountMgr_ = std::make_shared<OhosAccountManager>();

    //调用OhosAccountManager的OnInitialize方法
    ret = ohosAccountMgr_->OnInitialize();
    if (!ret) {
        ACCOUNT_LOGE("Ohos account manager initialize failed");
        HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStartFailed",
            HiviewDFX::HiSysEvent::EventType::FAULT, "ERROR_TYPE", ret);
        return ret;
    }
    dumpHelper_ = std::make_unique<AccountDumpHelper>(ohosAccountMgr_);
    IAccountContext::SetInstance(this);
    ACCOUNT_LOGI("init end success");
    return true;
}

2.2.3 OhosAccountManager的初始化

  • OhosAccountManager::OnInitialize首先调用BuildEventsMapper()进行事件映射,查看BuildEventsMapper()实现可发现,写死的事件有帐号登入、登出、注销和Token失效,并与对应的方法绑定
  • 组织帐号配置文件路径,做为参数建立OhosAccountDataDeal对象,并调用它的Init方法,查看Init()实现可发现,Init()读取帐号配置文件并保存到jsonData_
  • 调用AccountInfoFromJson()获取帐号信息并保存到currentAccount_

```c++
//base\account\os_account\services\accountmgr\src\ohos_accountmanager.cpp
bool OhosAccountManager::OnInitialize()
{
accountState
= std::make_unique<AccountStateMachine>();框架

//事件映射
BuildEventsMapper();

//组织帐号配置文件路径
std::int32_t userId = GetUserId();
std::string filePath;
filePath.append(ACCOUNT_CFG_DIR_ROOT_PATH).append(std::to_string(userId)).append(ACCOUNT_CFG_FILE_NAME);

//建立OhosAccountDataDeal对象
dataDealer_ = std::make_unique<OhosAccountDataDeal>(filePath);

std::int32_t tryTimes = 0;
while (tryTimes < MAX_RETRY_TIMES) {
    tryTimes++;

    //调用ohos_account_data_deal的Init方法
    ErrCode errCode = dataDealer_->Init();
    if (errCode == ERR_OK) {
        break;
    }

    // when json file corrupted, have it another try
    if ((tryTimes == MAX_RETRY_TIMES) || (errCode != ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION)) {
        ACCOUNT_LOGE("parse json file failed: %{public}d, tryTime: %{public}d", errCode, tryTimes);
        eventMap_.clear();
        eventFuncMap_.clear();
        return false;
    }
}

// get account info from config file
dataDealer_->AccountInfoFromJson(currentAccount_);
accountState_->SetAccountState(currentAccount_.ohosAccountStatus_);
return true;

}


#### 2.2.4 OhosAccountManager::BuildEventsMapper()

- `OhosAccountManager::BuildEventsMapper()`将帐号登入、登出、注销和Token失效四个事件与相应的处理函数绑定

```c++
//base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp
void OhosAccountManager::BuildEventsMapper()
{
    eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGIN,
        ACCOUNT_BIND_SUCCESS_EVT));
    eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOUT,
        ACCOUNT_MANUAL_UNBOUND_EVT));
    eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_TOKEN_INVALID,
        ACCOUNT_TOKEN_EXPIRED_EVT));
    eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOFF,
        ACCOUNT_MANUAL_LOGOFF_EVT));

    eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGIN, &OhosAccountManager::LoginOhosAccount));
    eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOUT, &OhosAccountManager::LogoutOhosAccount));
    eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOFF, &OhosAccountManager::LogoffOhosAccount));
    eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_TOKEN_INVALID,
        &OhosAccountManager::HandleOhosAccountTokenInvalidEvent));
}

2.2.5 ohos_account_data_deal的Init()实现

  • OhosAccountDataDeal::Init()首先检查帐号配置文件存不存在,若是不存在则建立,若是存在则读取帐号配置文件内容并保存到jsonData_

```c++
//base\account\os_account\services\accountmgr\src\ohos_account_datadeal.cpp
ErrCode OhosAccountDataDeal::Init()
{
if (!FileExists(configFile
)) {
ACCOUNTLOGI("file %{public}s not exist, create!", configFile.c_str());
BuildJsonFileFromScratch();
}

std::ifstream fin(configFile_);
if (!fin) {
    ACCOUNT_LOGE("Failed to open file %{public}s", configFile_.c_str());
    return ERR_ACCOUNT_DATADEAL_INPUT_FILE_ERROR;
}

// NOT-allow exceptions when parse json file
nlohmann::json jsonData = json::parse(fin, nullptr, false);
if (!jsonData.is_structured()) {
    ACCOUNT_LOGE("Invalid json file, remove");
    fin.close();
    if (RemoveFile(configFile_)) {
        ACCOUNT_LOGE("Remove invalid json file failed");
    }
    return ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION;
}

// jsonData_ keeps well-structured json key-values
jsonData_ = jsonData;
initOk_ = true;
fin.close();
return ERR_OK;

}


## 3 分布式帐号模块接口说明

分布式账号模块的功能主要包括获取、查询和更新分布式帐号信息,仅支持系统应用

在分布式帐号模块的初始化中,可发现如下函数的注册:

```c++
//base\account\os_account\interfaces\kits\napi\distributedaccount\src\napi_distributed_account.cpp
napi_value NapiDistributedAccount::Init(napi_env env, napi_value exports)
{
    ACCOUNT_LOGI("enter");
    napi_property_descriptor descriptor[] = {
        DECLARE_NAPI_FUNCTION("getDistributedAccountAbility", GetDistributedAccountAbility),
    };
    napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor);

    napi_property_descriptor properties[] = {
        DECLARE_NAPI_FUNCTION("queryOsAccountDistributedInfo", QueryOhosAccountInfo),
        DECLARE_NAPI_FUNCTION("updateOsAccountDistributedInfo", UpdateOsAccountDistributedInfo),
    };
    napi_value cons = nullptr;
    napi_define_class(env, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), DISTRIBUTED_ACCOUNT_CLASS_NAME.size(),
        JsConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons);
    napi_create_reference(env, cons, 1, &constructorRef_);
    napi_set_named_property(env, exports, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), cons);

    return exports;
}
方法 描述
getDistributedAccountAbility 获取分布式账号单实例对象
queryOsAccountDistributedInfo 查询分布式账号信息
updateOsAccountDistributedInfo 更新分布式账号信息

4 分布式帐号模块接口调用流程

这里以queryOsAccountDistributedInfo为例,来分析调用流程:
Dingtalk_20211130150315.jpg

Dingtalk_20211201195628.jpg

  1. NapiDistributedAccount::QueryOhosAccountInfo实际调用的是OhosAccountKits::GetInstance().QueryOhosAccountInfo()

```c++
//base\account\os_account\interfaces\kits\napi\distributedaccount\src\napi_distributed_account.cpp
napi_value NapiDistributedAccount::QueryOhosAccountInfo(napi_env env, napi_callback_info cbInfo)
{
......
napi_create_async_work(
env, nullptr, resource,
[](napi_env env, void data) {
DistributedAccountAsyncContext
asyncContext = (DistributedAccountAsyncContext*)data;
std::pair<bool, OhosAccountInfo> accountInfo = OhosAccountKits::GetInstance().QueryOhosAccountInfo();
......

return result;

}


2. `OhosAccountKitsImpl::QueryOhosAccountInfo()`实际调用的是`AccountProxy::QueryOhosAccountInfo()`

```c++
//base\account\os_account\interfaces\innerkits\ohosaccount\native\src\ohos_account_kits_impl.cpp
std::pair<bool, OhosAccountInfo> OhosAccountKitsImpl::QueryOhosAccountInfo()
{
    auto accountProxy = GetService();
    if (accountProxy == nullptr) {
        ACCOUNT_LOGE("Get proxy failed");
        return std::make_pair(false, OhosAccountInfo());
    }

    //调用AccountProxy::QueryOhosAccountInfo()
    return accountProxy->QueryOhosAccountInfo();
}
  1. AccountProxy::QueryOhosAccountInfo()调用SendRequest()发送QUERY_OHOS_ACCOUNT_INFO请求

```c++
//base\account\os_account\frameworks\ohosaccount\native\src\account_proxy.cpp
std::pair<bool, OhosAccountInfo> AccountProxy::QueryOhosAccountInfo(void)
{
...

//调用SendRequest()发送QUERY_OHOS_ACCOUNT_INFO请求
auto ret = Remote()->SendRequest(QUERY_OHOS_ACCOUNT_INFO, data, reply, option);
if (ret != ERR_NONE) {
    ACCOUNT_LOGE("SendRequest failed %d", ret);
    return std::make_pair(false, OhosAccountInfo());
}

...

return std::make_pair(true, OhosAccountInfo(Str16ToStr8(name), Str16ToStr8(uid), status));

}


4. 咱们看看它的对端`AccountStub::OnRemoteRequest`是如何处理发送端的请求并返回什么样的结果的:

   从`stubFuncMap_`匹配请求码,而后获取`stubFuncMap_`的第二项来处理请求

```c++
//base\account\os_account\services\accountmgr\src\account_stub.cpp
std::int32_t AccountStub::OnRemoteRequest(std::uint32_t code, MessageParcel &data,
                                          MessageParcel &reply, MessageOption &option)
{
    ...

    //从stubFuncMap_匹配请求码
    const auto &itFunc = stubFuncMap_.find(code);
    if (itFunc != stubFuncMap_.end()) {
        return (this->*(itFunc->second))(data, reply);
    }

    ACCOUNT_LOGW("remote request unhandled: %{public}d", code);
    return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
  1. 咱们来看看stubFuncMap_长啥样:

    很容易看出,QUERY_OHOS_ACCOUNT_INFO请求码对应的是AccountStub::CmdQueryOhosAccountInfo()

```c++
//base\account\os_account\services\accountmgr\src\account_stub.cpp
const std::map<std::uint32t, AccountStubFunc> AccountStub::stubFuncMap {
std::make_pair(UPDATE_OHOS_ACCOUNT_INFO, &AccountStub::CmdUpdateOhosAccountInfo),
std::make_pair(QUERY_OHOS_ACCOUNT_INFO, &AccountStub::CmdQueryOhosAccountInfo),
std::make_pair(QUERY_OHOS_ACCOUNT_QUIT_TIPS, &AccountStub::CmdQueryOhosQuitTips),
std::make_pair(QUERY_DEVICE_ACCOUNT_ID, &AccountStub::CmdQueryDeviceAccountId),
std::make_pair(QUERY_DEVICE_ACCOUNT_ID_FROM_UID, &AccountStub::CmdQueryDeviceAccountIdFromUid),
};


6. 咱们看看`AccountStub::CmdQueryOhosAccountInfo()`的实现:

   - `CmdQueryOhosAccountInfo()`中首先检查调用的进程是否是`root`或者`system`,从这能够看出,`Account`的相关接口只有系统用户才能使用

   - 接着检查是否有`PERMISSION_MANAGE_USERS`权限

   - 而后获取`AccountInfo`的实际上是`QueryOhosAccountInfo()`,它的实现是在`AccountMgrService`里面

```c++
//base\account\os_account\services\accountmgr\src\account_stub.cpp
std::int32_t AccountStub::CmdQueryOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
{
    //检查调用的进程是否是root或者system
    //检查是否有PERMISSION_MANAGE_USERS权限
    if (!IsRootOrSystemAccount() && !HasAccountRequestPermission(PERMISSION_MANAGE_USERS)) {
        ACCOUNT_LOGE("Check permission failed");
        return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
    }

    //调用AccountMgrService::QueryOhosAccountInfo
    std::pair<bool, OhosAccountInfo> info = QueryOhosAccountInfo();
    if (!info.first) {
        ACCOUNT_LOGE("Query ohos account info failed");
        return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
    }

    ...
    return ERR_OK;
}
  1. AccountMgrService::QueryOhosAccountInfo()里调用OhosAccountManagerGetAccountInfo()

```c++
//base\account\os_account\services\accountmgr\src\account_mgrservice.cpp
std::pair<bool, OhosAccountInfo> AccountMgrService::QueryOhosAccountInfo(void)
{
//调用OhosAccountManager::GetAccountInfo
AccountInfo accountInfo = ohosAccountMgr
->GetAccountInfo();
if (accountInfo.ohosAccountUid_.empty()) {
ACCOUNT_LOGE("invalid id");
accountInfo.clear();
}
...

return std::make_pair(true, OhosAccountInfo(name, id, status));

}


```c++
//base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp
AccountInfo OhosAccountManager::GetAccountInfo()
{
    std::lock_guard<std::mutex> mutexLock(mgrMutex_);
    return currentAccount_;
}

AccountInfo currentAccount_;

这里只是返回currentAccount_变量,它是一个AccountInfo,在前面的帐号管理服务启动的时候,咱们知道currentAccount_是在初始化过程当中经过读取帐号配置文件到jsonData_中获得的

5 帐号登入、登出、注销以及Token失效

  1. 前面提到,OhosAccountManager::OnInitialize会首先调用BuildEventsMapper()进行事件映射

```c++
//base\account\os_account\services\accountmgr\src\ohos_accountmanager.cpp
void OhosAccountManager::BuildEventsMapper()
{
eventMap
.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGIN,
ACCOUNT_BIND_SUCCESSEVT));
eventMap
.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOUT,
ACCOUNT_MANUAL_UNBOUNDEVT));
eventMap
.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_TOKEN_INVALID,
ACCOUNT_TOKEN_EXPIREDEVT));
eventMap
.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOFF,
ACCOUNT_MANUAL_LOGOFF_EVT));

eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGIN, &OhosAccountManager::LoginOhosAccount));
eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOUT, &OhosAccountManager::LogoutOhosAccount));
eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOFF, &OhosAccountManager::LogoffOhosAccount));
eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_TOKEN_INVALID,
    &OhosAccountManager::HandleOhosAccountTokenInvalidEvent));

}


2. 能够看到,监听的事件处理回调有登入、登出、注销以及Token失效四种类型,下面以`LoginOhosAccount`为例看看它们具体作了什么:

```c++
//base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp
bool OhosAccountManager::LoginOhosAccount(const std::string &name, const std::string &uid, const std::string &eventStr)
{
    std::lock_guard<std::mutex> mutexLock(mgrMutex_);
    bool ret = HandleEvent(eventStr); // update account status
    if (!ret) {
        ACCOUNT_LOGE("LoginOhosAccount: HandleEvent %{public}s failed", eventStr.c_str());
        return false;
    }

    AccountInfo accountInfo(name, uid, currentAccount_.ohosAccountStatus_);
    accountInfo.bindTime_ = std::time(nullptr);
    accountInfo.userId_ = GetUserId();
    ret = SetAccount(accountInfo); // set account info
    if (!ret) {
        ACCOUNT_LOGE("LoginOhosAccount: SetAccount failed");
        return false;
    }
    ACCOUNT_LOGI("LoginOhosAccount success");
    return true;
}
...

从上面能够看出,登陆、登出、注销及Token失效操做步骤基本一致,首先对收到的事件进行处理,而后将帐号信息更新到缓存和配置文件中

  1. 所以,这里咱们只须要看看HandleEvent()作了什么处理:

    这里首先根据eventStr找到对应的事件类型,而后将事件更新到帐号状态机

```c++
//base\account\os_account\services\accountmgr\src\ohos_accountmanager.cpp
bool OhosAccountManager::HandleEvent(const std::string &eventStr)
{
//根据eventStr找到对应的事件类型
auto iter = eventMap
.find(eventStr);
if (iter == eventMap_.end()) {
ACCOUNT_LOGE("invalid event: %{public}s", eventStr.c_str());
return false;
}

int event = iter->second;
//将事件更新到帐号状态机
bool ret = accountState_->StateChangeProcess(event);
if (!ret) {
    ACCOUNT_LOGE("Handle event %{public}d failed", event);
    return false;
}
std::int32_t newState = accountState_->GetAccountState();
if (newState != currentAccount_.ohosAccountStatus_) {
    HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStateMachineEvent",
        HiviewDFX::HiSysEvent::EventType::FAULT, "DEVICE_MODE", currentAccount_.userId_,
        "OPERATION_TYPE", event, "OLD_STATE", currentAccount_.ohosAccountStatus_, "NEW_STATE", newState);
    currentAccount_.ohosAccountStatus_ = newState;
}
return true;

}


```c++
//base\account\os_account\services\accountmgr\src\account_state_machine.cpp
bool AccountStateMachine::StateChangeProcess(int evt)
{
    // for performance record
    std::string stateRecordStr;
    int64_t processTicks = GetTickCount();
    stateRecordStr.append("state from[").append(std::to_string(currentState_)).append("] to [");

    // get all the current state event action
    auto stateIter = stateMachineMap_.find(currentState_);
    if (stateIter == stateMachineMap_.end()) {
        ACCOUNT_LOGE("current state %d is not in state machine map.", currentState_);
        return false;
    }

    // get the current event action
    auto eventIter = stateIter->second.find(evt);
    if (eventIter == stateIter->second.end()) {
        ACCOUNT_LOGE("event %d is not in state machine map.", evt);
        return false;
    }

    // maybe action is null
    if (eventIter->second == nullptr) {
        ACCOUNT_LOGI("event %d has no action.", evt);
        return true;
    }

    int nextState = eventIter->second->GetNextState();
    if (currentState_ != nextState) {
        ACCOUNT_LOGI("account state change, (oldstate, newstate) = (%d, %d)", currentState_, nextState);
        currentState_ = nextState;
    }

    // Record state change performance
    processTicks = GetTickCount() - processTicks;
    stateRecordStr.append(std::to_string(nextState)).append("], event[").append(std::to_string(evt)).append("] Cost");
    PerfStat::GetInstance().SetAccountStateChangeTime(stateRecordStr, processTicks);

    return true;
}

能够看到,在状态机里面只是简单完成状态的切换

6 总结

经过本文的学习可了解到帐号子系统源码架构的各个组成部分的实现以及流程(包括框架代码、内部接口、外部接口、系统服务等),结合上文内容,可进一步对帐号子系统其它组件进行深刻的学习。

下一步,

(1) 着重理解帐号子系统框架代码,为开发的可重用性和扩充性作准备;

(2) 着重理解帐号管理服务模块,看看帐号管理服务是如何为各功能模块的业务请求提供应答的;

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让咱们一块儿携手前行共建鸿蒙生态。

想了解更多关于鸿蒙的内容,请访问:

51CTO和华为官方合做共建的鸿蒙技术社区

https://harmonyos.51cto.com/#bkwz

::: hljs-center

21_9.jpg

:::