* Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Prompt } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';
import { NumberConstants } from '@ohos/commonconstants';
import type Context from '@ohos.app.ability.common';
import type ctx from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import {
AppItemInfo,
AppModel,
AppStatus,
GridLayoutItemInfo,
launcherAbilityManager,
LaunchLayoutCacheManager,
NotHarmonyUtil,
LegacyInfo,
DockItemInfo,
GridLayoutUtil,
CommonConstants,
ResidentLayoutCacheMgr
} from '../TsIndex';
import taskPool from '@ohos.taskpool';
import {
CommonUtils,
FileUtils,
LogDomain,
LogHelper,
CheckEmptyUtils
} from '@ohos/basicutils/src/main/ets/TsIndex';
import { GlobalContext } from '@ohos/frameworkwrapper/src/main/ets/TsIndex';
import { BusinessError } from '@kit.BasicServicesKit';
import { ResUtils } from '@ohos/windowscene';
import { AppFoundationServiceExtensionManager } from '../manager/AppFoundationServiceExtensionManager';
import { BusinessType } from '../constants/CommonConstants';
import fileIo from '@ohos.file.fs';
const TAG = 'appInstall_AppInstallUtils';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.HOME, TAG);
const WAIT_FOR_STRING = '__WAIT_FOR_';
const CONNECT_SYMBOL: string = '__';
const WAIT_FOR_STRING_INDEX: number = 2;
const PRE_DOWNLOAD_MENU_LEAST_NUM = 1;
const DEFAULT_USER_ID: number = 100;
const APP_NOT_IN_LIST = 1 << 5;
const DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
const THROTTLING_INTERVAL = 500;
const NO_NETWORK_TASK = 1;
export class AppInstallUtils {
private static mInstance: AppInstallUtils;
private mLauncherLayoutCacheManager: LaunchLayoutCacheManager = LaunchLayoutCacheManager.getInstance();
private lastClickBundleName: string = '';
private lastClickTime: number = 0;
private constructor() {
}
public static getInstance(): AppInstallUtils {
if (!AppInstallUtils.mInstance) {
AppInstallUtils.mInstance = new AppInstallUtils();
}
return AppInstallUtils.mInstance;
}
* 通过taskPool获取图标
* @param bundleNames
* @returns
*/
public async getIconFromAppGalleryPool(bundleNames: string[]): Promise<string> {
let icon: string = '';
try {
icon = await taskPool.execute(getIconFromAppGallery, bundleNames, GlobalContext.getContext()) as string;
} catch (e) {
log.showError('getIconFromAppGalleryPool error e= %{public}s', e?.message);
}
return icon;
}
* 获取图标
* @param bundleNames
* @returns
*/
public async getIconFromAppGallery(bundleNames: string[]): Promise<string | undefined> {
return getIconFromAppGallery(bundleNames, GlobalContext.getContext());
}
* 暂停下载任务
* @param bundleName
*/
public pauseTask(bundleName: string): void {
log.showInfo('AbsTaskOperation, start pause');
try {
taskPool.execute(pauseDownload, bundleName).then((result) => {
log.showWarn('AbsTaskOperation, end pause : result= %{public}d', result);
});
} catch (e) {
log.showError('AbsTaskOperation, err pause : e= %{public}s', e?.message);
}
}
* 恢复下载任务
* @param bundleName
*/
public resumeTask(bundleName: string): void {
log.showInfo('AbsTaskOperation, start resume');
try {
taskPool.execute(resumeDownload, bundleName, false).then((result) => {
log.showWarn('AbsTaskOperation, end resume : result= %{public}d', result);
});
} catch (e) {
log.showError('AbsTaskOperation, err resume : e= %{public}s', e?.message);
}
}
* 检查下载任务
* @param item
*/
public checkTask(item: AppItemInfo | GridLayoutItemInfo): void {
log.showInfo('AbsTaskOperation, start check, appStatus:%{public}d', item.appStatus);
try {
taskPool.execute(checkDownload, checkTaskInfo).then((result) => {
log.showWarn('AbsTaskOperation, end check : result= %{public}s', result);
});
} catch (e) {
log.showError('AbsTaskOperation, err check : e= %{public}s', e?.message);
}*/
}
* 取消下载应用,如果下载成功,移除图标
* @param bundleName
*/
public cancelTask(bundleName: string): void {
log.showInfo('AbsTaskOperation, start cancel, %{public}s', bundleName);
try {
taskPool.execute(cancelDownload, bundleName).then((result) => {
if (result === 1) {
log.showError('clickAppToCancel failed! bundleName:%{public}s result= %{public}d', bundleName, result);
} else {
log.showInfo('cancelTask bundleName:%{public}s result= %{public}d', bundleName, result);
}
this.cancelDownloadTask(bundleName);
}).catch((err: BusinessError) => {
log.showError('cancelTask error! bundleName[%{public}s], %{public}d:%{public}s', err?.code, err?.message);
});
} catch (e) {
log.showError('cancelTask error! bundleName[%{public}s], e= %{public}s', bundleName, e?.message);
}
}
private getAppListWithBundleName(bundleName: string): GridLayoutItemInfo[] {
const appList = this.mLauncherLayoutCacheManager.getAllSameBundleNameAppItem(bundleName);
if (appList.findIndex(item => item.appIndex === undefined || item.appIndex === 0) === -1) {
const item = new GridLayoutItemInfo();
item.bundleName = bundleName;
item.appIndex = 0;
appList.push(item);
}
return appList;
}
private cancelDownloadTask(bundleName: string): void {
if (bundleName.startsWith(WAIT_FOR_STRING)) {
bundleName = this.getNormalBundleName(bundleName);
}
const apps = launcherAbilityManager.getLauncherAbilityInfoByBundleName(bundleName);
if (apps.length === 0) {
const appList = this.getAppListWithBundleName(bundleName);
appList.forEach(item => {
log.showWarn('remove item bundleName:%{public}s appIndex:%{public}d status:%{public}d',
item.bundleName, item.appIndex, item.appStatus);
AppModel.getInstance().appItemRemove(item.bundleName, item.appIndex ?? 0);
});
} else {
log.showWarn('cancelTask bundleName:%{public}s is find in BMS, the app is updating', bundleName);
}
}
* 请求下载任务
*
* @param taskInfo
* @returns 请求是否成功
*/
public async requestTask(item: AppItemInfo | GridLayoutItemInfo): Promise<boolean> {
if (CheckEmptyUtils.isEmpty(item)) {
log.showWarn('requestTask item is empty');
return false;
}
log.showInfo('AbsTaskOperation, start request , %{public}s', item.bundleName);
const requestTaskInfo = this.getRequestTaskInfo(item);
const result: installInfoManager.RequestResultInfo =
await taskPool.execute(requestDownload, requestTaskInfo) as installInfoManager.RequestResultInfo;
if (result.resultCode === 0 && result.downloadInfos[0].status === 0) {
PreInstallUtils.resetIntent(item);
}
log.showInfo('requestTask bundleName[%{public}s] resultCode= %{public}d', item.bundleName, result.resultCode);
return result.resultCode === 0;
} catch (e) {
log.showError('requestTask error! bundleName[%{public}s], e= %{public}s', item.bundleName, e?.message);
}*/
return false;
}
* 请求AG创建无网络待办任务
*
* @param taskInfo
* @returns 任务创建是否成功
*/
public async requestNoNetworkTask(item: GridLayoutItemInfo): Promise<boolean> {
if (CheckEmptyUtils.isEmpty(item)) {
log.showWarn('requestNoNetworkTask item is empty');
return false;
}
log.showInfo('requestNoNetworkTask, start request , %{public}s', item.bundleName);
const requestTaskInfo = this.getNoNetworkRequestTaskInfo(item);
const result: installInfoManager.RequestResultInfo =
await taskPool.execute(requestDownload, requestTaskInfo) as installInfoManager.RequestResultInfo;
if (result.resultCode !== 0) {
log.showWarn('requestTask bundleName[%{public}s] resultCode= %{public}d', item.bundleName, result.resultCode);
return false;
}
return true;
} catch (e) {
log.showError('requestTask error! bundleName[%{public}s], e= %{public}s', item.bundleName, e?.message);
}*/
return false;
}
* 构建无网络待办任务对象,该类型需要传appName、iconFd
*
* @param item 构建请求对象的应用
* @returns RequestTaskInfo
*/
private getNoNetworkRequestTaskInfo(item: GridLayoutItemInfo): ESObject {
const bundleName = item.bundleName;
log.showInfo(`getRequestTaskInfo bundleName ${bundleName}, icon ${item.iconResource}`);
let iconFd: number = -1;
if (FileUtils.isExist(item.iconResource?.replace(CommonConstants.SANDBOX_FILE_PREFIX, ''))) {
iconFd = FileUtils.openFile(item.iconResource).fd;
log.showInfo(`getRequestTaskInfo iconFd: ${iconFd}`);
}
if (CheckEmptyUtils.isEmpty(item.appName)) {
item.appName = bundleName;
}
downloadInfos: new Array({
bundleName: bundleName,
taskType: NO_NETWORK_TASK,
appName: item.appName,
iconFd: iconFd
} as installInfoManager.DownloadInfo),
};
return requestTaskInfo;*/
return {};
}
private getRequestTaskInfo(item: AppItemInfo | GridLayoutItemInfo): ESObject {
const requestTaskInfo: installInfoManager.RequestTaskInfo = {
downloadInfos: new Array({ bundleName: bundleName } as installInfoManager.DownloadInfo),
};
log.showInfo(`requestTaskInfo bundleInfo: ${bundleName}`);
return requestTaskInfo;*/
return {};
}
private getCheckTaskInfo(item: AppItemInfo | GridLayoutItemInfo): ESObject {
let bundleName = item.bundleName;
if (item.appStatus === AppStatus.WAIT_FOR_HARMONY) {
let extendInfo: Map<string, Object> = CommonUtils.jsonStrToMap(item.intent);
if (extendInfo && extendInfo.has('requestBundleName')) {
bundleName = extendInfo.get('requestBundleName') as string;
}
}
'ownerInfo': this.getOwnerInfo(item.callerName ?? ''),
'bundleName': bundleName,
'callerName': item.callerName ?? '',
};
log.showInfo(`checkTaskInfo bundleInfo: ${bundleName}`);
return checkTaskInfo;*/
return {};
}
* 未OpenHarmony化包名转普通包名
*
* @param waitForBundleName 未OpenHarmony化包名
* @returns string 普通包名
*/
public getNormalBundleName(waitForBundleName: string): string {
let args: string[] = waitForBundleName.split(CONNECT_SYMBOL);
return args.length > WAIT_FOR_STRING_INDEX ? args[WAIT_FOR_STRING_INDEX] : waitForBundleName;
}
* 获取OwnerInfo
* @param callerName
* @returns
*/
public getOwnerInfo(callerName: string): ESObject {
let ownerInfo: ESObject;
switch (callerName) {
case 'com.ohos.clouddrive':
ownerInfo = {
'bundleName': callerName,
'moduleName': 'phone',
'abilityName': 'BackupServiceAbility',
};
break;
case 'com.ohos.dataclone':
ownerInfo = {
'bundleName': callerName,
'moduleName': 'phone',
'abilityName': 'SilentInstallServiceExtAbility',
};
break;
case 'com.ohos.databackup':
case 'com.ohos.hisuite':
ownerInfo = {
'bundleName': callerName,
'moduleName': 'phone',
'abilityName': 'InstallServiceExtensionAbility',
};
break;
default:
ownerInfo = {
'bundleName': '',
'moduleName': '',
'abilityName': '',
};
log.showInfo(' AppItemInfo has not checked');
break;
}
return ownerInfo;
}
* 是否添加'优先下载'的菜单
* @param item GridLayoutItemInfo
* @returns
*/
public isAddPreDownloadMenu(item: GridLayoutItemInfo): boolean {
if (!this.isPreDownloadMenuAppType(item) || !this.isPreDownloadMenuStatus(item)) {
return false;
}
let num: number = 0;
let desktopLayoutItemList: GridLayoutItemInfo[] =
this.mLauncherLayoutCacheManager.getAllGridLayoutItemList(BusinessType.BUSINESS_BASIC_DESKTOP);
for (let i = 0; i < desktopLayoutItemList.length; i++) {
let info: GridLayoutItemInfo = desktopLayoutItemList[i];
if (!CheckEmptyUtils.isEmpty(info)) {
num = num + this.getPreDownloadMenuNum(info, 'desktop');
if (num > PRE_DOWNLOAD_MENU_LEAST_NUM) {
log.showInfo('addPreDownloadMenu add true, bundleName:%{public}s, appName:%{public}s, num:%{public}d',
item.bundleName, item.appName, num);
return true;
}
}
}
let dockLayoutItemList: DockItemInfo[] | undefined = ResidentLayoutCacheMgr.getInstance().getAllDockItems();
if (dockLayoutItemList === undefined) {
return num > PRE_DOWNLOAD_MENU_LEAST_NUM;
}
for (let i = 0; i < dockLayoutItemList?.length; i++) {
if (CheckEmptyUtils.isEmpty(dockLayoutItemList[i])) {
continue;
}
let info: GridLayoutItemInfo = GridLayoutUtil.dockItemToGridLayout(dockLayoutItemList[i]);
if (!CheckEmptyUtils.isEmpty(info)) {
num = num + this.getPreDownloadMenuNum(info, 'dock');
if (num > PRE_DOWNLOAD_MENU_LEAST_NUM) {
break;
}
}
}
log.showInfo('addPreDownloadMenu add %{public}s, bundleName:%{public}s, appName:%{public}s, num:%{public}d',
num > PRE_DOWNLOAD_MENU_LEAST_NUM, item.bundleName, item.appName, num);
return num > PRE_DOWNLOAD_MENU_LEAST_NUM;
}
* 点击优先下载
* @param item GridLayoutItemInfo
*/
public clickAppToPreDownload(item: GridLayoutItemInfo): void {
try {
let appList: GridLayoutItemInfo[] =
this.mLauncherLayoutCacheManager.getAllSameBundleNameAppItem(item.bundleName);
let status: number | undefined = appList[0]?.appStatus ?? item.appStatus;
if (!this.isPreDownloadMenuAppStatus(status)) {
log.showWarn('addPreDownloadMenu bundleName:%{public}s click return, appStatus:%{public}d, defaultStatus:%{public}d',
item.bundleName, status, item.appStatus);
return;
}
let checkTaskOptions: CheckTaskOptions | undefined = undefined;
checkTaskOptions = this.getCheckTaskOptions(item);
log.showInfo('addPreDownloadMenu bundleName:%{public}s click, status:%{public}d, callerName:%{public}s,checkTaskOptions:%{public}s',
item.bundleName, status, item.callerName, JSON.stringify(checkTaskOptions));
taskPool.execute(adjustTaskPriority, item.bundleName, 0, checkTaskOptions).catch((error: Error) => {
log.error('addPreDownloadMenu click pending error', error.message);
});
} catch (e) {
log.error('addPreDownloadMenu click error', e.message);
}
}
* 处理点击图标优先下载
*/
public dealClickPreDownload(itemInfo: GridLayoutItemInfo): void {
let currentTime: number = new Date().getTime();
if (itemInfo.bundleName === this.lastClickBundleName && currentTime - this.lastClickTime < THROTTLING_INTERVAL) {
log.showWarn('The click time interval less than throttling interval, return.');
return;
}
this.lastClickBundleName = itemInfo.bundleName;
this.lastClickTime = currentTime;
log.showInfo(`PreDownload true, bundleName = ${itemInfo?.bundleName}`);
this.clickAppToPreDownload(itemInfo);
}
private isPreDownloadMenuStatus(item: GridLayoutItemInfo): boolean {
let appList: GridLayoutItemInfo[] =
this.mLauncherLayoutCacheManager.getAllSameBundleNameAppItem(item.bundleName);
let status: number | undefined = appList[0]?.appStatus ?? item.appStatus;
let res: boolean = this.isPreDownloadMenuAppStatus(status);
log.showInfo('addPreDownloadMenu status %{public}s, bundleName:%{public}s, appName:%{public}s, appStatus:%{public}d,%{public}d',
res, item.bundleName, item.appName, item.appStatus, status);
return res;
}
private getPreDownloadMenuNum(item: GridLayoutItemInfo, tag: string): number {
let num: number = 0;
if (item.typeId === CommonConstants.TYPE_APP && this.isPreDownloadMenuApp(item)) {
log.showInfo('addPreDownloadMenu %{public}s num bundleName:%{public}s, appName:%{public}s, appStatus:%{public}d',
tag, item.bundleName, item.appName, item.appStatus);
num++;
} else if (item.typeId === CommonConstants.TYPE_FOLDER) {
let appList: GridLayoutItemInfo[] | undefined = item.layoutInfo?.flat().filter(itemInFolder =>
itemInFolder && itemInFolder.typeId === CommonConstants.TYPE_APP && this.isPreDownloadMenuApp(itemInFolder));
if (appList === undefined) {
return num;
}
if (appList.length > 0) {
log.showInfo('addPreDownloadMenu %{public}s folder num bundleName:%{public}s, appName:%{public}s, appStatus:%{public}d',
tag, appList[0].bundleName, appList[0].appName, appList[0].appStatus);
}
if (appList.length > 1) {
log.showInfo('addPreDownloadMenu %{public}s folder num bundleName:%{public}s, appName:%{public}s, appStatus:%{public}d',
tag, appList[1].bundleName, appList[1].appName, appList[1].appStatus);
}
num = appList.length;
}
return num;
}
private isPreDownloadMenuApp(item: GridLayoutItemInfo): boolean {
if (!this.isPreDownloadMenuAppType(item)) {
return false;
}
let appList: GridLayoutItemInfo[] =
this.mLauncherLayoutCacheManager.getAllSameBundleNameAppItem(item.bundleName);
let status: number | undefined = appList[0]?.appStatus ?? item.appStatus;
return this.isPreDownloadMenuAppStatus(status) || status === AppStatus.DOWNLOADING;
}
private isPreDownloadMenuAppType(item: GridLayoutItemInfo): boolean {
if (!item) {
return false;
}
if (item.appIndex !== CommonConstants.MAIN_APP_INDEX) {
return false;
}
return true;
}
private isPreDownloadMenuAppStatus(appStatus: number | undefined): boolean {
return appStatus === AppStatus.PENDING || appStatus === AppStatus.WAITING || appStatus === AppStatus.PAUSING;
}
private getCheckTaskOptions(item: GridLayoutItemInfo): CheckTaskOptions {
let checkTaskOptions: CheckTaskOptions = {
'ownerInfo': this.getOwnerInfo(item.callerName ?? ''),
'callerName': item.callerName ?? '',
};
return checkTaskOptions;
}
* 点击分身应用时根据主应用的状态进行不同的操作
* @param bundleName
*/
public clickTwinApp(bundleName: string): void {
let appList: GridLayoutItemInfo[] = this.mLauncherLayoutCacheManager.getAllSameBundleNameAppItem(bundleName);
if (!appList.length) {
log.showWarn(`clickTwinApp err, ${bundleName} not find cache`);
return;
}
let mainAppItem: GridLayoutItemInfo = appList[0];
let mainAppItemAppStatus: number | undefined = mainAppItem.appStatus;
log.showInfo(`clickTwinApp, main app bundlaName is ${bundleName}, status is ${mainAppItemAppStatus}`);
if (mainAppItemAppStatus === AppStatus.PENDING || mainAppItemAppStatus === AppStatus.WAIT_FOR_HARMONY) {
this.checkTask(mainAppItem);
} else if (mainAppItemAppStatus === AppStatus.WAITING || mainAppItemAppStatus === AppStatus.WIFI_WAITING ||
mainAppItemAppStatus === AppStatus.INSTALL_WAITING || mainAppItemAppStatus === AppStatus.PAUSING) {
Prompt.showToast({
message: ResUtils.getInnerStringNumS($r('app.string.click_twin_app_not_installed'), `${mainAppItem.appName}`)
});
} else if (mainAppItemAppStatus === AppStatus.DOWNLOADING) {
Prompt.showToast({
message: ResUtils.getInnerStringNumS($r('app.string.click_twin_app_download_start'), `${mainAppItem.appName}`)
});
} else if (mainAppItemAppStatus === AppStatus.INSTALLING) {
Prompt.showToast({
message: ResUtils.getInnerStringNumS($r('app.string.click_twin_app_download_installing'),
`${mainAppItem.appName}`)
});
} else if (mainAppItemAppStatus === AppStatus.INSTALLED) {
Prompt.showToast({
message: ResUtils.getInnerStringNumS($r('app.string.click_twin_app_wait_data_recover'),
`${mainAppItem.appName}`)
});
}
}
* 查询并点亮未OpenHarmony化可出入湖应用
*
* @param gridLayoutItemInfoList 未安装应用信息info
*/
public async queryAndLightDeliverApp(gridLayoutItemInfoList: GridLayoutItemInfo[]): Promise<void> {
try {
if (launcherAbilityManager.getUserId() !== DEFAULT_USER_ID) {
log.showWarn('only default user support deliver');
return;
}
let date: Date = new Date();
let preference = await preferences.getPreferences(
GlobalContext.getInstance().getObject('desktopContext') as ctx.ServiceExtensionContext, 'DESKTOP_LAYOUT_INFO');
let queryAndLightAddDeliverAppTime: number = preference.getSync('queryAndLightAddDeliverApp', 0) as number;
if (queryAndLightAddDeliverAppTime !== 0 &&
queryAndLightAddDeliverAppTime > this.minusDays(date, NumberConstants.CONSTANT_NUMBER_ONE)) {
log.showInfo('not need query, last query time %{public}d', queryAndLightAddDeliverAppTime);
return;
}
let pkgNameArr: string[] = [];
gridLayoutItemInfoList.forEach(appItemInfo => {
if (appItemInfo.appStatus === AppStatus.WAIT_FOR_HARMONY &&
CommonUtils.jsonStrToMap(appItemInfo.intent).get(NotHarmonyUtil.NOT_HARMONY_APP_MASK_STATE) as number !== 1) {
pkgNameArr.push(appItemInfo.bundleName);
}
});
if (CheckEmptyUtils.isEmptyArr(pkgNameArr)) {
log.showInfo('queryAndLightAddDeliverAp pkgNameArr is empty');
return;
}
let appFoundation: AppFoundationServiceExtensionManager = AppFoundationServiceExtensionManager.getInstance();
await appFoundation.queryAppMappingInfo(pkgNameArr);
let deliverBundleNamesMap: Map<string, number> = appFoundation.getDeliverBundleNamesMap();
if (!appFoundation.queryMappingResult() && CheckEmptyUtils.isEmpty(deliverBundleNamesMap)) {
log.showError('queryAppMappingInfo failed, do not save time');
return;
}
let deliverBundleNames: string[] = this.removeNotInAppList32App(deliverBundleNamesMap, gridLayoutItemInfoList);
if (!CheckEmptyUtils.isEmptyArr(deliverBundleNames)) {
log.showInfo('lightAddDeliverApp start');
let relationMap: Map<string, boolean> = new Map();
let publicTestRelationMap: Map<string, boolean> = new Map();
deliverBundleNames.forEach(item => {
log.showInfo('queryAndLightAddDeliverApp hasohosApp: %{public}s', item);
relationMap.set(item, true);
});
NotHarmonyUtil.lightingNotHarmonyAppIcons(relationMap, publicTestRelationMap);
NotHarmonyUtil.refreshNotHarmonyFolderPosition(relationMap, publicTestRelationMap);
let lightArrString: string = preference.getSync('lightDeliverBundleNames', '') as string;
if (lightArrString) {
lightArrString += ',';
}
preference.putSync('lightDeliverBundleNames', lightArrString + deliverBundleNames.join(','));
log.showInfo('lightAddDeliverApp end');
}
preference.putSync('queryAndLightAddDeliverApp', date.getTime());
await preference.flush().then(() => {
log.showInfo('save queryAndLightAddDeliverApp to sp success');
}).catch((reject: Error) => {
log.showInfo('save queryAndLightAddDeliverApp to sp fail: %{public}s', reject?.message);
});
log.showInfo('queryAndLightAddDeliverApp time %{public}s', date.toString());
} catch (err) {
log.showError(`queryAndLightAddDeliverApp, Failed to get preferences error: ${err.code} : ${err.message}`);
}
}
private removeNotInAppList32App(deliverBundleNamesMap: Map<string, number>,
gridLayoutItemInfoList: GridLayoutItemInfo[]): string[] {
let deliverBundleNames: string[] = [];
if (CheckEmptyUtils.isEmpty(deliverBundleNamesMap) || CheckEmptyUtils.isEmptyArr(gridLayoutItemInfoList)) {
log.showWarn('removeNotInAppList32App params is empty');
return deliverBundleNames;
}
deliverBundleNamesMap.forEach((type, item) => {
if (type & APP_NOT_IN_LIST) {
let gridLayoutInfo: GridLayoutItemInfo | undefined =
gridLayoutItemInfoList.find(grid => grid.bundleName === item);
if (gridLayoutInfo && NotHarmonyUtil.isSupport64(CommonUtils.jsonStrToMap(gridLayoutInfo.intent)
.get('legacyInfo') as LegacyInfo)) {
log.showInfo('queryAndLightAddDeliverApp hasohosApp is support deliver 64: %{public}s', item);
deliverBundleNames.push(item);
}
} else {
deliverBundleNames.push(item);
}
});
return deliverBundleNames;
}
* 在date基础减去上days天数
*
* @param date 基础日期
* @param days 减去天数
* @return 减去后的毫秒值
*/
private minusDays(date: Date, days: number): number {
let curTime: number = date.getTime();
return curTime - (days * DAY_IN_MILLIS);
}
public cancelRestoreLauncherData(bundleNames: string[]): void {
log.showInfo('cancelRestoreLauncherData, start cancel length: %{public}d', bundleNames.length);
try {
taskPool.execute(cancelDownloadBatch, bundleNames);
} catch (e) {
log.showInfo('cancelRestoreLauncherData, err cancel : e= %{public}s', e?.message);
}
}
}
* 应用市场请求图标
* @param bundleNames
* @param context
* @returns
*/
async function getIconFromAppGallery(bundleNames: string[], context: Context.BaseContext): Promise<string | undefined> {
'use concurrent';
const TAG = 'appinstall getIconFromAppGallery';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.HOME, TAG);
const ICON_NAME_PRE = 'appgallery_';
const OLD_ICON_FOLDER_NAME = '/oldIcons';
const READ_DATA_SIZE = 4096;
let filesDir: string = (context as ctx.ServiceExtensionContext)?.filesDir;
log.showInfo('AbsTaskOperation, start getAppIcon. %{public}s', filesDir);
let stream: fileIo.Stream | undefined = undefined;
let fd: number = -1;
try {
if (result.resultCode !== 0 || result.appIcons[0].code !== 0) {
log.showInfo('getAppIcons err resultCode: %{public}d, code: %{public}d', result.resultCode, result.appIcons[0].code);
return undefined;
}
log.showInfo('getAppIcon result : bundleName=%{public}s, iconfd=%{public}d', result.appIcons[0].bundleName, result.appIcons[0].iconFd);
const fileName: string = ICON_NAME_PRE + bundleNames[0];
const fileNameWithoutPoint: string = fileName.split('.').join('');
if (!FileUtils.isExist(filesDir + OLD_ICON_FOLDER_NAME)) {
FileUtils.createFolder(filesDir + OLD_ICON_FOLDER_NAME);
}
let filesPath: string = filesDir + OLD_ICON_FOLDER_NAME + '/' + fileNameWithoutPoint + '.png';
if (FileUtils.isExist(filesPath)) {
FileUtils.deleteConfigFile(filesPath);
}
fd = result.appIcons[0].iconFd;
stream = fs.createStreamSync(filesPath, 'a+');
let arrayBuffer = new ArrayBuffer(READ_DATA_SIZE);
let readLine: number = 0;
class Option {
offset: number = 0;
length: number = 0;
encoding: string = 'utf-8';
}
while ((readLine = fs.readSync(fd, arrayBuffer)) !== 0) {
let option: Option = new Option();
option.length = readLine;
log.showInfo('getIconFromAppGallery readLine =%{public}d', readLine);
stream.writeSync(arrayBuffer, option);
}
return filesPath;*/
return '';
} catch (err) {
log.showInfo('getAppIcons err: %{public}s', err?.message);
} finally {
if (stream) {
try {
stream.closeSync();
} catch (error) {
log.showError(`stream file closeSync error, error : ${error?.code}`);
}
}
if (fd && fd !== -1) {
fs.closeSync(fd);
}
}
return undefined;
}
async function pauseDownload(bundleName: string): Promise<ESObject> {
'use concurrent';
return {};
}
async function resumeDownload(bundleName: string, isForce: boolean): Promise<ESObject> {
'use concurrent';
return {};
}
async function checkDownload(taskInfo: ESObject): Promise<boolean> {
'use concurrent';
return false;
}
async function cancelDownload(bundleName: string): Promise<ESObject> {
'use concurrent';
return {};
}
export async function adjustTaskPriority(bundleName: string, priority: number,
checkTaskOptions?: CheckTaskOptions): Promise<void> {
'use concurrent';
}
export interface CheckTaskOptions {
ownerInfo: ESObject;
callerName: string;
}
async function cancelDownloadBatch(bundleNames: string[]): Promise<void> {
'use concurrent';
const TAG = 'AppGalleryDownloadManager';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.HOME, TAG);
for (let i = 0; i < bundleNames.length; i++) {
log.showInfo('cancelDownloadBatch, end cancel: bundleName=%{public}s, result= %{public}d', bundleNames[i], result);*/
}
}
async function requestDownload(taskInfo: ESObject):
Promise<ESObject> {
'use concurrent';
return {};
}