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