OpenHarmony 源码解析之账号子系统

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

想了解更多内容,请访问:

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

https://harmonyos.51cto.com

1 简介

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

1.1 OpenHarmony架构图

OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区

1.2 账号子系统架构图

OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区

1.3 账号子系统目录结构

  1. /base/account/os_account 
  2. ├── frameworks                           
  3. │   ├── appaccount                                          # 应用账号kit代码 
  4. │   ├── ohosaccount                                         # 云账号kit代码 
  5. │   ├── common                                              # 共通基础代码 
  6. │   │   ├── account_error                                   # 错误码 
  7. │   │   ├── database                                        # 数据库基础代码 
  8. │   │   ├── log                                             # 打印日志代码 
  9. │   │   └── perf_stat                                       # 性能统计 
  10. ├── interfaces                           
  11. │   ├── innerkits                        
  12. │   │   ├── appaccount                                      # 应用账号内部接口 
  13. │   │   ├── ohosaccount                                     # 云账号内部接口 
  14. │   └── kits                             
  15. │       └── napi                         
  16. │           ├── appaccount                                  # 应用账号对外接口 
  17. │           └── distributedaccount                          # 分布式账号对外接口 
  18. ├── sa_profile                                              # 帐号SA配置文件定义目录 
  19. └── services                             
  20.     └── accountmgr                                          # 帐号管理服务         

2 账号管理服务的启动

2.1 rc启动服务

  1. #base\account\os_account\services\accountmgr\accountmgr.rc 
  2. on post-fs-data 
  3.     start accountmgr 
  4.  
  5. service accountmgr /system/bin/sa_main /system/profile/accountmgr.xml 
  6.     class z_core 
  7.     user system 
  8.     group system shell 
  9.     seclabel u:r:accountmgr:s0 
  10.     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指令,如:
  1. on post-fs-data 
  2.     start accountmgr 

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

  • service: 执行可执行程序,如:
  1. service accountmgr /system/bin/sa_main /system/profile/accountmgr.xml 
  2.     class z_core 
  3.     user system 
  4.     group system shell 
  5.     seclabel u:r:accountmgr:s0 
  6.     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”,例如:

  1. class_start core 
  2. class_start main 
  3. on nonencrypted 
  4. class_start late_start 

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

2.2 AccountMgrService的启动流程

OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区

