1 /*
2 * Copyright (C) 2022 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 #include "download_service_ability.h"
16
17 #include <new>
18 #include <ctime>
19 #include <cinttypes>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 #include <functional>
24 #include "string_ex.h"
25 #include "access_token.h"
26 #include "errors.h"
27 #include "event_runner.h"
28 #include "inner_event.h"
29 #include "iremote_object.h"
30 #include "message_parcel.h"
31 #include "ipc_skeleton.h"
32 #include "accesstoken_kit.h"
33 #include "system_ability.h"
34 #include "system_ability_definition.h"
35 #include "dump_service_impl.h"
36 #include "task_fault.h"
37 #include "task_statistics.h"
38 #include "download_common.h"
39 #include "download_service_manager.h"
40 #include "log.h"
41
42 namespace OHOS::Request::Download {
43 using namespace OHOS::HiviewDFX;
44 using namespace Security::AccessToken;
45
46 static const std::string DOWNLOAD_PERMISSION_NAME_INTERNET = "ohos.permission.INTERNET";
47 static const std::string DOWNLOAD_PERMISSION_NAME_SESSION = "ohos.permission.DOWNLOAD_SESSION_MANAGER";
48
49
50 REGISTER_SYSTEM_ABILITY_BY_ID(DownloadServiceAbility, DOWNLOAD_SERVICE_ID, true);
51 const std::int64_t INIT_INTERVAL = 5000L;
52 // const std::int64_t INTERVAL_ZERO = 0L;
53 std::mutex DownloadServiceAbility::instanceLock_;
54 sptr<DownloadServiceAbility> DownloadServiceAbility::instance_;
55 std::shared_ptr<AppExecFwk::EventHandler> DownloadServiceAbility::serviceHandler_;
56
DownloadServiceAbility(int32_t systemAbilityId,bool runOnCreate)57 DownloadServiceAbility::DownloadServiceAbility(int32_t systemAbilityId, bool runOnCreate)
58 : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
59 {
60 }
61
~DownloadServiceAbility()62 DownloadServiceAbility::~DownloadServiceAbility()
63 {
64 DOWNLOAD_HILOGE("~DownloadServiceAbility state_ is %{public}d.", static_cast<int>(state_));
65 }
66
GetInstance()67 sptr<DownloadServiceAbility> DownloadServiceAbility::GetInstance()
68 {
69 if (instance_ == nullptr) {
70 std::lock_guard<std::mutex> autoLock(instanceLock_);
71 if (instance_ == nullptr) {
72 instance_ = new DownloadServiceAbility(DOWNLOAD_SERVICE_ID, true);
73 }
74 }
75 return instance_;
76 }
77
Init()78 int32_t DownloadServiceAbility::Init()
79 {
80 bool ret = Publish(DownloadServiceAbility::GetInstance());
81 if (!ret) {
82 DOWNLOAD_HILOGE("DownloadServiceAbility Publish failed.");
83 return E_DOWNLOAD_PUBLISH_FAIL;
84 }
85 auto instance = DownloadServiceManager::GetInstance();
86 if (instance == nullptr) {
87 DOWNLOAD_HILOGE("DownloadServiceManager is null");
88 return ERR_INVALID_VALUE;
89 }
90 state_ = ServiceRunningState::STATE_RUNNING;
91 uint32_t threadNum = 4;
92 DOWNLOAD_HILOGI("Start Download Service Manager with %{public}d threas", threadNum);
93 instance->Create(threadNum);
94 DOWNLOAD_HILOGE("state_ is %{public}d.", static_cast<int>(state_));
95 DOWNLOAD_HILOGI("Init DownloadServiceAbility success.");
96 return ERR_OK;
97 }
98
OnStart()99 void DownloadServiceAbility::OnStart()
100 {
101 DOWNLOAD_HILOGI("DownloadServiceAbility::Enter OnStart.");
102 if (instance_ == nullptr) {
103 instance_ = this;
104 }
105 if (state_ == ServiceRunningState::STATE_RUNNING) {
106 DOWNLOAD_HILOGI("DownloadServiceAbility is already running.");
107 return;
108 }
109 InitServiceHandler();
110 TaskStatistics::GetInstance().StartTimerThread();
111
112 int32_t ret = Init();
113 if (ret != ERR_OK) {
114 TaskFault::GetInstance().ReportServiceStartFault(ret);
115 auto callback = [ = ]() { Init(); };
116 serviceHandler_->PostTask(callback, INIT_INTERVAL);
117 DOWNLOAD_HILOGE("DownloadServiceAbility Init failed. Try again 5s later");
118 return;
119 }
120 state_ = ServiceRunningState::STATE_RUNNING;
121 return;
122 }
123
InitServiceHandler()124 void DownloadServiceAbility::InitServiceHandler()
125 {
126 DOWNLOAD_HILOGI("InitServiceHandler started.");
127 if (serviceHandler_ != nullptr) {
128 DOWNLOAD_HILOGI("InitServiceHandler already init.");
129 return;
130 }
131 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("DownloadServiceAbility");
132 serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
133 DOWNLOAD_HILOGI("InitServiceHandler succeeded.");
134 }
135
ManualStart()136 void DownloadServiceAbility::ManualStart()
137 {
138 if (state_ != ServiceRunningState::STATE_RUNNING) {
139 DOWNLOAD_HILOGI("DownloadServiceAbility restart.");
140 OnStart();
141 }
142 }
143
OnStop()144 void DownloadServiceAbility::OnStop()
145 {
146 DOWNLOAD_HILOGI("OnStop started.");
147 if (state_ != ServiceRunningState::STATE_RUNNING) {
148 return;
149 }
150 auto instance = DownloadServiceManager::GetInstance();
151 if (instance == nullptr) {
152 DOWNLOAD_HILOGE("DownloadServiceManager is null");
153 return;
154 }
155 instance->Destroy();
156 serviceHandler_ = nullptr;
157 instance_ = nullptr;
158 state_ = ServiceRunningState::STATE_NOT_START;
159 DOWNLOAD_HILOGI("OnStop end.");
160 }
161
Request(const DownloadConfig & config,ExceptionError & err)162 int32_t DownloadServiceAbility::Request(const DownloadConfig &config, ExceptionError &err)
163 {
164 ManualStart();
165 int32_t taskId = -1;
166 auto instance = DownloadServiceManager::GetInstance();
167 if (instance == nullptr) {
168 DOWNLOAD_HILOGE("DownloadServiceManager is null");
169 err.code = EXCEPTION_SERVICE_ERROR;
170 err.errInfo = "DownloadServiceManager is null";
171 return taskId;
172 }
173 taskId = static_cast<int32_t>(instance->AddTask(config));
174 if (taskId < 0) {
175 DOWNLOAD_HILOGE("taskId [%{public}d] is invalid, config url: %{public}s",
176 taskId, config.GetUrl().c_str());
177 err.code = EXCEPTION_SERVICE_ERROR;
178 err.errInfo = "taskId "+ std::to_string(taskId) + " is invalid, config url: " + config.GetUrl();
179 return taskId;
180 }
181 instance->InstallCallback(taskId, NotifyHandler);
182 DOWNLOAD_HILOGI("DownloadServiceAbility Allocate Task[%{public}d] started.", taskId);
183 return taskId;
184 }
185
Pause(uint32_t taskId)186 bool DownloadServiceAbility::Pause(uint32_t taskId)
187 {
188 ManualStart();
189 auto instance = DownloadServiceManager::GetInstance();
190 if (instance == nullptr) {
191 DOWNLOAD_HILOGE("DownloadServiceManager is null");
192 return false;
193 }
194 DOWNLOAD_HILOGI("DownloadServiceAbility Pause started.");
195 return instance->Pause(taskId, IPCSkeleton::GetCallingUid());
196 }
197
Query(uint32_t taskId,DownloadInfo & info)198 bool DownloadServiceAbility::Query(uint32_t taskId, DownloadInfo &info)
199 {
200 ManualStart();
201 auto instance = DownloadServiceManager::GetInstance();
202 if (instance == nullptr) {
203 DOWNLOAD_HILOGE("DownloadServiceManager is null");
204 return false;
205 }
206 DOWNLOAD_HILOGI("DownloadServiceAbility Query started.");
207 return instance->Query(taskId, IPCSkeleton::GetCallingUid(), info);
208 }
209
QueryMimeType(uint32_t taskId,std::string & mimeType)210 bool DownloadServiceAbility::QueryMimeType(uint32_t taskId, std::string &mimeType)
211 {
212 ManualStart();
213 auto instance = DownloadServiceManager::GetInstance();
214 if (instance == nullptr) {
215 DOWNLOAD_HILOGE("DownloadServiceManager is null");
216 return false;
217 }
218 DOWNLOAD_HILOGI("DownloadServiceAbility QueryMimeType started.");
219 return instance->QueryMimeType(taskId, IPCSkeleton::GetCallingUid(), mimeType);
220 }
221
Remove(uint32_t taskId)222 bool DownloadServiceAbility::Remove(uint32_t taskId)
223 {
224 ManualStart();
225 auto instance = DownloadServiceManager::GetInstance();
226 if (instance == nullptr) {
227 DOWNLOAD_HILOGE("DownloadServiceManager is null");
228 return false;
229 }
230 DOWNLOAD_HILOGI("DownloadServiceAbility Remove started.");
231 return instance->Remove(taskId, IPCSkeleton::GetCallingUid());
232 }
233
Resume(uint32_t taskId)234 bool DownloadServiceAbility::Resume(uint32_t taskId)
235 {
236 ManualStart();
237 auto instance = DownloadServiceManager::GetInstance();
238 if (instance == nullptr) {
239 DOWNLOAD_HILOGE("DownloadServiceManager is null");
240 return false;
241 }
242 DOWNLOAD_HILOGI("DownloadServiceAbility Resume started.");
243 return instance->Resume(taskId, IPCSkeleton::GetCallingUid());
244 }
245
On(uint32_t taskId,const std::string & type,const sptr<DownloadNotifyInterface> & listener)246 bool DownloadServiceAbility::On(uint32_t taskId, const std::string &type, const sptr<DownloadNotifyInterface> &listener)
247 {
248 std::string combineType = type + "-" + std::to_string(taskId);
249 DOWNLOAD_HILOGI("DownloadServiceAbility::On started. type=%{public}s", combineType.c_str());
250 auto iter = registeredListeners_.find(combineType);
251 if (iter == registeredListeners_.end()) {
252 std::lock_guard<std::mutex> lck(listenerMapMutex_);
253 std::pair<std::string, sptr<DownloadNotifyInterface>> newObj(combineType, listener);
254 const auto temp = registeredListeners_.insert(newObj);
255 if (!temp.second) {
256 DOWNLOAD_HILOGE("DownloadServiceAbility::On insert type=%{public}s object fail.", combineType.c_str());
257 return false;
258 }
259 if (DoUnregisteredNotify(taskId, type)) {
260 DOWNLOAD_HILOGD("notify unregistered on event");
261 }
262 } else {
263 std::lock_guard<std::mutex> lck(listenerMapMutex_);
264 DOWNLOAD_HILOGI("DownloadServiceAbility::On Replace listener.");
265 registeredListeners_[combineType] = listener;
266 }
267 DOWNLOAD_HILOGI("DownloadServiceAbility::On end.");
268 return true;
269 }
270
Off(uint32_t taskId,const std::string & type)271 bool DownloadServiceAbility::Off(uint32_t taskId, const std::string &type)
272 {
273 std::string combineType = type + "-" + std::to_string(taskId);
274 DOWNLOAD_HILOGI("DownloadServiceAbility::Off started.");
275 auto iter = registeredListeners_.find(combineType);
276 if (iter != registeredListeners_.end()) {
277 DOWNLOAD_HILOGE("DownloadServiceAbility::Off delete type=%{public}s object message.", combineType.c_str());
278 std::lock_guard<std::mutex> lck(listenerMapMutex_);
279 registeredListeners_.erase(iter);
280 return true;
281 }
282 return false;
283 }
284
CheckPermission()285 bool DownloadServiceAbility::CheckPermission()
286 {
287 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
288 TypeATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
289 if (tokenType == TOKEN_INVALID) {
290 DOWNLOAD_HILOGE("invalid token id %{public}d", tokenId);
291 return false;
292 }
293 int result = AccessTokenKit::VerifyAccessToken(tokenId, DOWNLOAD_PERMISSION_NAME_INTERNET);
294 if (result != PERMISSION_GRANTED) {
295 DOWNLOAD_HILOGE("Current tokenId permission is %{public}d", result);
296 }
297 return result == PERMISSION_GRANTED;
298 }
299
NotifyHandler(const std::string & type,uint32_t taskId,int64_t argv1,int64_t argv2,bool isNotify)300 void DownloadServiceAbility::NotifyHandler(const std::string &type, uint32_t taskId, int64_t argv1, int64_t argv2,
301 bool isNotify)
302 {
303 if (!isNotify) {
304 DOWNLOAD_HILOGE("isNotify false");
305 return;
306 }
307 std::string combineType = type + "-" + std::to_string(taskId);
308 DOWNLOAD_HILOGD("combineType=%{public}s argv1=%{public}" PRId64 "argv2=%{public}" PRId64, combineType.c_str(),
309 argv1, argv2);
310 auto iter = DownloadServiceAbility::GetInstance()->registeredListeners_.find(combineType);
311 if (iter != DownloadServiceAbility::GetInstance()->registeredListeners_.end()) {
312 DOWNLOAD_HILOGD("DownloadServiceAbility::NotifyHandler type=%{public}s object message.", combineType.c_str());
313 std::vector<int64_t> params;
314 params.push_back(argv1);
315 params.push_back(argv2);
316 iter->second->CallBack(params);
317 } else {
318 DownloadServiceAbility::GetInstance()->AddUnregisteredNotify(taskId, type);
319 }
320 }
321
OnDump()322 void DownloadServiceAbility::OnDump()
323 {
324 std::lock_guard<std::mutex> guard(lock_);
325 struct tm *timeNow = nullptr;
326 time_t second = time(0);
327 if (second > 0) {
328 timeNow = localtime(&second);
329 if (timeNow != nullptr) {
330 DOWNLOAD_HILOGI(
331 "DownloadServiceAbility dump time:%{public}d-%{public}d-%{public}d %{public}d:%{public}d:%{public}d",
332 timeNow->tm_year + startTime_, timeNow->tm_mon + extraMonth_, timeNow->tm_mday, timeNow->tm_hour,
333 timeNow->tm_min, timeNow->tm_sec);
334 }
335 } else {
336 DOWNLOAD_HILOGI("DownloadServiceAbility dump, time(0) is nullptr");
337 }
338 }
339
Dump(int fd,const std::vector<std::u16string> & args)340 int DownloadServiceAbility::Dump(int fd, const std::vector<std::u16string> &args)
341 {
342 int uid = static_cast<int>(IPCSkeleton::GetCallingUid());
343 const int maxUid = 10000;
344 if (uid > maxUid) {
345 return 0;
346 }
347
348 std::vector<std::string> argsStr;
349 for (auto item : args) {
350 argsStr.emplace_back(Str16ToStr8(item));
351 }
352
353 return DumpServiceImpl::GetInstance().Dump(fd, argsStr);
354 }
355
AddUnregisteredNotify(uint32_t taskId,const std::string & type)356 void DownloadServiceAbility::AddUnregisteredNotify(uint32_t taskId, const std::string &type)
357 {
358 std::string combineType = type + "-" + std::to_string(taskId);
359 DOWNLOAD_HILOGD("add combineType %{public}s", combineType.c_str());
360 if (type == EVENT_COMPLETE || type == EVENT_FAIL) {
361 std::lock_guard<std::mutex> lck(unregisteredNotifyMutex_);
362 auto iter = unregisteredNotify_.find(combineType);
363 if (iter == unregisteredNotify_.end()) {
364 unregisteredNotify_.insert(std::make_pair(combineType, taskId));
365 }
366 }
367 }
368
DoUnregisteredNotify(uint32_t taskId,const std::string & type)369 bool DownloadServiceAbility::DoUnregisteredNotify(uint32_t taskId, const std::string &type)
370 {
371 std::string combineType = type + "-" + std::to_string(taskId);
372 DOWNLOAD_HILOGD("notify combineType: %{public}s", combineType.c_str());
373 DownloadInfo info;
374 if (!Query(taskId, info)) {
375 DOWNLOAD_HILOGD("not find task download info");
376 return false;
377 }
378 auto status = info.GetStatus();
379 uint32_t code = 0;
380 if (info.GetFailedReason() != ERROR_UNKNOWN) {
381 code = static_cast<uint32_t>(info.GetFailedReason());
382 }
383 std::lock_guard<std::mutex> lck(unregisteredNotifyMutex_);
384 auto iter = unregisteredNotify_.find(combineType);
385 if (iter != unregisteredNotify_.end()) {
386 if (status == SESSION_SUCCESS || status == SESSION_FAILED) {
387 DOWNLOAD_HILOGD("notify taskId: %{public}d event: %{public}s", taskId, type.c_str());
388 NotifyHandler(type, taskId, code, 0, true);
389 unregisteredNotify_.erase(iter);
390 return true;
391 }
392 }
393 return false;
394 }
395 } // namespace OHOS::Request::Download
396