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