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.getOsAccountLocalIdFromProcess((err, localId) => { 73 Log.showDebug(TAG, `getOsAccountLocalIdFromProcess 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)) { 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 != null && this.mAppMap.has(bundleName)) { 190 appItemInfo = this.mAppMap.get(bundleName); 191 } 192 if (appItemInfo != undefined) { 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 != undefined) { 200 abilityInfos = res; 201 } 202 }) 203 .catch((err)=>{ 204 Log.showError(TAG, `getAppInfoByBundleName launcherBundleMgr getLauncherAbilityInfos error: ${JSON.stringify(err)}`); 205 }); 206 207 if (abilityInfos == undefined || abilityInfos.length == 0) { 208 Log.showDebug(TAG, `${bundleName} has no launcher ability`); 209 return undefined; 210 } 211 let appInfo = abilityInfos[0]; 212 if (abilityName != undefined) { 213 appInfo = abilityInfos.find(item => { 214 return item.elementName.abilityName === abilityName; 215 }); 216 } 217 const data = await this.convertToAppItemInfo(appInfo); 218 return data; 219 } 220 221 private async convertToAppItemInfo(info): Promise<AppItemInfo> { 222 const appItemInfo = new AppItemInfo(); 223 appItemInfo.appName = await ResourceManager.getInstance().getAppNameSync( 224 info.labelId, info.elementName.bundleName, info.elementName.moduleName, info.applicationInfo.label 225 ); 226 appItemInfo.isSystemApp = info.applicationInfo.systemApp; 227 appItemInfo.isUninstallAble = info.applicationInfo.removable; 228 appItemInfo.appIconId = info.iconId; 229 appItemInfo.appLabelId = info.labelId; 230 appItemInfo.bundleName = info.elementName.bundleName; 231 appItemInfo.abilityName = info.elementName.abilityName; 232 appItemInfo.moduleName = info.elementName.moduleName; 233 appItemInfo.keyName = info.elementName.bundleName + info.elementName.abilityName + info.elementName.moduleName; 234 appItemInfo.typeId = CommonConstants.TYPE_APP; 235 appItemInfo.installTime = String(new Date()); 236 appItemInfo.badgeNumber = await BadgeManager.getInstance().getBadgeByBundleSync(info.elementName.bundleName); 237 await ResourceManager.getInstance().updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName, appItemInfo.moduleName); 238 this.mAppMap.set(appItemInfo.bundleName, appItemInfo); 239 return appItemInfo; 240 } 241 242 /** 243 * uninstall application, notice the userId need to be the login user 244 * 245 * @params bundleName application bundleName 246 * @params callback to get result 247 */ 248 async uninstallLauncherAbility(bundleName: string, callback): Promise<void> { 249 Log.showInfo(TAG, `uninstallLauncherAbility bundleName: ${bundleName}`); 250 const bundlerInstaller = await bundleMgr.getBundleInstaller(); 251 bundlerInstaller.uninstall(bundleName, { 252 userId: this.mUserId, 253 installFlag: 0, 254 isKeepData: false 255 }, (result) => { 256 Log.showDebug(TAG, `uninstallLauncherAbility result => ${JSON.stringify(result)}`); 257 callback(result); 258 }); 259 } 260 261 /** 262 * start the app 263 * 264 * @params paramAbilityName: Ability name 265 * @params paramBundleName: Application package name 266 */ 267 startLauncherAbility(paramAbilityName: string, paramBundleName: string, paramModuleName: string) { 268 Log.showDebug(TAG, `startApplication abilityName: ${paramAbilityName}, bundleName: ${paramBundleName}, moduleName ${paramModuleName}`); 269 globalThis.desktopContext.startAbility({ 270 bundleName: paramBundleName, 271 abilityName: paramAbilityName, 272 moduleName: paramModuleName 273 }).then(() => { 274 Log.showDebug(TAG, 'startApplication promise success'); 275 }, (err) => { 276 Log.showError(TAG, `startApplication promise error: ${JSON.stringify(err)}`); 277 }); 278 279 const sysEventInfo = { 280 domain: 'LAUNCHER_APP', 281 name: 'START_ABILITY', 282 eventType: hiSysEvent.EventType.BEHAVIOR, 283 params: { 284 'BUNDLE_NAME': paramBundleName, 285 'ABILITY_NAME': paramAbilityName, 286 'MODULE_NAME': paramModuleName 287 } 288 }; 289 hiSysEvent.write(sysEventInfo, 290 (err, value) => { 291 if (err) { 292 Log.showError(TAG, `startApplication hiSysEvent write error: ${err.code}`); 293 } else { 294 Log.showDebug(TAG, `startApplication hiSysEvent write success: ${value}`); 295 } 296 }) 297 } 298 299 /** 300 * start form config ability 301 * 302 * @params paramAbilityName 303 * @params paramBundleName 304 */ 305 startAbilityFormEdit(paramAbilityName: string, paramBundleName: string, paramModuleName: string, paramCardId: number) { 306 Log.showDebug(TAG, `startAbility abilityName: ${paramAbilityName},bundleName: ${paramBundleName}, moduleName: ${paramModuleName} ,paramCardId: ${paramCardId}`); 307 globalThis.desktopContext.startAbility({ 308 bundleName: paramBundleName, 309 abilityName: paramAbilityName, 310 moduleName: paramModuleName, 311 parameters: 312 { 313 formId: paramCardId.toString() 314 } 315 }).then((ret) => { 316 Log.showDebug(TAG, `startAbility ret: ${JSON.stringify(ret)}`); 317 }, (err) => { 318 Log.showError(TAG, `startAbility catch error: ${JSON.stringify(err)}`); 319 }); 320 } 321 322 async getShortcutInfo(paramBundleName, callback) { 323 Log.showDebug(TAG, `getShortcutInfo bundleName: ${paramBundleName}`); 324 await launcherBundleMgr.getShortcutInfos(paramBundleName) 325 .then(shortcutInfo => { 326 callback(paramBundleName, shortcutInfo); 327 }) 328 .catch(err => { 329 }); 330 } 331 332 /** 333 * start application by uri 334 * 335 * @params paramBundleName application bundle name 336 * @params paramAbilityName application abilit uri 337 */ 338 startLauncherAbilityByUri(paramBundleName, abilityUri) { 339 Log.showInfo(TAG, `startLauncherAbilityByUri bundleName:${paramBundleName} abilityUri:${abilityUri}`); 340 const result = globalThis.desktopContext.startAbility({ 341 bundleName: paramBundleName, 342 uri: abilityUri 343 }).then(() => { 344 Log.showDebug(TAG, 'startLauncherAbilityByUri promise success'); 345 }, (err) => { 346 Log.showError(TAG, `startLauncherAbilityByUri promise error: ${JSON.stringify(err)}`); 347 }); 348 Log.showDebug(TAG, `startLauncherAbilityByUri AceApplication : startAbility : ${result}`); 349 } 350 351 cleanAppMapCache(): void { 352 this.mAppMap.clear(); 353 } 354} 355 356export const launcherAbilityManager = LauncherAbilityManager.getInstance(); 357