1  /*
2   * Copyright (c) 2022-2024 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 "distributed_sched_test_util.h"
17  
18  #include <future>
19  
20  #include "accesstoken_kit.h"
21  #include "bundle_installer_interface.h"
22  #include "if_system_ability_manager.h"
23  #include "iservice_registry.h"
24  #include "nativetoken_kit.h"
25  #include "nocopyable.h"
26  #include "status_receiver_host.h"
27  #include "status_receiver_interface.h"
28  #include "system_ability_definition.h"
29  #include "token_setproc.h"
30  
31  #include "dtbschedmgr_log.h"
32  
33  namespace OHOS {
34  namespace DistributedSchedule {
35  using namespace AppExecFwk;
36  namespace {
37  const std::string TAG = "DistributedSchedUtil";
38  const char* DISTSCHED_PROCESS_NAME = "distributedsched";
39  constexpr int32_t DMS_LOAD_SA_TIMEOUT_MS = 10000;
40  constexpr int32_t USER_ID = 100;
41  constexpr int32_t PERMS_NUM = 4;
42  constexpr int32_t FAILED_RETURN = -1;
43  }
44  
45  class StatusReceiverImpl : public StatusReceiverHost {
46  public:
47      StatusReceiverImpl();
48      ~StatusReceiverImpl() override;
49      void OnStatusNotify(const int progress) override;
50      void OnFinished(const int32_t resultCode, const std::string &resultMsg) override;
51  
52  private:
53      mutable std::promise<std::string> resultMsgSignal_;
54      int iProgress_ = 0;
55  
56      DISALLOW_COPY_AND_MOVE(StatusReceiverImpl);
57  };
58  
StatusReceiverImpl()59  StatusReceiverImpl::StatusReceiverImpl()
60  {
61      HILOGI("create status receiver instance");
62  }
63  
~StatusReceiverImpl()64  StatusReceiverImpl::~StatusReceiverImpl()
65  {
66      HILOGI("destroy status receiver instance");
67  }
68  
OnStatusNotify(const int progress)69  void StatusReceiverImpl::OnStatusNotify(const int progress)
70  {
71      iProgress_ = progress;
72      HILOGI("OnStatusNotify progress:%{public}d", progress);
73  }
74  
OnFinished(const int32_t resultCode,const std::string & resultMsg)75  void StatusReceiverImpl::OnFinished(const int32_t resultCode, const std::string &resultMsg)
76  {
77      HILOGI("on finished result is %{public}d, %{public}s", resultCode, resultMsg.c_str());
78      resultMsgSignal_.set_value(resultMsg);
79  }
80  
81  sptr<IRemoteObject> DistributedSchedUtil::remote_ = nullptr;
82  std::mutex DistributedSchedUtil::remoteMutex_;
83  std::condition_variable DistributedSchedUtil::remoteConVar_;
84  
MockPermission()85  void DistributedSchedUtil::MockPermission()
86  {
87      static const char *perms[] = {
88          "ohos.permission.ABILITY_BACKGROUND_COMMUNICATION",
89          "ohos.permission.ACCESS_SERVICE_DM",
90          "ohos.permission.DISTRIBUTED_DATASYNC",
91          "ohos.permission.RUNNING_STATE_OBSERVER"
92  
93      };
94      MockProcessAndPermission(DISTSCHED_PROCESS_NAME, perms, PERMS_NUM);
95  }
96  
MockBundlePermission()97  void DistributedSchedUtil::MockBundlePermission()
98  {
99      static const char *perms[] = {
100          "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
101      };
102      MockProcessAndPermission("DistributedSchedPermissionTest", perms, sizeof(perms) / sizeof(perms[0]));
103  }
104  
MockManageMissions()105  void DistributedSchedUtil::MockManageMissions()
106  {
107      static const char *perms[] = {
108          "ohos.permission.MANAGE_MISSIONS"
109      };
110      MockProcessAndPermission("DistributedSchedPermissionTest", perms, sizeof(perms) / sizeof(perms[0]));
111  }
112  
MockProcess(const char * processName)113  void DistributedSchedUtil::MockProcess(const char* processName)
114  {
115      MockProcessAndPermission(processName);
116  }
117  
GetBundleManager()118  sptr<AppExecFwk::IBundleMgr> DistributedSchedUtil::GetBundleManager()
119  {
120      sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
121      if (samgrProxy == nullptr) {
122          return nullptr;
123      }
124      sptr<IRemoteObject> bmsProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
125      if (bmsProxy == nullptr) {
126          HILOGE("failed to get bms from samgr");
127          return nullptr;
128      }
129      return iface_cast<AppExecFwk::IBundleMgr>(bmsProxy);
130  }
131  
MockProcessAndPermission(const char * processName,const char * perms[],int32_t permsNum)132  void DistributedSchedUtil::MockProcessAndPermission(const char* processName, const char *perms[], int32_t permsNum)
133  {
134      uint64_t tokenId;
135      NativeTokenInfoParams infoInstance = {
136          .dcapsNum = 0,
137          .permsNum = permsNum,
138          .aclsNum = 0,
139          .dcaps = nullptr,
140          .perms = perms,
141          .acls = nullptr,
142          .processName = processName,
143          .aplStr = "system_core",
144      };
145      tokenId = GetAccessTokenId(&infoInstance);
146      SetSelfTokenID(tokenId);
147      OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
148  }
149  
LoadDistributedSchedService()150  bool DistributedSchedUtil::LoadDistributedSchedService()
151  {
152      std::unique_lock<std::mutex> lock(remoteMutex_);
153      sptr<DistributedSchedLoadCallback> loadCallback(new DistributedSchedLoadCallback());
154      if (loadCallback == nullptr) {
155          HILOGE("loadCallback is nullptr");
156          return false;
157      }
158      auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
159      if (samgrProxy == nullptr) {
160          HILOGE("get samgr failed");
161          return false;
162      }
163      int32_t ret = samgrProxy->LoadSystemAbility(DISTRIBUTED_SCHED_SA_ID, loadCallback);
164      if (ret != ERR_OK) {
165          HILOGE("load dms SA failed");
166          return false;
167      }
168      auto waitStatus = remoteConVar_.wait_for(lock, std::chrono::milliseconds(DMS_LOAD_SA_TIMEOUT_MS),
169          []() { return remote_ != nullptr; });
170      if (!waitStatus) {
171          HILOGE("dms SA load timeout");
172          return false;
173      }
174      return true;
175  }
176  
LoadSystemAbilitySuccessNotify(const sptr<IRemoteObject> & remoteObject)177  void DistributedSchedUtil::LoadSystemAbilitySuccessNotify(const sptr<IRemoteObject>& remoteObject)
178  {
179      std::lock_guard<std::mutex> lock(remoteMutex_);
180      remote_ = remoteObject;
181      remoteConVar_.notify_one();
182  }
183  
LoadSystemAbilityFailNotify()184  void DistributedSchedUtil::LoadSystemAbilityFailNotify()
185  {
186      std::lock_guard<std::mutex> lock(remoteMutex_);
187      remote_ = nullptr;
188  }
189  
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)190  void DistributedSchedLoadCallback::OnLoadSystemAbilitySuccess(
191      int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject)
192  {
193      HILOGD("called.");
194      DistributedSchedUtil::LoadSystemAbilitySuccessNotify(remoteObject);
195  }
196  
OnLoadSystemAbilityFail(int32_t systemAbilityId)197  void DistributedSchedLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
198  {
199      HILOGD("called.");
200      DistributedSchedUtil::LoadSystemAbilityFailNotify();
201  }
202  }
203  }