1 /*
2 * Copyright (c) 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 "permission_record_manager.h"
17
18 #include <algorithm>
19 #include <cinttypes>
20 #include <numeric>
21
22 #include "ability_manager_privacy_client.h"
23 #include "accesstoken_kit.h"
24 #include "accesstoken_log.h"
25 #include "active_status_callback_manager.h"
26 #include "audio_manager_privacy_client.h"
27 #include "app_manager_privacy_client.h"
28 #include "camera_manager_privacy_client.h"
29 #include "constant.h"
30 #include "constant_common.h"
31 #include "data_translator.h"
32 #include "i_state_change_callback.h"
33 #include "iservice_registry.h"
34 #include "permission_record_repository.h"
35 #include "permission_used_record_cache.h"
36 #include "privacy_error.h"
37 #include "privacy_field_const.h"
38 #include "state_change_callback_proxy.h"
39 #include "system_ability_definition.h"
40 #include "time_util.h"
41 #include "window_manager_privacy_client.h"
42
43 namespace OHOS {
44 namespace Security {
45 namespace AccessToken {
46 namespace {
47 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
48 LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionRecordManager"
49 };
50 static const std::string DEFAULT_DEVICEID = "0";
51 static const std::string FIELD_COUNT_NUMBER = "count";
52 constexpr const char* CAMERA_PERMISSION_NAME = "ohos.permission.CAMERA";
53 constexpr const char* MICROPHONE_PERMISSION_NAME = "ohos.permission.MICROPHONE";
54 static const std::string PERMISSION_MANAGER_BUNDLE_NAME = "com.ohos.permissionmanager";
55 static const std::string PERMISSION_MANAGER_DIALOG_ABILITY = "com.ohos.permissionmanager.GlobalExtAbility";
56 static const std::string RESOURCE_KEY = "ohos.sensitive.resource";
57 }
GetInstance()58 PermissionRecordManager& PermissionRecordManager::GetInstance()
59 {
60 static PermissionRecordManager instance;
61 return instance;
62 }
63
PermissionRecordManager()64 PermissionRecordManager::PermissionRecordManager() : hasInited_(false) {}
65
~PermissionRecordManager()66 PermissionRecordManager::~PermissionRecordManager()
67 {
68 if (!hasInited_) {
69 return;
70 }
71 deleteTaskWorker_.Stop();
72 hasInited_ = false;
73 Unregister();
74 }
75
AddRecord(const PermissionRecord & record)76 void PermissionRecordManager::AddRecord(const PermissionRecord& record)
77 {
78 Utils::UniqueWriteGuard<Utils::RWLock> lk(this->rwLock_);
79 ACCESSTOKEN_LOG_INFO(LABEL,
80 "add record: tokenId %{public}d, opCode %{public}d, status: %{public}d, timestamp: %{public}" PRId64,
81 record.tokenId, record.opCode, record.status, record.timestamp);
82 PermissionUsedRecordCache::GetInstance().AddRecordToBuffer(record);
83 }
84
GetPermissionRecord(AccessTokenID tokenId,const std::string & permissionName,int32_t successCount,int32_t failCount,PermissionRecord & record)85 int32_t PermissionRecordManager::GetPermissionRecord(AccessTokenID tokenId, const std::string& permissionName,
86 int32_t successCount, int32_t failCount, PermissionRecord& record)
87 {
88 HapTokenInfo tokenInfo;
89 if (AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo) != Constant::SUCCESS) {
90 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid tokenId(%{public}d)", tokenId);
91 return PrivacyError::ERR_TOKENID_NOT_EXIST;
92 }
93 int32_t opCode;
94 if (!Constant::TransferPermissionToOpcode(permissionName, opCode)) {
95 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid (%{public}s)", permissionName.c_str());
96 return PrivacyError::ERR_PERMISSION_NOT_EXIST;
97 }
98 if (successCount == 0 && failCount == 0) {
99 record.status = PERM_INACTIVE;
100 } else {
101 record.status = GetAppStatus(tokenId);
102 }
103 record.tokenId = tokenId;
104 record.accessCount = successCount;
105 record.rejectCount = failCount;
106 record.opCode = opCode;
107 record.timestamp = TimeUtil::GetCurrentTimestamp();
108 record.accessDuration = 0;
109 ACCESSTOKEN_LOG_DEBUG(LABEL, "record status: %{public}d", record.status);
110 return Constant::SUCCESS;
111 }
112
AddPermissionUsedRecord(AccessTokenID tokenId,const std::string & permissionName,int32_t successCount,int32_t failCount)113 int32_t PermissionRecordManager::AddPermissionUsedRecord(AccessTokenID tokenId, const std::string& permissionName,
114 int32_t successCount, int32_t failCount)
115 {
116 ExecuteDeletePermissionRecordTask();
117
118 PermissionRecord record;
119 int32_t result = GetPermissionRecord(tokenId, permissionName, successCount, failCount, record);
120 if (result != Constant::SUCCESS) {
121 return result;
122 }
123
124 if (record.status == PERM_INACTIVE) {
125 return PrivacyError::ERR_PARAM_INVALID;
126 }
127
128 AddRecord(record);
129 return Constant::SUCCESS;
130 }
131
RemovePermissionUsedRecords(AccessTokenID tokenId,const std::string & deviceID)132 void PermissionRecordManager::RemovePermissionUsedRecords(AccessTokenID tokenId, const std::string& deviceID)
133 {
134 // only support remove by tokenId(local)
135 std::string device = GetDeviceId(tokenId);
136 if (device.empty()) {
137 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid tokenId = %{public}d", tokenId);
138 return;
139 }
140
141 if (!deviceID.empty() && device != deviceID) {
142 ACCESSTOKEN_LOG_ERROR(LABEL, "deviceID mismatch");
143 return;
144 }
145
146 Utils::UniqueWriteGuard<Utils::RWLock> lk(this->rwLock_);
147 PermissionUsedRecordCache::GetInstance().RemoveRecords(tokenId); // remove from cache and database
148 }
149
GetPermissionUsedRecords(const PermissionUsedRequest & request,PermissionUsedResult & result)150 int32_t PermissionRecordManager::GetPermissionUsedRecords(
151 const PermissionUsedRequest& request, PermissionUsedResult& result)
152 {
153 ExecuteDeletePermissionRecordTask();
154
155 if (!request.isRemote && !GetRecordsFromLocalDB(request, result)) {
156 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to GetRecordsFromLocalDB");
157 return PrivacyError::ERR_PARAM_INVALID;
158 }
159 return Constant::SUCCESS;
160 }
161
GetPermissionUsedRecordsAsync(const PermissionUsedRequest & request,const sptr<OnPermissionUsedRecordCallback> & callback)162 int32_t PermissionRecordManager::GetPermissionUsedRecordsAsync(
163 const PermissionUsedRequest& request, const sptr<OnPermissionUsedRecordCallback>& callback)
164 {
165 auto task = [request, callback]() {
166 ACCESSTOKEN_LOG_INFO(LABEL, "GetPermissionUsedRecordsAsync task called");
167 PermissionUsedResult result;
168 int32_t retCode = PermissionRecordManager::GetInstance().GetPermissionUsedRecords(request, result);
169 callback->OnQueried(retCode, result);
170 };
171 std::thread recordThread(task);
172 recordThread.detach();
173 return Constant::SUCCESS;
174 }
175
GetLocalRecordTokenIdList(std::set<AccessTokenID> & tokenIdList)176 void PermissionRecordManager::GetLocalRecordTokenIdList(std::set<AccessTokenID>& tokenIdList)
177 {
178 std::vector<GenericValues> results;
179 {
180 Utils::UniqueWriteGuard<Utils::RWLock> lk(this->rwLock_);
181 // find tokenId from cache
182 PermissionUsedRecordCache::GetInstance().FindTokenIdList(tokenIdList);
183 // find tokenId from database
184 PermissionRecordRepository::GetInstance().GetAllRecordValuesByKey(PrivacyFiledConst::FIELD_TOKEN_ID, results);
185 }
186 for (const auto& res : results) {
187 tokenIdList.emplace(res.GetInt(PrivacyFiledConst::FIELD_TOKEN_ID));
188 }
189 }
190
GetRecordsFromLocalDB(const PermissionUsedRequest & request,PermissionUsedResult & result)191 bool PermissionRecordManager::GetRecordsFromLocalDB(const PermissionUsedRequest& request, PermissionUsedResult& result)
192 {
193 GenericValues andConditionValues;
194 GenericValues orConditionValues;
195 if (DataTranslator::TranslationIntoGenericValues(request, andConditionValues, orConditionValues)
196 != Constant::SUCCESS) {
197 ACCESSTOKEN_LOG_ERROR(LABEL, "query time or flag is invalid");
198 return false;
199 }
200
201 std::set<AccessTokenID> tokenIdList;
202 if (request.tokenId == 0) {
203 GetLocalRecordTokenIdList(tokenIdList);
204 } else {
205 tokenIdList.emplace(request.tokenId);
206 }
207 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetLocalRecordTokenIdList.size = %{public}zu", tokenIdList.size());
208 Utils::UniqueWriteGuard<Utils::RWLock> lk(this->rwLock_);
209 for (const auto& tokenId : tokenIdList) {
210 andConditionValues.Put(PrivacyFiledConst::FIELD_TOKEN_ID, static_cast<int32_t>(tokenId));
211 std::vector<GenericValues> findRecordsValues;
212 PermissionUsedRecordCache::GetInstance().GetRecords(request.permissionList,
213 andConditionValues, orConditionValues, findRecordsValues); // find records from cache and database
214 andConditionValues.Remove(PrivacyFiledConst::FIELD_TOKEN_ID);
215 BundleUsedRecord bundleRecord;
216 if (!CreateBundleUsedRecord(tokenId, bundleRecord)) {
217 continue;
218 }
219 if (!findRecordsValues.empty()) {
220 GetRecords(request.flag, findRecordsValues, bundleRecord, result);
221 }
222 if (!bundleRecord.permissionRecords.empty()) {
223 result.bundleRecords.emplace_back(bundleRecord);
224 }
225 }
226 return true;
227 }
228
CreateBundleUsedRecord(const AccessTokenID tokenId,BundleUsedRecord & bundleRecord)229 bool PermissionRecordManager::CreateBundleUsedRecord(const AccessTokenID tokenId, BundleUsedRecord& bundleRecord)
230 {
231 HapTokenInfo tokenInfo;
232 if (AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo) != Constant::SUCCESS) {
233 ACCESSTOKEN_LOG_ERROR(LABEL, "GetHapTokenInfo failed");
234 return false;
235 }
236 bundleRecord.tokenId = tokenId;
237 bundleRecord.isRemote = false;
238 bundleRecord.deviceId = GetDeviceId(tokenId);
239 bundleRecord.bundleName = tokenInfo.bundleName;
240 return true;
241 }
242
GetRecords(int32_t flag,std::vector<GenericValues> recordValues,BundleUsedRecord & bundleRecord,PermissionUsedResult & result)243 void PermissionRecordManager::GetRecords(
244 int32_t flag, std::vector<GenericValues> recordValues, BundleUsedRecord& bundleRecord, PermissionUsedResult& result)
245 {
246 std::vector<PermissionUsedRecord> permissionRecords;
247 for (auto it = recordValues.rbegin(); it != recordValues.rend(); ++it) {
248 GenericValues record = *it;
249 PermissionUsedRecord tmpPermissionRecord;
250 int64_t timestamp = record.GetInt64(PrivacyFiledConst::FIELD_TIMESTAMP);
251 result.beginTimeMillis = ((result.beginTimeMillis == 0) || (timestamp < result.beginTimeMillis)) ?
252 timestamp : result.beginTimeMillis;
253 result.endTimeMillis = (timestamp > result.endTimeMillis) ? timestamp : result.endTimeMillis;
254
255 record.Put(PrivacyFiledConst::FIELD_FLAG, flag);
256 if (DataTranslator::TranslationGenericValuesIntoPermissionUsedRecord(record, tmpPermissionRecord)
257 != Constant::SUCCESS) {
258 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to transform opcode(%{public}d) into permission",
259 record.GetInt(PrivacyFiledConst::FIELD_OP_CODE));
260 continue;
261 }
262
263 auto iter = std::find_if(permissionRecords.begin(), permissionRecords.end(),
264 [tmpPermissionRecord](const PermissionUsedRecord& rec) {
265 return tmpPermissionRecord.permissionName == rec.permissionName;
266 });
267 if (iter != permissionRecords.end()) {
268 UpdateRecords(flag, tmpPermissionRecord, *iter);
269 } else {
270 permissionRecords.emplace_back(tmpPermissionRecord);
271 }
272 }
273 bundleRecord.permissionRecords = permissionRecords;
274 }
275
UpdateRecords(int32_t flag,const PermissionUsedRecord & inBundleRecord,PermissionUsedRecord & outBundleRecord)276 void PermissionRecordManager::UpdateRecords(
277 int32_t flag, const PermissionUsedRecord& inBundleRecord, PermissionUsedRecord& outBundleRecord)
278 {
279 outBundleRecord.accessCount += inBundleRecord.accessCount;
280 outBundleRecord.rejectCount += inBundleRecord.rejectCount;
281 if (inBundleRecord.lastAccessTime > outBundleRecord.lastAccessTime) {
282 outBundleRecord.lastAccessTime = inBundleRecord.lastAccessTime;
283 outBundleRecord.lastAccessDuration = inBundleRecord.lastAccessDuration;
284 }
285 outBundleRecord.lastRejectTime = (inBundleRecord.lastRejectTime > outBundleRecord.lastRejectTime) ?
286 inBundleRecord.lastRejectTime : outBundleRecord.lastRejectTime;
287
288 if (flag == 0) {
289 return;
290 }
291 if (inBundleRecord.lastAccessTime > 0 && outBundleRecord.accessRecords.size() < Constant::MAX_DETAIL_RECORD) {
292 outBundleRecord.accessRecords.emplace_back(inBundleRecord.accessRecords[0]);
293 }
294 if (inBundleRecord.lastRejectTime > 0 && outBundleRecord.rejectRecords.size() < Constant::MAX_DETAIL_RECORD) {
295 outBundleRecord.rejectRecords.emplace_back(inBundleRecord.rejectRecords[0]);
296 }
297 }
298
ExecuteDeletePermissionRecordTask()299 void PermissionRecordManager::ExecuteDeletePermissionRecordTask()
300 {
301 if (deleteTaskWorker_.GetCurTaskNum() > 1) {
302 ACCESSTOKEN_LOG_INFO(LABEL, "Already has delete task!");
303 return;
304 }
305
306 auto deleteRecordsTask = [this]() {
307 ACCESSTOKEN_LOG_DEBUG(LABEL, "DeletePermissionRecord task called");
308 DeletePermissionRecord(Constant::RECORD_DELETE_TIME);
309 };
310 deleteTaskWorker_.AddTask(deleteRecordsTask);
311 }
312
DeletePermissionRecord(int32_t days)313 int32_t PermissionRecordManager::DeletePermissionRecord(int32_t days)
314 {
315 Utils::UniqueWriteGuard<Utils::RWLock> lk(this->rwLock_);
316 GenericValues countValue;
317 PermissionRecordRepository::GetInstance().CountRecordValues(countValue);
318 int64_t total = countValue.GetInt64(FIELD_COUNT_NUMBER);
319 if (total > Constant::MAX_TOTAL_RECORD) {
320 uint32_t excessiveSize = total - Constant::MAX_TOTAL_RECORD;
321 if (!PermissionRecordRepository::GetInstance().DeleteExcessiveSizeRecordValues(excessiveSize)) {
322 return Constant::FAILURE;
323 }
324 }
325 GenericValues andConditionValues;
326 int64_t deleteTimestamp = TimeUtil::GetCurrentTimestamp() - days;
327 andConditionValues.Put(PrivacyFiledConst::FIELD_TIMESTAMP_END, deleteTimestamp);
328 if (!PermissionRecordRepository::GetInstance().DeleteExpireRecordsValues(andConditionValues)) {
329 return Constant::FAILURE;
330 }
331 return Constant::SUCCESS;
332 }
333
HasStarted(const PermissionRecord & record)334 bool PermissionRecordManager::HasStarted(const PermissionRecord& record)
335 {
336 std::lock_guard<std::mutex> lock(startRecordListMutex_);
337 bool hasStarted = std::any_of(startRecordList_.begin(), startRecordList_.end(),
338 [record](const auto& rec) { return (rec.opCode == record.opCode) && (rec.tokenId == record.tokenId); });
339 if (hasStarted) {
340 ACCESSTOKEN_LOG_ERROR(LABEL, "tokenId(%{public}d), opCode(%{public}d) has been started.",
341 record.tokenId, record.opCode);
342 }
343
344 return hasStarted;
345 }
346
FindRecordsToUpdateAndExecuted(uint32_t tokenId,ActiveChangeType status,std::vector<std::string> & permList,std::vector<std::string> & camPermList)347 void PermissionRecordManager::FindRecordsToUpdateAndExecuted(uint32_t tokenId,
348 ActiveChangeType status, std::vector<std::string>& permList, std::vector<std::string>& camPermList)
349 {
350 std::lock_guard<std::mutex> lock(startRecordListMutex_);
351 for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) {
352 if ((it->tokenId == tokenId) && ((it->status) != status)) {
353 std::string perm;
354 Constant::TransferOpcodeToPermission(it->opCode, perm);
355 if (!GetGlobalSwitchStatus(perm)) {
356 continue;
357 }
358
359 // app use camera background without float window
360 bool isShow = IsFlowWindowShow(tokenId);
361 if ((perm == CAMERA_PERMISSION_NAME) && (status == PERM_ACTIVE_IN_BACKGROUND) && (!isShow)) {
362 ACCESSTOKEN_LOG_INFO(LABEL, "camera float window is close!");
363 camPermList.emplace_back(perm);
364 continue;
365 }
366 permList.emplace_back(perm);
367 int64_t curStamp = TimeUtil::GetCurrentTimestamp();
368 // update accessDuration and store in database
369 it->accessDuration = curStamp - it->timestamp;
370 AddRecord(*it);
371
372 // update status to input, accessDuration to 0 and timestamp to now in cache
373 it->status = status;
374 it->accessDuration = 0;
375 it->timestamp = curStamp;
376 ACCESSTOKEN_LOG_DEBUG(LABEL, "tokenId %{public}d get target permission %{public}s.", tokenId, perm.c_str());
377 }
378 }
379 }
380
381 /*
382 * when foreground change background or background change foreground,change accessDuration and store in database,
383 * change status and accessDuration and timestamp in cache
384 */
NotifyAppStateChange(AccessTokenID tokenId,ActiveChangeType status)385 void PermissionRecordManager::NotifyAppStateChange(AccessTokenID tokenId, ActiveChangeType status)
386 {
387 ACCESSTOKEN_LOG_INFO(LABEL, "tokenId %{public}d, status %{public}d", tokenId, status);
388 std::vector<std::string> permList;
389 std::vector<std::string> camPermList;
390 // find permissions from startRecordList_ by tokenId which status diff from currStatus
391 FindRecordsToUpdateAndExecuted(tokenId, status, permList, camPermList);
392
393 if (!camPermList.empty()) {
394 ExecuteCameraCallbackAsync(tokenId);
395 }
396 // each permission sends a status change notice
397 for (const auto& perm : permList) {
398 CallbackExecute(tokenId, perm, status);
399 }
400 }
401
AddRecordToStartList(const PermissionRecord & record)402 void PermissionRecordManager::AddRecordToStartList(const PermissionRecord& record)
403 {
404 std::lock_guard<std::mutex> lock(startRecordListMutex_);
405 startRecordList_.emplace_back(record);
406 }
407
GetRecordFromStartList(uint32_t tokenId,int32_t opCode,PermissionRecord & record)408 bool PermissionRecordManager::GetRecordFromStartList(uint32_t tokenId, int32_t opCode, PermissionRecord& record)
409 {
410 std::lock_guard<std::mutex> lock(startRecordListMutex_);
411 for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) {
412 if ((it->opCode == opCode) && (it->tokenId == tokenId)) {
413 record = *it;
414 record.accessDuration = TimeUtil::GetCurrentTimestamp() - record.timestamp;
415 startRecordList_.erase(it);
416 return true;
417 }
418 }
419 return false;
420 }
421
CallbackExecute(AccessTokenID tokenId,const std::string & permissionName,int32_t status)422 void PermissionRecordManager::CallbackExecute(
423 AccessTokenID tokenId, const std::string& permissionName, int32_t status)
424 {
425 ACCESSTOKEN_LOG_INFO(LABEL, "entry ExecuteCallbackAsync, int32_t status is %{public}d", status);
426 ActiveStatusCallbackManager::GetInstance().ExecuteCallbackAsync(
427 tokenId, permissionName, GetDeviceId(tokenId), (ActiveChangeType)status);
428 }
429
GetGlobalSwitchStatus(const std::string & permissionName)430 bool PermissionRecordManager::GetGlobalSwitchStatus(const std::string& permissionName)
431 {
432 bool isOpen = true;
433 // only manage camera and microphone global switch now, other default true
434 if (permissionName == MICROPHONE_PERMISSION_NAME) {
435 isOpen = !AudioManagerPrivacyClient::GetInstance().IsMicrophoneMute();
436 } else if (permissionName == CAMERA_PERMISSION_NAME) {
437 isOpen = !CameraManagerPrivacyClient::GetInstance().IsCameraMuted();
438 }
439
440 ACCESSTOKEN_LOG_INFO(LABEL, "permission is %{public}s, status is %{public}d", permissionName.c_str(), isOpen);
441 return isOpen;
442 }
443
444 /*
445 * StartUsing when close and choose open, update status to foreground or background from inactive
446 * StartUsing when open and choose close, update status to inactive and store in database
447 */
SavePermissionRecords(const std::string & permissionName,PermissionRecord & record,bool switchStatus)448 void PermissionRecordManager::SavePermissionRecords(
449 const std::string& permissionName, PermissionRecord& record, bool switchStatus)
450 {
451 int64_t curStamp = TimeUtil::GetCurrentTimestamp();
452 if (switchStatus) {
453 ACCESSTOKEN_LOG_INFO(LABEL, "global switch is open, update record from inactive");
454 // no need to store in database when status from inactive to foreground or background
455 record.status = GetAppStatus(record.tokenId);
456 record.timestamp = curStamp;
457 } else {
458 ACCESSTOKEN_LOG_INFO(LABEL, "global switch is close, update record to inactive");
459 if (record.status != PERM_INACTIVE) {
460 // update accessDuration and store in database
461 record.accessDuration = curStamp - record.timestamp;
462 AddRecord(record);
463 // update status to input, accessDuration to 0 and timestamp to now in cache
464 record.status = PERM_INACTIVE;
465 record.accessDuration = 0;
466 record.timestamp = curStamp;
467 }
468 }
469 CallbackExecute(record.tokenId, permissionName, record.status);
470 }
471
NotifyMicChange(bool switchStatus)472 void PermissionRecordManager::NotifyMicChange(bool switchStatus)
473 {
474 ACCESSTOKEN_LOG_INFO(LABEL, "===========OnMicStateChange(%{public}d)", switchStatus);
475 for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) {
476 if ((it->opCode) != Constant::OP_MICROPHONE) {
477 continue;
478 }
479 SavePermissionRecords("ohos.permission.MICROPHONE", *it, switchStatus);
480 }
481 }
482
NotifyCameraChange(bool switchStatus)483 void PermissionRecordManager::NotifyCameraChange(bool switchStatus)
484 {
485 ACCESSTOKEN_LOG_INFO(LABEL, "=========OnCameraStateChange(%{public}d)", switchStatus);
486 for (auto it = startRecordList_.begin(); it != startRecordList_.end(); ++it) {
487 if ((it->opCode) != Constant::OP_CAMERA) {
488 continue;
489 }
490 SavePermissionRecords("ohos.permission.CAMERA", *it, switchStatus);
491 }
492 }
493
ShowGlobalDialog(const std::string & permissionName)494 bool PermissionRecordManager::ShowGlobalDialog(const std::string& permissionName)
495 {
496 std::string resource;
497 if (permissionName == CAMERA_PERMISSION_NAME) {
498 resource = "camera";
499 } else if (permissionName == MICROPHONE_PERMISSION_NAME) {
500 resource = "microphone";
501 } else {
502 ACCESSTOKEN_LOG_INFO(LABEL, "invalid permissionName(%{public}s).", permissionName.c_str());
503 return true;
504 }
505
506 AAFwk::Want want;
507 want.SetElementName(PERMISSION_MANAGER_BUNDLE_NAME, PERMISSION_MANAGER_DIALOG_ABILITY);
508 want.SetParam(RESOURCE_KEY, resource);
509 ErrCode err = AbilityManagerPrivacyClient::GetInstance().StartAbility(want, nullptr);
510 if (err != ERR_OK) {
511 ACCESSTOKEN_LOG_ERROR(LABEL, "Fail to StartAbility, err:%{public}d", err);
512 return false;
513 }
514 return true;
515 }
516
StartUsingPermission(AccessTokenID tokenId,const std::string & permissionName)517 int32_t PermissionRecordManager::StartUsingPermission(AccessTokenID tokenId, const std::string& permissionName)
518 {
519 if (!Register()) {
520 return PrivacyError::ERR_MALLOC_FAILED;
521 }
522 int32_t accessCount = 1;
523 int32_t failCount = 0;
524
525 PermissionRecord record = { 0 };
526 int32_t result = GetPermissionRecord(tokenId, permissionName, accessCount, failCount, record);
527 if (result != Constant::SUCCESS) {
528 return result;
529 }
530
531 if (HasStarted(record)) {
532 return PrivacyError::ERR_PERMISSION_ALREADY_START_USING;
533 }
534
535 if (!GetGlobalSwitchStatus(permissionName)) {
536 if (!ShowGlobalDialog(permissionName)) {
537 ACCESSTOKEN_LOG_ERROR(LABEL, "show permission dialog failed.");
538 return ERR_SERVICE_ABNORMAL;
539 }
540 record.status = PERM_INACTIVE;
541 } else {
542 CallbackExecute(tokenId, permissionName, record.status);
543 }
544 AddRecordToStartList(record);
545 return Constant::SUCCESS;
546 }
547
SetCameraCallback(sptr<IRemoteObject> callback)548 void PermissionRecordManager::SetCameraCallback(sptr<IRemoteObject> callback)
549 {
550 std::lock_guard<std::mutex> lock(cameraMutex_);
551 cameraCallback_ = callback;
552 }
553
ExecuteCameraCallbackAsync(AccessTokenID tokenId)554 void PermissionRecordManager::ExecuteCameraCallbackAsync(AccessTokenID tokenId)
555 {
556 ACCESSTOKEN_LOG_DEBUG(LABEL, "entry");
557 sptr<IRemoteObject> cameraCallback = nullptr;
558 {
559 std::lock_guard<std::mutex> lock(cameraMutex_);
560 cameraCallback = cameraCallback_;
561 if (cameraCallback == nullptr) {
562 ACCESSTOKEN_LOG_ERROR(LABEL, "cameraCallback is null");
563 return;
564 }
565 }
566 auto callback = iface_cast<IStateChangeCallback>(cameraCallback);
567 if (callback != nullptr) {
568 ACCESSTOKEN_LOG_INFO(LABEL, "callback excute changeType %{public}d", PERM_INACTIVE);
569 callback->StateChangeNotify(tokenId, false);
570 SetCameraCallback(nullptr);
571 }
572 ACCESSTOKEN_LOG_DEBUG(LABEL, "The callback execution is complete");
573 }
574
575 /*
576 * when camera float window is not show, notice camera service to use StopUsingPermission
577 */
NotifyCameraFloatWindowChange(AccessTokenID tokenId,bool isShowing)578 void PermissionRecordManager::NotifyCameraFloatWindowChange(AccessTokenID tokenId, bool isShowing)
579 {
580 camFloatWindowShowing_ = isShowing;
581 floatWindowTokenId_ = tokenId;
582 if ((GetAppStatus(tokenId) == ActiveChangeType::PERM_ACTIVE_IN_BACKGROUND) && !isShowing) {
583 ACCESSTOKEN_LOG_INFO(LABEL, "camera float window is close!");
584 ExecuteCameraCallbackAsync(tokenId);
585 } else {
586 ACCESSTOKEN_LOG_INFO(LABEL, "camera float window is show!");
587 }
588 }
589
StartUsingPermission(AccessTokenID tokenId,const std::string & permissionName,const sptr<IRemoteObject> & callback)590 int32_t PermissionRecordManager::StartUsingPermission(AccessTokenID tokenId, const std::string& permissionName,
591 const sptr<IRemoteObject>& callback)
592 {
593 if (permissionName != CAMERA_PERMISSION_NAME) {
594 ACCESSTOKEN_LOG_ERROR(LABEL, "ERR_PARAM_INVALID is null.");
595 return PrivacyError::ERR_PARAM_INVALID;
596 }
597 if (!Register()) {
598 return PrivacyError::ERR_MALLOC_FAILED;
599 }
600
601 int32_t accessCount = 1;
602 int32_t failCount = 0;
603
604 PermissionRecord record = { 0 };
605 int32_t result = GetPermissionRecord(tokenId, permissionName, accessCount, failCount, record);
606 if (result != Constant::SUCCESS) {
607 return result;
608 }
609
610 if (HasStarted(record)) {
611 return PrivacyError::ERR_PERMISSION_ALREADY_START_USING;
612 }
613
614 if (!GetGlobalSwitchStatus(permissionName)) {
615 if (!ShowGlobalDialog(permissionName)) {
616 ACCESSTOKEN_LOG_ERROR(LABEL, "show permission dialog failed.");
617 return ERR_SERVICE_ABNORMAL;
618 }
619 record.status = PERM_INACTIVE;
620 } else {
621 CallbackExecute(tokenId, permissionName, record.status);
622 }
623 AddRecordToStartList(record);
624 SetCameraCallback(callback);
625 return Constant::SUCCESS;
626 }
627
StopUsingPermission(AccessTokenID tokenId,const std::string & permissionName)628 int32_t PermissionRecordManager::StopUsingPermission(AccessTokenID tokenId, const std::string& permissionName)
629 {
630 ExecuteDeletePermissionRecordTask();
631
632 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
633 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid tokenId(%{public}d)", tokenId);
634 return PrivacyError::ERR_TOKENID_NOT_EXIST;
635 }
636 int32_t opCode;
637 if (!Constant::TransferPermissionToOpcode(permissionName, opCode)) {
638 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid permission(%{public}s)", permissionName.c_str());
639 return PrivacyError::ERR_PERMISSION_NOT_EXIST;
640 }
641
642 PermissionRecord record;
643 if (!GetRecordFromStartList(tokenId, opCode, record)) {
644 return PrivacyError::ERR_PERMISSION_NOT_START_USING;
645 }
646
647 if (record.status != PERM_INACTIVE) {
648 AddRecord(record);
649 CallbackExecute(tokenId, permissionName, PERM_INACTIVE);
650 }
651 return Constant::SUCCESS;
652 }
653
PermListToString(const std::vector<std::string> & permList)654 void PermissionRecordManager::PermListToString(const std::vector<std::string>& permList)
655 {
656 std::string permStr;
657 permStr = accumulate(permList.begin(), permList.end(), std::string(" "));
658
659 ACCESSTOKEN_LOG_INFO(LABEL, "permStr =%{public}s", permStr.c_str());
660 }
661
PermissionListFilter(const std::vector<std::string> & listSrc,std::vector<std::string> & listRes)662 int32_t PermissionRecordManager::PermissionListFilter(
663 const std::vector<std::string>& listSrc, std::vector<std::string>& listRes)
664 {
665 PermissionDef permissionDef;
666 std::set<std::string> permSet;
667 for (const auto& permissionName : listSrc) {
668 if (AccessTokenKit::GetDefPermission(permissionName, permissionDef) == Constant::SUCCESS &&
669 permSet.count(permissionName) == 0) {
670 listRes.emplace_back(permissionName);
671 permSet.insert(permissionName);
672 continue;
673 }
674 ACCESSTOKEN_LOG_ERROR(LABEL, "permission %{public}s invalid!", permissionName.c_str());
675 }
676 if ((listRes.empty()) && (!listSrc.empty())) {
677 ACCESSTOKEN_LOG_ERROR(LABEL, "valid permission size is 0!");
678 return PrivacyError::ERR_PARAM_INVALID;
679 }
680 PermListToString(listRes);
681 return Constant::SUCCESS;
682 }
683
IsAllowedUsingPermission(AccessTokenID tokenId,const std::string & permissionName)684 bool PermissionRecordManager::IsAllowedUsingPermission(AccessTokenID tokenId, const std::string& permissionName)
685 {
686 // when app in foreground, return true, only for camera and microphone
687 if ((permissionName != CAMERA_PERMISSION_NAME) && (permissionName != MICROPHONE_PERMISSION_NAME)) {
688 return false;
689 }
690
691 HapTokenInfo tokenInfo;
692 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
693 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid tokenId(%{public}d)", tokenId);
694 return false;
695 }
696
697 int32_t status = GetAppStatus(tokenId);
698 ACCESSTOKEN_LOG_INFO(LABEL, "tokenId %{public}d, status is %{public}d", tokenId, status);
699
700 if (status == ActiveChangeType::PERM_ACTIVE_IN_FOREGROUND) {
701 return true;
702 } else if (permissionName == CAMERA_PERMISSION_NAME) {
703 return IsFlowWindowShow(tokenId);
704 }
705 return false;
706 }
707
RegisterPermActiveStatusCallback(const std::vector<std::string> & permList,const sptr<IRemoteObject> & callback)708 int32_t PermissionRecordManager::RegisterPermActiveStatusCallback(
709 const std::vector<std::string>& permList, const sptr<IRemoteObject>& callback)
710 {
711 std::vector<std::string> permListRes;
712 int32_t res = PermissionListFilter(permList, permListRes);
713 if (res != Constant::SUCCESS) {
714 return res;
715 }
716 return ActiveStatusCallbackManager::GetInstance().AddCallback(permListRes, callback);
717 }
718
UnRegisterPermActiveStatusCallback(const sptr<IRemoteObject> & callback)719 int32_t PermissionRecordManager::UnRegisterPermActiveStatusCallback(const sptr<IRemoteObject>& callback)
720 {
721 return ActiveStatusCallbackManager::GetInstance().RemoveCallback(callback);
722 }
723
GetDeviceId(AccessTokenID tokenId)724 std::string PermissionRecordManager::GetDeviceId(AccessTokenID tokenId)
725 {
726 HapTokenInfo tokenInfo;
727 if (AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo) != Constant::SUCCESS) {
728 return "";
729 }
730 if (tokenInfo.deviceID == DEFAULT_DEVICEID) { // local
731 return ConstantCommon::GetLocalDeviceId();
732 }
733 return tokenInfo.deviceID;
734 }
735
GetAppStatus(AccessTokenID tokenId)736 int32_t PermissionRecordManager::GetAppStatus(AccessTokenID tokenId)
737 {
738 int32_t status = PERM_INACTIVE;
739 HapTokenInfo tokenInfo;
740 if (AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo) != Constant::SUCCESS) {
741 ACCESSTOKEN_LOG_ERROR(LABEL, "invalid tokenId(%{public}d)", tokenId);
742 return status;
743 }
744 status = PERM_ACTIVE_IN_BACKGROUND;
745 std::vector<AppStateData> foreGroundAppList;
746 AppManagerPrivacyClient::GetInstance().GetForegroundApplications(foreGroundAppList);
747
748 if (std::any_of(foreGroundAppList.begin(), foreGroundAppList.end(),
749 [=](const auto& foreGroundApp) { return foreGroundApp.bundleName == tokenInfo.bundleName; })) {
750 status = PERM_ACTIVE_IN_FOREGROUND;
751 }
752 return status;
753 }
754
IsFlowWindowShow(AccessTokenID tokenId)755 bool PermissionRecordManager::IsFlowWindowShow(AccessTokenID tokenId)
756 {
757 return floatWindowTokenId_ == tokenId && camFloatWindowShowing_;
758 }
759
Register()760 bool PermissionRecordManager::Register()
761 {
762 if (micMuteCallback_ == nullptr) {
763 micMuteCallback_ = new(std::nothrow) AudioRoutingManagerListenerStub();
764 if (micMuteCallback_ == nullptr) {
765 return false;
766 }
767 AudioManagerPrivacyClient::GetInstance().SetMicStateChangeCallback(micMuteCallback_);
768 }
769 if (camMuteCallback_ == nullptr) {
770 camMuteCallback_ = new(std::nothrow) CameraServiceCallbackStub();
771 if (camMuteCallback_ == nullptr) {
772 return false;
773 }
774 CameraManagerPrivacyClient::GetInstance().SetMuteCallback(camMuteCallback_);
775 }
776 if (appStateCallback_ == nullptr) {
777 appStateCallback_ = new(std::nothrow) ApplicationStateObserverStub();
778 if (appStateCallback_ == nullptr) {
779 return false;
780 }
781 AppManagerPrivacyClient::GetInstance().RegisterApplicationStateObserver(appStateCallback_);
782 }
783 if (floatWindowCallback_ == nullptr) {
784 floatWindowCallback_ = new(std::nothrow) WindowManagerPrivacyAgent();
785 if (floatWindowCallback_ == nullptr) {
786 return false;
787 }
788 WindowManagerPrivacyClient::GetInstance().RegisterWindowManagerAgent(
789 WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT, floatWindowCallback_);
790 }
791 return true;
792 }
793
Unregister()794 void PermissionRecordManager::Unregister()
795 {
796 if (appStateCallback_ != nullptr) {
797 AppManagerPrivacyClient::GetInstance().UnregisterApplicationStateObserver(appStateCallback_);
798 appStateCallback_= nullptr;
799 }
800 if (floatWindowCallback_ == nullptr) {
801 WindowManagerPrivacyClient::GetInstance().UnregisterWindowManagerAgent(
802 WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT, floatWindowCallback_);
803 floatWindowCallback_ = nullptr;
804 }
805 }
806
OnAppMgrRemoteDiedHandle()807 void PermissionRecordManager::OnAppMgrRemoteDiedHandle()
808 {
809 appStateCallback_ = nullptr;
810 }
811
OnAudioMgrRemoteDiedHandle()812 void PermissionRecordManager::OnAudioMgrRemoteDiedHandle()
813 {
814 micMuteCallback_ = nullptr;
815 }
816
OnCameraMgrRemoteDiedHandle()817 void PermissionRecordManager::OnCameraMgrRemoteDiedHandle()
818 {
819 camMuteCallback_ = nullptr;
820 }
821
OnWindowMgrRemoteDiedHandle()822 void PermissionRecordManager::OnWindowMgrRemoteDiedHandle()
823 {
824 floatWindowCallback_ = nullptr;
825 }
826
Init()827 void PermissionRecordManager::Init()
828 {
829 if (hasInited_) {
830 return;
831 }
832 ACCESSTOKEN_LOG_INFO(LABEL, "init");
833 deleteTaskWorker_.Start(1);
834 hasInited_ = true;
835 }
836 } // namespace AccessToken
837 } // namespace Security
838 } // namespace OHOS
839