1/** 2 * Copyright (c) 2021-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 16import bundleMgr from '@ohos.bundle'; 17import osAccount from '@ohos.account.osAccount'; 18import hiSysEvent from '@ohos.hiSysEvent'; 19import launcherBundleMgr from '@ohos.bundle.innerBundleManager'; 20import { LauncherAbilityInfo } from 'bundle/launcherAbilityInfo'; 21import { Log } from '../utils/Log'; 22import { Trace } from '../utils/Trace'; 23import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'; 24import { AppItemInfo } from '../bean/AppItemInfo'; 25import { CommonConstants } from '../constants/CommonConstants'; 26import { ResourceManager } from './ResourceManager'; 27import { EventConstants } from '../constants/EventConstants'; 28import { BadgeManager } from '../manager/BadgeManager'; 29 30const TAG = 'LauncherAbilityManager'; 31 32/** 33 * Wrapper class for innerBundleManager and formManager interfaces. 34 */ 35class LauncherAbilityManager { 36 private static readonly CURRENT_USER_ID = -2; 37 private static readonly BUNDLE_STATUS_CHANGE_KEY = 'BundleStatusChange'; 38 private readonly mAppMap = new Map<string, AppItemInfo>(); 39 private mUserId: number = 100; 40 41 private readonly mBundleStatusCallback: any = { 42 add: (bundleName, userId) => { 43 Log.showDebug(TAG, `mBundleStatusCallback add bundleName: ${bundleName}, userId: ${userId}, mUserId ${this.mUserId}`); 44 this.mUserId == userId && this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_ADDED, bundleName, userId); 45 }, 46 remove: (bundleName, userId) => { 47 Log.showDebug(TAG, `mBundleStatusCallback remove bundleName: ${bundleName}, userId: ${userId}, mUserId ${this.mUserId}`); 48 this.mUserId == userId && this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_REMOVED, bundleName, userId); 49 }, 50 update: (bundleName, userId) => { 51 Log.showDebug(TAG, `mBundleStatusCallback update bundleName: ${bundleName}, userId: ${userId}, mUserId ${this.mUserId}`); 52 this.mUserId == userId && this.notifyLauncherAbilityChange(EventConstants.EVENT_PACKAGE_CHANGED, bundleName, userId); 53 } 54 }; 55 56 private readonly mLauncherAbilityChangeListeners: any[] = []; 57 58 /** 59 * Get desktop application information management object 60 * 61 * @return Desktop application information management object instance 62 */ 63 static getInstance(): LauncherAbilityManager { 64 if (globalThis.LauncherAbilityManagerInstance == null) { 65 globalThis.LauncherAbilityManagerInstance = new LauncherAbilityManager(); 66 } 67 return globalThis.LauncherAbilityManagerInstance; 68 } 69 70 private constructor() { 71 const osAccountManager = osAccount.getAccountManager(); 72 osAccountManager.getOsAccountLocalId((err, localId) => { 73 Log.showDebug(TAG, `getOsAccountLocalId localId ${localId}`); 74 this.mUserId = localId; 75 }); 76 } 77 78 getUserId(): number { 79 return this.mUserId; 80 } 81 82 /** 83 * Monitor system application status. 84 * 85 * @params listener: listening object 86 */ 87 registerLauncherAbilityChangeListener(listener: any): void { 88 if (listener != null) { 89 if (this.mLauncherAbilityChangeListeners.length == 0) { 90 launcherBundleMgr.on(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY, this.mBundleStatusCallback).then(data => { 91 Log.showDebug(TAG, `registerCallback success: ${JSON.stringify(data)}`); 92 }).catch(err => { 93 Log.showError(TAG, `registerCallback fail: ${JSON.stringify(err)}`); 94 }); 95 } 96 const index = this.mLauncherAbilityChangeListeners.indexOf(listener); 97 if (index == CommonConstants.INVALID_VALUE) { 98 this.mLauncherAbilityChangeListeners.push(listener); 99 } 100 } 101 } 102 103 /** 104 * Cancel monitoring system application status. 105 * 106 * @params listener: listening object 107 */ 108 unregisterLauncherAbilityChangeListener(listener: any): void { 109 if (listener != null) { 110 const index = this.mLauncherAbilityChangeListeners.indexOf(listener); 111 if (index != CommonConstants.INVALID_VALUE) { 112 this.mLauncherAbilityChangeListeners.splice(index, 1); 113 } 114 if (this.mLauncherAbilityChangeListeners.length == 0) { 115 launcherBundleMgr.off(LauncherAbilityManager.BUNDLE_STATUS_CHANGE_KEY).then(data => { 116 Log.showDebug(TAG, 'unregisterCallback success'); 117 }).catch(err => { 118 Log.showError(TAG, `unregisterCallback fail: ${JSON.stringify(err)}`); 119 }); 120 } 121 } 122 } 123 124 private notifyLauncherAbilityChange(event, bundleName: string, userId): void { 125 for (let index = 0; index < this.mLauncherAbilityChangeListeners.length; index++) { 126 this.mLauncherAbilityChangeListeners[index](event, bundleName, userId); 127 } 128 } 129 130 /** 131 * get all app List info from BMS 132 */ 133 async getLauncherAbilityList(): Promise<AppItemInfo[]> { 134 let abilityList = null; 135 await launcherBundleMgr.getAllLauncherAbilityInfos(LauncherAbilityManager.CURRENT_USER_ID) 136 .then((res) => { 137 abilityList = res; 138 }) 139 .catch((err) => { 140 Log.showError(TAG, `getLauncherAbilityList error: ${JSON.stringify(err)}`); 141 }); 142 const appItemInfoList = new Array<AppItemInfo>(); 143 if (CheckEmptyUtils.isEmpty(abilityList)) { 144 Log.showDebug(TAG, 'getLauncherAbilityList Empty'); 145 return appItemInfoList; 146 } 147 for (let i = 0; i < abilityList.length; i++) { 148 let appItem = await this.convertToAppItemInfo(abilityList[i]); 149 appItemInfoList.push(appItem); 150 } 151 return appItemInfoList; 152 } 153 154 /** 155 * get AbilityInfos by bundleName from BMS 156 * 157 * @params bundleName Application package name 158 * @return List of entry capabilities information of the target application 159 */ 160 async getLauncherAbilityInfo(bundleName: string): Promise<AppItemInfo[]> { 161 let abilityInfos: LauncherAbilityInfo[]; 162 await launcherBundleMgr.getLauncherAbilityInfos(bundleName, this.mUserId) 163 .then((res) => { 164 abilityInfos = res; 165 }) 166 .catch((err) => { 167 Log.showError(TAG, `getLauncherAbilityInfo error: ${JSON.stringify(err)}`); 168 }); 169 const appItemInfoList = new Array<AppItemInfo>(); 170 if (CheckEmptyUtils.isEmpty(abilityInfos) || abilityInfos.length === 0) { 171 Log.showDebug(TAG, 'getLauncherAbilityInfo Empty'); 172 return appItemInfoList; 173 } 174 for (let i = 0; i < abilityInfos.length; i++) { 175 let appItem = await this.convertToAppItemInfo(abilityInfos[i]); 176 appItemInfoList.push(appItem); 177 } 178 return appItemInfoList; 179 } 180 181 /** 182 * get AppItemInfo from BMS with bundleName 183 * @params bundleName 184 * @return AppItemInfo 185 */ 186 async getAppInfoByBundleName(bundleName: string, abilityName?: string): Promise<AppItemInfo | undefined> { 187 let appItemInfo: AppItemInfo | undefined = undefined; 188 // get from cache 189 if (this.mAppMap && this.mAppMap.has(bundleName)) { 190 appItemInfo = this.mAppMap.get(bundleName); 191 } 192 if (appItemInfo && abilityName && appItemInfo.abilityName === abilityName) { 193 return appItemInfo; 194 } 195 // get from system 196 let abilityInfos = new Array<LauncherAbilityInfo>(); 197 await launcherBundleMgr.getLauncherAbilityInfos(bundleName, LauncherAbilityManager.CURRENT_USER_ID) 198 .then((res)=>{ 199 if (res && res.length) { 200 abilityInfos = res; 201 } 202 }) 203 .catch((err)=>{ 204 Log.showError(TAG, `getAppInfoByBundleName launcherBundleMgr getLauncherAbilityInfos error: ${JSON.stringify(err)}`); 205 }); 206 if (!abilityInfos || abilityInfos.length === 0) { 207 Log.showDebug(TAG, `${bundleName} has no launcher ability`); 208 return undefined; 209 } 210 let appInfo = abilityInfos[0]; 211 if (abilityName) { 212 appInfo = abilityInfos.find(item => { 213 return item.elementName.abilityName === abilityName; 214 }); 215 } 216 if (!appInfo) { 217 appInfo = abilityInfos[0]; 218 } 219 const data = await this.convertToAppItemInfo(appInfo); 220 return data; 221 } 222 223 private async convertToAppItemInfo(info): Promise<AppItemInfo> { 224 const appItemInfo = new AppItemInfo(); 225 appItemInfo.appName = await ResourceManager.getInstance().getAppNameSync( 226 info.labelId, info.elementName.bundleName, info.elementName.moduleName, info.applicationInfo.label 227 ); 228 appItemInfo.isSystemApp = info.applicationInfo.systemApp; 229 appItemInfo.isUninstallAble = info.applicationInfo.removable; 230 appItemInfo.appIconId = info.iconId; 231 appItemInfo.appLabelId = info.labelId; 232 appItemInfo.bundleName = info.elementName.bundleName; 233 appItemInfo.abilityName = info.elementName.abilityName; 234 appItemInfo.moduleName = info.elementName.moduleName; 235 appItemInfo.keyName = info.elementName.bundleName + info.elementName.abilityName + info.elementName.moduleName; 236 appItemInfo.typeId = CommonConstants.TYPE_APP; 237 appItemInfo.installTime = String(new Date()); 238 appItemInfo.badgeNumber = await BadgeManager.getInstance().getBadgeByBundleSync(info.elementName.bundleName); 239 await ResourceManager.getInstance().updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName, appItemInfo.moduleName); 240 this.mAppMap.set(appItemInfo.bundleName, appItemInfo); 241 return appItemInfo; 242 } 243 244 /** 245 * uninstall application, notice the userId need to be the login user 246 * 247 * @params bundleName application bundleName 248 * @params callback to get result 249 */ 250 async uninstallLauncherAbility(bundleName: string, callback): Promise<void> { 251 Log.showInfo(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`); 252 const bundlerInstaller = await bundleMgr.getBundleInstaller(); 253 bundlerInstaller.uninstall(bundleName, { 254 userId: this.mUserId, 255 installFlag: 0, 256 isKeepData: false 257 }, (result) => { 258 Log.showDebug(TAG, `uninstallLauncherAbility result => ${JSON.stringify(result)}`); 259 callback(result); 260 }); 261 } 262 263 /** 264 * start the app 265 * 266 * @params paramAbilityName: Ability name 267 * @params paramBundleName: Application package name 268 */ 269 startLauncherAbility(paramAbilityName: string, paramBundleName: string, paramModuleName: string) { 270 Log.showDebug(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}, moduleName ${paramModuleName}`); 271 globalThis.desktopContext.startAbility({ 272 bundleName: paramBundleName, 273 abilityName: paramAbilityName, 274 moduleName: paramModuleName 275 }).then(() => { 276 Log.showDebug(TAG, 'startApplication promise success'); 277 }, (err) => { 278 Log.showError(TAG, `startApplication promise error: ${JSON.stringify(err)}`); 279 }); 280 281 const sysEventInfo = { 282 domain: 'LAUNCHER_APP', 283 name: 'START_ABILITY', 284 eventType: hiSysEvent.EventType.BEHAVIOR, 285 params: { 286 'BUNDLE_NAME': paramBundleName, 287 'ABILITY_NAME': paramAbilityName, 288 'MODULE_NAME': paramModuleName 289 } 290 }; 291 hiSysEvent.write(sysEventInfo, 292 (err, value) => { 293 if (err) { 294 Log.showError(TAG, `startApplication hiSysEvent write error: ${err.code}`); 295 } else { 296 Log.showDebug(TAG, `startApplication hiSysEvent write success: ${value}`); 297 } 298 }) 299 } 300 301 /** 302 * start form config ability 303 * 304 * @params paramAbilityName 305 * @params paramBundleName 306 */ 307 startAbilityFormEdit(paramAbilityName: string, paramBundleName: string, paramModuleName: string, paramCardId: number) { 308 Log.showDebug(TAG, `startAbility abilityName: ${paramAbilityName},bundleName: ${paramBundleName}, moduleName: ${paramModuleName} ,paramCardId: ${paramCardId}`); 309 globalThis.desktopContext.startAbility({ 310 bundleName: paramBundleName, 311 abilityName: paramAbilityName, 312 moduleName: paramModuleName, 313 parameters: 314 { 315 formId: paramCardId.toString() 316 } 317 }).then((ret) => { 318 Log.showDebug(TAG, `startAbility ret: ${JSON.stringify(ret)}`); 319 }, (err) => { 320 Log.showError(TAG, `startAbility catch error: ${JSON.stringify(err)}`); 321 }); 322 } 323 324 async getShortcutInfo(paramBundleName, callback) { 325 Log.showDebug(TAG, `getShortcutInfo bundleName: ${paramBundleName}`); 326 await launcherBundleMgr.getShortcutInfos(paramBundleName) 327 .then(shortcutInfo => { 328 callback(paramBundleName, shortcutInfo); 329 }) 330 .catch(err => { 331 }); 332 } 333 334 /** 335 * start application by uri 336 * 337 * @params paramBundleName application bundle name 338 * @params paramAbilityName application abilit uri 339 */ 340 startLauncherAbilityByUri(paramBundleName, abilityUri) { 341 Log.showInfo(TAG, `startLauncherAbilityByUri bundleName:${paramBundleName} abilityUri:${abilityUri}`); 342 const result = globalThis.desktopContext.startAbility({ 343 bundleName: paramBundleName, 344 uri: abilityUri 345 }).then(() => { 346 Log.showDebug(TAG, 'startLauncherAbilityByUri promise success'); 347 }, (err) => { 348 Log.showError(TAG, `startLauncherAbilityByUri promise error: ${JSON.stringify(err)}`); 349 }); 350 Log.showDebug(TAG, `startLauncherAbilityByUri AceApplication : startAbility : ${result}`); 351 } 352 353 cleanAppMapCache() { 354 this.mAppMap.clear(); 355 } 356} 357 358export const launcherAbilityManager = LauncherAbilityManager.getInstance(); 359