2.2.1 AccountMgrService通过OnStart调用Init

  • AccountMgrService继承自SystemAbility,当应用启动时首先应用程序框架会调用AccountMgrService的生命周期函数OnStart();
  • OnStart()首先判断服务运行状态是否已经开启,如果没有开启,则调用Init()进行初始化操作
  • 初始化操作完成并返回true给OnStart()后,服务运行状态则更新为开启状态
  1. //base\account\os_account\services\accountmgr\src\account_mgr_service.cpp 
  2. void AccountMgrService::OnStart() 
  3.     //判断服务运行状态是否已经开启 
  4.     if (state_ == ServiceRunningState::STATE_RUNNING) { 
  5.         ACCOUNT_LOGI("AccountMgrService has already started."); 
  6.         return
  7.     } 
  8.  
  9.     PerfStat::GetInstance().SetInstanceStartTime(GetTickCount()); 
  10.     ACCOUNT_LOGI("start is triggered"); 
  11.     //如果服务运行状态没有开启,则调用Init()进行初始化操作 
  12.     if (!Init()) { 
  13.         ACCOUNT_LOGE("failed to init AccountMgrService"); 
  14.         return
  15.     } 
  16.     //初始化操作完成并返回true给OnStart()后,服务运行状态则更新为开启状态 
  17.     state_ = ServiceRunningState::STATE_RUNNING; 
  18.     ACCOUNT_LOGI("AccountMgrService::OnStart start service success."); 

 2.2.2 AccountMgrService的Init()实现

  • Init()被调用后,依然要先判断服务运行状态是否已经开启
  • 随后,检查DEVICE_OWNER_DIR是否存在,如果不存在就强制创建
  • 如果服务还没有被注册,则调用Publish()来注册服务,Publish()执行成功后,标记服务已经被注册
  • 创建OhosAccountManager对象,并调用它的OnInitialize方法
  1. //base\account\os_account\services\accountmgr\src\account_mgr_service.cpp 
  2. bool AccountMgrService::Init() 
  3.     //判断服务运行状态是否已经开启 
  4.     if (state_ == ServiceRunningState::STATE_RUNNING) { 
  5.         ACCOUNT_LOGW("Service is already running!"); 
  6.         return false
  7.     } 
  8.  
  9.     //检查DEVICE_OWNER_DIR是否存在,如果不存在就强制创建 
  10.     if (!OHOS::FileExists(DEVICE_OWNER_DIR)) { 
  11.         ACCOUNT_LOGI("Device owner dir not exist, create!"); 
  12.         if (!OHOS::ForceCreateDirectory(DEVICE_OWNER_DIR)) { 
  13.             ACCOUNT_LOGW("Create device owner dir failure!"); 
  14.         } 
  15.     } 
  16.  
  17.     bool ret = false
  18.     //如果服务还没有被注册,则调用Publish()来注册服务,Publish()执行成功后,标记服务已经被注册 
  19.     if (!registerToService_) { 
  20.         ret = Publish(&DelayedRefSingleton<AccountMgrService>::GetInstance()); 
  21.         if (!ret) { 
  22.             HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStartFailed"
  23.                 HiviewDFX::HiSysEvent::EventType::FAULT, "ERROR_TYPE", ERR_ACCOUNT_MGR_ADD_TO_SA_ERROR); 
  24.             ACCOUNT_LOGE("AccountMgrService::Init Publish failed!"); 
  25.             return false
  26.         } 
  27.         registerToService_ = true
  28.     } 
  29.  
  30.     PerfStat::GetInstance().SetInstanceInitTime(GetTickCount()); 
  31.  
  32.     //创建OhosAccountManager对象 
  33.     ohosAccountMgr_ = std::make_shared<OhosAccountManager>(); 
  34.      
  35.     //调用OhosAccountManager的OnInitialize方法 
  36.     ret = ohosAccountMgr_->OnInitialize(); 
  37.     if (!ret) { 
  38.         ACCOUNT_LOGE("Ohos account manager initialize failed"); 
  39.         HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStartFailed"
  40.             HiviewDFX::HiSysEvent::EventType::FAULT, "ERROR_TYPE", ret); 
  41.         return ret; 
  42.     } 
  43.     dumpHelper_ = std::make_unique<AccountDumpHelper>(ohosAccountMgr_); 
  44.     IAccountContext::SetInstance(this); 
  45.     ACCOUNT_LOGI("init end success"); 
  46.     return true

2.2.3 OhosAccountManager的初始化

  • OhosAccountManager::OnInitialize首先调用BuildEventsMapper()进行事件映射,查看BuildEventsMapper()实现可发现,写死的事件有账号登入、登出、注销和Token失效,并与对应的方法绑定
  • 组织账号配置文件路径,作为参数创建OhosAccountDataDeal对象,并调用它的Init方法,查看Init()实现可发现,Init()读取账号配置文件并保存到jsonData_中
  • 调用AccountInfoFromJson()获取账号信息并保存到currentAccount_中
  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. bool OhosAccountManager::OnInitialize() 
  3.     accountState_ = std::make_unique<AccountStateMachine>(); 
  4.      
  5.     //事件映射 
  6.     BuildEventsMapper(); 
  7.  
  8.     //组织账号配置文件路径 
  9.     std::int32_t userId = GetUserId(); 
  10.     std::string filePath; 
  11.     filePath.append(ACCOUNT_CFG_DIR_ROOT_PATH).append(std::to_string(userId)).append(ACCOUNT_CFG_FILE_NAME); 
  12.      
  13.     //创建OhosAccountDataDeal对象 
  14.     dataDealer_ = std::make_unique<OhosAccountDataDeal>(filePath); 
  15.  
  16.     std::int32_t tryTimes = 0; 
  17.     while (tryTimes < MAX_RETRY_TIMES) { 
  18.         tryTimes++; 
  19.          
  20.         //调用ohos_account_data_deal的Init方法 
  21.         ErrCode errCode = dataDealer_->Init(); 
  22.         if (errCode == ERR_OK) { 
  23.             break; 
  24.         } 
  25.  
  26.         // when json file corrupted, have it another try 
  27.         if ((tryTimes == MAX_RETRY_TIMES) || (errCode != ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION)) { 
  28.             ACCOUNT_LOGE("parse json file failed: %{public}d, tryTime: %{public}d", errCode, tryTimes); 
  29.             eventMap_.clear(); 
  30.             eventFuncMap_.clear(); 
  31.             return false
  32.         } 
  33.     } 
  34.  
  35.     // get account info from config file 
  36.     dataDealer_->AccountInfoFromJson(currentAccount_); 
  37.     accountState_->SetAccountState(currentAccount_.ohosAccountStatus_); 
  38.     return true

