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