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 image from '@ohos.multimedia.image'; 17import missionManager from '@ohos.app.ability.missionManager'; 18import { Log } from '../utils/Log'; 19import { CheckEmptyUtils } from '../utils/CheckEmptyUtils'; 20import { launcherAbilityManager } from './LauncherAbilityManager'; 21import { SnapShotInfo } from '../bean/SnapShotInfo'; 22import { MissionInfo } from '../bean/MissionInfo'; 23import { RecentMissionInfo } from '../bean/RecentMissionInfo'; 24import { RecentBundleMissionInfo } from '../bean/RecentBundleMissionInfo'; 25import { windowManager } from './WindowManager'; 26 27const TAG = 'AmsMissionManager'; 28 29/** 30 * missionManager for Launcher 31 */ 32class AmsMissionManager { 33 private static readonly RECENT_MISSIONS_LIMIT_NUM = 20; 34 private mMissionId: number; 35 private mLockState: boolean; 36 37 static getInstance(): AmsMissionManager { 38 if (globalThis.AmsMissionManagerInstance == null) { 39 globalThis.AmsMissionManagerInstance = new AmsMissionManager(); 40 // remove this if toolchain fix requireNApi bug 41 image.toString(); 42 } 43 return globalThis.AmsMissionManagerInstance; 44 } 45 46 47 /** 48 * Get origin recent missions 49 * 50 * @return {Array} missions 51 */ 52 async getOriginRecentMissionsList(): Promise<Array<missionManager.MissionInfo>> { 53 try { 54 let arrayMissionInfo = new Array<missionManager.MissionInfo>(); 55 let res = await missionManager.getMissionInfos('', AmsMissionManager.RECENT_MISSIONS_LIMIT_NUM); 56 if (!CheckEmptyUtils.isEmptyArr(res)) { 57 Log.showDebug(TAG, `getOriginRecentMissionsList res.length: ${res.length}`); 58 arrayMissionInfo = res; 59 return arrayMissionInfo; 60 } 61 } catch (err) { 62 Log.showError(TAG, `getOriginRecentMissionsList fail, err: ${JSON.stringify(err)}`); 63 } 64 } 65 66 /** 67 * Get recent missions list 68 * 69 * @return {Array} missions list 70 */ 71 async getRecentMissionsList(): Promise<Array<RecentMissionInfo>> { 72 const recentMissionsList = new Array<RecentMissionInfo>(); 73 let missionInfos: Array<missionManager.MissionInfo> = await this.getOriginRecentMissionsList(); 74 if (CheckEmptyUtils.isEmptyArr(missionInfos)) { 75 Log.showDebug(TAG, 'getRecentMissionsList Empty'); 76 return recentMissionsList; 77 } 78 for (const recentItem of missionInfos) { 79 const recentMissionInfo = new RecentMissionInfo(); 80 recentMissionInfo.missionId = recentItem.missionId; 81 recentMissionInfo.bundleName = recentItem.want.bundleName; 82 recentMissionInfo.abilityName = recentItem.want.abilityName; 83 recentMissionInfo.moduleName = recentItem.want.parameters?.moduleName ? String(recentItem.want.parameters?.moduleName) : ''; 84 recentMissionInfo.lockedState = recentItem.lockedState; 85 recentMissionInfo.snapShotTime = recentItem.timestamp; 86 const appInfo = await launcherAbilityManager.getAppInfoByBundleName(recentMissionInfo.bundleName, recentMissionInfo.abilityName); 87 if (appInfo == undefined) { 88 continue; 89 } 90 recentMissionInfo.appLabelId = appInfo.appLabelId; 91 recentMissionInfo.appIconId = appInfo.appIconId; 92 recentMissionInfo.appName = appInfo.appName; 93 recentMissionsList.push(recentMissionInfo); 94 } 95 Log.showInfo(TAG, `getRecentMissionsList recentMissionsList length: ${recentMissionsList.length}`); 96 return recentMissionsList; 97 } 98 99 /** 100 * Get recent missions list group by bundleName 101 * 102 * @return {Array} missions list 103 */ 104 async getRecentBundleMissionsList(): Promise<Array<RecentBundleMissionInfo>> { 105 const recentMissionsList = new Array<RecentBundleMissionInfo>(); 106 let missionInfos: Array<missionManager.MissionInfo> = await this.getOriginRecentMissionsList(); 107 if (CheckEmptyUtils.isEmptyArr(missionInfos)) { 108 Log.showDebug(TAG, 'getRecentBundleMissionsList Empty'); 109 return recentMissionsList; 110 } 111 for (let i = 0; i < missionInfos.length; i++) { 112 let missionInfo = missionInfos[i]; 113 let bundleName = missionInfo.want.bundleName!; 114 let abilityName = missionInfo.want.abilityName!; 115 let localMissionInfo = recentMissionsList.find((item) => item.bundleName === bundleName); 116 if (localMissionInfo) { 117 let missionInfoAdd = new MissionInfo(); 118 missionInfoAdd.missionId = missionInfo.missionId; 119 localMissionInfo.missionInfoList!.push(missionInfoAdd); 120 } else { 121 let recentTaskInfo = new RecentBundleMissionInfo(); 122 recentTaskInfo.bundleName = bundleName; 123 const appInfo = await launcherAbilityManager.getAppInfoByBundleName(bundleName, abilityName); 124 if (appInfo == undefined) { 125 continue; 126 } 127 recentTaskInfo.abilityName = appInfo.abilityName; 128 recentTaskInfo.moduleName = appInfo.moduleName; 129 recentTaskInfo.keyName = bundleName + appInfo.abilityName + appInfo.moduleName; 130 recentTaskInfo.appLabelId = appInfo.appLabelId; 131 recentTaskInfo.appIconId = appInfo.appIconId; 132 recentTaskInfo.appName = appInfo.appName; 133 recentTaskInfo.missionInfoList = new Array<MissionInfo>(); 134 let missionInfoAdd = new MissionInfo(); 135 missionInfoAdd.missionId = missionInfo.missionId; 136 recentTaskInfo.missionInfoList.push(missionInfoAdd); 137 recentMissionsList.push(recentTaskInfo); 138 } 139 } 140 Log.showInfo(TAG, `getRecentBundleMissionsList recentMissionsList length:${recentMissionsList.length}`); 141 return recentMissionsList; 142 } 143 144 /** 145 * Clear the given mission in the ability manager service. 146 * 147 * @param missionId 148 */ 149 async clearMission(missionId: number): Promise<void> { 150 Log.showInfo(TAG, `clearMission Id:${missionId}`); 151 try { 152 await missionManager.clearMission(missionId); 153 Log.showDebug(TAG, 'clearMission success'); 154 } catch (err) { 155 Log.showError(TAG, `clearMission fail, err:${JSON.stringify(err)}`); 156 } 157 } 158 159 /** 160 * Clear all missions in the ability manager service. 161 * locked mission will not clear 162 * 163 * @return nothing. 164 */ 165 async clearAllMissions(): Promise<void> { 166 try { 167 await missionManager.clearAllMissions(); 168 Log.showDebug(TAG, 'clearAllMissions success'); 169 } catch (err) { 170 Log.showError(TAG, `clearAllMissions fail, err: ${JSON.stringify(err)}`); 171 } 172 } 173 174 /** 175 * lockMission 176 * 177 * @param missionId mission id to lock. 178 */ 179 lockMission(missionId: number): void { 180 Log.showInfo(TAG, `lockMission start! missionId: ${missionId}`); 181 this.mMissionId = missionId; 182 this.mLockState = true; 183 missionManager.lockMission(missionId, this.lockCallback.bind(this)); 184 } 185 186 /** 187 * unlockMission 188 * 189 * @param missionId mission id to unlock. 190 */ 191 unlockMission(missionId: number): void { 192 Log.showInfo(TAG, `unlockMission start! missionId: ${missionId}`); 193 this.mMissionId = missionId; 194 this.mLockState = false; 195 missionManager.unlockMission(missionId, this.lockCallback.bind(this)); 196 } 197 198 private async lockCallback(): Promise<void> { 199 Log.showDebug(TAG, 'lockCallback start'); 200 // update mission recent card 201 let mRecentMissionsList = await amsMissionManager.getRecentMissionsList(); 202 mRecentMissionsList.find(item => { 203 return item.missionId === this.mMissionId; 204 }).lockedState = this.mLockState; 205 if (globalThis.recentMode && windowManager.isSplitWindowMode(globalThis.recentMode)) { 206 mRecentMissionsList.forEach((item, index) => { 207 if (item.missionId == globalThis.splitMissionId) { 208 mRecentMissionsList.splice(index, 1); 209 return; 210 } 211 }); 212 } 213 AppStorage.setOrCreate('recentMissionsList', mRecentMissionsList); 214 }; 215 216 /** 217 * Get recent mission snapshot info 218 * 219 * @param missionId mission id to get snapshot. 220 * @return snapshot info 221 */ 222 async getMissionSnapShot(missionId: number): Promise<SnapShotInfo> { 223 let snapShotInfo: SnapShotInfo = new SnapShotInfo(); 224 Log.showInfo(TAG, `getMissionSnapShot start! missionId: ${missionId}`); 225 try { 226 let missionSnapshot: missionManager.MissionSnapshot = null; 227 missionSnapshot = await missionManager.getMissionSnapShot('', missionId); 228 Log.showInfo(TAG, 'getMissionSnapShot end'); 229 const imageInfo = await missionSnapshot.snapshot.getImageInfo(); 230 Log.showDebug(TAG, `getMissionSnapShot ${missionId} success ${JSON.stringify(imageInfo)}`); 231 snapShotInfo.missionId = missionId; 232 snapShotInfo.snapShotImage = missionSnapshot.snapshot; 233 snapShotInfo.snapShotImageWidth = imageInfo.size.width; 234 snapShotInfo.snapShotImageHeight = imageInfo.size.height; 235 } catch (err) { 236 Log.showError(TAG, `missionManager.getMissionSnapShot fail, missionId:${missionId} err: ${JSON.stringify(err)}`); 237 } 238 return snapShotInfo; 239 } 240 241 /** 242 * Move mission to front 243 * 244 * @param missionId 245 */ 246 async moveMissionToFront(missionId: number, winMode?: number) { 247 Log.showInfo(TAG, `moveMissionToFront missionId: ${missionId}`); 248 try { 249 winMode ? await missionManager.moveMissionToFront(missionId, { windowMode: winMode }): 250 await missionManager.moveMissionToFront(missionId); 251 Log.showDebug(TAG, 'moveMissionToFront missionId end success'); 252 } catch (err) { 253 Log.showError(TAG, `moveMissionToFront fail, err: ${JSON.stringify(err)}`); 254 } 255 } 256} 257 258export const amsMissionManager = AmsMissionManager.getInstance();