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