2.2.4 OhosAccountManager::BuildEventsMapper()

  • OhosAccountManager::BuildEventsMapper()将账号登入、登出、注销和Token失效四个事件与相应的处理函数绑定
  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. void OhosAccountManager::BuildEventsMapper() 
  3.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGIN, 
  4.         ACCOUNT_BIND_SUCCESS_EVT)); 
  5.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOUT, 
  6.         ACCOUNT_MANUAL_UNBOUND_EVT)); 
  7.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_TOKEN_INVALID, 
  8.         ACCOUNT_TOKEN_EXPIRED_EVT)); 
  9.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOFF, 
  10.         ACCOUNT_MANUAL_LOGOFF_EVT)); 
  11.  
  12.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGIN, &OhosAccountManager::LoginOhosAccount)); 
  13.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOUT, &OhosAccountManager::LogoutOhosAccount)); 
  14.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOFF, &OhosAccountManager::LogoffOhosAccount)); 
  15.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_TOKEN_INVALID, 
  16.         &OhosAccountManager::HandleOhosAccountTokenInvalidEvent)); 

 2.2.5 ohos_account_data_deal的Init()实现

  • OhosAccountDataDeal::Init()首先检查账号配置文件存不存在,如果不存在则创建,如果存在则读取账号配置文件内容并保存到jsonData_中
  1. //base\account\os_account\services\accountmgr\src\ohos_account_data_deal.cpp 
  2. ErrCode OhosAccountDataDeal::Init() 
  3.     if (!FileExists(configFile_)) { 
  4.         ACCOUNT_LOGI("file %{public}s not exist, create!", configFile_.c_str()); 
  5.         BuildJsonFileFromScratch(); 
  6.     } 
  7.  
  8.     std::ifstream fin(configFile_); 
  9.     if (!fin) { 
  10.         ACCOUNT_LOGE("Failed to open file %{public}s", configFile_.c_str()); 
  11.         return ERR_ACCOUNT_DATADEAL_INPUT_FILE_ERROR; 
  12.     } 
  13.  
  14.     // NOT-allow exceptions when parse json file 
  15.     nlohmann::json jsonData = json::parse(fin, nullptr, false); 
  16.     if (!jsonData.is_structured()) { 
  17.         ACCOUNT_LOGE("Invalid json file, remove"); 
  18.         fin.close(); 
  19.         if (RemoveFile(configFile_)) { 
  20.             ACCOUNT_LOGE("Remove invalid json file failed"); 
  21.         } 
  22.         return ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION; 
  23.     } 
  24.  
  25.     // jsonData_ keeps well-structured json key-values 
  26.     jsonData_ = jsonData; 
  27.     initOk_ = true
  28.     fin.close(); 
  29.     return ERR_OK; 

3 分布式账号模块接口说明

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

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

  1. //base\account\os_account\interfaces\kits\napi\distributedaccount\src\napi_distributed_account.cpp 
  2. napi_value NapiDistributedAccount::Init(napi_env env, napi_value exports) 
  3.     ACCOUNT_LOGI("enter"); 
  4.     napi_property_descriptor descriptor[] = { 
  5.         DECLARE_NAPI_FUNCTION("getDistributedAccountAbility", GetDistributedAccountAbility), 
  6.     }; 
  7.     napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor); 
  8.  
  9.     napi_property_descriptor properties[] = { 
  10.         DECLARE_NAPI_FUNCTION("queryOsAccountDistributedInfo", QueryOhosAccountInfo), 
  11.         DECLARE_NAPI_FUNCTION("updateOsAccountDistributedInfo", UpdateOsAccountDistributedInfo), 
  12.     }; 
  13.     napi_value cons = nullptr; 
  14.     napi_define_class(env, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), DISTRIBUTED_ACCOUNT_CLASS_NAME.size(), 
  15.         JsConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons); 
  16.     napi_create_reference(env, cons, 1, &constructorRef_); 
  17.     napi_set_named_property(env, exports, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), cons); 
  18.  
  19.     return exports; 

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

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

OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区

 

 

