• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #define MLOG_TAG "DfxDeprecatedPermUsage"
17 
18 #include "dfx_deprecated_perm_usage.h"
19 
20 #include <charconv>
21 
22 #include "hisysevent.h"
23 #include "ipc_skeleton.h"
24 #include "media_log.h"
25 #include "medialibrary_bundle_manager.h"
26 #include "medialibrary_errno.h"
27 #include "preferences_helper.h"
28 
29 namespace OHOS {
30 namespace Media {
31 const std::string DFX_DEPRECATED_PERM_USAGE_XML = "/data/storage/el2/base/preferences/dfx_deprecated_perm_usage.xml";
32 constexpr char MEDIA_LIBRARY[] = "MEDIALIBRARY";
33 const std::string OPERATION_OBJECT = "OPERATION_OBJECT";
34 const std::string OPERATION_TYPE = "OPERATION_TYPE";
35 const std::string BUNDLE_NAME_LIST = "BUNDLE_NAME_LIST";
36 const size_t BATCH_SIZE = 300;
37 
38 std::mutex DfxDeprecatedPermUsage::mutex_;
39 
Record(const uint32_t object,const uint32_t type)40 int32_t DfxDeprecatedPermUsage::Record(const uint32_t object, const uint32_t type)
41 {
42     std::unique_lock<std::mutex> lock(mutex_, std::defer_lock);
43     CHECK_AND_RETURN_RET_WARN_LOG(lock.try_lock(), E_OK, "Record or statistics has started, skipping this operation");
44 
45     std::string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
46     CHECK_AND_EXECUTE(!bundleName.empty(), bundleName = std::to_string(IPCSkeleton::GetCallingUid()));
47 
48     int32_t errCode = NativePreferences::E_OK;
49     std::shared_ptr<NativePreferences::Preferences> prefs =
50         NativePreferences::PreferencesHelper::GetPreferences(DFX_DEPRECATED_PERM_USAGE_XML, errCode);
51     CHECK_AND_RETURN_RET_LOG(prefs, E_ERR, "get preferences error: %{public}d", errCode);
52 
53     std::string key = std::to_string(object) + "," + std::to_string(type);
54     std::vector<std::string> bundleNames = prefs->Get(key, std::vector<std::string>{});
55     if (std::find(bundleNames.begin(), bundleNames.end(), bundleName) == bundleNames.end()) {
56         bundleNames.push_back(bundleName);
57         prefs->Put(key, bundleNames);
58         prefs->FlushSync();
59     }
60     return E_OK;
61 }
62 
StrToUint32(const std::string & str,uint32_t & value)63 static bool StrToUint32(const std::string &str, uint32_t &value)
64 {
65     auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
66     return ec == std::errc{} && ptr == str.data() + str.size();
67 }
68 
Statistics()69 int32_t DfxDeprecatedPermUsage::Statistics()
70 {
71     std::unique_lock<std::mutex> lock(mutex_, std::defer_lock);
72     CHECK_AND_RETURN_RET_WARN_LOG(lock.try_lock(), E_OK, "Record or statistics has started, skipping this operation");
73 
74     int32_t errCode = NativePreferences::E_OK;
75     std::shared_ptr<NativePreferences::Preferences> prefs =
76         NativePreferences::PreferencesHelper::GetPreferences(DFX_DEPRECATED_PERM_USAGE_XML, errCode);
77     CHECK_AND_RETURN_RET_LOG(prefs, E_ERR, "get preferences error: %{public}d", errCode);
78 
79     std::unordered_map<std::string, NativePreferences::PreferencesValue> allDatas = prefs->GetAllDatas();
80     CHECK_AND_RETURN_RET_INFO_LOG(!allDatas.empty(), E_OK, "has no data to statistics");
81 
82     MEDIA_INFO_LOG("Statistics start, allDatas size: %{public}zu", allDatas.size());
83     int32_t reportResult = 0;
84     for (const auto &[key, val] : allDatas) {
85         size_t commaPos = key.find(",");
86         CHECK_AND_CONTINUE_ERR_LOG(commaPos != std::string::npos, "invalid key format: %{public}s", key.c_str());
87         std::string objectStr = key.substr(0, commaPos);
88         std::string typeStr = key.substr(commaPos + 1);
89         uint32_t object = 0;
90         uint32_t type = 0;
91         CHECK_AND_CONTINUE_ERR_LOG(StrToUint32(objectStr, object) && StrToUint32(typeStr, type),
92             "object or type is invalid, key format: %{public}s",
93             key.c_str());
94         std::vector<std::string> bundleNames = val;
95         CHECK_AND_CONTINUE_ERR_LOG(!bundleNames.empty(), "bundleNames is empty");
96         int32_t batchResult = ReportBatch(object, type, bundleNames);
97         if (batchResult != 0) {
98             MEDIA_ERR_LOG("ReportBatch failed, error: %{public}d", batchResult);
99             reportResult = batchResult;
100         }
101     }
102     if (reportResult == 0) {
103         prefs->Clear();
104         prefs->FlushSync();
105     }
106     return E_OK;
107 }
108 
ReportBatch(const uint32_t object,const uint32_t type,const std::vector<std::string> & bundleNames)109 int32_t DfxDeprecatedPermUsage::ReportBatch(
110     const uint32_t object, const uint32_t type, const std::vector<std::string> &bundleNames)
111 {
112     int32_t batchResult = 0;
113     for (size_t start = 0; start < bundleNames.size(); start += BATCH_SIZE) {
114         std::ostringstream oss;
115         size_t end = std::min(start + BATCH_SIZE, bundleNames.size());
116         oss << bundleNames[start];
117         for (size_t i = start + 1; i < end; ++i) {
118             oss << "," << bundleNames[i];
119         }
120         int32_t ret = Report(object, type, oss.str());
121         if (ret != 0) {
122             MEDIA_ERR_LOG("Report failed, error: %{public}d", ret);
123             batchResult = ret;
124         }
125     }
126     return batchResult;
127 }
128 
Report(const uint32_t object,const uint32_t type,const std::string & bundleNameList)129 int32_t DfxDeprecatedPermUsage::Report(const uint32_t object, const uint32_t type, const std::string &bundleNameList)
130 {
131     int32_t ret = HiSysEventWrite(
132         MEDIA_LIBRARY,
133         "MEDIALIB_DEPRECATED_PERM_USAGE",
134         HiviewDFX::HiSysEvent::EventType::STATISTIC,
135         OPERATION_OBJECT, object,
136         OPERATION_TYPE, type,
137         BUNDLE_NAME_LIST, bundleNameList);
138 
139     CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "Deprecated perm usage statistics report error: %{public}d", ret);
140     MEDIA_INFO_LOG("Deprecated perm usage statistics report success");
141     return ret;
142 }
143 }  // namespace Media
144 }  // namespace OHOS