• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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");
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, "dataability '%{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                     it = clients_.erase(it);
305                     TAG_LOGI(AAFwkTag::DATA_ABILITY,
306                         "Ability '%{public}s|%{public}s' --X-> Data ability '%{public}s|%{public}s'",
307                         client->GetApplicationInfo().bundleName.c_str(),
308                         client->GetAbilityInfo().name.c_str(),
309                         ability_->GetApplicationInfo().bundleName.c_str(),
310                         ability_->GetAbilityInfo().name.c_str());
311                 } else {
312                     ++it;
313                 }
314             } else {
315                 ++it;
316             }
317         }
318         return ERR_OK;
319     }
320     auto it = clients_.begin();
321     while (it != clients_.end()) {
322         if (!it->isNotHap) {
323             auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
324             if (!clientAbilityRecord) {
325                 TAG_LOGD(AAFwkTag::DATA_ABILITY, "null clientAbilityRecord");
326                 it = clients_.erase(it);
327                 continue;
328             }
329             it = clients_.erase(it);
330         } else {
331             ++it;
332         }
333     }
334 
335     return ERR_OK;
336 }
337 
GetClientCount(const sptr<IRemoteObject> & client) const338 size_t DataAbilityRecord::GetClientCount(const sptr<IRemoteObject> &client) const
339 {
340     CHECK_POINTER_AND_RETURN(ability_, 0);
341     CHECK_POINTER_AND_RETURN(scheduler_, 0);
342 
343     if (ability_->GetAbilityState() != ACTIVE) {
344         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
345         return 0;
346     }
347 
348     if (client) {
349         return std::count_if(
350             clients_.begin(), clients_.end(), [client](const ClientInfo &ci) { return ci.client == client; });
351     }
352 
353     return clients_.size();
354 }
355 
KillBoundClientProcesses()356 int DataAbilityRecord::KillBoundClientProcesses()
357 {
358     CHECK_POINTER_AND_RETURN(ability_, ERR_INVALID_STATE);
359     CHECK_POINTER_AND_RETURN(scheduler_, ERR_INVALID_STATE);
360 
361     if (ability_->GetAbilityState() != ACTIVE) {
362         TAG_LOGE(AAFwkTag::DATA_ABILITY, "not loaded");
363         return ERR_INVALID_STATE;
364     }
365 
366     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
367     if (!appScheduler) {
368         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid app scheduler");
369         return ERR_INVALID_STATE;
370     }
371 
372     for (auto it = clients_.begin(); it != clients_.end(); ++it) {
373         if (it->tryBind && it->isNotHap == false) {
374             auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
375             CHECK_POINTER_CONTINUE(clientAbilityRecord);
376             TAG_LOGI(AAFwkTag::DATA_ABILITY,
377                 "Killing bound client '%{public}s|%{public}s' of data ability '%{public}s|%{public}s'",
378                 clientAbilityRecord->GetApplicationInfo().bundleName.c_str(),
379                 clientAbilityRecord->GetAbilityInfo().name.c_str(),
380                 ability_->GetApplicationInfo().bundleName.c_str(),
381                 ability_->GetAbilityInfo().name.c_str());
382             appScheduler->KillProcessByAbilityToken(clientAbilityRecord->GetToken());
383         }
384     }
385 
386     return ERR_OK;
387 }
388 
GetRequest() const389 const AbilityRequest &DataAbilityRecord::GetRequest() const
390 {
391     return request_;
392 }
393 
GetAbilityRecord()394 std::shared_ptr<AbilityRecord> DataAbilityRecord::GetAbilityRecord()
395 {
396     return ability_;
397 }
398 
GetToken()399 sptr<IRemoteObject> DataAbilityRecord::GetToken()
400 {
401     if (!ability_) {
402         return nullptr;
403     }
404 
405     return ability_->GetToken();
406 }
407 
Dump() const408 void DataAbilityRecord::Dump() const
409 {
410     CHECK_POINTER(ability_);
411 
412     TAG_LOGI(AAFwkTag::DATA_ABILITY,
413         "attached: %{public}s, clients: %{public}zu, refcnt: %{public}d, state: %{public}s",
414         scheduler_ ? "true" : "false",
415         clients_.size(),
416         scheduler_ ? scheduler_->GetSptrRefCount() : 0,
417         AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()).c_str());
418 
419     int i = 0;
420 
421     for (auto it = clients_.begin(); it != clients_.end(); ++it) {
422         if (it->isNotHap == false) {
423             auto clientAbilityRecord = Token::GetAbilityRecordByToken(it->client);
424             CHECK_POINTER_CONTINUE(clientAbilityRecord);
425             TAG_LOGI(AAFwkTag::DATA_ABILITY, "  %{public}2d '%{public}s|%{public}s' - tryBind: %{public}s",
426                 i++,
427                 clientAbilityRecord->GetApplicationInfo().bundleName.c_str(),
428                 clientAbilityRecord->GetAbilityInfo().name.c_str(),
429                 it->tryBind ? "true" : "false");
430         } else {
431             TAG_LOGI(AAFwkTag::DATA_ABILITY, "  %{public}2d '%{public}s' - tryBind: %{public}s",
432                 i++,
433                 "caller is system",
434                 it->tryBind ? "true" : "false");
435         }
436     }
437 }
438 
Dump(std::vector<std::string> & info) const439 void DataAbilityRecord::Dump(std::vector<std::string> &info) const
440 {
441     CHECK_POINTER(ability_);
442     info.emplace_back("    AbilityRecord ID #" + std::to_string(ability_->GetRecordId()) + "   state #" +
443                       AbilityRecord::ConvertAbilityState(ability_->GetAbilityState()) + "   start time [" +
444                       std::to_string(ability_->GetStartTime()) + "]");
445     info.emplace_back("    main name [" + ability_->GetAbilityInfo().name + "]");
446     info.emplace_back("    bundle name [" + ability_->GetAbilityInfo().bundleName + "]");
447     info.emplace_back("    ability type [DATA]");
448     info.emplace_back("    app state #" + AbilityRecord::ConvertAppState(ability_->GetAppState()));
449     info.emplace_back("    Clients: " + std::to_string(clients_.size()));
450 
451     for (auto &&client : clients_) {
452         if (client.isNotHap == false) {
453             auto clientAbilityRecord = Token::GetAbilityRecordByToken(client.client);
454             CHECK_POINTER_CONTINUE(clientAbilityRecord);
455             info.emplace_back("     > " + clientAbilityRecord->GetAbilityInfo().bundleName + "/" +
456                               clientAbilityRecord->GetAbilityInfo().name + "  tryBind #" +
457                               (client.tryBind ? "true" : "false") + "  isNotHap  # " +
458                               (client.isNotHap ? "true" : "false"));
459         } else {
460             info.emplace_back(std::string("     > Caller is System /  tryBind # ") +
461                               (client.tryBind ? "true" : "false") + "  isNotHap  # " +
462                               (client.isNotHap ? "true" : "false"));
463         }
464     }
465 }
466 
OnSchedulerDied(const wptr<IRemoteObject> & remote)467 void DataAbilityRecord::OnSchedulerDied(const wptr<IRemoteObject> &remote)
468 {
469     TAG_LOGI(AAFwkTag::DATA_ABILITY, "called");
470     auto object = remote.promote();
471     DelayedSingleton<ConnectionStateManager>::GetInstance()->HandleDataAbilityCallerDied(GetDiedCallerPid(object));
472 
473     if (clients_.empty()) {
474         TAG_LOGD(AAFwkTag::DATA_ABILITY, "no clients");
475         return;
476     }
477 
478     auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
479     if (!appScheduler) {
480         TAG_LOGE(AAFwkTag::DATA_ABILITY, "invalid app scheduler");
481         return;
482     }
483 
484     if (object) {
485         auto it = clients_.begin();
486         while (it != clients_.end()) {
487             if (it->client == object) {
488                 TAG_LOGD(AAFwkTag::DATA_ABILITY, "remove system caller");
489                 it = clients_.erase(it);
490                 TAG_LOGI(AAFwkTag::DATA_ABILITY, "dataability '%{public}s|%{public}s'",
491                     ability_->GetApplicationInfo().bundleName.c_str(),
492                     ability_->GetAbilityInfo().name.c_str());
493             } else {
494                 ++it;
495             }
496         }
497         return;
498     }
499     auto it = clients_.begin();
500     while (it != clients_.end()) {
501         if (it->isNotHap) {
502             it = clients_.erase(it);
503             TAG_LOGI(AAFwkTag::DATA_ABILITY, "dataability '%{public}s|%{public}s'",
504                 ability_->GetApplicationInfo().bundleName.c_str(),
505                 ability_->GetAbilityInfo().name.c_str());
506         } else {
507             ++it;
508         }
509     }
510 }
511 
GetDiedCallerPid(const sptr<IRemoteObject> & remote)512 int32_t DataAbilityRecord::GetDiedCallerPid(const sptr<IRemoteObject> &remote)
513 {
514     if (!remote) {
515         return 0;
516     }
517 
518     int32_t result = 0;
519     for (auto it = clients_.begin(); it != clients_.end(); it++) {
520         if (it->client == remote) {
521             result = it->clientPid;
522             break;
523         }
524     }
525 
526     return result;
527 }
528 }  // namespace AAFwk
529 }  // namespace OHOS
530