OpenHarmony 源码解析之账号子系统-鸿蒙HarmonyOS技术社区

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

  1. //base\account\os_account\interfaces\kits\napi\distributedaccount\src\napi_distributed_account.cpp 
  2. napi_value NapiDistributedAccount::QueryOhosAccountInfo(napi_env env, napi_callback_info cbInfo) 
  3.     ...... 
  4.     napi_create_async_work( 
  5.         env, nullptr, resource, 
  6.         [](napi_env env, void *data) { 
  7.             DistributedAccountAsyncContext *asyncContext = (DistributedAccountAsyncContext*)data; 
  8.             std::pair<bool, OhosAccountInfo> accountInfo = OhosAccountKits::GetInstance().QueryOhosAccountInfo(); 
  9.        ...... 
  10.  
  11.     return result; 

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

  1. //base\account\os_account\interfaces\innerkits\ohosaccount\native\src\ohos_account_kits_impl.cpp 
  2. std::pair<bool, OhosAccountInfo> OhosAccountKitsImpl::QueryOhosAccountInfo() 
  3.     auto accountProxy = GetService(); 
  4.     if (accountProxy == nullptr) { 
  5.         ACCOUNT_LOGE("Get proxy failed"); 
  6.         return std::make_pair(false, OhosAccountInfo()); 
  7.     } 
  8.  
  9.     //调用AccountProxy::QueryOhosAccountInfo() 
  10.     return accountProxy->QueryOhosAccountInfo(); 

 AccountProxy::QueryOhosAccountInfo()调用SendRequest()发送QUERY_OHOS_ACCOUNT_INFO请求

  1. //base\account\os_account\frameworks\ohosaccount\native\src\account_proxy.cpp 
  2. std::pair<bool, OhosAccountInfo> AccountProxy::QueryOhosAccountInfo(void) 
  3.     ... 
  4.          
  5.     //调用SendRequest()发送QUERY_OHOS_ACCOUNT_INFO请求 
  6.     auto ret = Remote()->SendRequest(QUERY_OHOS_ACCOUNT_INFO, data, reply, option); 
  7.     if (ret != ERR_NONE) { 
  8.         ACCOUNT_LOGE("SendRequest failed %d", ret); 
  9.         return std::make_pair(false, OhosAccountInfo()); 
  10.     } 
  11.      
  12.     ... 
  13.      
  14.     return std::make_pair(true, OhosAccountInfo(Str16ToStr8(name), Str16ToStr8(uid), status)); 

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

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

  1. //base\account\os_account\services\accountmgr\src\account_stub.cpp 
  2. std::int32_t AccountStub::OnRemoteRequest(std::uint32_t code, MessageParcel &data, 
  3.                                           MessageParcel &reply, MessageOption &option
  4.     ... 
  5.  
  6.     //从stubFuncMap_匹配请求码 
  7.     const auto &itFunc = stubFuncMap_.find(code); 
  8.     if (itFunc != stubFuncMap_.end()) { 
  9.         return (this->*(itFunc->second))(data, reply); 
  10.     } 
  11.  
  12.     ACCOUNT_LOGW("remote request unhandled: %{public}d", code); 
  13.     return IPCObjectStub::OnRemoteRequest(code, data, reply, option); 

 我们来看看stubFuncMap_长啥样:

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

  1. //base\account\os_account\services\accountmgr\src\account_stub.cpp 
  2. const std::map<std::uint32_t, AccountStubFunc> AccountStub::stubFuncMap_ { 
  3.     std::make_pair(UPDATE_OHOS_ACCOUNT_INFO, &AccountStub::CmdUpdateOhosAccountInfo), 
  4.     std::make_pair(QUERY_OHOS_ACCOUNT_INFO, &AccountStub::CmdQueryOhosAccountInfo), 
  5.     std::make_pair(QUERY_OHOS_ACCOUNT_QUIT_TIPS, &AccountStub::CmdQueryOhosQuitTips), 
  6.     std::make_pair(QUERY_DEVICE_ACCOUNT_ID, &AccountStub::CmdQueryDeviceAccountId), 
  7.     std::make_pair(QUERY_DEVICE_ACCOUNT_ID_FROM_UID, &AccountStub::CmdQueryDeviceAccountIdFromUid), 
  8. }; 

 我们看看AccountStub::CmdQueryOhosAccountInfo()的实现:

  • CmdQueryOhosAccountInfo()中首先检查调用的进程是不是root或者system,从这可以看出,Account的相关接口只有系统用户才能使用
  • 接着检查是否有PERMISSION_MANAGE_USERS权限
  • 然后获取AccountInfo的其实是QueryOhosAccountInfo(),它的实现是在AccountMgrService里面
  1. //base\account\os_account\services\accountmgr\src\account_stub.cpp 
  2. std::int32_t AccountStub::CmdQueryOhosAccountInfo(MessageParcel &data, MessageParcel &reply) 
  3.     //检查调用的进程是不是root或者system 
  4.     //检查是否有PERMISSION_MANAGE_USERS权限 
  5.     if (!IsRootOrSystemAccount() && !HasAccountRequestPermission(PERMISSION_MANAGE_USERS)) { 
  6.         ACCOUNT_LOGE("Check permission failed"); 
  7.         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR; 
  8.     } 
  9.  
  10.     //调用AccountMgrService::QueryOhosAccountInfo 
  11.     std::pair<bool, OhosAccountInfo> info = QueryOhosAccountInfo(); 
  12.     if (!info.first) { 
  13.         ACCOUNT_LOGE("Query ohos account info failed"); 
  14.         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR; 
  15.     } 
  16.  
  17.     ... 
  18.     return ERR_OK; 

 在AccountMgrService::QueryOhosAccountInfo()里调用OhosAccountManager的GetAccountInfo()

  1. //base\account\os_account\services\accountmgr\src\account_mgr_service.cpp 
  2. std::pair<bool, OhosAccountInfo> AccountMgrService::QueryOhosAccountInfo(void) 
  3.     //调用OhosAccountManager::GetAccountInfo 
  4.     AccountInfo accountInfo = ohosAccountMgr_->GetAccountInfo(); 
  5.     if (accountInfo.ohosAccountUid_.empty()) { 
  6.         ACCOUNT_LOGE("invalid id"); 
  7.         accountInfo.clear(); 
  8.     } 
  9.     ... 
  10.          
  11.     return std::make_pair(true, OhosAccountInfo(name, id, status)); 
  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. AccountInfo OhosAccountManager::GetAccountInfo() 
  3.     std::lock_guard<std::mutex> mutexLock(mgrMutex_); 
  4.     return currentAccount_; 
  5.  
  6. AccountInfo currentAccount_; 

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

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

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

  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. void OhosAccountManager::BuildEventsMapper() 
  3.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGIN, 
  4.         ACCOUNT_BIND_SUCCESS_EVT)); 
  5.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOUT, 
  6.         ACCOUNT_MANUAL_UNBOUND_EVT)); 
  7.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_TOKEN_INVALID, 
  8.         ACCOUNT_TOKEN_EXPIRED_EVT)); 
  9.     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(OHOS_ACCOUNT_EVENT_LOGOFF, 
  10.         ACCOUNT_MANUAL_LOGOFF_EVT)); 
  11.  
  12.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGIN, &OhosAccountManager::LoginOhosAccount)); 
  13.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOUT, &OhosAccountManager::LogoutOhosAccount)); 
  14.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_LOGOFF, &OhosAccountManager::LogoffOhosAccount)); 
  15.     eventFuncMap_.insert(std::make_pair(OHOS_ACCOUNT_EVENT_TOKEN_INVALID, 
  16.         &OhosAccountManager::HandleOhosAccountTokenInvalidEvent)); 

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

  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. bool OhosAccountManager::LoginOhosAccount(const std::string &name, const std::string &uid, const std::string &eventStr) 
  3.     std::lock_guard<std::mutex> mutexLock(mgrMutex_); 
  4.     bool ret = HandleEvent(eventStr); // update account status 
  5.     if (!ret) { 
  6.         ACCOUNT_LOGE("LoginOhosAccount: HandleEvent %{public}s failed", eventStr.c_str()); 
  7.         return false
  8.     } 
  9.  
  10.     AccountInfo accountInfo(name, uid, currentAccount_.ohosAccountStatus_); 
  11.     accountInfo.bindTime_ = std::time(nullptr); 
  12.     accountInfo.userId_ = GetUserId(); 
  13.     ret = SetAccount(accountInfo); // set account info 
  14.     if (!ret) { 
  15.         ACCOUNT_LOGE("LoginOhosAccount: SetAccount failed"); 
  16.         return false
  17.     } 
  18.     ACCOUNT_LOGI("LoginOhosAccount success"); 
  19.     return true
  20. ... 

 从上面可以看出,登录、登出、注销及Token失效操作步骤基本一致,首先对收到的事件进行处理,然后将账号信息更新到缓存和配置文件中

