• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "storage/storage_status_service.h"
17 #include "accesstoken_kit.h"
18 #include "ipc_skeleton.h"
19 #include "hitrace_meter.h"
20 #include "storage_daemon_communication/storage_daemon_communication.h"
21 #include "storage_service_constant.h"
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "storage/bundle_manager_connector.h"
25 #include "storage/storage_total_status_service.h"
26 #include "iservice_registry.h"
27 #include "system_ability_definition.h"
28 #include "utils/storage_radar.h"
29 #ifdef STORAGE_SERVICE_GRAPHIC
30 #include "datashare_abs_result_set.h"
31 #include "datashare_helper.h"
32 #include "datashare_predicates.h"
33 #endif
34 
35 using namespace std;
36 using namespace OHOS::StorageService;
37 namespace OHOS {
38 namespace StorageManager {
39 using namespace OHOS::StorageService;
40 
41 namespace {
42 const string MEDIA_TYPE = "media";
43 const string FILE_TYPE = "file";
44 const string MEDIALIBRARY_DATA_URI = "datashare:///media";
45 const string MEDIA_QUERYOPRN_QUERYVOLUME = "query_media_volume";
46 constexpr const char *SETTING_BUNDLE_NAME = "settings";
47 static std::atomic<bool> checkDirSizeFlag = false;
48 constexpr int DECIMAL_PLACE = 2;
49 constexpr double TO_MB = 1024.0 * 1024.0;
50 const int64_t MAX_INT64 = std::numeric_limits<int64_t>::max();
51 #ifdef STORAGE_SERVICE_GRAPHIC
52 const int MEDIA_TYPE_IMAGE = 1;
53 const int MEDIA_TYPE_AUDIO = 3;
54 const int MEDIA_TYPE_VIDEO = 2;
55 const int32_t GET_DATA_SHARE_HELPER_TIMES = 5;
56 #endif
57 } // namespace
58 
StorageStatusService()59 StorageStatusService::StorageStatusService() {}
~StorageStatusService()60 StorageStatusService::~StorageStatusService() {}
61 
62 #ifdef STORAGE_SERVICE_GRAPHIC
GetMediaTypeAndSize(const std::shared_ptr<DataShare::DataShareResultSet> & resultSet,StorageStats & storageStats)63 void GetMediaTypeAndSize(const std::shared_ptr<DataShare::DataShareResultSet> &resultSet, StorageStats &storageStats)
64 {
65     if (resultSet == nullptr) {
66         LOGE("StorageStatusService::GetMediaTypeAndSize, input resultSet is nullptr.");
67         return;
68     }
69     int thumbnailType = -1;
70     while (resultSet->GoToNextRow() == E_OK) {
71         int32_t index = 0;
72         int mediatype = 0;
73         int64_t size = 0;
74         if (resultSet->GetColumnIndex("media_type", index) || resultSet->GetInt(index, mediatype)) {
75             LOGE("get media_type column index or int value err.");
76             continue;
77         }
78         if (resultSet->GetColumnIndex("size", index) || resultSet->GetLong(index, size)) {
79             LOGE("get size column index or long value err.");
80             continue;
81         }
82         LOGI("media type: %{public}d, size: %{public}lld", mediatype, static_cast<long long>(size));
83         if (mediatype == MEDIA_TYPE_IMAGE || mediatype == thumbnailType) {
84             storageStats.image_ += size;
85         } else if (mediatype == MEDIA_TYPE_AUDIO) {
86             storageStats.audio_ = size;
87         } else if (mediatype == MEDIA_TYPE_VIDEO) {
88             storageStats.video_ = size;
89         } else {
90             LOGD("unsupprted media_type: %{public}d", mediatype);
91         }
92     }
93 }
94 #endif
95 
GetMediaStorageStats(StorageStats & storageStats)96 int32_t GetMediaStorageStats(StorageStats &storageStats)
97 {
98     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
99     LOGE("GetMediaStorageStats start");
100 #ifdef STORAGE_SERVICE_GRAPHIC
101     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
102     if (sam == nullptr) {
103         LOGE("StorageStatusService::GetMediaStorageStats samgr == nullptr");
104         return E_SA_IS_NULLPTR;
105     }
106     auto remoteObj = sam->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
107     if (remoteObj == nullptr) {
108         LOGE("StorageStatusService::GetMediaStorageStats remoteObj == nullptr");
109         return E_REMOTE_IS_NULLPTR;
110     }
111     int32_t tryCount = 1;
112     LOGE("GetMediaStorageStats start Creator");
113     auto dataShareHelper = DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI);
114     while (dataShareHelper == nullptr && tryCount < GET_DATA_SHARE_HELPER_TIMES) {
115         LOGW("dataShareHelper is retrying, attempt %{public}d", tryCount);
116         dataShareHelper = DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI);
117         tryCount++;
118     }
119     if (dataShareHelper == nullptr) {
120         LOGE("dataShareHelper is null!");
121         return E_MEDIALIBRARY_ERROR;
122     }
123     vector<string> columns;
124     Uri uri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_QUERYOPRN_QUERYVOLUME + "/" + MEDIA_QUERYOPRN_QUERYVOLUME);
125     DataShare::DataSharePredicates predicates;
126     LOGE("GetMediaStorageStats start Query");
127     auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
128     if (queryResultSet == nullptr) {
129         LOGE("queryResultSet is null!");
130         return E_QUERY;
131     }
132     auto count = 0;
133     auto ret = queryResultSet->GetRowCount(count);
134     if ((ret != E_OK) || (count < 0)) {
135         LOGE("get row count from rdb failed");
136         return E_GETROWCOUNT;
137     }
138     GetMediaTypeAndSize(queryResultSet, storageStats);
139     dataShareHelper->Release();
140 #endif
141     LOGE("GetMediaStorageStats end");
142     return E_OK;
143 }
144 
GetFileStorageStats(int32_t userId,StorageStats & storageStats)145 int32_t GetFileStorageStats(int32_t userId, StorageStats &storageStats)
146 {
147     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
148     LOGE("GetFileStorageStats start");
149     int32_t err = E_OK;
150     int32_t prjId = userId * USER_ID_BASE + UID_FILE_MANAGER;
151     std::shared_ptr<StorageDaemonCommunication> sdCommunication;
152     sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
153     err = sdCommunication->GetOccupiedSpace(StorageDaemon::USRID, prjId, storageStats.file_);
154     LOGE("GetFileStorageStats end");
155     return err;
156 }
157 
GetCurrentUserId()158 int StorageStatusService::GetCurrentUserId()
159 {
160     int uid = -1;
161     uid = IPCSkeleton::GetCallingUid();
162     int userId = uid / 200000;
163     return userId;
164 }
165 
GetCallingPkgName()166 std::string StorageStatusService::GetCallingPkgName()
167 {
168     uint32_t pid = IPCSkeleton::GetCallingTokenID();
169     Security::AccessToken::HapTokenInfo tokenInfo = Security::AccessToken::HapTokenInfo();
170     Security::AccessToken::AccessTokenKit::GetHapTokenInfo(pid, tokenInfo);
171     return tokenInfo.bundleName;
172 }
173 
GetBundleStats(const std::string & pkgName,BundleStats & bundleStats,int32_t appIndex,uint32_t statFlag)174 int32_t StorageStatusService::GetBundleStats(const std::string &pkgName,
175     BundleStats &bundleStats, int32_t appIndex, uint32_t statFlag)
176 {
177     int userId = GetCurrentUserId();
178     return GetBundleStats(pkgName, userId, bundleStats, appIndex, statFlag);
179 }
180 
GetUserStorageStats(StorageStats & storageStats)181 int32_t StorageStatusService::GetUserStorageStats(StorageStats &storageStats)
182 {
183     int userId = GetCurrentUserId();
184     return GetUserStorageStats(userId, storageStats);
185 }
186 
GetUserStorageStats(int32_t userId,StorageStats & storageStats)187 int32_t StorageStatusService::GetUserStorageStats(int32_t userId, StorageStats &storageStats)
188 {
189     bool isCeEncrypt = false;
190     auto sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
191     int ret = sdCommunication->GetFileEncryptStatus(userId, isCeEncrypt, true);
192     if (ret != E_OK || isCeEncrypt) {
193         LOGE("User %{public}d de has not decrypt.", userId);
194         return ret;
195     }
196     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
197     // totalSize
198     int64_t totalSize = 0;
199     int32_t err = StorageTotalStatusService::GetInstance().GetTotalSize(totalSize);
200     if (err != E_OK) {
201         LOGE("StorageStatusService::GetUserStorageStats getTotalSize failed");
202         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetTotalSize", userId, err, GetCallingPkgName());
203         return err;
204     }
205     // appSize
206     LOGD("StorageStatusService::GetUserStorageStats userId is %{public}d", userId);
207     int64_t appSize = 0;
208     err = GetAppSize(userId, appSize);
209     if (err != E_OK) {
210         LOGE("StorageStatusService::GetUserStorageStats getAppSize failed");
211         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetAppSize", userId, err, GetCallingPkgName());
212         return err;
213     }
214 
215     storageStats.total_ = totalSize;
216     storageStats.app_ = appSize;
217 
218     err = GetMediaAndFileStorageStats(userId, storageStats);
219 
220     LOGE("StorageStatusService::GetUserStorageStats success for userId=%{public}d, "
221         "totalSize=%{public}lld, appSize=%{public}lld, videoSize=%{public}lld, audioSize=%{public}lld, "
222         "imageSize=%{public}lld, fileSize=%{public}lld",
223         userId, static_cast<long long>(storageStats.total_), static_cast<long long>(storageStats.app_),
224         static_cast<long long>(storageStats.video_), static_cast<long long>(storageStats.audio_),
225         static_cast<long long>(storageStats.image_), static_cast<long long>(storageStats.file_));
226     return err;
227 }
228 
GetMediaAndFileStorageStats(int32_t userId,StorageStats & storageStats)229 int32_t StorageStatusService::GetMediaAndFileStorageStats(int32_t userId, StorageStats &storageStats)
230 {
231     // mediaSize
232     auto err = GetMediaStorageStats(storageStats);
233     if (err != E_OK) {
234         LOGE("StorageStatusService::GetUserStorageStats GetMediaStorageStats failed");
235         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetMediaStorageStats", userId, err,
236             GetCallingPkgName());
237         return err;
238     }
239     // fileSize
240     err = GetFileStorageStats(userId, storageStats);
241     if (err != E_OK) {
242         LOGE("StorageStatusService::GetUserStorageStats GetFileStorageStats failed");
243         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetFileStorageStats", userId, err,
244             GetCallingPkgName());
245         return err;
246     }
247     auto ret = QueryOccupiedSpaceForSa(storageStats);
248     if (ret != E_OK) {
249         LOGE("StorageStatusService::GetUserStorageStats QueryOccupiedSpaceForSa failed, err: %{public}d", ret);
250         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::QueryOccupiedSpaceForSa", userId, ret,
251             GetCallingPkgName());
252     }
253     return err;
254 }
255 
ConvertBytesToMB(int64_t bytes)256 std::string StorageStatusService::ConvertBytesToMB(int64_t bytes)
257 {
258     std::ostringstream oss;
259     oss << std::fixed << std::setprecision(DECIMAL_PLACE) << static_cast<double>(bytes) / TO_MB << "MB";
260     return oss.str();
261 }
262 
QueryOccupiedSpaceForSa(StorageStats & storageStats)263 int32_t StorageStatusService::QueryOccupiedSpaceForSa(StorageStats &storageStats)
264 {
265     std::string bundleName;
266     int32_t uid = IPCSkeleton::GetCallingUid();
267     auto bundleMgr = BundleMgrConnector::GetInstance().GetBundleMgrProxy();
268     if (bundleMgr == nullptr) {
269         LOGE("Connect bundle manager sa proxy failed.");
270         return E_SERVICE_IS_NULLPTR;
271     }
272     if (!bundleMgr->GetBundleNameForUid(uid, bundleName)) {
273         LOGE("Invoke bundleMgr interface to get bundle name failed.");
274         return E_BUNDLEMGR_ERROR;
275     }
276     if (bundleName != SETTING_BUNDLE_NAME) {
277         LOGE("permissionCheck error");
278         return E_PERMISSION_DENIED;
279     }
280     if (checkDirSizeFlag.load()) {
281         LOGI("The task to query SA space usage is running, ignore");
282         return E_OK;
283     }
284     std::thread([this, storageStats]() {
285         checkDirSizeFlag.store(true);
286         int64_t freeSize = 0;
287         auto errNo = StorageTotalStatusService::GetInstance().GetFreeSize(freeSize);
288         if (errNo != E_OK) {
289             LOGE("StorageStatusService::GetUserStorageStats getFreeSize failed");
290         }
291         std::string storageStatusResult = "{App size is:" + ConvertBytesToMB(storageStats.app_) +
292                                           ",audio size is:" + ConvertBytesToMB(storageStats.audio_) +
293                                           ",image size is:" + ConvertBytesToMB(storageStats.image_) +
294                                           ",video size is:" + ConvertBytesToMB(storageStats.video_) +
295                                           ",file size is:" + ConvertBytesToMB(storageStats.file_) +
296                                           ",free size is:" + ConvertBytesToMB(freeSize) + "}";
297         auto sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
298         if (sdCommunication == nullptr) {
299             LOGE("get sdCommunication error");
300             return;
301         }
302         sdCommunication->QueryOccupiedSpaceForSa(storageStatusResult);
303         checkDirSizeFlag.store(false);
304     }).detach();
305     return E_OK;
306 }
307 
GetCurrentBundleStats(BundleStats & bundleStats,uint32_t statFlag)308 int32_t StorageStatusService::GetCurrentBundleStats(BundleStats &bundleStats, uint32_t statFlag)
309 {
310     int userId = GetCurrentUserId();
311     std::string pkgName = GetCallingPkgName();
312     int32_t ret = GetBundleStats(pkgName, userId, bundleStats, DEFAULT_APP_INDEX, statFlag);
313     if (ret != E_OK) {
314         LOGE("storage status service GetBundleStats failed, please check");
315         std::string extraData = "pkgName=" + pkgName + ",statFlag=" + std::to_string(statFlag);
316         StorageRadar::ReportBundleMgrResult("GetCurrentBundleStats::GetBundleStats", ret, userId, extraData);
317     }
318     return ret;
319 }
320 
GetBundleStats(const std::string & pkgName,int32_t userId,BundleStats & pkgStats,int32_t appIndex,uint32_t statFlag)321 int32_t StorageStatusService::GetBundleStats(const std::string &pkgName, int32_t userId,
322     BundleStats &pkgStats, int32_t appIndex, uint32_t statFlag)
323 {
324     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
325     auto bundleMgr = BundleMgrConnector::GetInstance().GetBundleMgrProxy();
326     if (bundleMgr == nullptr) {
327         LOGE("StorageStatusService::GetBundleStats connect bundlemgr failed");
328         return E_SERVICE_IS_NULLPTR;
329     }
330 
331     if (userId < 0 || userId > StorageService::MAX_USER_ID) {
332         LOGE("StorageStatusService::Invaild userId.");
333         return E_USERID_RANGE;
334     }
335 
336     if (appIndex < 0 || appIndex > StorageService::MAX_APP_INDEX) {
337         LOGE("StorageStatusService::Invalid appIndex: %{public}d", appIndex);
338         return E_APPINDEX_RANGE;
339     }
340     vector<int64_t> bundleStats;
341     bool res = bundleMgr->GetBundleStats(pkgName, userId, bundleStats, appIndex, statFlag);
342     if (!res || bundleStats.size() != dataDir.size()) {
343         LOGE("StorageStatusService::An error occurred in querying bundle stats.");
344         std::string extraData = "bundleStats size=" + std::to_string(bundleStats.size())
345             + ", dataDir size=" + std::to_string(dataDir.size());
346         StorageRadar::ReportBundleMgrResult("GetBundleStats", res, userId, extraData);
347         return E_BUNDLEMGR_ERROR;
348     }
349     for (uint i = 0; i < bundleStats.size(); i++) {
350         if (bundleStats[i] == E_ERR) {
351             LOGE("StorageStatusService::Failed to query %{public}s data.", dataDir[i].c_str());
352             bundleStats[i] = 0;
353         }
354     }
355     pkgStats.appSize_ = bundleStats[APP];
356     pkgStats.cacheSize_ = bundleStats[CACHE];
357     pkgStats.dataSize_ = bundleStats[LOCAL] + bundleStats[DISTRIBUTED] + bundleStats[DATABASE];
358     LOGE("StorageStatusService::GetBundleStats success for pkgName=%{public}s, userId=%{public}d, appIndex=%{public}d"
359         ", appSize=%{public}lld, cacheSize=%{public}lld, dataSize=%{public}lld",
360         pkgName.c_str(), userId, appIndex, static_cast<long long>(pkgStats.appSize_),
361         static_cast<long long>(pkgStats.cacheSize_), static_cast<long long>(pkgStats.dataSize_));
362     return E_OK;
363 }
364 
GetAppSize(int32_t userId,int64_t & appSize)365 int32_t StorageStatusService::GetAppSize(int32_t userId, int64_t &appSize)
366 {
367     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
368     LOGD("StorageStatusService::GetAppSize start");
369     auto bundleMgr = BundleMgrConnector::GetInstance().GetBundleMgrProxy();
370     if (bundleMgr == nullptr) {
371         LOGE("StorageStatusService::GetUserStorageStats connect bundlemgr failed");
372         return E_SERVICE_IS_NULLPTR;
373     }
374 
375     vector<int64_t> bundleStats;
376     bool res = bundleMgr->GetAllBundleStats(userId, bundleStats);
377     if (!res || bundleStats.size() != dataDir.size()) {
378         LOGE("StorageStatusService::GetAllBundleStats fail. res %{public}d, bundleStats.size %{public}zu",
379              res, bundleStats.size());
380         std::string extraData = "bundleStats size=" + std::to_string(bundleStats.size())
381             + ", dataDir size=" + std::to_string(dataDir.size());
382         StorageRadar::ReportBundleMgrResult("GetAppSize::GetAllBundleStats", res, userId, extraData);
383         return E_BUNDLEMGR_ERROR;
384     }
385 
386     for (uint i = 0; i < bundleStats.size(); i++) {
387         if (bundleStats[i] > 0 && appSize > MAX_INT64 - bundleStats[i]) {
388             return E_CALCULATE_OVERFLOW_UP;
389         }
390         appSize += bundleStats[i];
391     }
392     LOGD("StorageStatusService::GetAppSize end");
393     return E_OK;
394 }
395 
GetUserStorageStatsByType(int32_t userId,StorageStats & storageStats,std::string type)396 int32_t StorageStatusService::GetUserStorageStatsByType(int32_t userId, StorageStats &storageStats, std::string type)
397 {
398     storageStats.video_ = 0;
399     storageStats.image_ = 0;
400     storageStats.file_ = 0;
401     int32_t err = E_OK;
402     if (type == MEDIA_TYPE) {
403         LOGI("GetUserStorageStatsByType media");
404         err = GetMediaStorageStats(storageStats);
405         if (err != E_OK) {
406             StorageRadar::ReportGetStorageStatus("GetMediaStorageStats", userId, err, "setting");
407         }
408     } else if (type == FILE_TYPE) {
409         LOGI("GetUserStorageStatsByType file");
410         err = GetFileStorageStats(userId, storageStats);
411         if (err != E_OK) {
412             StorageRadar::ReportGetStorageStatus("GetFileStorageStats", userId, err, "setting");
413         }
414     } else {
415         LOGI("GetUserStorageStatsByType type: %{public}s", type.c_str());
416     }
417 
418     return err;
419 }
420 } // StorageManager
421 } // OHOS
422