1/* 2 * Copyright (c) 2022-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 16import bundle from '@ohos.bundle.bundleManager' 17import storageStatistics from '@ohos.file.storageStatistics' 18import { AppData } from '../model/AppData' 19import CheckEmptyUtils from '../utils/CheckEmptyUtils' 20import Logger from '../utils/Logger' 21import ParseData from '../common/ParseData' 22import { StorageData } from '../model/StorageData' 23 24const TAG: string = 'QueryStorageData' 25 26export class QueryStorageData { 27 // Size data may get 0, so set -1 as default value 28 public totalSize: number = -1 29 public freeSize: number = -1 30 public itemSizeList: number[] = [] 31 public appDataList: AppData[] = [] 32 public classifiedDataList: StorageData[] = [] 33 private context: Context = getContext(this) as Context 34 35 private async initClassifiedDataList() { 36 this.classifiedDataList = [] 37 let storageStats: storageStatistics.StorageStats = await storageStatistics.getUserStorageStats() 38 this.classifiedDataList.push({ 39 name: $r('app.string.query_data_application'), 40 size: storageStats.app, 41 color: '#F9A20F', 42 }) 43 this.classifiedDataList.push({ 44 name: $r('app.string.query_data_audio'), 45 size: storageStats.audio, 46 color: '#F2400A' 47 }) 48 this.classifiedDataList.push({ 49 name: $r('app.string.query_data_video'), 50 size: storageStats.video, 51 color: '#E65392' 52 }) 53 this.classifiedDataList.push({ 54 name: $r('app.string.query_data_image'), 55 size: storageStats.image, 56 color: '#A12DF7' }) 57 this.classifiedDataList.push({ 58 name: $r('app.string.query_data_file'), 59 size: storageStats.file, 60 color: '#4B48F7' 61 }) 62 this.classifiedDataList.push({ 63 name: $r('app.string.query_data_system'), 64 size: await storageStatistics.getSystemSize(), 65 color: '#007DFF' 66 }) 67 Logger.info(TAG, `classifiedDataList: ${JSON.stringify(this.classifiedDataList)}`) 68 } 69 70 private async initAppDataList() { 71 this.appDataList = [] 72 let bundleFlags = bundle.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT | bundle.ApplicationFlag.GET_APPLICATION_INFO_WITH_PERMISSION | bundle.ApplicationFlag.GET_APPLICATION_INFO_WITH_METADATA | bundle.ApplicationFlag.GET_APPLICATION_INFO_WITH_DISABLE; 73 let applicationInfo: bundle.ApplicationInfo[] = 74 await bundle.getAllApplicationInfo(bundleFlags) 75 for (let i = 0; i < applicationInfo.length; i++) { 76 let info: bundle.ApplicationInfo = applicationInfo[i] 77 let appName: string = await this.getAppNameSync(info.labelId, info.name, info.label) 78 this.appDataList.push({ 79 appName: appName, 80 bundleName: info.name, 81 bundleStats: await storageStatistics.getBundleStats(info.name), 82 hasLabel: this.isAppHasAvailableLabel(appName) 83 }) 84 } 85 Logger.info(TAG, `appDataList: ${JSON.stringify(this.appDataList)}`) 86 } 87 88 private async initItemSizeList() { 89 this.itemSizeList = [] 90 for (let i = 0; i < this.classifiedDataList.length; i++) { 91 this.itemSizeList.push(ParseData.parseSize(this.classifiedDataList[i].size)) 92 } 93 Logger.info(TAG, `itemSizeList: ${JSON.stringify(this.itemSizeList)}`) 94 } 95 96 public async initData(callback?: (hasInit: boolean) => void) { 97 if(callback === undefined){ 98 return 99 } 100 101 try { 102 await this.initClassifiedDataList() 103 await this.initAppDataList() 104 await this.initItemSizeList() 105 this.totalSize = await storageStatistics.getTotalSize() 106 this.freeSize = await storageStatistics.getFreeSize() 107 } catch (error) { 108 Logger.error(TAG, `Init data failed ! error: ${error}`) 109 callback(false) 110 return 111 } 112 callback(true) 113 return 114 } 115 116 public async getUsedSize(callback: (usedSize: number) => void) { 117 if (this.totalSize > -1 && this.freeSize > -1) { 118 callback(this.totalSize - this.freeSize) 119 return 120 } 121 Logger.info(TAG, `totalSize or freeSize is -1, init data`) 122 await this.initData() 123 callback(this.totalSize - this.freeSize) 124 return 125 } 126 127 private async getAppNameSync(labelId: number, bundleName: string, appName: string): Promise<string> { 128 if (CheckEmptyUtils.isEmpty(labelId) || labelId <= 0 || CheckEmptyUtils.checkStrIsEmpty(bundleName)) { 129 Logger.info(TAG, `getAppNameSync param empty! appName: ${appName}`); 130 return bundleName; 131 } else { 132 let cacheKey = labelId + bundleName; 133 Logger.info(TAG, `getAppNameSync getResourceManager cacheKey: ${cacheKey}`); 134 if (this.isResourceManagerEmpty()) { 135 Logger.info(TAG, 'getAppNameSync resourceManager is empty'); 136 return bundleName; 137 } 138 let resMgrName: string = ''; 139 try { 140 let bundleContext: Context = this.context.createBundleContext(bundleName); 141 resMgrName = bundleContext.resourceManager.getStringSync(labelId); 142 } catch (err) { 143 Logger.error(TAG, `getAppNameSync error: ${JSON.stringify(err)}`); 144 } 145 146 Logger.info(TAG, `getAppNameSync resMgrName: ${resMgrName}`); 147 if (resMgrName != '') { 148 return resMgrName; 149 } else { 150 return bundleName; 151 } 152 } 153 } 154 155 private isResourceManagerEmpty(): boolean { 156 return CheckEmptyUtils.isEmpty(this.context) 157 || CheckEmptyUtils.isEmpty(this.context.resourceManager) 158 } 159 160 private isAppHasAvailableLabel(appName: string): boolean { 161 if (CheckEmptyUtils.checkStrIsEmpty(appName) || appName === 'label') { 162 return false 163 } 164 165 return true 166 } 167} 168 169export default new QueryStorageData()