OpenHarmony 源码解析之账号子系统
发布时间:2022-01-15 10:42 所属栏目:52 来源:互联网
导读:1 简介 在标准系统上,账号子系统主要提供分布式帐号登录状态管理能力,支持在端侧对接厂商云帐号应用,提供云帐号登录状态查询和更新的管理能力 1.1 OpenHarmony架构图 OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 1.2 账号子系统架构图 OpenH
1 简介 在标准系统上,账号子系统主要提供分布式帐号登录状态管理能力,支持在端侧对接厂商云帐号应用,提供云帐号登录状态查询和更新的管理能力 1.1 OpenHarmony架构图 OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 1.2 账号子系统架构图 OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 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启动服务 #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/tasks 2.1.1 rc文件结构解析 rc文件是以模块为单位的,模块分为3种类型:on、service、import import: 导入其它的rc文件 on: 执行chown、mkdir、write、export、symlink等简单的shell指令,如: on post-fs-data start accountmgr post-fs-data将一个section里的所有命令加入到一个执行队列,在未来的某个时候会顺序执行队列里的命令 service: 执行可执行程序,如: 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”,例如: class_start core class_start main on nonencrypted class_start late_start 当执行到这里是service模块就会被调用 2.2 AccountMgrService的启动流程 OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 2.2.1 AccountMgrService通过OnStart调用Init AccountMgrService继承自SystemAbility,当应用启动时首先应用程序框架会调用AccountMgrService的生命周期函数OnStart(); OnStart()首先判断服务运行状态是否已经开启,如果没有开启,则调用Init()进行初始化操作 初始化操作完成并返回true给OnStart()后,服务运行状态则更新为开启状态 //base\account\os_account\services\accountmgr\src\account_mgr_service.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."); } 2.2.2 AccountMgrService的Init()实现 Init()被调用后,依然要先判断服务运行状态是否已经开启 随后,检查DEVICE_OWNER_DIR是否存在,如果不存在就强制创建 如果服务还没有被注册,则调用Publish()来注册服务,Publish()执行成功后,标记服务已经被注册 创建OhosAccountManager对象,并调用它的OnInitialize方法 //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_中 //base\account\os_account\services\accountmgr\src\ohos_account_manager.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失效四个事件与相应的处理函数绑定 //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_中 //base\account\os_account\services\accountmgr\src\ohos_account_data_deal.cpp ErrCode OhosAccountDataDeal::Init() { if (!FileExists(configFile_)) { ACCOUNT_LOGI("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 分布式账号模块接口说明 分布式帐号模块的功能主要包括获取、查询和更新分布式账号信息,仅支持系统应用 在分布式账号模块的初始化中,可发现以下函数的注册: //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; } 4 分布式账号模块接口调用流程 这里以queryOsAccountDistributedInfo为例,来分析调用流程: OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区 NapiDistributedAccount::QueryOhosAccountInfo实际调用的是OhosAccountKits::GetInstance().QueryOhosAccountInfo() //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; } OhosAccountKitsImpl::QueryOhosAccountInfo()实际调用的是AccountProxy::QueryOhosAccountInfo() //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(); } AccountProxy::QueryOhosAccountInfo()调用SendRequest()发送QUERY_OHOS_ACCOUNT_INFO请求 //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)); } 我们看看它的对端AccountStub::OnRemoteRequest是如何处理发送端的请求并返回什么样的结果的: 从stubFuncMap_匹配请求码,然后获取stubFuncMap_的第二项来处理请求 //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); } 我们来看看stubFuncMap_长啥样: 很容易看出,QUERY_OHOS_ACCOUNT_INFO请求码对应的是AccountStub::CmdQueryOhosAccountInfo() //base\account\os_account\services\accountmgr\src\account_stub.cpp const std::map<std::uint32_t, 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), }; 我们看看AccountStub::CmdQueryOhosAccountInfo()的实现: CmdQueryOhosAccountInfo()中首先检查调用的进程是不是root或者system,从这可以看出,Account的相关接口只有系统用户才能使用 接着检查是否有PERMISSION_MANAGE_USERS权限 然后获取AccountInfo的其实是QueryOhosAccountInfo(),它的实现是在AccountMgrService里面 //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; } 在AccountMgrService::QueryOhosAccountInfo()里调用OhosAccountManager的GetAccountInfo() //base\account\os_account\services\accountmgr\src\account_mgr_service.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)); } //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失效 前面提到,OhosAccountManager::OnInitialize会首先调用BuildEventsMapper()进行事件映射 //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)); } 可以看到,监听的事件处理回调有登入、登出、注销以及Token失效四种类型,下面以LoginOhosAccount为例看看它们具体做了什么: //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失效操作步骤基本一致,首先对收到的事件进行处理,然后将账号信息更新到缓存和配置文件中 因此,这里我们只需要看看HandleEvent()做了什么处理: 这里首先根据eventStr找到对应的事件类型,然后将事件更新到账号状态机 //base\account\os_account\services\accountmgr\src\ohos_account_manager.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; } //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 总结 通过本文的学习可了解到账号子系统源码架构的各个组成部分的实现以及流程(包括框架代码、内部接口、外部接口、系统服务等),结合上文内容,可进一步对账号子系统其它组件进行深入的学习。 (编辑:ASP站长网) |
相关内容
网友评论
推荐文章
热点阅读