• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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