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