• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 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 bundleManager from '@ohos.bundle.bundleManager';
17import commonEvent from '@ohos.commonEvent';
18import { AbilityInfo } from 'bundleManager/AbilityInfo';
19import { ExtensionAbilityInfo } from 'bundleManager/ExtensionAbilityInfo';
20import { CustomizeData } from 'bundle/customizeData';
21import { Metadata } from 'bundleManager/Metadata';
22import Log from '../../default/Log';
23import switchUserManager from '../../default/SwitchUserManager';
24
25export type AbilityInfoWithId = (AbilityInfo | ExtensionAbilityInfo) & { itemId: string };
26export type BundleListener = {
27  onBundleNotify: (bundleName: string, event: BundleEventType) => void;
28};
29export type ListenerHandle = {
30  unRegister: () => void;
31};
32export type PluginData = {
33  [key: string | number]: any;
34};
35
36export enum BundleEventType {
37  BUNDLE_ADD,
38  BUNDLE_CHANGE,
39  BUNDLE_REMOVE,
40  UNKNOWN_EVENT,
41}
42
43const TAG = 'SourceLoader-BundleParseUtil';
44const DEFAULT_BUNDLE_FLAG =
45  bundleManager.AbilityFlag.GET_ABILITY_INFO_WITH_METADATA | bundleManager.AbilityFlag.GET_ABILITY_INFO_WITH_PERMISSION;
46
47const BUNDLE_SUBSCRIBE_INFO = {
48  events: [
49    commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED,
50    commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED,
51    commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED,
52  ],
53};
54
55export async function queryAbility(action: string, userId: number, bundleName?: string): Promise<(AbilityInfo | ExtensionAbilityInfo)[]> {
56  Log.showDebug(TAG, `queryAbility, action: ${action} , userId: ${userId}`);
57  if (bundleName) {
58    Log.showDebug(TAG, `queryAbility, bundleName: ${bundleName}`);
59    return await queryAbilityWithBundleName(action, userId, bundleName);
60  }
61  return await queryAbilityWithoutBundleName(action, userId);
62}
63
64async function queryAbilityWithBundleName(action: string, userId: number, bundleName: string): Promise<(AbilityInfo | ExtensionAbilityInfo)[]> {
65  Log.showInfo(TAG, `queryAbilityWithBundleName, action: ${action} bundleName: ${bundleName}`);
66  let abilitys: AbilityInfo[] = [];
67  try {
68    abilitys = await bundleManager.queryAbilityInfo(
69      {
70        action: action,
71        bundleName: bundleName,
72      },
73      DEFAULT_BUNDLE_FLAG,
74      userId
75    );
76  } catch (error) {
77    Log.showError(TAG, `queryAbilityWithBundleName, queryAbilityByWant error: ${JSON.stringify(error)}`);
78  }
79  let extensionAbilitys: ExtensionAbilityInfo[] = [];
80  try {
81    extensionAbilitys = await bundleManager.queryExtensionAbilityInfo(
82      {
83        action: action,
84        bundleName: bundleName,
85      },
86      bundleManager.ExtensionAbilityType.UNSPECIFIED,
87      DEFAULT_BUNDLE_FLAG,
88      userId
89    );
90  } catch (error) {
91    Log.showError(TAG, `queryAbilityWithBundleName, queryExtensionAbilityInfo error: ${JSON.stringify(error)}`);
92  }
93  Log.showDebug(TAG, 'queryAbilityWithBundleName, end');
94  let rets = [...abilitys, ...extensionAbilitys];
95  Log.showDebug(TAG, `queryAbilityWithBundleName, rets: ${JSON.stringify(rets)}`);
96  return rets;
97}
98
99async function queryAbilityWithoutBundleName(action: string, userId: number): Promise<(AbilityInfo | ExtensionAbilityInfo)[]> {
100  Log.showInfo(TAG, `queryAbilityWithoutBundleName, action: ${action}`);
101  let abilitys: AbilityInfo[] = [];
102  try {
103    abilitys = await bundleManager.queryAbilityInfo({ action: action }, DEFAULT_BUNDLE_FLAG, userId);
104  } catch (error) {
105    Log.showError(TAG, `queryAbilityWithoutBundleName, queryAbilityByWant error: ${JSON.stringify(error)}`);
106  }
107  let extensionAbilitys: ExtensionAbilityInfo[] = [];
108  try {
109    extensionAbilitys = await bundleManager.queryExtensionAbilityInfo({
110      action: action
111    }, bundleManager.ExtensionAbilityType.UNSPECIFIED, DEFAULT_BUNDLE_FLAG, userId);
112  } catch (error) {
113    Log.showError(TAG, `queryAbilityWithoutBundleName, queryExtensionAbilityInfo error: ${JSON.stringify(error)}`);
114  }
115  Log.showDebug(TAG, 'queryAbilityWithoutBundleName, end');
116  let rets = [...abilitys, ...extensionAbilitys];
117  Log.showDebug(TAG, `queryAbilityWithoutBundleName, rets: ${JSON.stringify(rets)}`);
118  return rets;
119}
120
121export function filterAbilityInfo(info: AbilityInfoWithId, filterKey: string): PluginData | undefined {
122  Log.showInfo(TAG, `filterAbilityInfo, info: ${JSON.stringify(info)} filterKey: ${filterKey}`);
123  let pluginDatas: (CustomizeData | Metadata)[] = [];
124  if (info.metaData && info.metaData.length) {
125    pluginDatas = info.metaData.filter((data) => data.name == filterKey);
126  } else if (info.metadata && info.metadata.length) {
127    pluginDatas = info.metadata.filter((data) => data.name == filterKey);
128  }
129  Log.showInfo(TAG, `filterAbilityInfo, pluginDatas: ${JSON.stringify(pluginDatas)}`);
130  if (!pluginDatas.length) {
131    Log.showDebug(TAG, `filterKey: ${filterKey}, metadata: ${JSON.stringify(info.metadata.values)}`);
132    return undefined;
133  }
134  let pluginData: PluginData;
135  if (pluginDatas[0].value && pluginDatas[0].value.length > 0) {
136    pluginData = JSON.parse('{' + pluginDatas[0].value + '}') as PluginData;
137  } else if (pluginDatas[0].extra && pluginDatas[0].extra.length > 0) {
138    pluginData = JSON.parse('{' + pluginDatas[0].extra + '}') as PluginData;
139  }
140  if (!pluginData) {
141    Log.showError(TAG, `Can't parse pluginData: ${pluginDatas[0]}, filterKey: ${filterKey}`);
142    return undefined;
143  }
144  Log.showInfo(TAG, `filterAbilityInfo, pluginData: ${JSON.stringify(pluginData)}`);
145  return pluginData;
146}
147
148export function registerBundleListener(listener: BundleListener, callback: (handle: ListenerHandle) => void): void {
149  commonEvent.createSubscriber(BUNDLE_SUBSCRIBE_INFO, (err, handle) => {
150    Log.showDebug(TAG, `registerBundleListener, err: ${JSON.stringify(err)}, handle: ${handle}`);
151    if (err.code != 0) {
152      Log.showError(TAG, `Can't regitser bundle subscribe, err: ${JSON.stringify(err)}`);
153      return;
154    }
155    commonEvent.subscribe(handle, (err, data) => {
156      Log.showInfo(TAG, `bundle change, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
157      if (err.code != 0) {
158        Log.showError(TAG, `Can't handle bundle change, err: ${JSON.stringify(err)}`);
159        return;
160      }
161
162      switchUserManager.getInstance()
163        .getCurrentUserInfo()
164        .then((userInfo) => {
165          if (data.parameters.userId != userInfo.userId) {
166            return;
167          } else {
168            let event = BundleEventType.UNKNOWN_EVENT;
169            switch (data.event) {
170              case commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED:
171                event = BundleEventType.BUNDLE_ADD;
172                break;
173              case commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED:
174                event = BundleEventType.BUNDLE_CHANGE;
175                break;
176              case commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED:
177                event = BundleEventType.BUNDLE_REMOVE;
178                break;
179              default:
180                Log.showError(TAG, `unknow event: ${event}`);
181            }
182            listener.onBundleNotify(data.bundleName ?? 'unkown', event);
183          }
184        });
185    });
186    callback({
187      unRegister: () => {
188        commonEvent.unsubscribe(handle, () => {
189          Log.showInfo(TAG, `unRegister bundle info listener, handle: ${handle}`);
190        });
191      },
192    });
193  });
194}
195