1 /*
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "multiuser/os_account_observer.h"
17
18 #include "common_event_manager.h"
19 #include "common_event_support.h"
20 #include "device/device_manager_agent.h"
21 #include "dfsu_mount_argument_descriptors.h"
22 #include "os_account_manager.h"
23 #include "utils_log.h"
24
25 namespace OHOS {
26 namespace Storage {
27 namespace DistributedFile {
28 using namespace std;
29 namespace {
30 static const std::string SAME_ACCOUNT = "account";
31 const int32_t INVALID_USER_ID = -1;
32 } // namespace
33
OsAccountObserver(const EventFwk::CommonEventSubscribeInfo & subscribeInfo)34 OsAccountObserver::OsAccountObserver(const EventFwk::CommonEventSubscribeInfo &subscribeInfo)
35 : EventFwk::CommonEventSubscriber(subscribeInfo)
36 {
37 LOGI("init first to create network of default user");
38 lock_guard<mutex> lock(serializer_);
39 curUsrId_ = GetCurrentUserId();
40 if (curUsrId_ == INVALID_USER_ID) {
41 LOGE("GetCurrentUserId Fail");
42 return;
43 }
44 AddMPInfo(curUsrId_, SAME_ACCOUNT);
45 auto dm = DeviceManagerAgent::GetInstance();
46 dm->Recv(make_unique<DfsuCmd<DeviceManagerAgent>>(&DeviceManagerAgent::InitDeviceInfos));
47 LOGI("init first to create network of user %{public}d, done", curUsrId_);
48 }
49
~OsAccountObserver()50 OsAccountObserver::~OsAccountObserver()
51 {
52 }
53
AddMPInfo(const int id,const std::string & relativePath)54 void OsAccountObserver::AddMPInfo(const int id, const std::string &relativePath)
55 {
56 auto smp = make_shared<MountPoint>(Utils::DfsuMountArgumentDescriptors::Alpha(id, relativePath));
57 char resolvedPath[PATH_MAX] = {'\0'};
58 if (smp == nullptr || realpath(smp->GetMountArgument().GetCtrlPath().c_str(), resolvedPath) == nullptr) {
59 LOGI("user id: %{public}d cannot join group", id);
60 needAddUserId_.store(id);
61 return;
62 }
63 auto dm = DeviceManagerAgent::GetInstance();
64 dm->Recv(make_unique<DfsuCmd<DeviceManagerAgent, weak_ptr<MountPoint>>>(&DeviceManagerAgent::JoinGroup, smp));
65 mountPoints_[id].emplace_back(smp);
66 }
67
OnReceiveEvent(const EventFwk::CommonEventData & eventData)68 void OsAccountObserver::OnReceiveEvent(const EventFwk::CommonEventData &eventData)
69 {
70 const AAFwk::Want& want = eventData.GetWant();
71 std::string action = want.GetAction();
72 LOGI("AccountSubscriber: OnReceiveEvent action:%{public}s.", action.c_str());
73 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
74 int32_t id = eventData.GetCode();
75 LOGI("user id changed to %{public}d", id);
76 lock_guard<mutex> lock(serializer_);
77 if (curUsrId_ != -1 && curUsrId_ != id) {
78 // first stop curUsrId_ network
79 RemoveMPInfo(curUsrId_);
80 } else if (curUsrId_ != -1 && curUsrId_ == id) {
81 return;
82 }
83
84 // then start new network
85 curUsrId_ = id;
86 AddMPInfo(id, SAME_ACCOUNT);
87 LOGI("user id %{public}d, add network done", curUsrId_);
88 } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) {
89 int32_t id = eventData.GetCode();
90 LOGI("user id: %{public}d unlocked", id);
91 lock_guard<mutex> lock(serializer_);
92 if (needAddUserId_.load() == id) {
93 LOGI("user id: %{public}d now begin to join group", id);
94 AddMPInfo(id, SAME_ACCOUNT);
95 }
96 needAddUserId_.store(-1);
97 } else {
98 LOGE("no expect action");
99 }
100 }
101
RemoveMPInfo(const int id)102 void OsAccountObserver::RemoveMPInfo(const int id)
103 {
104 auto iter = mountPoints_.find(id);
105 if (iter == mountPoints_.end()) {
106 LOGE("user id %{public}d not find in map", curUsrId_);
107 return;
108 }
109
110 auto dm = DeviceManagerAgent::GetInstance();
111 for (auto smp : iter->second) {
112 dm->Recv(make_unique<DfsuCmd<DeviceManagerAgent, shared_ptr<MountPoint>>>(&DeviceManagerAgent::QuitGroup, smp));
113 }
114 mountPoints_.erase(iter);
115
116 LOGE("remove mount info of user id %{public}d", id);
117 }
118
GetCurrentUserId()119 int32_t OsAccountObserver::GetCurrentUserId()
120 {
121 std::vector<int32_t> userIds{};
122 auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(userIds);
123 if (ret != NO_ERROR || userIds.empty()) {
124 LOGE("query active os account id failed, ret = %{public}d", ret);
125 return INVALID_USER_ID;
126 }
127 return userIds[0];
128 }
129 } // namespace DistributedFile
130 } // namespace Storage
131 } // namespace OHOS
132