因此,这里我们只需要看看HandleEvent()做了什么处理:

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

  1. //base\account\os_account\services\accountmgr\src\ohos_account_manager.cpp 
  2. bool OhosAccountManager::HandleEvent(const std::string &eventStr) 
  3.     //根据eventStr找到对应的事件类型 
  4.     auto iter = eventMap_.find(eventStr); 
  5.     if (iter == eventMap_.end()) { 
  6.         ACCOUNT_LOGE("invalid event: %{public}s", eventStr.c_str()); 
  7.         return false
  8.     } 
  9.  
  10.     int event = iter->second
  11.     //将事件更新到账号状态机 
  12.     bool ret = accountState_->StateChangeProcess(event); 
  13.     if (!ret) { 
  14.         ACCOUNT_LOGE("Handle event %{public}d failed", event); 
  15.         return false
  16.     } 
  17.     std::int32_t newState = accountState_->GetAccountState(); 
  18.     if (newState != currentAccount_.ohosAccountStatus_) { 
  19.         HiviewDFX::HiSysEvent::Write(HiviewDFX::HiSysEvent::Domain::ACCOUNT, "AccountServiceStateMachineEvent"
  20.             HiviewDFX::HiSysEvent::EventType::FAULT, "DEVICE_MODE", currentAccount_.userId_, 
  21.             "OPERATION_TYPE", event, "OLD_STATE", currentAccount_.ohosAccountStatus_, "NEW_STATE", newState); 
  22.         currentAccount_.ohosAccountStatus_ = newState; 
  23.     } 
  24.     return true
  1. //base\account\os_account\services\accountmgr\src\account_state_machine.cpp 
  2. bool AccountStateMachine::StateChangeProcess(int evt) 
  3.     // for performance record 
  4.     std::string stateRecordStr; 
  5.     int64_t processTicks = GetTickCount(); 
  6.     stateRecordStr.append("state from[").append(std::to_string(currentState_)).append("] to ["); 
  7.  
  8.     // get all the current state event action 
  9.     auto stateIter = stateMachineMap_.find(currentState_); 
  10.     if (stateIter == stateMachineMap_.end()) { 
  11.         ACCOUNT_LOGE("current state %d is not in state machine map.", currentState_); 
  12.         return false
  13.     } 
  14.  
  15.     // get the current event action 
  16.     auto eventIter = stateIter->second.find(evt); 
  17.     if (eventIter == stateIter->second.end()) { 
  18.         ACCOUNT_LOGE("event %d is not in state machine map.", evt); 
  19.         return false
  20.     } 
  21.  
  22.     // maybe action is null 
  23.     if (eventIter->second == nullptr) { 
  24.         ACCOUNT_LOGI("event %d has no action.", evt); 
  25.         return true
  26.     } 
  27.  
  28.     int nextState = eventIter->second->GetNextState(); 
  29.     if (currentState_ != nextState) { 
  30.         ACCOUNT_LOGI("account state change, (oldstate, newstate) = (%d, %d)", currentState_, nextState); 
  31.         currentState_ = nextState; 
  32.     } 
  33.  
  34.     // Record state change performance 
  35.     processTicks = GetTickCount() - processTicks; 
  36.     stateRecordStr.append(std::to_string(nextState)).append("], event[").append(std::to_string(evt)).append("] Cost"); 
  37.     PerfStat::GetInstance().SetAccountStateChangeTime(stateRecordStr, processTicks); 
  38.  
  39.     return true

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

