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