1/**
2 * Copyright (c) 2023-2023 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 bundleManager from '@ohos.bundle.bundleManager';
17import { AppItemInfo } from '../bean/AppItemInfo';
18import { CheckEmptyUtils } from '../utils/CheckEmptyUtils';
19import { ResourceManager } from './ResourceManager';
20import commonBundleManager from './CommonBundleManager';
21import { Log } from '../utils/Log';
22
23const TAG = 'AtomicServiceAbilityManager';
24
25/**
26 * 原服务管理
27 */
28class AtomicServiceAbilityManager {
29  private readonly mAtomicServiceAppMap = new Map<string, AppItemInfo>();
30  private static mInstance: AtomicServiceAbilityManager;
31
32  /**
33   * 获取桌面应用信息管理对象
34   *
35   * @return 桌面应用信息管理对象单一实例
36   */
37  static getInstance(): AtomicServiceAbilityManager {
38    if (AtomicServiceAbilityManager.mInstance == null) {
39      AtomicServiceAbilityManager.mInstance = new AtomicServiceAbilityManager();
40      globalThis.AtomicServiceAbilityManagerInstance = AtomicServiceAbilityManager.mInstance;
41    }
42    Log.showInfo(TAG, 'getInstance!');
43    return AtomicServiceAbilityManager.mInstance;
44  }
45
46  private constructor() {
47  }
48
49  /**
50   * 获取userId.
51   */
52  getUserId(): number {
53    return commonBundleManager.getUserId();
54  }
55
56  /**
57   * 从包管理获取所有的原服务应用信息
58   *
59   * @returns 所有的原服务应用信息
60   */
61  async getAtomicServiceAbilityList(): Promise<AppItemInfo[]> {
62    let abilityList: Array<bundleManager.AbilityInfo> = await commonBundleManager.getAllAbilityList(bundleManager.BundleType.ATOMIC_SERVICE);
63    let appItemInfoList: AppItemInfo[] = [];
64    if (CheckEmptyUtils.isEmptyArr(abilityList)) {
65      return appItemInfoList;
66    }
67    for (let i = 0; i < abilityList.length; i++) {
68      let appItem: AppItemInfo = await this.convertAtomicServiceToAppItemInfo(abilityList[i]);
69      if (!CheckEmptyUtils.isEmpty(appItem)) {
70        appItemInfoList.push(appItem);
71      }
72    }
73    return appItemInfoList;
74  }
75
76  /**
77   * 从包管理获取应用信息
78   *
79   * @param bundleName 包名
80   * @returns 应用信息
81   */
82  async getAtomicServiceAbilityInfoAsync(bundleName: string): Promise<AppItemInfo[]> {
83    if (CheckEmptyUtils.checkStrIsEmpty(bundleName)) {
84      Log.showError(TAG, 'getAtomicServiceAbilityInfoAsync reqParam bundleName is empty');
85      return [];
86    }
87    let bundleInfo: bundleManager.BundleInfo = await commonBundleManager.getBundleInfoByBundleName(bundleName, bundleManager.BundleType.ATOMIC_SERVICE);
88    if (CheckEmptyUtils.isEmpty(bundleInfo)) {
89      Log.showInfo(TAG, `getAtomicServiceAbilityInfoAsync by bundleName:${bundleName} no result from MGR`);
90      return [];
91    }
92    let appItemInfoList :AppItemInfo[] = [];
93    if (CheckEmptyUtils.isEmptyArr(bundleInfo.hapModulesInfo)) {
94      return appItemInfoList;
95    }
96    for (let i = 0; i < bundleInfo.hapModulesInfo.length; i++) {
97      if (CheckEmptyUtils.isEmptyArr(bundleInfo.hapModulesInfo[i].abilitiesInfo)) {
98        continue;
99      }
100      for (let j = 0; j < bundleInfo.hapModulesInfo[i].abilitiesInfo.length; j++) {
101        let appItem: AppItemInfo = await this.convertAtomicServiceToAppItemInfo(bundleInfo.hapModulesInfo[i].abilitiesInfo[j], bundleInfo.appInfo);
102        if (!CheckEmptyUtils.isEmpty(appItem)) {
103          appItemInfoList.push(appItem);
104        }
105      }
106    }
107    return appItemInfoList;
108  }
109
110  /**
111   * 从缓存中获取或包管理获取原服务ability信息
112   *
113   * @param bundleName 包名
114   * @returns 一个ability信息
115   */
116  async getAnAtomicServiceAbilityInfoFromCache(bundleName: string): Promise<AppItemInfo | undefined> {
117    let appItemInfo: AppItemInfo | undefined = undefined;
118    if (CheckEmptyUtils.checkStrIsEmpty(bundleName)) {
119      Log.showError(TAG, 'getAnAtomicServiceAbilityInfoFromCache reqParam bundleName is empty');
120      return appItemInfo;
121    }
122    // get from cache
123    if (this.mAtomicServiceAppMap != null && this.mAtomicServiceAppMap.has(bundleName)) {
124      appItemInfo = this.mAtomicServiceAppMap.get(bundleName);
125    }
126    if (!CheckEmptyUtils.isEmpty(appItemInfo)) {
127      Log.showInfo(TAG, `getAnAtomicServiceAbilityInfoFromCache cache result: ${JSON.stringify(appItemInfo)}`);
128      return appItemInfo;
129    }
130    // get from mgr
131    let abilityList: AppItemInfo[] = await this.getAtomicServiceAbilityInfoAsync(bundleName);
132    if (CheckEmptyUtils.isEmptyArr(abilityList)) {
133      Log.showInfo(TAG, `${bundleName} has no atomic ability`);
134      return undefined;
135    }
136    Log.showInfo(TAG, `getAnAtomicServiceAbilityInfoFromCache from MGR: ${JSON.stringify(abilityList[0])}`);
137    return abilityList[0];
138  }
139
140  private async convertAtomicServiceToAppItemInfo(info: bundleManager.AbilityInfo,
141                                                  applicationInfo?: bundleManager.ApplicationInfo): Promise<AppItemInfo | undefined> {
142    if (CheckEmptyUtils.isEmpty(info)) {
143      Log.showError(TAG, 'convertAtomicServiceToAppItemInfo reqParam is empty');
144      return undefined;
145    }
146    let appInfo: bundleManager.ApplicationInfo = info.applicationInfo;
147    if (CheckEmptyUtils.isEmpty(appInfo)) {
148      appInfo = applicationInfo;
149    }
150    if (CheckEmptyUtils.isEmpty(appInfo)) {
151      Log.showError(TAG, 'convertAtomicServiceToAppItemInfo applicationInfo is empty');
152      return undefined;
153    }
154    const appItemInfo = new AppItemInfo();
155    appItemInfo.appName = await ResourceManager.getInstance().getAppNameSync(
156      appInfo.labelId, info.bundleName, info.moduleName, appInfo.label
157    );
158    appItemInfo.isSystemApp = appInfo.systemApp;
159    appItemInfo.isUninstallAble = appInfo.removable;
160    appItemInfo.appIconId = appInfo.iconId;
161    appItemInfo.appLabelId = appInfo.labelId;
162    appItemInfo.bundleName = info.bundleName;
163    appItemInfo.abilityName = info.name;
164    appItemInfo.moduleName = info.moduleName;
165    appItemInfo.keyName = info.bundleName + info.name + info.moduleName;
166    appItemInfo.bundleType = bundleManager.BundleType.ATOMIC_SERVICE;
167    await ResourceManager.getInstance().updateIconCache(appItemInfo.appIconId, appItemInfo.bundleName, appItemInfo.moduleName);
168    this.mAtomicServiceAppMap.set(appItemInfo.bundleName, appItemInfo);
169    Log.showInfo(TAG, `convertAtomicServiceToAppItemInfo appItemInfo: ${JSON.stringify(appItemInfo)}`);
170    return appItemInfo;
171  }
172
173  cleanAppMapCache(): void {
174    this.mAtomicServiceAppMap.clear();
175  }
176}
177
178const atomicServiceAbilityManager = AtomicServiceAbilityManager.getInstance();
179export default atomicServiceAbilityManager;
180