6 总结

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

下一步,

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

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

想了解更多内容,请访问:

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

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-02-17 20:57:07

OpenHarmon操作系统鸿蒙

2021-12-17 16:42:09

鸿蒙HarmonyOS应用

2021-09-18 14:40:37

鸿蒙HarmonyOS应用

2021-11-08 15:04:47

鸿蒙HarmonyOS应用

2023-04-12 15:31:11

系统服务管理鸿蒙

2022-01-10 15:30:11

鸿蒙HarmonyOS应用

2022-05-10 11:17:27

电话子系统数据服务模块

2021-11-18 10:28:03

鸿蒙HarmonyOS应用

2022-05-24 15:46:51

Wi-FiSTA模式

2021-09-13 15:15:18

鸿蒙HarmonyOS应用

2023-04-06 09:14:11

多模输入子系统鸿蒙

2022-01-13 10:11:59

鸿蒙HarmonyOS应用

2023-06-28 15:00:02

开源鸿蒙输入系统架构

2021-09-17 14:38:58

鸿蒙HarmonyOS应用

2022-01-20 14:33:29

openharmonwayland协议鸿蒙

2022-02-14 14:47:11

SystemUIOpenHarmon鸿蒙

2022-03-18 16:07:04

Graphic子系统鸿蒙

2022-05-17 10:42:36

reboot源码解析

2022-06-13 14:18:39

电源管理子系统耗电量服务

2021-09-16 15:08:08

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号