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