• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 '@ohos.base';
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                systemParameter.set('bootevent.lockscreen.ready','true')
194                this.currentLockStatus = ScreenLockStatus.Locking;
195            }
196        });
197    }
198
199    private checkPinAuthProperty(callback: Callback<void>) {
200        Log.showDebug(TAG, "checkPinAuthProperty")
201        this.accountModel.getAuthProperty(AuthType.PIN, (properties) => {
202            Log.showInfo(TAG, `checkPinAuthProperty: AUTH_SUB_TYPE:${properties.authSubType}`);
203            switch (properties.authSubType) {
204                case AuthSubType.PIN_SIX:
205                    AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking);
206                    mRouterPath = URI_DIGITALPASSWORD;
207                    this.checkFaceAuthProperty(() => {
208                        callback()
209                    })
210                    break;
211                case AuthSubType.PIN_MIXED:
212                    AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking);
213                    mRouterPath = URI_MIXEDPASSWORD;
214                    this.checkFaceAuthProperty(() => {
215                        callback()
216                    })
217                    break;
218                case AuthSubType.PIN_NUMBER:
219                    AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Locking);
220                    mRouterPath = URI_CUSTOMPASSWORD;
221                    this.checkFaceAuthProperty(() => {
222                        callback()
223                    })
224                    break;
225                default:
226                    AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock);
227                    mWillRecognizeFace = false
228            }
229        })
230    }
231
232    private checkFaceAuthProperty(callback: Callback<void>) {
233        Log.showDebug(TAG, "checkFaceAuthProperty")
234        this.accountModel.getAuthProperty(AuthType.FACE, (properties) => {
235            Log.showInfo(TAG, `checkFaceAuthProperty:AUTH_SUB_TYPE:${properties.authSubType}`);
236            switch (properties.authSubType) {
237                case AuthSubType.FACE_2D:
238                case AuthSubType.FACE_3D:
239                    mWillRecognizeFace = true
240                    callback()
241                    break;
242                default:
243                    mWillRecognizeFace = false
244            }
245        })
246    }
247
248    unlockScreen() {
249        Log.showInfo(TAG, `unlockScreen`);
250        this.accountModel.isActivateAccount((isActivate: boolean) => {
251            if (!isActivate) {
252                return
253            }
254            mUnLockBeginAnimation(() => {
255                let status = AppStorage.Link('lockStatus')
256                Log.showDebug(TAG, `unlocking lockStatus:${JSON.stringify(status?.get())}`);
257                if (status?.get() == ScreenLockStatus.Unlock) {
258                    Log.showInfo(TAG, `unlock the screen`);
259                    this.unlocking();
260                } else {
261                    let slidestatus = AppStorage.Get('slidestatus')
262                    if(!slidestatus){
263                        AppStorage.SetOrCreate('slidestatus', true);
264                        Log.showInfo(TAG, `unlockScreen Router.push`);
265                        Router.push({ uri: mRouterPath });
266                    }
267                }
268            })
269        })
270    }
271
272    unlocking() {
273        Log.showInfo(TAG, `unlocking`);
274        //set the lockStatus to 'Unlock'
275        AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock);
276        this.currentLockStatus = ScreenLockStatus.Unlock;
277        AppStorage.SetOrCreate('slidestatus', false);
278        //unlock the screen
279        this.screenLockModel.hiddenScreenLockWindow(() => {
280            Log.showInfo(TAG, `hiddenScreenLockWindow finish`);
281            //notify the base service that the unlock is completed
282            this.notifyUnlockScreenResult(UnlockResult.Success);
283        });
284    }
285
286    notifyUnlockScreenResult(result: UnlockResult) {
287        Log.showInfo(TAG, `notifyUnlockScreenResult`);
288        this.screenLockModel.sendScreenLockEvent(UNLOCK_SCREEN_RESULT, result, (error, data) => {
289            Log.showInfo(TAG, `notifyUnlockScreenResult: error:${JSON.stringify(error)} data:${JSON.stringify(data)}`);
290        });
291    }
292
293    notifyLockScreenResult(result: LockResult) {
294        Log.showInfo(TAG, `notifyLockScreenResult`);
295        this.screenLockModel.sendScreenLockEvent(LOCK_SCREEN_RESULT, result, (error, data) => {
296            Log.showInfo(TAG, `notifyLockScreenResult: error:${JSON.stringify(error)} data:${JSON.stringify(data)}`);
297        });
298    }
299
300    notifyDrawDone() {
301        Log.showInfo(TAG, `notifyDrawDone`);
302        //notify the base service that the screen is loaded
303        this.screenLockModel.sendScreenLockEvent(SCREENLOCK_DRAW_DONE, 0, (error, result) => {
304            Log.showInfo(TAG, `notifyDrawDone:  error:${JSON.stringify(error)} result:${JSON.stringify(result)}`);
305        });
306    }
307
308    authUser(authSubType: AuthSubType, passwordData: number[] | string, callback): void {
309        Log.showInfo(TAG, `authUser authSubType:${authSubType}`);
310        let password: string = '';
311        if (typeof passwordData == 'string') {
312            password = passwordData;
313        } else {
314            password = passwordData.join('');
315        }
316        this.accountModel.registerPWDInputer(password).then(() => {
317            Log.showInfo(TAG, `registerPWDInputer success`);
318            this.accountModel.authUser(CHALLENGE_INT, AuthType.PIN, AuthTurstLevel.ATL4, (result, extraInfo) => {
319                Log.showDebug(TAG, `authUser  callback:${result} extraInfo:${JSON.stringify(extraInfo)}`);
320                this.accountModel.unregisterInputer();
321                callback(result, extraInfo);
322            })
323        }).catch(() => {
324            Log.showError(TAG, `registerPWDInputer fails`);
325        })
326    }
327
328    authUserByFace() {
329        if (!mWillRecognizeFace) {
330            Log.showInfo(TAG, "Recognize face is not support")
331            return
332        }
333        Log.showInfo(TAG, `authUserByFace`);
334        this.accountModel.authUser(CHALLENGE_INT, AuthType.FACE, AuthTurstLevel.ATL1, (result, extraInfo) => {
335            Log.showDebug(TAG, `authUserByFace callback:${result} extraInfo:${JSON.stringify(extraInfo)}`);
336            if (result == 0) {
337                AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.Unlock);
338                this.unlockScreen()
339            } else {
340                AppStorage.SetOrCreate('lockStatus', ScreenLockStatus.FaceNotRecognized);
341                this.currentLockStatus = ScreenLockStatus.FaceNotRecognized;
342            }
343        })
344    }
345
346    onUserSwitch(userId: number) {
347        this.accountModel.onUserSwitch(userId)
348    }
349
350    goBack() {
351        Log.showInfo(TAG, `screen lock service goBack`);
352        Router.back();
353        this.notifyUnlockScreenResult(UnlockResult.Cancel)
354        this.accountModel.unregisterInputer();
355    }
356
357    destroy() {
358        this.screenLockModel.eventCancelListener(EVENT_SYSTEM_READY);
359        this.screenLockModel.eventCancelListener(EVENT_END_SCREEN_ON);
360        this.screenLockModel.eventCancelListener(EVENT_BEGIN_SLEEP);
361        this.screenLockModel.eventCancelListener(EVENT_UNLOCK_SCREEN);
362        this.accountModel.eventCancelListener(ACTIVATING_TYPE, ACTIVATING_EVENT);
363        this.accountModel.eventCancelListener(ACTIVATE_TYPE, ACTIVATE_EVENT)
364        this.accountModel.commonEventCancelListener();
365        this.accountModel.modelFinish()
366        this.stopMonitorMemory()
367    }
368
369    setUnlockAnimation(beginAnimation: Callback<Callback<void>>) {
370        mUnLockBeginAnimation = beginAnimation;
371    }
372
373    getAuthProperty(authType, callback) {
374        Log.showInfo(TAG, `getAuthProperty param: authType ${authType}`);
375        this.accountModel.getAuthProperty(authType, (properties) => {
376            callback(properties);
377        })
378    }
379
380    private publishByUser(eventName: string, activeUserId: number) {
381        Log.showDebug(TAG, `publishByUser event name: ${eventName}, userId: ${activeUserId}`)
382        let publishData : CommonEventPublishData = {
383            parameters : {
384                userId : activeUserId
385            }
386        };
387        commonEvent.publish(eventName, publishData, (error, value) => {
388            if (error.code) {
389                Log.showError(TAG, 'Operation failed. Cause: ' + JSON.stringify(error));
390            } else {
391                Log.showDebug(TAG, 'publish common event success. ' + JSON.stringify(value));
392            }
393        });
394    }
395
396    private startMonitorMemory() {
397        this.memoryMonitor = setInterval(() => {
398            const pss = hiDebug.getPss();
399            Log.showInfo(TAG, `app pss info is: ${pss}`);
400            if (pss > MEMORY_MONITOR_LIMIT_KB) {
401                WriteFaultLog({FAULT_ID: FaultID.MEMORY, MSG: "pss over limit"})
402            }
403        }, MEMORY_MONITOR_PERIOD_MS)
404    }
405
406    private stopMonitorMemory() {
407        if (this.memoryMonitor !== -1) {
408            clearInterval(this.memoryMonitor);
409            this.memoryMonitor = -1;
410        }
411    }
412}
413
414let screenLockService = createOrGet(ScreenLockService, TAG);
415
416export default screenLockService as ScreenLockService;