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 */ 15import Log from '../../../../../../../../common/src/main/ets/default/Log'; 16import Trace from '../../../../../../../../common/src/main/ets/default/Trace' 17import {WriteFaultLog, FaultID} from '../../../../../../../../common/src/main/ets/default/SysFaultLogger' 18import ScreenLockModel from './screenLockModel'; 19import AccountModel, {AuthType, AuthSubType, AuthTurstLevel} from './accountsModel' 20import {ScreenLockStatus} from '../../../../../../../../common/src/main/ets/default/ScreenLockCommon'; 21import createOrGet from '../../../../../../../../common/src/main/ets/default/SingleInstanceHelper' 22import Router from '@system.router'; 23import commonEvent from '@ohos.commonEvent'; 24import hiDebug from '@ohos.hidebug'; 25import systemParameter from '@ohos.systemparameter'; 26import { CommonEventPublishData } from 'commonEvent/commonEventPublishData'; 27import {Callback} from 'basic'; 28 29const TAG = 'ScreenLock-ScreenLockService'; 30const URI_DIGITALPASSWORD = 'pages/digitalPassword' 31const URI_MIXEDPASSWORD = 'pages/mixedPassword' 32const URI_CUSTOMPASSWORD = 'pages/customPassword' 33 34 35//Event type name 36const EVENT_BEGIN_WAKEUP: string = 'beginWakeUp' 37const EVENT_END_WAKEUP: string = 'endWakeUp' 38const EVENT_BEGIN_SCREENON: string = 'beginScreenOn' 39const EVENT_END_SCREEN_ON: string = 'endScreenOn' 40const EVENT_BEGIN_SCREENOFF: string = 'beginScreenOff' 41const EVENT_END_SCREENOFF: string = 'endScreenOff' 42const EVENT_UNLOCK_SCREEN: string = 'unlockScreen' 43const EVENT_LOCK_SCREEN: string = 'lockScreen' 44const EVENT_BEGIN_EXITANIMATION: string = 'beginExitAnimation' 45const EVENT_BEGIN_SLEEP: string = 'beginSleep' 46const EVENT_END_SLEEP: string = 'endSleep' 47const EVENT_CHANGE_USER: string = 'changeUser' 48const EVENT_SCREENLOCK_ENABLE: string = 'screenlockEnabled' 49const EVENT_SYSTEM_READY: string = 'systemReady' 50 51const SERVICE_RESTART: string = 'serviceRestart' 52 53const LOCK_SCREEN_RESULT: string = 'lockScreenResult' 54const UNLOCK_SCREEN_RESULT: string = 'unlockScreenResult' 55const SCREENLOCK_DRAW_DONE: string = 'screenDrawDone' 56 57const ACTIVATING_TYPE = "activating" 58const ACTIVATE_TYPE = "activate" 59const ACTIVATING_EVENT = "activatingEvent" 60const ACTIVATE_EVENT = "activateEvent" 61 62const CHALLENGE_INT = 0 63 64const MAIN_USER = 100 65 66const MEMORY_MONITOR_PERIOD_MS = 600000 67const MEMORY_MONITOR_LIMIT_KB = 120 * 1024 68 69export {AuthType, AuthSubType}; 70 71export enum UnlockResult { 72 Success = 0, 73 Fail = 1, 74 Cancel = 2 75} 76 77export enum LockResult { 78 Success = 0, 79 Fail = 1, 80 Cancel = 2 81} 82 83let mRouterPath: string = "" 84 85let mWillRecognizeFace: boolean = false 86 87let mUnLockBeginAnimation: Callback<Callback<void>> = (callback: Callback<void>) => { 88 callback() 89} 90 91export class ScreenLockService { 92 accountModel: AccountModel = new AccountModel() 93 screenLockModel: ScreenLockModel = new ScreenLockModel() 94 currentLockStatus : ScreenLockStatus; 95 memoryMonitor: number = -1; 96 init() { 97 Log.showDebug(TAG, 'init'); 98 this.startMonitorMemory(); 99 this.accountModel.modelInit(); 100 this.monitorEvents(); 101 this.accountModel.updateAllUsers() 102 this.checkPinAuthProperty(() => { 103 Log.showInfo(TAG, `checkPinAuthProperty back`) 104 this.authUserByFace() 105 }) 106 } 107 108 monitorEvents() { 109 Log.showDebug(TAG, 'registered events start'); 110 this.screenLockModel.eventListener((typeName: String) => { 111 switch (typeName) { 112 // System ready on device boot 113 case EVENT_SYSTEM_READY: 114 Log.showInfo(TAG, `EVENT_SYSTEM_READY event`); 115 this.lockScreen(); 116 break; 117 //Bright screen 118 case EVENT_END_SCREEN_ON: 119 Log.showInfo(TAG, `EVENT_END_SCREEN_ON event`); 120 this.authUserByFace() 121 AppStorage.SetOrCreate('deviceStatus', EVENT_END_SCREEN_ON); 122 break; 123 //The device is going to sleep 124 case EVENT_BEGIN_SLEEP: 125 Trace.start(Trace.CORE_METHOD_SLEEP_TO_LOCK_SCREEN); 126 Log.showInfo(TAG, `EVENT_BEGIN_SLEEP event`); 127 this.lockScreen(); 128 this.accountModel.updateAllUsers() 129 AppStorage.SetOrCreate('deviceStatus', EVENT_BEGIN_SLEEP); 130 break; 131 //unlock request was received 132 case EVENT_UNLOCK_SCREEN: 133 Log.showInfo(TAG, `EVENT_UNLOCK_SCREEN event`); 134 this.unlockScreen(); 135 break; 136 //lock request was received 137 case EVENT_LOCK_SCREEN: 138 Log.showInfo(TAG, `EVENT_LOCK_SCREEN event`); 139 this.lockScreen(); 140 break; 141 case SERVICE_RESTART: 142 setTimeout(() => { 143 this.monitorEvents(); 144 this.lockScreen(); 145 }, 2000); 146 break; 147 default: 148 Log.showError(TAG, `eventListener:typeName ${typeName}`) 149 } 150 }) 151 152 this.accountModel.eventListener(ACTIVATING_TYPE, ACTIVATING_EVENT, () => { 153 Log.showInfo(TAG, `ACTIVATING_TYPE event`); 154 this.lockScreen(); 155 }) 156 157 this.accountModel.eventListener(ACTIVATE_TYPE, ACTIVATE_EVENT, () => { 158 Log.showInfo(TAG, `ACTIVATE_TYPE event`); 159 this.accountModel.updateAllUsers() 160 this.checkPinAuthProperty(() => { 161 Log.showInfo(TAG, `checkPinAuthProperty back`) 162 this.authUserByFace() 163 }) 164 }) 165 166 this.accountModel.commonEventListener(()=>{ 167 Log.showInfo(TAG, `commonEventListener event`); 168 this.accountModel.updateAllUsers(); 169 }) 170 171 Log.showDebug(TAG, 'registered events end'); 172 } 173 174 lockScreen() { 175 Trace.start(Trace.CORE_METHOD_SHOW_LOCK_SCREEN); 176 Log.showDebug(TAG, `lockScreen`); 177 let length = parseInt(Router.getLength()) 178 Log.showDebug(TAG, `Router.getLength: ${length}`) 179 for (let index = 1; index < length; index++) { 180 Log.showInfo(TAG, `back to index`); 181 Router.back(); 182 } 183 //lock the screen 184 this.screenLockModel.showScreenLockWindow(() => { 185 Log.showInfo(TAG, `showScreenLockWindow finish`); 186 this.checkPinAuthProperty(() => { 187 }); 188 Log.showInfo(TAG, `screenlock status:${this.currentLockStatus}, userId : ${this.accountModel.getCurrentUserId()}`); 189 if (this.currentLockStatus == ScreenLockStatus.Locking) { 190 Log.showInfo(TAG, `had locked, no need to publish lock_screen`); 191 } else { 192 this.notifyLockScreenResult(LockResult.Success) 193 this.publishByUser("common.event.LOCK_SCREEN", this.accountModel.getCurrentUserId()); 194 setTimeout(() => { 195 systemParameter.set('bootevent.lockscreen.ready','true') 196 }, 1000); 197 this.currentLockStatus = ScreenLockStatus.Locking; 198 } 199 }); 200 } 201 202 private checkPinAuthProperty(callback: Callback<void>) { 203 Log.showDebug(TAG, "checkPinAuthProperty") 204 this.accountModel.getAuthProperty(AuthType.PIN, (properties) => { 205 Log.showInfo(TAG, `checkPinAuthProperty: AUTH_SUB_TYPE:${properties.authSubType}`); 206 switch (properties.authSubType) { 207 case AuthSubType.PIN_SIX: 208 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking); 209 mRouterPath = URI_DIGITALPASSWORD; 210 this.checkFaceAuthProperty(() => { 211 callback() 212 }) 213 break; 214 case AuthSubType.PIN_MIXED: 215 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking); 216 mRouterPath = URI_MIXEDPASSWORD; 217 this.checkFaceAuthProperty(() => { 218 callback() 219 }) 220 break; 221 case AuthSubType.PIN_NUMBER: 222 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking); 223 mRouterPath = URI_CUSTOMPASSWORD; 224 this.checkFaceAuthProperty(() => { 225 callback() 226 }) 227 break; 228 default: 229 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock); 230 mWillRecognizeFace = false 231 } 232 }) 233 } 234 235 private checkFaceAuthProperty(callback: Callback<void>) { 236 Log.showDebug(TAG, "checkFaceAuthProperty") 237 this.accountModel.getAuthProperty(AuthType.FACE, (properties) => { 238 Log.showInfo(TAG, `checkFaceAuthProperty:AUTH_SUB_TYPE:${properties.authSubType}`); 239 switch (properties.authSubType) { 240 case AuthSubType.FACE_2D: 241 case AuthSubType.FACE_3D: 242 mWillRecognizeFace = true 243 callback() 244 break; 245 default: 246 mWillRecognizeFace = false 247 } 248 }) 249 } 250 251 unlockScreen() { 252 Log.showInfo(TAG, `unlockScreen`); 253 this.accountModel.isActivateAccount((isActivate: boolean) => { 254 if (!isActivate) { 255 return 256 } 257 mUnLockBeginAnimation(() => { 258 let status = AppStorage.Link('lockStatus') 259 Log.showDebug(TAG, `unlocking lockStatus:${JSON.stringify(status?.get())}`); 260 if (status?.get() == ScreenLockStatus.Unlock) { 261 Log.showInfo(TAG, `unlock the screen`); 262 this.unlocking(); 263 } else { 264 let slidestatus = AppStorage.Get('slidestatus') 265 if(!slidestatus){ 266 AppStorage.SetOrCreate('slidestatus', true); 267 Log.showInfo(TAG, `unlockScreen Router.push`); 268 Router.push({ uri: mRouterPath }); 269 } 270 } 271 }) 272 }) 273 } 274 275 unlocking() { 276 Log.showInfo(TAG, `unlocking`); 277 //set the lockStatus to 'Unlock' 278 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock); 279 this.currentLockStatus = ScreenLockStatus.Unlock; 280 AppStorage.SetOrCreate('slidestatus', false); 281 //unlock the screen 282 this.screenLockModel.hiddenScreenLockWindow(() => { 283 Log.showInfo(TAG, `hiddenScreenLockWindow finish`); 284 //notify the base service that the unlock is completed 285 this.notifyUnlockScreenResult(UnlockResult.Success); 286 this.publishByUser("common.event.UNLOCK_SCREEN", this.accountModel.getCurrentUserId()); 287 }); 288 } 289 290 notifyUnlockScreenResult(result: UnlockResult) { 291 Log.showInfo(TAG, `notifyUnlockScreenResult`); 292 this.screenLockModel.sendScreenLockEvent(UNLOCK_SCREEN_RESULT, result, (error, data) => { 293 Log.showInfo(TAG, `notifyUnlockScreenResult: error:${JSON.stringify(error)} data:${JSON.stringify(data)}`); 294 }); 295 } 296 297 notifyLockScreenResult(result: LockResult) { 298 Log.showInfo(TAG, `notifyLockScreenResult`); 299 this.screenLockModel.sendScreenLockEvent(LOCK_SCREEN_RESULT, result, (error, data) => { 300 Log.showInfo(TAG, `notifyLockScreenResult: error:${JSON.stringify(error)} data:${JSON.stringify(data)}`); 301 }); 302 } 303 304 notifyDrawDone() { 305 Log.showInfo(TAG, `notifyDrawDone`); 306 //notify the base service that the screen is loaded 307 this.screenLockModel.sendScreenLockEvent(SCREENLOCK_DRAW_DONE, 0, (error, result) => { 308 Log.showInfo(TAG, `notifyDrawDone: error:${JSON.stringify(error)} result:${JSON.stringify(result)}`); 309 }); 310 } 311 312 authUser(authSubType: AuthSubType, passwordData: number[] | string, callback): void { 313 Log.showInfo(TAG, `authUser authSubType:${authSubType}`); 314 let password: string = ''; 315 if (typeof passwordData == 'string') { 316 password = passwordData; 317 } else { 318 password = passwordData.join(''); 319 } 320 this.accountModel.registerPWDInputer(password).then(() => { 321 Log.showInfo(TAG, `registerPWDInputer success`); 322 this.accountModel.authUser(CHALLENGE_INT, AuthType.PIN, AuthTurstLevel.ATL4, (result, extraInfo) => { 323 Log.showDebug(TAG, `authUser callback:${result} extraInfo:${JSON.stringify(extraInfo)}`); 324 this.accountModel.unregisterInputer(); 325 callback(result, extraInfo); 326 }) 327 }).catch(() => { 328 Log.showError(TAG, `registerPWDInputer fails`); 329 }) 330 } 331 332 authUserByFace() { 333 if (!mWillRecognizeFace) { 334 Log.showInfo(TAG, "Recognize face is not support") 335 return 336 } 337 Log.showInfo(TAG, `authUserByFace`); 338 this.accountModel.authUser(CHALLENGE_INT, AuthType.FACE, AuthTurstLevel.ATL1, (result, extraInfo) => { 339 Log.showDebug(TAG, `authUserByFace callback:${result} extraInfo:${JSON.stringify(extraInfo)}`); 340 if (result == 0) { 341 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock); 342 this.unlockScreen() 343 } else { 344 AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.FaceNotRecognized); 345 this.currentLockStatus = ScreenLockStatus.FaceNotRecognized; 346 } 347 }) 348 } 349 350 onUserSwitch(userId: number) { 351 this.accountModel.onUserSwitch(userId) 352 } 353 354 goBack() { 355 Log.showInfo(TAG, `screen lock service goBack`); 356 Router.back(); 357 this.accountModel.unregisterInputer(); 358 } 359 360 destroy() { 361 this.screenLockModel.eventCancelListener(EVENT_SYSTEM_READY); 362 this.screenLockModel.eventCancelListener(EVENT_END_SCREEN_ON); 363 this.screenLockModel.eventCancelListener(EVENT_BEGIN_SLEEP); 364 this.screenLockModel.eventCancelListener(EVENT_UNLOCK_SCREEN); 365 this.accountModel.eventCancelListener(ACTIVATING_TYPE, ACTIVATING_EVENT); 366 this.accountModel.eventCancelListener(ACTIVATE_TYPE, ACTIVATE_EVENT) 367 this.accountModel.commonEventCancelListener(); 368 this.accountModel.modelFinish() 369 this.stopMonitorMemory() 370 } 371 372 setUnlockAnimation(beginAnimation: Callback<Callback<void>>) { 373 mUnLockBeginAnimation = beginAnimation; 374 } 375 376 getAuthProperty(authType, callback) { 377 Log.showInfo(TAG, `getAuthProperty param: authType ${authType}`); 378 this.accountModel.getAuthProperty(authType, (properties) => { 379 callback(properties); 380 }) 381 } 382 383 private publishByUser(eventName: string, activeUserId: number) { 384 Log.showDebug(TAG, `publishByUser event name: ${eventName}, userId: ${activeUserId}`) 385 let publishData : CommonEventPublishData = { 386 parameters : { 387 userId : activeUserId 388 } 389 }; 390 commonEvent.publish(eventName, publishData, (error, value) => { 391 if (error.code) { 392 Log.showError(TAG, 'Operation failed. Cause: ' + JSON.stringify(error)); 393 } else { 394 Log.showDebug(TAG, 'publish common event success. ' + JSON.stringify(value)); 395 } 396 }); 397 } 398 399 private startMonitorMemory() { 400 this.memoryMonitor = setInterval(() => { 401 const pss = hiDebug.getPss(); 402 Log.showInfo(TAG, `app pss info is: ${pss}`); 403 if (pss > MEMORY_MONITOR_LIMIT_KB) { 404 WriteFaultLog({FAULT_ID: FaultID.MEMORY, MSG: "pss over limit"}) 405 } 406 }, MEMORY_MONITOR_PERIOD_MS) 407 } 408 409 private stopMonitorMemory() { 410 if (this.memoryMonitor !== -1) { 411 clearInterval(this.memoryMonitor); 412 this.memoryMonitor = -1; 413 } 414 } 415} 416 417let screenLockService = createOrGet(ScreenLockService, TAG); 418 419export default screenLockService as ScreenLockService;