1 /*
2  * Copyright (c) 2021-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 "data_ability_record.h"
17 
18 #include "ability_util.h"
19 #include "connection_state_manager.h"
20 
21 namespace OHOS {
22 namespace AAFwk {
DataAbilityRecord(const AbilityRequest & req)23 DataAbilityRecord::DataAbilityRecord(const AbilityRequest &req) : request_(req)
24 {
25     TAG_LOGD(AAFwkTag::DATA_ABILITY, "called");
26 
27     if (request_.abilityInfo.type != AppExecFwk::AbilityType::DATA) {
28         TAG_LOGE(AAFwkTag::DATA_ABILITY, "wrong ability type");
29     }
30 }
31 
~DataAbilityRecord()32 DataAbilityRecord::~DataAbilityRecord()
33 {
34     TAG_LOGD(AAFwkTag::DATA_ABILITY, "called");
35 }
36 
StartLoading()37 int DataAbilityRecord::StartLoading()
38 {
39     TAG_LOGI(AAFwkTag::DATA_ABILITY, "called");
40 
41     if (ability_ || scheduler_) {
42         TAG_LOGE(AAFwkTag::DATA_ABILITY, "already started");
43         return ERR_ALREADY_EXISTS;
44     }
45 
46     if (request_.abilityInfo.type != AppExecFwk::AbilityType::DATA) {
47         TAG_LOGE(AAFwkTag::DATA_ABILITY, "wrong ability type");
48         return ERR_INVALID_VALUE;
49     }
50 
51     auto ability = AbilityRecord::CreateAbilityRecord(request_);
52     if (!ability) {
53         TAG_LOGE(AAFwkTag::DATA_ABILITY, "allocate ability failed");
54         return ERR_NO_MEMORY;
55     }
56 
57     int ret = ability->LoadAbility();
58     if (ret != ERR_OK) {
59         TAG_LOGE(AAFwkTag::DATA_ABILITY, "LoadAbility failed");
60         return ret;
61     }
62 
63     ability_ = ability;
64 
65     // Ability state is 'INITIAL' now.
66 
67     return ERR_OK;
68 }
69 
WaitForLoaded(ffrt::mutex & mutex,const std::chrono::system_clock::duration & timeout)70 int DataAbilityRecord::WaitForLoaded(ffrt::mutex &mutex, const std::chrono::system_clock::duration &timeout)
71 {
72     CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE);
73 
74     // Data ability uses 'ACTIVATE' as loaded state.
75     if (ability_->GetAbilityState() == ACTIVE) {
76         return ERR_OK;
77     }
78 
79     std::unique_lock<ffrt::mutex> lock(mutex, std::adopt_lock);
80     auto ret = loadedCond_.wait_for(lock, timeout, [this] { return ability_->GetAbilityState() == ACTIVE; });
81     if (!ret) {
82         return ERR_TIMED_OUT;
83     }
84 
85     if (!scheduler_ || ability_->GetAbilityState() != ACTIVE) {
86         return ERR_INVALID_STATE;
87     }
88 
89     return ERR_OK;
90 }
91 
GetScheduler()92 sptr<IAbilityScheduler> DataAbilityRecord::GetScheduler()
93 {
94     // Check if data ability is attached.
95     CHECK_POINTER_AND_RETURN(ability_, nullptr);
96     CHECK_POINTER_AND_RETURN(scheduler_, nullptr);
97 
98     // Check if data ability is loaded.
99     if (ability_->GetAbilityState() != ACTIVE) {
100         return nullptr;
101     }
102 
103     return scheduler_;
104 }
105 
Attach(const sptr<IAbilityScheduler> & scheduler)106 int DataAbilityRecord::Attach(const sptr<IAbilityScheduler> &scheduler)
107 {
108     TAG_LOGD(AAFwkTag::DATA_ABILITY, "called");
109 
110     if (!scheduler) {
111         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid scheduler");
112         return ERR_INVALID_DATA;
113     }
114 
115     if (!ability_) {
116         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not startloading");
117         return ERR_INVALID_STATE;
118     }
119 
120     if (scheduler_) {
121         TAG_LOGE(AAFwkTag::DATA_ABILITY, "already attached");
122         return ERR_INVALID_STATE;
123     }
124 
125     // INITIAL => ACTIVATING
126 
127     if (ability_->GetAbilityState() != INITIAL) {
128         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not in 'INITIAL' state");
129         return ERR_INVALID_STATE;
130     }
131 
132     TAG_LOGD(AAFwkTag::DATA_ABILITY, "Attaching");
133     ability_->SetScheduler(scheduler);
134     scheduler_ = scheduler;
135 
136     TAG_LOGI(AAFwkTag::DATA_ABILITY, "Scheduling 'OnStart' for '%{public}s|%{public}s'",
137         ability_->GetApplicationInfo().bundleName.c_str(),
138         ability_->GetAbilityInfo().name.c_str());
139 
140     ability_->SetAbilityState(ACTIVATING);
141 
142     LifeCycleStateInfo state;
143     state.state = AbilityLifeCycleState::ABILITY_STATE_ACTIVE;
144 
145     scheduler->ScheduleAbilityTransaction(ability_->GetWant(), state);
146 
147     return ERR_OK;
148 }
149 
OnTransitionDone(int state)150 int DataAbilityRecord::OnTransitionDone(int state)
151 {
152     CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE);
153     CHECK_POINTER_AND_RETURN(scheduler_, ERR_INVALID_STATE);
154 
155     if (ability_->GetAbilityState() != ACTIVATING) {
156         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not in 'ACTIVATING' state");
157         return ERR_INVALID_STATE;
158     }
159 
160     if (state != AbilityLifeCycleState::ABILITY_STATE_ACTIVE) {
161         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not ACTIVE");
162         ability_->SetAbilityState(INITIAL);
163         loadedCond_.notify_all();
164         return ERR_INVALID_STATE;
165     }
166 
167     // ACTIVATING => ACTIVE(loaded):
168     // Set loaded state, data ability uses 'ACTIVE' as loaded state.
169 
170     ability_->SetAbilityState(ACTIVE);
171     loadedCond_.notify_all();
172 
173     TAG_LOGI(AAFwkTag::DATA_ABILITY, "'%{public}s|%{public}s' loaded",
174         ability_->GetApplicationInfo().bundleName.c_str(),
175         ability_->GetAbilityInfo().name.c_str());
176 
177     return ERR_OK;
178 }
179 
AddClient(const sptr<IRemoteObject> & client,bool tryBind,bool isNotHap)180 int DataAbilityRecord::AddClient(const sptr<IRemoteObject> &client, bool tryBind, bool isNotHap)
181 {
182     if (!client) {
183         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid param");
184         return ERR_INVALID_STATE;
185     }
186 
187     if (!ability_ || !scheduler_) {
188         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not attached");
189         return ERR_INVALID_STATE;
190     }
191 
192     if (ability_->GetAbilityState() != ACTIVE) {
193         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
194         return ERR_INVALID_STATE;
195     }
196 
197     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
198     if (!appScheduler) {
199         TAG_LOGE(AAFwkTag::DATA_ABILITY, "get appScheduler failed");
200         return ERR_NULL_OBJECT;
201     }
202 
203     TAG_LOGI(AAFwkTag::DATA_ABILITY, "add death monitoring for caller");
204     if (client != nullptr && callerDeathRecipient_ != nullptr) {
205         client->RemoveDeathRecipient(callerDeathRecipient_);
206     }
207     if (callerDeathRecipient_ == nullptr) {
208         std::weak_ptr<DataAbilityRecord> thisWeakPtr(weak_from_this());
209         callerDeathRecipient_ = new DataAbilityCallerRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
210             auto dataAbilityRecord = thisWeakPtr.lock();
211             if (dataAbilityRecord) {
212                 dataAbilityRecord->OnSchedulerDied(remote);
213             }
214         });
215     }
216     if (client != nullptr) {
217         client->AddDeathRecipient(callerDeathRecipient_);
218     }
219 
220     // One client can be added multi-times, so 'RemoveClient()' must be called in corresponding times.
221     auto &clientInfo = clients_.emplace_back();
222     clientInfo.client = client;
223     clientInfo.tryBind = tryBind;
224     clientInfo.isNotHap = isNotHap;
225     clientInfo.clientPid = IPCSkeleton::GetCallingPid();
226 
227     return ERR_OK;
228 }
229 
RemoveClient(const sptr<IRemoteObject> & client,bool isNotHap)230 int DataAbilityRecord::RemoveClient(const sptr<IRemoteObject> &client, bool isNotHap)
231 {
232     TAG_LOGI(AAFwkTag::DATA_ABILITY, "called");
233 
234     if (!client) {
235         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid client");
236         return ERR_INVALID_STATE;
237     }
238 
239     if (!ability_ || !scheduler_) {
240         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not attached");
241         return ERR_INVALID_STATE;
242     }
243 
244     if (ability_->GetAbilityState() != ACTIVE) {
245         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
246         return ERR_INVALID_STATE;
247     }
248 
249     if (clients_.empty()) {
250         TAG_LOGD(AAFwkTag::DATA_ABILITY, "no clients");
251         return ERR_OK;
252     }
253 
254     for (auto it(clients_.begin()); it != clients_.end(); ++it) {
255         if (it->client == client) {
256             clients_.erase(it);
257             TAG_LOGI(AAFwkTag::DATA_ABILITY, "Data ability '%{public}s|%{public}s'",
258                 ability_->GetApplicationInfo().bundleName.c_str(),
259                 ability_->GetAbilityInfo().name.c_str());
260             break;
261         }
262     }
263 
264     return ERR_OK;
265 }
266 
RemoveClients(const std::shared_ptr<AbilityRecord> & client)267 int DataAbilityRecord::RemoveClients(const std::shared_ptr<AbilityRecord> &client)
268 {
269     TAG_LOGD(AAFwkTag::DATA_ABILITY, "called");
270 
271     if (!ability_ || !scheduler_) {
272         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not attached");
273         return ERR_INVALID_STATE;
274     }
275 
276     if (ability_->GetAbilityState() != ACTIVE) {
277         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
278         return ERR_INVALID_STATE;
279     }
280 
281     if (clients_.empty()) {
282         TAG_LOGD(AAFwkTag::DATA_ABILITY, "no clients");
283         return ERR_OK;
284     }
285 
286     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
287     if (!appScheduler) {
288         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid app scheduler");
289         return ERR_NULL_OBJECT;
290     }
291 
292     if (client) {
293         TAG_LOGD(AAFwkTag::DATA_ABILITY, "Removing with filter");
294         auto it = clients_.begin();
295         while (it != clients_.end()) {
296             if (!it->isNotHap) {
297                 auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
298                 if (!clientAbilityRecord) {
299                     TAG_LOGE(AAFwkTag::DATA_ABILITY, "null clientAbilityRecord");
300                     ++it;
301                     continue;
302                 }
303                 if (clientAbilityRecord == client) {
304                     appScheduler->AbilityBehaviorAnalysis(
305                         ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 0);
306                     it = clients_.erase(it);
307                     TAG_LOGI(AAFwkTag::DATA_ABILITY,
308                         "Ability '%{public}s|%{public}s' --X-> Data ability '%{public}s|%{public}s'",
309                         client->GetApplicationInfo().bundleName.c_str(),
310                         client->GetAbilityInfo().name.c_str(),
311                         ability_->GetApplicationInfo().bundleName.c_str(),
312                         ability_->GetAbilityInfo().name.c_str());
313                 } else {
314                     ++it;
315                 }
316             } else {
317                 ++it;
318             }
319         }
320     } else {
321         TAG_LOGD(AAFwkTag::DATA_ABILITY, "Removing clients");
322         auto it = clients_.begin();
323         while (it != clients_.end()) {
324             if (!it->isNotHap) {
325                 auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
326                 if (!clientAbilityRecord) {
327                     TAG_LOGD(AAFwkTag::DATA_ABILITY, "null clientAbilityRecord");
328                     it = clients_.erase(it);
329                     continue;
330                 }
331                 appScheduler->AbilityBehaviorAnalysis(ability_->GetToken(), clientAbilityRecord->GetToken(), 0, 0, 0);
332                 it = clients_.erase(it);
333             } else {
334                 ++it;
335             }
336         }
337     }
338 
339     return ERR_OK;
340 }
341 
GetClientCount(const sptr<IRemoteObject> & client) const342 size_t DataAbilityRecord::GetClientCount(const sptr<IRemoteObject> &client) const
343 {
344     CHECK_POINTER_AND_RETURN(ability_, 0);
345     CHECK_POINTER_AND_RETURN(scheduler_, 0);
346 
347     if (ability_->GetAbilityState() != ACTIVE) {
348         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
349         return 0;
350     }
351 
352     if (client) {
353         return std::count_if(
354             clients_.begin(), clients_.end(), [client](const ClientInfo &ci) { return ci.client == client; });
355     }
356 
357     return clients_.size();
358 }
359 
KillBoundClientProcesses()360 int DataAbilityRecord::KillBoundClientProcesses()
361 {
362     CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE);
363     CHECK_POINTER_AND_RETURN(scheduler_, ERR_INVALID_STATE);
364 
365     if (ability_->GetAbilityState() != ACTIVE) {
366         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
367         return ERR_INVALID_STATE;
368     }
369 
370     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
371     if (!appScheduler) {
372         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid app scheduler");
373         return ERR_INVALID_STATE;
374     }
375 
376     for (auto it = clients_.begin(); it != clients_.end(); ++it) {
377         if (it->tryBind && it->isNotHap == false) {
378             auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
379             CHECK_POINTER_CONTINUE(clientAbilityRecord);
380             TAG_LOGI(AAFwkTag::DATA_ABILITY,
381                 "Killing bound client '%{public}s|%{public}s' of data ability '%{public}s|%{public}s'",
382                 clientAbilityRecord->GetApplicationInfo().bundleName.c_str(),
383                 clientAbilityRecord->GetAbilityInfo().name.c_str(),
384                 ability_->GetApplicationInfo().bundleName.c_str(),
385                 ability_->GetAbilityInfo().name.c_str());
386             appScheduler->KillProcessByAbilityToken(clientAbilityRecord->GetToken());
387         }
388     }
389 
390     return ERR_OK;
391 }
392 
GetRequest() const393 const AbilityRequest &DataAbilityRecord::GetRequest() const
394 {
395     return request_;
396 }
397 
GetAbilityRecord()398 std::shared_ptr<AbilityRecord> DataAbilityRecord::GetAbilityRecord()
399 {
400     return ability_;
401 }
402 
GetToken()403 sptr<IRemoteObject> DataAbilityRecord::GetToken()
404 {
405     if (!ability_) {
406         return nullptr;
407     }
408 
409     return ability_->GetToken();
410 }
411 
Dump() const412 void DataAbilityRecord::Dump() const
413 {
414     CHECK_POINTER(ability_);
415 
416     TAG_LOGI(AAFwkTag::DATA_ABILITY,
417         "attached: %{public}s, clients: %{public}zu, refcnt: %{public}d, state: %{public}s",
418         scheduler_ ? "true" : "false",
419         clients_.size(),
420         scheduler_ ? scheduler_->GetSptrRefCount() : 0,
421         AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()).c_str());
422 
423     int i = 0;
424 
425     for (auto it = clients_.begin(); it != clients_.end(); ++it) {
426         if (it->isNotHap == false) {
427             auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
428             CHECK_POINTER_CONTINUE(clientAbilityRecord);
429             TAG_LOGI(AAFwkTag::DATA_ABILITY, "  %{public}2d '%{public}s|%{public}s' - tryBind: %{public}s",
430                 i++,
431                 clientAbilityRecord->GetApplicationInfo().bundleName.c_str(),
432                 clientAbilityRecord->GetAbilityInfo().name.c_str(),
433                 it->tryBind ? "true" : "false");
434         } else {
435             TAG_LOGI(AAFwkTag::DATA_ABILITY, "  %{public}2d '%{public}s' - tryBind: %{public}s",
436                 i++,
437                 "caller is system",
438                 it->tryBind ? "true" : "false");
439         }
440     }
441 }
442 
Dump(std::vector<std::string> & info) const443 void DataAbilityRecord::Dump(std::vector<std::string> &info) const
444 {
445     CHECK_POINTER(ability_);
446     info.emplace_back("    AbilityRecord ID #" + std::to_string(ability_->GetRecordId()) + "   state #" +
447                       AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()) + "   start time [" +
448                       std::to_string(ability_->GetStartTime()) + "]");
449     info.emplace_back("    main name [" + ability_->GetAbilityInfo().name + "]");
450     info.emplace_back("    bundle name [" + ability_->GetAbilityInfo().bundleName + "]");
451     info.emplace_back("    ability type [DATA]");
452     info.emplace_back("    app state #" + AbilityRecord::ConvertAppState(ability_->GetAppState()));
453     info.emplace_back("    Clients: " + std::to_string(clients_.size()));
454 
455     for (auto &&client : clients_) {
456         if (client.isNotHap == false) {
457             auto clientAbilityRecord = Token::GetAbilityRecordByToken(client.client);
458             CHECK_POINTER_CONTINUE(clientAbilityRecord);
459             info.emplace_back("     > " + clientAbilityRecord->GetAbilityInfo().bundleName + "/" +
460                               clientAbilityRecord->GetAbilityInfo().name + "  tryBind #" +
461                               (client.tryBind ? "true" : "false") + "  isNotHap  # " +
462                               (client.isNotHap ? "true" : "false"));
463         } else {
464             info.emplace_back(std::string("     > Caller is System /  tryBind # ") +
465                               (client.tryBind ? "true" : "false") + "  isNotHap  # " +
466                               (client.isNotHap ? "true" : "false"));
467         }
468     }
469 }
470 
OnSchedulerDied(const wptr<IRemoteObject> & remote)471 void DataAbilityRecord::OnSchedulerDied(const wptr<IRemoteObject> &remote)
472 {
473     TAG_LOGI(AAFwkTag::DATA_ABILITY, "called");
474     auto object = remote.promote();
475     DelayedSingleton<ConnectionStateManager>::GetInstance()->HandleDataAbilityCallerDied(GetDiedCallerPid(object));
476 
477     if (clients_.empty()) {
478         TAG_LOGD(AAFwkTag::DATA_ABILITY, "no clients");
479         return;
480     }
481 
482     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
483     if (!appScheduler) {
484         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid app scheduler");
485         return;
486     }
487 
488     if (object) {
489         auto it = clients_.begin();
490         while (it != clients_.end()) {
491             if (it->client == object) {
492                 TAG_LOGD(AAFwkTag::DATA_ABILITY, "remove system caller");
493                 it = clients_.erase(it);
494                 TAG_LOGI(AAFwkTag::DATA_ABILITY, "Data ability '%{public}s|%{public}s'",
495                     ability_->GetApplicationInfo().bundleName.c_str(),
496                     ability_->GetAbilityInfo().name.c_str());
497             } else {
498                 ++it;
499             }
500         }
501     } else {
502         auto it = clients_.begin();
503         while (it != clients_.end()) {
504             if (it->isNotHap) {
505                 TAG_LOGD(AAFwkTag::DATA_ABILITY, "remove system caller");
506                 it = clients_.erase(it);
507                 TAG_LOGI(AAFwkTag::DATA_ABILITY, "Data ability '%{public}s|%{public}s'",
508                     ability_->GetApplicationInfo().bundleName.c_str(),
509                     ability_->GetAbilityInfo().name.c_str());
510             } else {
511                 ++it;
512             }
513         }
514     }
515 }
516 
GetDiedCallerPid(const sptr<IRemoteObject> & remote)517 int32_t DataAbilityRecord::GetDiedCallerPid(const sptr<IRemoteObject> &remote)
518 {
519     if (!remote) {
520         return 0;
521     }
522 
523     int32_t result = 0;
524     for (auto it = clients_.begin(); it != clients_.end(); it++) {
525         if (it->client == remote) {
526             result = it->clientPid;
527             break;
528         }
529     }
530 
531     return result;
532 }
533 }  // namespace AAFwk
534 }  // namespace OHOS
535