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 recentMissionInfo.snapShotTime = recentItem.timestamp; 87 const appInfo = await launcherAbilityManager.getAppInfoByBundleName(recentMissionInfo.bundleName, recentMissionInfo.abilityName); 88 if (appInfo == undefined) { 89 continue; 90 } 91 recentMissionInfo.appLabelId = appInfo.appLabelId; 92 recentMissionInfo.appIconId = appInfo.appIconId; 93 recentMissionInfo.appName = appInfo.appName; 94 recentMissionsList.push(recentMissionInfo); 95 } 96 Log.showInfo(TAG, `getRecentMissionsList recentMissionsList length: ${recentMissionsList.length}`); 97 return recentMissionsList; 98 } 99 100 /** 101 * Get recent missions list group by bundleName 102 * 103 * @return {Array} missions list 104 */ 105 async getRecentBundleMissionsList(): Promise<Array<RecentBundleMissionInfo>> { 106 const recentMissionsList = new Array<RecentBundleMissionInfo>(); 107 let missionInfos: Array<missionManager.MissionInfo> = await this.getOriginRecentMissionsList(); 108 if (CheckEmptyUtils.isEmptyArr(missionInfos)) { 109 Log.showDebug(TAG, 'getRecentBundleMissionsList Empty'); 110 return recentMissionsList; 111 } 112 for (let i = 0; i < missionInfos.length; i++) { 113 let missionInfo = missionInfos[i]; 114 let bundleName = missionInfo.want.bundleName!; 115 let abilityName = missionInfo.want.abilityName!; 116 let localMissionInfo = recentMissionsList.find((item) => item.bundleName === bundleName); 117 if (localMissionInfo) { 118 let missionInfoAdd = new MissionInfo(); 119 missionInfoAdd.missionId = missionInfo.missionId; 120 localMissionInfo.missionInfoList!.push(missionInfoAdd); 121 } else { 122 let recentTaskInfo = new RecentBundleMissionInfo(); 123 recentTaskInfo.bundleName = bundleName; 124 const appInfo = await launcherAbilityManager.getAppInfoByBundleName(bundleName, abilityName); 125 if (appInfo == undefined) { 126 continue; 127 } 128 recentTaskInfo.abilityName = appInfo.abilityName; 129 recentTaskInfo.moduleName = appInfo.moduleName; 130 recentTaskInfo.keyName = bundleName + appInfo.abilityName + appInfo.moduleName; 131 recentTaskInfo.appLabelId = appInfo.appLabelId; 132 recentTaskInfo.appIconId = appInfo.appIconId; 133 recentTaskInfo.appName = appInfo.appName; 134 recentTaskInfo.missionInfoList = new Array<MissionInfo>(); 135 let missionInfoAdd = new MissionInfo(); 136 missionInfoAdd.missionId = missionInfo.missionId; 137 recentTaskInfo.missionInfoList.push(missionInfoAdd); 138 recentMissionsList.push(recentTaskInfo); 139 } 140 } 141 Log.showInfo(TAG, `getRecentBundleMissionsList recentMissionsList length:${recentMissionsList.length}`); 142 return recentMissionsList; 143 } 144 145 /** 146 * Clear the given mission in the ability manager service. 147 * 148 * @param missionId 149 */ 150 async clearMission(missionId: number): Promise<void> { 151 Log.showInfo(TAG, `clearMission Id:${missionId}`); 152 await missionManager.clearMission(missionId) 153 .then((data) => { 154 Log.showDebug(TAG, `clearMission data:${JSON.stringify(data)}`); 155 }) 156 .catch((err) => { 157 Log.showError(TAG, `clearMission err:${JSON.stringify(err)}`); 158 }); 159 } 160 161 /** 162 * Clear all missions in the ability manager service. 163 * locked mission will not clear 164 * 165 * @return nothing. 166 */ 167 async clearAllMissions(): Promise<void> { 168 await missionManager.clearAllMissions() 169 .then((data) => { 170 Log.showDebug(TAG, `clearAllMissions data: ${JSON.stringify(data)}`); 171 }) 172 .catch((err) => { 173 Log.showError(TAG, `clearAllMissions err: ${JSON.stringify(err)}`); 174 }); 175 } 176 177 /** 178 * lockMission 179 * 180 * @param missionId mission id to lock. 181 */ 182 lockMission(missionId: number): void { 183 Log.showInfo(TAG, `lockMission start! missionId: ${missionId}`); 184 this.mMissionId = missionId; 185 this.mLockState = true; 186 missionManager.lockMission(missionId, this.lockCallback.bind(this)); 187 } 188 189 /** 190 * unlockMission 191 * 192 * @param missionId mission id to unlock. 193 */ 194 unlockMission(missionId: number): void { 195 Log.showInfo(TAG, `unlockMission start! missionId: ${missionId}`); 196 this.mMissionId = missionId; 197 this.mLockState = false; 198 missionManager.unlockMission(missionId, this.lockCallback.bind(this)); 199 } 200 201 private async lockCallback(): Promise<void> { 202 Log.showDebug(TAG, 'lockCallback start'); 203 // update mission recent card 204 let mRecentMissionsList = await amsMissionManager.getRecentMissionsList(); 205 mRecentMissionsList.find(item => { 206 return item.missionId === this.mMissionId; 207 }).lockedState = this.mLockState; 208 if (globalThis.recentMode && windowManager.isSplitWindowMode(globalThis.recentMode)) { 209 mRecentMissionsList.forEach((item, index) => { 210 if (item.missionId == globalThis.splitMissionId) { 211 mRecentMissionsList.splice(index, 1); 212 return; 213 } 214 }); 215 } 216 AppStorage.setOrCreate('recentMissionsList', mRecentMissionsList); 217 }; 218 219 /** 220 * Get recent mission snapshot info 221 * 222 * @param missionId mission id to get snapshot. 223 * @return snapshot info 224 */ 225 async getMissionSnapShot(missionId: number): Promise<SnapShotInfo> { 226 let snapShotInfo: SnapShotInfo = new SnapShotInfo(); 227 Log.showInfo(TAG, `getMissionSnapShot start! missionId: ${missionId}`); 228 try { 229 let missionSnapshot: missionManager.MissionSnapshot = null; 230 missionSnapshot = await missionManager.getMissionSnapShot('', missionId); 231 Log.showInfo(TAG, 'getMissionSnapShot end'); 232 const imageInfo = await missionSnapshot.snapshot.getImageInfo(); 233 Log.showDebug(TAG, `getMissionSnapShot ${missionId} success`); 234 snapShotInfo.missionId = missionId; 235 snapShotInfo.snapShotImage = missionSnapshot.snapshot; 236 snapShotInfo.snapShotImageWidth = imageInfo.size.width; 237 snapShotInfo.snapShotImageHeight = imageInfo.size.height; 238 } catch (err) { 239 Log.showError(TAG, `missionManager.getMissionSnapShot err: ${err}`); 240 } 241 return snapShotInfo; 242 } 243 244 /** 245 * Move mission to front 246 * 247 * @param missionId 248 */ 249 async moveMissionToFront(missionId: number, winMode?: number) { 250 Log.showInfo(TAG, `moveMissionToFront missionId: ${missionId}`); 251 let promise = winMode ? missionManager.moveMissionToFront(missionId, { windowMode: winMode }) : 252 missionManager.moveMissionToFront(missionId); 253 const res = await promise.catch(err => { 254 Log.showError(TAG, `moveMissionToFront err: ${JSON.stringify(err)}`); 255 }); 256 Log.showDebug(TAG, `moveMissionToFront missionId end: ${JSON.stringify(res)}`); 257 return res; 258 } 259} 260 261export const amsMissionManager = AmsMissionManager.getInstance();