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 let missionInfos = new Array<missionManager.MissionInfo>(); 54 await missionManager.getMissionInfos('', AmsMissionManager.RECENT_MISSIONS_LIMIT_NUM) 55 .then((res) => { 56 if (!CheckEmptyUtils.isEmptyArr(res)) { 57 Log.showDebug(TAG, `getOriginRecentMissionsList res.length: ${res.length}`); 58 missionInfos = res; 59 } 60 }) 61 .catch((err) => { 62 Log.showError(TAG, `getOriginRecentMissionsList error: ${JSON.stringify(err)}`); 63 }); 64 return missionInfos; 65 } 66 67 /** 68 * Get recent missions list 69 * 70 * @return {Array} missions list 71 */ 72 async getRecentMissionsList(): Promise<Array<RecentMissionInfo>> { 73 const recentMissionsList = new Array<RecentMissionInfo>(); 74 let missionInfos: Array<missionManager.MissionInfo> = await this.getOriginRecentMissionsList(); 75 if (CheckEmptyUtils.isEmptyArr(missionInfos)) { 76 Log.showDebug(TAG, 'getRecentMissionsList Empty'); 77 return recentMissionsList; 78 } 79 for (const recentItem of missionInfos) { 80 const recentMissionInfo = new RecentMissionInfo(); 81 recentMissionInfo.missionId = recentItem.missionId; 82 recentMissionInfo.bundleName = recentItem.want.bundleName; 83 recentMissionInfo.abilityName = recentItem.want.abilityName; 84 recentMissionInfo.moduleName = recentItem.want.parameters?.moduleName ? String(recentItem.want.parameters?.moduleName) : ''; 85 recentMissionInfo.lockedState = recentItem.lockedState; 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 await missionManager.clearMission(missionId) 152 .then((data) => { 153 Log.showDebug(TAG, `clearMission data:${JSON.stringify(data)}`); 154 }) 155 .catch((err) => { 156 Log.showError(TAG, `clearMission err:${JSON.stringify(err)}`); 157 }); 158 } 159 160 /** 161 * Clear all missions in the ability manager service. 162 * locked mission will not clear 163 * 164 * @return nothing. 165 */ 166 async clearAllMissions(): Promise<void> { 167 await missionManager.clearAllMissions() 168 .then((data) => { 169 Log.showDebug(TAG, `clearAllMissions data: ${JSON.stringify(data)}`); 170 }) 171 .catch((err) => { 172 Log.showError(TAG, `clearAllMissions err: ${JSON.stringify(err)}`); 173 }); 174 } 175 176 /** 177 * lockMission 178 * 179 * @param missionId mission id to lock. 180 */ 181 lockMission(missionId: number): void { 182 Log.showInfo(TAG, `lockMission start! missionId: ${missionId}`); 183 this.mMissionId = missionId; 184 this.mLockState = true; 185 missionManager.lockMission(missionId, this.lockCallback.bind(this)); 186 } 187 188 /** 189 * unlockMission 190 * 191 * @param missionId mission id to unlock. 192 */ 193 unlockMission(missionId: number): void { 194 Log.showInfo(TAG, `unlockMission start! missionId: ${missionId}`); 195 this.mMissionId = missionId; 196 this.mLockState = false; 197 missionManager.unlockMission(missionId, this.lockCallback.bind(this)); 198 } 199 200 private async lockCallback(): Promise<void> { 201 Log.showDebug(TAG, `lockCallback start`); 202 // update mission recent card 203 let mRecentMissionsList = await amsMissionManager.getRecentMissionsList(); 204 mRecentMissionsList.find(item => { 205 return item.missionId === this.mMissionId; 206 }).lockedState = this.mLockState; 207 if (globalThis.recentMode && windowManager.isSplitWindowMode(globalThis.recentMode)) { 208 mRecentMissionsList.forEach((item, index) => { 209 if (item.missionId == globalThis.splitMissionId) { 210 mRecentMissionsList.splice(index, 1); 211 return; 212 } 213 }); 214 } 215 AppStorage.SetOrCreate('recentMissionsList', mRecentMissionsList); 216 }; 217 218 /** 219 * Get recent mission snapshot info 220 * 221 * @param missionId mission id to get snapshot. 222 * @return snapshot info 223 */ 224 async getMissionSnapShot(missionId: number): Promise<SnapShotInfo> { 225 let snapShotInfo: SnapShotInfo = new SnapShotInfo(); 226 Log.showInfo(TAG, `getMissionSnapShot start! missionId: ${missionId}`); 227 try { 228 let missionSnapshot: missionManager.MissionSnapshot = null; 229 await missionManager.getMissionSnapShot('', missionId) 230 .then((res) => { 231 Log.showDebug(TAG, `getMissionSnapShot ${missionId} success ${JSON.stringify(res)}`); 232 missionSnapshot = res; 233 }) 234 .catch((err) => { 235 Log.showError(TAG, `getMissionSnapShot error: ${JSON.stringify(err)}`); 236 }); 237 const imageInfo = await missionSnapshot.snapshot.getImageInfo(); 238 Log.showDebug(TAG, `getMissionSnapShot success ${JSON.stringify(imageInfo)}`); 239 snapShotInfo.missionId = missionId; 240 snapShotInfo.snapShotImage = missionSnapshot.snapshot; 241 snapShotInfo.snapShotImageWidth = imageInfo.size.width; 242 snapShotInfo.snapShotImageHeight = imageInfo.size.height; 243 } catch (err) { 244 Log.showError(TAG, `missionManager.getMissionSnapShot err: ${err}`); 245 } 246 return snapShotInfo; 247 } 248 249 /** 250 * Move mission to front 251 * 252 * @param missionId 253 */ 254 async moveMissionToFront(missionId: number, winMode?: number) { 255 Log.showInfo(TAG, `moveMissionToFront missionId: ${missionId}`); 256 let promise = winMode ? missionManager.moveMissionToFront(missionId, { windowMode: winMode }) : 257 missionManager.moveMissionToFront(missionId); 258 const res = await promise.catch(err => { 259 Log.showError(TAG, `moveMissionToFront err: ${JSON.stringify(err)}`); 260 }); 261 Log.showDebug(TAG, `moveMissionToFront missionId end: ${JSON.stringify(res)}`); 262 return res; 263 } 264} 265 266export const amsMissionManager = AmsMissionManager.getInstance();