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 "hap_token_info.h"
20 #include "hitrace_meter.h"
21 #include "storage_daemon_communication/storage_daemon_communication.h"
22 #include "storage_service_constant.h"
23 #include "storage_service_errno.h"
24 #include "storage_service_log.h"
25 #include "storage/bundle_manager_connector.h"
26 #include "storage/storage_total_status_service.h"
27 #include "application_info.h"
28 #include "iservice_registry.h"
29 #include "system_ability_definition.h"
30 #include "utils/storage_radar.h"
31 #include "utils/storage_utils.h"
32 #ifdef STORAGE_SERVICE_GRAPHIC
33 #include "datashare_abs_result_set.h"
34 #include "datashare_helper.h"
35 #include "datashare_predicates.h"
36 #endif
37 
38 using namespace std;
39 using namespace OHOS::StorageService;
40 namespace OHOS {
41 namespace StorageManager {
42 using namespace OHOS::StorageService;
43 
44 namespace {
45 const string MEDIA_TYPE = "media";
46 const string FILE_TYPE = "file";
47 const string MEDIALIBRARY_DATA_URI = "datashare:///media";
48 const string MEDIA_QUERYOPRN_QUERYVOLUME = "query_media_volume";
49 #ifdef STORAGE_SERVICE_GRAPHIC
50 const int MEDIA_TYPE_IMAGE = 1;
51 const int MEDIA_TYPE_AUDIO = 3;
52 const int MEDIA_TYPE_VIDEO = 2;
53 const int32_t GET_DATA_SHARE_HELPER_TIMES = 5;
54 #endif
55 } // namespace
56 
StorageStatusService()57 StorageStatusService::StorageStatusService() {}
~StorageStatusService()58 StorageStatusService::~StorageStatusService() {}
59 
60 #ifdef STORAGE_SERVICE_GRAPHIC
GetMediaTypeAndSize(const std::shared_ptr<DataShare::DataShareResultSet> & resultSet,StorageStats & storageStats)61 void GetMediaTypeAndSize(const std::shared_ptr<DataShare::DataShareResultSet> &resultSet, StorageStats &storageStats)
62 {
63     if (resultSet == nullptr) {
64         LOGE("StorageStatusService::GetMediaTypeAndSize, input resultSet is nullptr.");
65         return;
66     }
67     int thumbnailType = -1;
68     while (resultSet->GoToNextRow() == E_OK) {
69         int32_t index = 0;
70         int mediatype = 0;
71         int64_t size = 0;
72         if (resultSet->GetColumnIndex("media_type", index) || resultSet->GetInt(index, mediatype)) {
73             LOGE("get media_type column index or int value err.");
74             continue;
75         }
76         if (resultSet->GetColumnIndex("size", index) || resultSet->GetLong(index, size)) {
77             LOGE("get size column index or long value err.");
78             continue;
79         }
80         LOGI("media_type: %{public}d, size: %{public}lld", mediatype, static_cast<long long>(size));
81         if (mediatype == MEDIA_TYPE_IMAGE || mediatype == thumbnailType) {
82             storageStats.image_ += size;
83         } else if (mediatype == MEDIA_TYPE_AUDIO) {
84             storageStats.audio_ = size;
85         } else if (mediatype == MEDIA_TYPE_VIDEO) {
86             storageStats.video_ = size;
87         } else {
88             LOGD("unsupprted media_type: %{public}d", mediatype);
89         }
90     }
91 }
92 #endif
93 
GetMediaStorageStats(StorageStats & storageStats)94 int32_t GetMediaStorageStats(StorageStats &storageStats)
95 {
96     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
97     LOGD("GetMediaStorageStats start");
98 #ifdef STORAGE_SERVICE_GRAPHIC
99     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
100     if (sam == nullptr) {
101         LOGE("StorageStatusService::GetMediaStorageStats samgr == nullptr");
102         return E_SA_IS_NULLPTR;
103     }
104     auto remoteObj = sam->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
105     if (remoteObj == nullptr) {
106         LOGE("StorageStatusService::GetMediaStorageStats remoteObj == nullptr");
107         return E_REMOTE_IS_NULLPTR;
108     }
109     int32_t tryCount = 1;
110     auto dataShareHelper = DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI);
111     while (dataShareHelper == nullptr && tryCount < GET_DATA_SHARE_HELPER_TIMES) {
112         LOGW("dataShareHelper is retrying, attempt %{public}d", tryCount);
113         dataShareHelper = DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI);
114         tryCount++;
115     }
116     if (dataShareHelper == nullptr) {
117         LOGE("dataShareHelper is null!");
118         return E_MEDIALIBRARY_ERROR;
119     }
120     vector<string> columns;
121     Uri uri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_QUERYOPRN_QUERYVOLUME + "/" + MEDIA_QUERYOPRN_QUERYVOLUME);
122     DataShare::DataSharePredicates predicates;
123     auto queryResultSet = dataShareHelper->Query(uri, predicates, columns);
124     if (queryResultSet == nullptr) {
125         LOGE("queryResultSet is null!");
126         return E_MEDIALIBRARY_ERROR;
127     }
128     auto count = 0;
129     auto ret = queryResultSet->GetRowCount(count);
130     if ((ret != E_OK) || (count < 0)) {
131         LOGE("get row count from rdb failed");
132         return E_MEDIALIBRARY_ERROR;
133     }
134     GetMediaTypeAndSize(queryResultSet, storageStats);
135     dataShareHelper->Release();
136 #endif
137     LOGD("GetMediaStorageStats end");
138     return E_OK;
139 }
140 
GetFileStorageStats(int32_t userId,StorageStats & storageStats)141 int32_t GetFileStorageStats(int32_t userId, StorageStats &storageStats)
142 {
143     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
144     LOGD("GetFileStorageStats start");
145     int32_t err = E_OK;
146     int32_t prjId = userId * USER_ID_BASE + UID_FILE_MANAGER;
147     std::shared_ptr<StorageDaemonCommunication> sdCommunication;
148     sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
149     err = sdCommunication->GetOccupiedSpace(StorageDaemon::USRID, prjId, storageStats.file_);
150     LOGD("GetFileStorageStats end");
151     return err;
152 }
153 
GetCurrentUserId()154 int StorageStatusService::GetCurrentUserId()
155 {
156     int uid = -1;
157     uid = IPCSkeleton::GetCallingUid();
158     int userId = uid / 200000;
159     return userId;
160 }
161 
GetCallingPkgName()162 std::string StorageStatusService::GetCallingPkgName()
163 {
164     uint32_t pid = IPCSkeleton::GetCallingTokenID();
165     Security::AccessToken::HapTokenInfo tokenInfo = Security::AccessToken::HapTokenInfo();
166     Security::AccessToken::AccessTokenKit::GetHapTokenInfo(pid, tokenInfo);
167     return tokenInfo.bundleName;
168 }
169 
GetBundleStats(const std::string & pkgName,BundleStats & bundleStats,int32_t appIndex,uint32_t statFlag)170 int32_t StorageStatusService::GetBundleStats(const std::string &pkgName,
171     BundleStats &bundleStats, int32_t appIndex, uint32_t statFlag)
172 {
173     int userId = GetCurrentUserId();
174     LOGD("StorageStatusService::userId is:%d, appIndex is: %d", userId, appIndex);
175     return GetBundleStats(pkgName, userId, bundleStats, appIndex, statFlag);
176 }
177 
GetUserStorageStats(StorageStats & storageStats)178 int32_t StorageStatusService::GetUserStorageStats(StorageStats &storageStats)
179 {
180     int userId = GetCurrentUserId();
181     return GetUserStorageStats(userId, storageStats);
182 }
183 
GetUserStorageStats(int32_t userId,StorageStats & storageStats)184 int32_t StorageStatusService::GetUserStorageStats(int32_t userId, StorageStats &storageStats)
185 {
186     int ret = 0;
187     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
188     // totalSize
189     int64_t totalSize = 0;
190     int32_t err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetTotalSize(totalSize);
191     if (err != E_OK) {
192         LOGE("StorageStatusService::GetUserStorageStats getTotalSize failed");
193         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetTotalSize", userId, ret, GetCallingPkgName());
194         return err;
195     }
196     // appSize
197     LOGD("StorageStatusService::GetUserStorageStats userId is %{public}d", userId);
198     int64_t appSize = 0;
199     err = GetAppSize(userId, appSize);
200     if (err != E_OK) {
201         LOGE("StorageStatusService::GetUserStorageStats getAppSize failed");
202         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetAppSize", userId, ret, GetCallingPkgName());
203         return err;
204     }
205 
206     storageStats.total_ = totalSize;
207     storageStats.app_ = appSize;
208 
209     // mediaSize
210     err = GetMediaStorageStats(storageStats);
211     if (err != E_OK) {
212         LOGE("StorageStatusService::GetUserStorageStats GetMediaStorageStats failed");
213         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetMediaStorageStats", userId, ret,
214             GetCallingPkgName());
215         return err;
216     }
217     // fileSize
218     err = GetFileStorageStats(userId, storageStats);
219     if (err != E_OK) {
220         LOGE("StorageStatusService::GetUserStorageStats GetFileStorageStats failed");
221         StorageRadar::ReportGetStorageStatus("GetUserStorageStats::GetFileStorageStats", userId, ret,
222             GetCallingPkgName());
223     }
224 
225     LOGE("StorageStatusService::GetUserStorageStats success for userId=%{public}d, "
226         "totalSize=%{public}lld, appSize=%{public}lld, videoSize=%{public}lld, audioSize=%{public}lld, "
227         "imageSize=%{public}lld, fileSize=%{public}lld",
228         userId, static_cast<long long>(storageStats.total_), static_cast<long long>(storageStats.app_),
229         static_cast<long long>(storageStats.video_), static_cast<long long>(storageStats.audio_),
230         static_cast<long long>(storageStats.image_), static_cast<long long>(storageStats.file_));
231     return err;
232 }
233 
GetBundleStatsForIncrease(uint32_t userId,const std::vector<std::string> & bundleNames,const std::vector<int64_t> & incrementalBackTimes,std::vector<int64_t> & pkgFileSizes,std::vector<int64_t> & incPkgFileSizes)234 int32_t StorageStatusService::GetBundleStatsForIncrease(uint32_t userId, const std::vector<std::string> &bundleNames,
235     const std::vector<int64_t> &incrementalBackTimes, std::vector<int64_t> &pkgFileSizes,
236     std::vector<int64_t> &incPkgFileSizes)
237 {
238     std::shared_ptr<StorageDaemonCommunication> sdCommunication;
239     sdCommunication = DelayedSingleton<StorageDaemonCommunication>::GetInstance();
240     int32_t err = sdCommunication->GetBundleStatsForIncrease(userId, bundleNames, incrementalBackTimes,
241         pkgFileSizes, incPkgFileSizes);
242     LOGI("StorageStatusService::GetBundleStatsForIncrease err is %{public}d", err);
243     return err;
244 }
245 
GetCurrentBundleStats(BundleStats & bundleStats,uint32_t statFlag)246 int32_t StorageStatusService::GetCurrentBundleStats(BundleStats &bundleStats, uint32_t statFlag)
247 {
248     int userId = GetCurrentUserId();
249 
250     std::string pkgName = GetCallingPkgName();
251     int32_t ret = GetBundleStats(pkgName, userId, bundleStats, DEFAULT_APP_INDEX, statFlag);
252     if (ret != E_OK) {
253         LOGE("storage status service GetBundleStats failed, please check");
254         RadarParameter parameterRes = {.orgPkg = DEFAULT_ORGPKGNAME,
255                                        .userId = DEFAULT_USER_ID,
256                                        .funcName = "GetBundleStats",
257                                        .bizScene = BizScene::SPACE_STATISTICS,
258                                        .bizStage = BizStage::BIZ_STAGE_GET_BUNDLE_STATS,
259                                        .keyElxLevel = "EL1",
260                                        .errorCode = ret};
261         StorageService::StorageRadar::GetInstance().RecordFuctionResult(parameterRes);
262     }
263     return ret;
264 }
265 
GetBundleStats(const std::string & pkgName,int32_t userId,BundleStats & pkgStats,int32_t appIndex,uint32_t statFlag)266 int32_t StorageStatusService::GetBundleStats(const std::string &pkgName, int32_t userId,
267     BundleStats &pkgStats, int32_t appIndex, uint32_t statFlag)
268 {
269     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
270     auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
271     if (bundleMgr == nullptr) {
272         LOGE("StorageStatusService::GetBundleStats connect bundlemgr failed");
273         return E_SERVICE_IS_NULLPTR;
274     }
275 
276     if (userId < 0 || userId > StorageService::MAX_USER_ID) {
277         LOGE("StorageStatusService::Invaild userId.");
278         return E_USERID_RANGE;
279     }
280 
281     if (appIndex < 0 || appIndex > StorageService::MAX_APP_INDEX) {
282         LOGE("StorageStatusService::Invalid appIndex: %{public}d", appIndex);
283         return E_USERID_RANGE;
284     }
285     vector<int64_t> bundleStats;
286     bool res = bundleMgr->GetBundleStats(pkgName, userId, bundleStats, appIndex, statFlag);
287     if (!res || bundleStats.size() != dataDir.size()) {
288         LOGE("StorageStatusService::An error occurred in querying bundle stats.");
289         return E_BUNDLEMGR_ERROR;
290     }
291     for (uint i = 0; i < bundleStats.size(); i++) {
292         if (bundleStats[i] == E_ERR) {
293             LOGE("StorageStatusService::Failed to query %{public}s data.", dataDir[i].c_str());
294             bundleStats[i] = 0;
295         }
296     }
297     pkgStats.appSize_ = bundleStats[APP];
298     pkgStats.cacheSize_ = bundleStats[CACHE];
299     pkgStats.dataSize_ = bundleStats[LOCAL] + bundleStats[DISTRIBUTED] + bundleStats[DATABASE];
300     LOGE("StorageStatusService::GetBundleStats success for pkgName=%{public}s, userId=%{public}d, appIndex=%{public}d"
301         ", appSize=%{public}lld, cacheSize=%{public}lld, dataSize=%{public}lld",
302         pkgName.c_str(), userId, appIndex, static_cast<long long>(pkgStats.appSize_),
303         static_cast<long long>(pkgStats.cacheSize_), static_cast<long long>(pkgStats.dataSize_));
304     return E_OK;
305 }
306 
GetAppSize(int32_t userId,int64_t & appSize)307 int32_t StorageStatusService::GetAppSize(int32_t userId, int64_t &appSize)
308 {
309     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
310     LOGD("StorageStatusService::GetAppSize start");
311     auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
312     if (bundleMgr == nullptr) {
313         LOGE("StorageStatusService::GetUserStorageStats connect bundlemgr failed");
314         return E_SERVICE_IS_NULLPTR;
315     }
316 
317     vector<int64_t> bundleStats;
318     bool res = bundleMgr->GetAllBundleStats(userId, bundleStats);
319     if (!res || bundleStats.size() != dataDir.size()) {
320         LOGE("StorageStatusService::GetAllBundleStats fail. res %{public}d, bundleStats.size %{public}zu",
321              res, bundleStats.size());
322         return E_BUNDLEMGR_ERROR;
323     }
324 
325     for (uint i = 0; i < bundleStats.size(); i++) {
326         appSize += bundleStats[i];
327     }
328     LOGD("StorageStatusService::GetAppSize end");
329     return E_OK;
330 }
331 
GetUserStorageStatsByType(int32_t userId,StorageStats & storageStats,std::string type)332 int32_t StorageStatusService::GetUserStorageStatsByType(int32_t userId, StorageStats &storageStats, std::string type)
333 {
334     storageStats.video_ = 0;
335     storageStats.image_ = 0;
336     storageStats.file_ = 0;
337     int32_t err = E_OK;
338     if (type == MEDIA_TYPE) {
339         LOGD("GetUserStorageStatsByType media");
340         err = GetMediaStorageStats(storageStats);
341     } else if (type == FILE_TYPE) {
342         LOGD("GetUserStorageStatsByType file");
343         err = GetFileStorageStats(userId, storageStats);
344     } else {
345         LOGD("GetUserStorageStatsByType type: %{public}s", type.c_str());
346     }
347 
348     return err;
349 }
350 } // StorageManager
351 } // OHOS
352