16e80583aSopenharmony_ci/** 26e80583aSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 36e80583aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 46e80583aSopenharmony_ci * you may not use this file except in compliance with the License. 56e80583aSopenharmony_ci * You may obtain a copy of the License at 66e80583aSopenharmony_ci * 76e80583aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 86e80583aSopenharmony_ci * 96e80583aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 106e80583aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 116e80583aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 126e80583aSopenharmony_ci * See the License for the specific language governing permissions and 136e80583aSopenharmony_ci * limitations under the License. 146e80583aSopenharmony_ci */ 156e80583aSopenharmony_ci 166e80583aSopenharmony_ciimport { Log } from '../utils/Log'; 176e80583aSopenharmony_ciimport { CheckEmptyUtils } from '../utils/CheckEmptyUtils'; 186e80583aSopenharmony_ciimport { EventConstants } from '../constants/EventConstants'; 196e80583aSopenharmony_ciimport { CommonConstants } from '../constants/CommonConstants'; 206e80583aSopenharmony_ciimport { FormModel } from './FormModel'; 216e80583aSopenharmony_ciimport { AppItemInfo } from '../bean/AppItemInfo'; 226e80583aSopenharmony_ciimport { localEventManager } from '../manager/LocalEventManager'; 236e80583aSopenharmony_ciimport { launcherAbilityManager } from '../manager/LauncherAbilityManager'; 246e80583aSopenharmony_ciimport SystemApplication from '../configs/SystemApplication'; 256e80583aSopenharmony_ciimport { AtomicServiceAppModel } from './AtomicServiceAppModel'; 266e80583aSopenharmony_ciimport launcherBundleManager from '@ohos.bundle.launcherBundleManager'; 276e80583aSopenharmony_ci 286e80583aSopenharmony_ciconst TAG = 'AppModel'; 296e80583aSopenharmony_ci 306e80583aSopenharmony_ci/** 316e80583aSopenharmony_ci * Desktop application information data model. 326e80583aSopenharmony_ci */ 336e80583aSopenharmony_ciexport class AppModel { 346e80583aSopenharmony_ci private mBundleInfoList: AppItemInfo[] = []; 356e80583aSopenharmony_ci private readonly mSystemApplicationName = []; 366e80583aSopenharmony_ci private readonly mAppStateChangeListener = []; 376e80583aSopenharmony_ci private readonly mShortcutInfoMap = new Map<string, launcherBundleManager.ShortcutInfo[]>(); 386e80583aSopenharmony_ci private readonly mFormModel: FormModel; 396e80583aSopenharmony_ci private readonly mInstallationListener; 406e80583aSopenharmony_ci private readonly mAtomicServiceAppModel: AtomicServiceAppModel; 416e80583aSopenharmony_ci 426e80583aSopenharmony_ci private constructor() { 436e80583aSopenharmony_ci Log.showInfo(TAG, 'constructor start'); 446e80583aSopenharmony_ci this.mSystemApplicationName = SystemApplication.SystemApplicationName.split(','); 456e80583aSopenharmony_ci this.mFormModel = FormModel.getInstance(); 466e80583aSopenharmony_ci this.mAtomicServiceAppModel = AtomicServiceAppModel.getInstance(); 476e80583aSopenharmony_ci this.mInstallationListener = this.installationSubscriberCallBack.bind(this); 486e80583aSopenharmony_ci } 496e80583aSopenharmony_ci 506e80583aSopenharmony_ci /** 516e80583aSopenharmony_ci * Get the application data model object. 526e80583aSopenharmony_ci * 536e80583aSopenharmony_ci * @return {object} application data model singleton 546e80583aSopenharmony_ci */ 556e80583aSopenharmony_ci static getInstance(): AppModel { 566e80583aSopenharmony_ci if (globalThis.AppModel == null) { 576e80583aSopenharmony_ci globalThis.AppModel = new AppModel(); 586e80583aSopenharmony_ci } 596e80583aSopenharmony_ci return globalThis.AppModel; 606e80583aSopenharmony_ci } 616e80583aSopenharmony_ci 626e80583aSopenharmony_ci /** 636e80583aSopenharmony_ci * Get the list of apps displayed on the desktop. 646e80583aSopenharmony_ci * (public function, reduce the frequency of method call) 656e80583aSopenharmony_ci * 666e80583aSopenharmony_ci * @return {array} bundleInfoList 676e80583aSopenharmony_ci */ 686e80583aSopenharmony_ci async getAppList() { 696e80583aSopenharmony_ci Log.showInfo(TAG, 'getAppList start'); 706e80583aSopenharmony_ci if (!CheckEmptyUtils.isEmptyArr(this.mBundleInfoList)) { 716e80583aSopenharmony_ci Log.showInfo(TAG, `getAppList bundleInfoList length: ${this.mBundleInfoList.length}`); 726e80583aSopenharmony_ci return this.mBundleInfoList; 736e80583aSopenharmony_ci } 746e80583aSopenharmony_ci const bundleInfoList: AppItemInfo[] = await this.getAppListAsync(); 756e80583aSopenharmony_ci return bundleInfoList; 766e80583aSopenharmony_ci } 776e80583aSopenharmony_ci 786e80583aSopenharmony_ci /** 796e80583aSopenharmony_ci * Get the list of apps displayed on the desktop (private function). 806e80583aSopenharmony_ci * 816e80583aSopenharmony_ci * @return {array} bundleInfoList, excluding system applications 826e80583aSopenharmony_ci */ 836e80583aSopenharmony_ci async getAppListAsync(): Promise<AppItemInfo[]> { 846e80583aSopenharmony_ci let allAbilityList: AppItemInfo[] = await launcherAbilityManager.getLauncherAbilityList(); 856e80583aSopenharmony_ci Log.showInfo(TAG, `getAppListAsync--->allAbilityList length: ${allAbilityList.length}`); 866e80583aSopenharmony_ci let launcherAbilityList: AppItemInfo[] = []; 876e80583aSopenharmony_ci for (const ability of allAbilityList) { 886e80583aSopenharmony_ci if (this.mSystemApplicationName.indexOf(ability.bundleName) === CommonConstants.INVALID_VALUE) { 896e80583aSopenharmony_ci launcherAbilityList.push(ability); 906e80583aSopenharmony_ci this.updateShortcutInfo(ability.bundleName); 916e80583aSopenharmony_ci this.mFormModel.updateAppItemFormInfo(ability.bundleName); 926e80583aSopenharmony_ci } 936e80583aSopenharmony_ci } 946e80583aSopenharmony_ci this.mBundleInfoList = launcherAbilityList; 956e80583aSopenharmony_ci Log.showInfo(TAG, `getAppListAsync--->allAbilityList length after filtration: ${launcherAbilityList.length}`); 966e80583aSopenharmony_ci return launcherAbilityList; 976e80583aSopenharmony_ci } 986e80583aSopenharmony_ci 996e80583aSopenharmony_ci /** 1006e80583aSopenharmony_ci * Register application list change event listener. 1016e80583aSopenharmony_ci * 1026e80583aSopenharmony_ci * @param listener 1036e80583aSopenharmony_ci */ 1046e80583aSopenharmony_ci registerStateChangeListener(listener): void { 1056e80583aSopenharmony_ci if (this.mAppStateChangeListener.indexOf(listener) === CommonConstants.INVALID_VALUE) { 1066e80583aSopenharmony_ci this.mAppStateChangeListener.push(listener); 1076e80583aSopenharmony_ci } 1086e80583aSopenharmony_ci } 1096e80583aSopenharmony_ci 1106e80583aSopenharmony_ci /** 1116e80583aSopenharmony_ci * Unregister application list change event listener. 1126e80583aSopenharmony_ci * 1136e80583aSopenharmony_ci * @param listener 1146e80583aSopenharmony_ci */ 1156e80583aSopenharmony_ci unregisterAppStateChangeListener(listener): void { 1166e80583aSopenharmony_ci let index: number = this.mAppStateChangeListener.indexOf(listener); 1176e80583aSopenharmony_ci if (index != CommonConstants.INVALID_VALUE) { 1186e80583aSopenharmony_ci this.mAppStateChangeListener.splice(index, 1); 1196e80583aSopenharmony_ci } 1206e80583aSopenharmony_ci } 1216e80583aSopenharmony_ci 1226e80583aSopenharmony_ci getUserId(): number { 1236e80583aSopenharmony_ci return launcherAbilityManager.getUserId(); 1246e80583aSopenharmony_ci } 1256e80583aSopenharmony_ci 1266e80583aSopenharmony_ci /** 1276e80583aSopenharmony_ci * Start listening to the system application status. 1286e80583aSopenharmony_ci */ 1296e80583aSopenharmony_ci registerAppListEvent(): void { 1306e80583aSopenharmony_ci launcherAbilityManager.registerLauncherAbilityChangeListener(this.mInstallationListener); 1316e80583aSopenharmony_ci } 1326e80583aSopenharmony_ci 1336e80583aSopenharmony_ci /** 1346e80583aSopenharmony_ci * Stop listening for system application status. 1356e80583aSopenharmony_ci */ 1366e80583aSopenharmony_ci unregisterAppListEvent(): void { 1376e80583aSopenharmony_ci launcherAbilityManager.unregisterLauncherAbilityChangeListener(this.mInstallationListener); 1386e80583aSopenharmony_ci } 1396e80583aSopenharmony_ci 1406e80583aSopenharmony_ci /** 1416e80583aSopenharmony_ci * The callback function of the application installation event. 1426e80583aSopenharmony_ci * 1436e80583aSopenharmony_ci * @param {Object} event 1446e80583aSopenharmony_ci * @param {string} bundleName 1456e80583aSopenharmony_ci * @param {number} userId 1466e80583aSopenharmony_ci */ 1476e80583aSopenharmony_ci private async installationSubscriberCallBack(event, bundleName, userId) { 1486e80583aSopenharmony_ci Log.showInfo(TAG, `installationSubscriberCallBack event: ${event}`); 1496e80583aSopenharmony_ci this.closePopup(); 1506e80583aSopenharmony_ci this.updateShortcutInfo(bundleName, event); 1516e80583aSopenharmony_ci this.mFormModel.updateAppItemFormInfo(bundleName, event); 1526e80583aSopenharmony_ci // initial mBundleInfoList 1536e80583aSopenharmony_ci if (CheckEmptyUtils.isEmptyArr(this.mBundleInfoList)) { 1546e80583aSopenharmony_ci await this.getAppListAsync(); 1556e80583aSopenharmony_ci } 1566e80583aSopenharmony_ci if (event === EventConstants.EVENT_PACKAGE_REMOVED) { 1576e80583aSopenharmony_ci this.removeItem(bundleName); 1586e80583aSopenharmony_ci this.mAtomicServiceAppModel.removeAtomicServiceItem(bundleName); 1596e80583aSopenharmony_ci this.mFormModel.deleteFormByBundleName(bundleName); 1606e80583aSopenharmony_ci 1616e80583aSopenharmony_ci // delete app from folder 1626e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_FOLDER_PACKAGE_REMOVED, bundleName); 1636e80583aSopenharmony_ci 1646e80583aSopenharmony_ci // delete app form dock 1656e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_RESIDENT_DOCK_ITEM_DELETE, { 1666e80583aSopenharmony_ci bundleName: bundleName, 1676e80583aSopenharmony_ci keyName: undefined 1686e80583aSopenharmony_ci }); 1696e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_RECENT_DOCK_ITEM_DELETE, { 1706e80583aSopenharmony_ci bundleName: bundleName, 1716e80583aSopenharmony_ci keyName: undefined 1726e80583aSopenharmony_ci }); 1736e80583aSopenharmony_ci 1746e80583aSopenharmony_ci // delete app from pageDesktop 1756e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_DELETE, { 1766e80583aSopenharmony_ci bundleName: bundleName, 1776e80583aSopenharmony_ci keyName: undefined 1786e80583aSopenharmony_ci }); 1796e80583aSopenharmony_ci 1806e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_RECOMMEND_FORM_DELETE, bundleName); 1816e80583aSopenharmony_ci } else { 1826e80583aSopenharmony_ci let appItemInfo: AppItemInfo = await this.getAndReplaceLauncherAbility(bundleName); 1836e80583aSopenharmony_ci 1846e80583aSopenharmony_ci if (CheckEmptyUtils.isEmpty(appItemInfo)) { 1856e80583aSopenharmony_ci appItemInfo = await this.mAtomicServiceAppModel.getAndReplaceAtomicAbility(bundleName); 1866e80583aSopenharmony_ci } 1876e80583aSopenharmony_ci 1886e80583aSopenharmony_ci if (CheckEmptyUtils.isEmpty(appItemInfo)) { 1896e80583aSopenharmony_ci Log.showError(TAG, `installationSubscriberCallBack neither launcher nor atomic app, bundleName:${bundleName} `); 1906e80583aSopenharmony_ci return; 1916e80583aSopenharmony_ci } 1926e80583aSopenharmony_ci if (event === EventConstants.EVENT_PACKAGE_CHANGED) { 1936e80583aSopenharmony_ci Log.showInfo(TAG, `installationSubscriber, PACKAGE_CHANGED, bundleName is ${bundleName}`); 1946e80583aSopenharmony_ci AppStorage.setOrCreate('formRefresh', String(new Date())); 1956e80583aSopenharmony_ci 1966e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_RECOMMEND_FORM_UPDATE, bundleName); 1976e80583aSopenharmony_ci Log.showError(TAG, `installationSubscriberCallBack unKnow bundleType:${appItemInfo.bundleType}`); 1986e80583aSopenharmony_ci } else { 1996e80583aSopenharmony_ci await this.mFormModel.updateAppItemFormInfo(bundleName); 2006e80583aSopenharmony_ci await this.mFormModel.updateAtomicServiceAppItemFormInfo(bundleName); 2016e80583aSopenharmony_ci localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_RECOMMEND_FORM_ADD, bundleName); 2026e80583aSopenharmony_ci } 2036e80583aSopenharmony_ci } 2046e80583aSopenharmony_ci this.notifyAppStateChangeEvent(); 2056e80583aSopenharmony_ci } 2066e80583aSopenharmony_ci 2076e80583aSopenharmony_ci private async getAndReplaceLauncherAbility(bundleName: string): Promise<AppItemInfo> { 2086e80583aSopenharmony_ci const abilityInfos: AppItemInfo[] = await launcherAbilityManager.getLauncherAbilityInfo(bundleName); 2096e80583aSopenharmony_ci if (CheckEmptyUtils.isEmptyArr(abilityInfos)) { 2106e80583aSopenharmony_ci return undefined; 2116e80583aSopenharmony_ci } 2126e80583aSopenharmony_ci Log.showDebug(TAG, `launcher abilityInfos: ${JSON.stringify(abilityInfos)}`); 2136e80583aSopenharmony_ci this.replaceItem(bundleName, abilityInfos); 2146e80583aSopenharmony_ci return abilityInfos[0]; 2156e80583aSopenharmony_ci } 2166e80583aSopenharmony_ci 2176e80583aSopenharmony_ci /** 2186e80583aSopenharmony_ci * Send event about application state change. 2196e80583aSopenharmony_ci */ 2206e80583aSopenharmony_ci private notifyAppStateChangeEvent() { 2216e80583aSopenharmony_ci for (let i = 0; i < this.mAppStateChangeListener.length; i++) { 2226e80583aSopenharmony_ci this.mAppStateChangeListener[i](this.mBundleInfoList); 2236e80583aSopenharmony_ci } 2246e80583aSopenharmony_ci } 2256e80583aSopenharmony_ci 2266e80583aSopenharmony_ci /** 2276e80583aSopenharmony_ci * Get the app index in bundleInfoList. 2286e80583aSopenharmony_ci * 2296e80583aSopenharmony_ci * @param {string} bundleName 2306e80583aSopenharmony_ci * @return {number} index 2316e80583aSopenharmony_ci */ 2326e80583aSopenharmony_ci private getItemIndex(bundleName): number { 2336e80583aSopenharmony_ci for (const listItem of this.mBundleInfoList) { 2346e80583aSopenharmony_ci if (listItem.bundleName === bundleName) { 2356e80583aSopenharmony_ci const index = this.mBundleInfoList.indexOf(listItem); 2366e80583aSopenharmony_ci return index; 2376e80583aSopenharmony_ci } 2386e80583aSopenharmony_ci } 2396e80583aSopenharmony_ci return CommonConstants.INVALID_VALUE; 2406e80583aSopenharmony_ci } 2416e80583aSopenharmony_ci 2426e80583aSopenharmony_ci /** 2436e80583aSopenharmony_ci * Append app items into the bundleInfoList. 2446e80583aSopenharmony_ci * 2456e80583aSopenharmony_ci * @param {array} abilityInfos 2466e80583aSopenharmony_ci */ 2476e80583aSopenharmony_ci private appendItem(abilityInfos): void { 2486e80583aSopenharmony_ci for (let index = 0; index < abilityInfos.length; index++) { 2496e80583aSopenharmony_ci this.mBundleInfoList.push(abilityInfos[index]); 2506e80583aSopenharmony_ci } 2516e80583aSopenharmony_ci } 2526e80583aSopenharmony_ci 2536e80583aSopenharmony_ci /** 2546e80583aSopenharmony_ci * Remove app item from the bundleInfoList. 2556e80583aSopenharmony_ci * 2566e80583aSopenharmony_ci * @param {string} bundleName 2576e80583aSopenharmony_ci */ 2586e80583aSopenharmony_ci private removeItem(bundleName: string): void { 2596e80583aSopenharmony_ci Log.showDebug(TAG, `removeItem bundleName: ${bundleName}`); 2606e80583aSopenharmony_ci let originItemIndex = this.getItemIndex(bundleName); 2616e80583aSopenharmony_ci while (originItemIndex != CommonConstants.INVALID_VALUE) { 2626e80583aSopenharmony_ci this.removeItemCache(this.mBundleInfoList[originItemIndex]); 2636e80583aSopenharmony_ci this.mBundleInfoList.splice(originItemIndex, 1); 2646e80583aSopenharmony_ci originItemIndex = this.getItemIndex(bundleName); 2656e80583aSopenharmony_ci } 2666e80583aSopenharmony_ci } 2676e80583aSopenharmony_ci 2686e80583aSopenharmony_ci /** 2696e80583aSopenharmony_ci * Remove app item from the cache. 2706e80583aSopenharmony_ci * 2716e80583aSopenharmony_ci * @param {string} bundleName 2726e80583aSopenharmony_ci */ 2736e80583aSopenharmony_ci private removeItemCache(appItemInfo: AppItemInfo): void { 2746e80583aSopenharmony_ci Log.showDebug(TAG, `removeItemCache bundleName: ${(appItemInfo.bundleName)}`); 2756e80583aSopenharmony_ci let cacheKey = appItemInfo.appLabelId + appItemInfo.bundleName + appItemInfo.moduleName; 2766e80583aSopenharmony_ci globalThis.ResourceManager.deleteAppResourceCache(cacheKey, 'name'); 2776e80583aSopenharmony_ci cacheKey = appItemInfo.appIconId + appItemInfo.bundleName + appItemInfo.moduleName; 2786e80583aSopenharmony_ci globalThis.ResourceManager.deleteAppResourceCache(cacheKey, 'icon'); 2796e80583aSopenharmony_ci } 2806e80583aSopenharmony_ci 2816e80583aSopenharmony_ci /** 2826e80583aSopenharmony_ci * Replace app items in the bundleInfoList. 2836e80583aSopenharmony_ci * 2846e80583aSopenharmony_ci * @param {string} bundleName 2856e80583aSopenharmony_ci * @param {array} abilityInfos 2866e80583aSopenharmony_ci */ 2876e80583aSopenharmony_ci private replaceItem(bundleName: string, abilityInfos): void { 2886e80583aSopenharmony_ci Log.showDebug(TAG, `replaceItem bundleName: ${bundleName}`); 2896e80583aSopenharmony_ci this.removeItem(bundleName); 2906e80583aSopenharmony_ci this.appendItem(abilityInfos); 2916e80583aSopenharmony_ci } 2926e80583aSopenharmony_ci 2936e80583aSopenharmony_ci /** 2946e80583aSopenharmony_ci * Put shortcut info into map. 2956e80583aSopenharmony_ci * 2966e80583aSopenharmony_ci * @param {string} bundleName 2976e80583aSopenharmony_ci * @param {array} shortcutInfo 2986e80583aSopenharmony_ci */ 2996e80583aSopenharmony_ci setShortcutInfo(bundleName: string, shortcutInfo: launcherBundleManager.ShortcutInfo[]): void { 3006e80583aSopenharmony_ci this.mShortcutInfoMap.set(bundleName, shortcutInfo); 3016e80583aSopenharmony_ci } 3026e80583aSopenharmony_ci 3036e80583aSopenharmony_ci /** 3046e80583aSopenharmony_ci * Get shortcut info from map. 3056e80583aSopenharmony_ci * 3066e80583aSopenharmony_ci * @param {string} bundleName 3076e80583aSopenharmony_ci * @return {array | undefined} shortcutInfo 3086e80583aSopenharmony_ci */ 3096e80583aSopenharmony_ci getShortcutInfo(bundleName: string): launcherBundleManager.ShortcutInfo[] | undefined { 3106e80583aSopenharmony_ci return this.mShortcutInfoMap.get(bundleName); 3116e80583aSopenharmony_ci } 3126e80583aSopenharmony_ci 3136e80583aSopenharmony_ci /** 3146e80583aSopenharmony_ci * Update shortcut info of map. 3156e80583aSopenharmony_ci * 3166e80583aSopenharmony_ci * @param {string} bundleName 3176e80583aSopenharmony_ci * @param {string | undefined} eventType 3186e80583aSopenharmony_ci */ 3196e80583aSopenharmony_ci private updateShortcutInfo(bundleName, eventType?): void { 3206e80583aSopenharmony_ci if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 3216e80583aSopenharmony_ci this.mShortcutInfoMap.delete(bundleName); 3226e80583aSopenharmony_ci return; 3236e80583aSopenharmony_ci } 3246e80583aSopenharmony_ci launcherAbilityManager.getShortcutInfo(bundleName, this.setShortcutInfo.bind(this)); 3256e80583aSopenharmony_ci } 3266e80583aSopenharmony_ci 3276e80583aSopenharmony_ci /** 3286e80583aSopenharmony_ci * Close popup. 3296e80583aSopenharmony_ci */ 3306e80583aSopenharmony_ci private closePopup(): void { 3316e80583aSopenharmony_ci ContextMenu.close(); 3326e80583aSopenharmony_ci } 3336e80583aSopenharmony_ci}