• 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 '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;