1/** 2 * Copyright (c) 2023 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 */ 15 16import screen from '@ohos.screen'; 17import userAuth from '@ohos.userIAM.userAuth'; 18import AuthUtils from '../common/utils/AuthUtils'; 19import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 20import { DialogType } from '../common/module/DialogType'; 21import FuncUtils from '../common/utils/FuncUtils'; 22import LogUtils from '../common/utils/LogUtils'; 23import Constants, { CmdData, CmdType, FingerPosition, WantParams, WidgetCommand } from '../common/vm/Constants'; 24import CustomPassword from './components/CustomPassword'; 25import FaceAuth from './components/FaceAuth'; 26import FingerprintAuth from './components/FingerprintAuth'; 27import PasswordAuth from './components/PasswordAuth'; 28import common from '@ohos.app.ability.common'; 29 30const DEFAULT_SIZE = 72; 31const FIVE_SECOND = 5000; 32const LANDSCAPE = 2; 33const TAG = 'Index'; 34let userAuthWidgetMgr: userAuth.UserAuthWidgetMgr; 35 36@Entry 37@Component 38struct Index { 39 @State authType: Array<userAuth.UserAuthType> = [userAuth.UserAuthType.PIN]; 40 @State type: string[] = []; 41 @State topHeight: number = DEFAULT_SIZE; 42 @State bottomHeight: number = DEFAULT_SIZE; 43 @State pinSubType: string = Constants.pinNumber; 44 @State dialogType: DialogType = DialogType.ALL; 45 @State windowModeType: string = 'DIALOG_BOX'; 46 @State cmdData: Array<CmdType> = []; 47 @State isLandscape: boolean = false; 48 @Provide underFingerPrint: boolean = false; 49 @State loadFlag: boolean = false; 50 @State isFaceLocked: boolean = false; 51 @State isFingerprintLocked: boolean = false; 52 @State skipLockedBiometricAuth: boolean = false; 53 54 onScreenChange(): void { 55 try { 56 screen.getAllScreens((err, data) => { 57 if (err.code) { 58 LogUtils.error(TAG, 'Failed to get all screens. err: ' + err.code); 59 (AppStorage.get('session') as UIExtensionContentSession)?.terminateSelf(); 60 return; 61 } 62 LogUtils.debug(TAG, ' get all screens. result:-- ' + JSON.stringify(data)); 63 this.isLandscape = data[0]?.orientation === LANDSCAPE || 64 data[0]?.supportedModeInfo[0]?.width > data[0]?.supportedModeInfo[0]?.height; 65 AppStorage.SetOrCreate('titleLength', (data[0]?.supportedModeInfo[0]?.width * 0.8 / fp2px(16))) 66 LogUtils.debug(TAG, 'titleLength: ' + (data[0]?.supportedModeInfo[0]?.width * 0.8 / fp2px(16))); 67 LogUtils.debug(TAG, 'title: ' + (AppStorage.get('wantParams') as WantParams)?.title.length); 68 AppStorage.SetOrCreate('IS_LANDSCAPE', this.isLandscape); 69 LogUtils.debug(TAG, 'WantParams: ' + JSON.stringify(AppStorage.get('wantParams') as WantParams)); 70 if ((AppStorage.get('wantParams') as WantParams)) { 71 this.getParams((AppStorage.get('wantParams') as WantParams)); 72 this.handleAuthStart(); 73 this.cmdData = (AppStorage.get('wantParams') as WantParams)?.cmd as CmdType[]; 74 } else { 75 LogUtils.error(TAG, 'aboutToAppear wantParams null'); 76 (AppStorage.get('session') as UIExtensionContentSession)?.terminateSelf(); 77 } 78 if (this.isLandscape && this.underFingerPrint) { 79 setTimeout(() => { 80 (AppStorage.get('session') as UIExtensionContentSession)?.terminateSelf(); 81 }, FIVE_SECOND) 82 } else { 83 this.loadFlag = true; 84 } 85 }); 86 } catch (error) { 87 LogUtils.error(TAG, 'getAllScreens catch error: ' + error?.code); 88 (AppStorage.get('session') as UIExtensionContentSession)?.terminateSelf(); 89 } 90 } 91 92 handleAuthStart(): void { 93 LogUtils.info(TAG, 'handleAuthStart'); 94 try { 95 userAuthWidgetMgr = userAuth.getUserAuthWidgetMgr(Constants.userAuthWidgetMgrVersion); 96 LogUtils.info(TAG, 'getUserAuthWidgetMgr success'); 97 let that = this; 98 userAuthWidgetMgr.on('command', { 99 sendCommand(result) { 100 LogUtils.info(TAG, 'sendCommand result: ' + result); 101 const cmdDataObj: WidgetCommand = JSON.parse(result || '{}'); 102 that.skipLockedBiometricAuth = cmdDataObj?.skipLockedBiometricAuth ?? false 103 cmdDataObj.cmd?.map((item) => { 104 if (item.payload?.lockoutDuration !== 0 && item.payload?.remainAttempts === 0) { 105 if (item.payload?.type === 'face') { 106 that.isFaceLocked = true; 107 } else if (item.payload?.type === 'fingerprint') { 108 that.isFingerprintLocked = true; 109 } 110 } 111 }) 112 if (that.skipLockedBiometricAuth) { 113 if (that.authType.length == 1 && that.authType.includes(userAuth.UserAuthType.FACE) && that.isFaceLocked) { 114 AuthUtils.getInstance().sendNotice(Constants.noticeEventWidgetReleased, [Constants.noticeTypeFace]); 115 if ((AppStorage.get('wantParams') as WantParams)?.navigationButtonText as string) { 116 AuthUtils.getInstance().sendNotice(Constants.noticeEventUserNavigation, [Constants.noticeTypeFace]); 117 } else { 118 AuthUtils.getInstance().sendNotice(Constants.noticeEventCancel, [Constants.noticeTypeFace]); 119 } 120 AppStorage.get<UIExtensionContentSession>('session')?.terminateSelf(); 121 return; 122 } 123 if (that.authType.length == 1 && that.authType.includes(userAuth.UserAuthType.FINGERPRINT) && 124 that.isFingerprintLocked) { 125 AuthUtils.getInstance().sendNotice(Constants.noticeEventWidgetReleased, [Constants.noticeTypeFinger]); 126 if ((AppStorage.get('wantParams') as WantParams)?.navigationButtonText as string) { 127 AuthUtils.getInstance().sendNotice(Constants.noticeEventUserNavigation, [Constants.noticeTypeFinger]); 128 } else { 129 AuthUtils.getInstance().sendNotice(Constants.noticeEventCancel, [Constants.noticeTypeFinger]); 130 } 131 AppStorage.get<UIExtensionContentSession>('session')?.terminateSelf(); 132 return; 133 } 134 if (that.authType.length == 2 && that.authType.includes(userAuth.UserAuthType.FACE) && that.isFaceLocked && 135 that.authType.includes(userAuth.UserAuthType.FINGERPRINT) && that.isFingerprintLocked) { 136 AuthUtils.getInstance() 137 .sendNotice(Constants.noticeEventWidgetReleased, 138 [Constants.noticeTypeFinger, Constants.noticeTypeFace]); 139 if ((AppStorage.get('wantParams') as WantParams)?.navigationButtonText as string) { 140 AuthUtils.getInstance() 141 .sendNotice(Constants.noticeEventUserNavigation, 142 [Constants.noticeTypeFinger, Constants.noticeTypeFace]); 143 } else { 144 AuthUtils.getInstance() 145 .sendNotice(Constants.noticeEventCancel, [Constants.noticeTypeFinger, Constants.noticeTypeFace]); 146 } 147 AppStorage.get<UIExtensionContentSession>('session')?.terminateSelf(); 148 return; 149 } 150 } 151 152 that.cmdData = cmdDataObj?.cmd || []; 153 if (cmdDataObj?.pinSubType !== null && cmdDataObj?.pinSubType !== undefined) { 154 that.pinSubType = cmdDataObj?.pinSubType; 155 } 156 that.handleIsUnder(cmdDataObj?.cmd || []); 157 } 158 }); 159 } catch (error) { 160 LogUtils.error(TAG, 'getUserAuthWidgetMgr catch error: ' + error?.code); 161 (AppStorage.get('session') as UIExtensionContentSession)?.terminateSelf(); 162 } 163 } 164 165 handleIsUnder(cmd: Array<CmdType>): void { 166 try { 167 LogUtils.info(TAG, 'handleIsUnder'); 168 cmd?.length > 0 && cmd.map((item) => { 169 const payload: CmdData = item?.payload; 170 if (payload.type === Constants.noticeTypeFinger) { 171 if (payload.sensorInfo && JSON.stringify(payload.sensorInfo) !== '{}') { 172 const fingerPosition: FingerPosition = JSON.parse(payload.sensorInfo); 173 if (fingerPosition?.sensorType === 'UNDER_SCREEN_SENSOR' || 174 fingerPosition?.sensorType === 'BOTH_SENSOR' || 175 fingerPosition?.sensorType === 'SensorType1') { 176 this.underFingerPrint = true; 177 } 178 } 179 } 180 }); 181 } catch (error) { 182 LogUtils.error(TAG, 'handleIsUnder catch error: ' + error?.code); 183 } 184 } 185 186 aboutToAppear(): void { 187 LogUtils.debug(TAG, 'aboutToAppear'); 188 FuncUtils.getWindowHeight(); 189 this.onScreenChange(); 190 } 191 192 aboutToDisappear(): void { 193 LogUtils.info(TAG, 'aboutToDisappear'); 194 if (userAuthWidgetMgr) { 195 userAuthWidgetMgr.off('command', { 196 sendCommand(result) { 197 LogUtils.info(TAG, 'aboutToDisappear userAuthWidgetMgr offCommand result: ' + JSON.stringify(result)); 198 } 199 }); 200 } 201 } 202 203 getParams(result: WantParams): void { 204 LogUtils.info(TAG, 'getParams'); 205 const resultInfo: WantParams = result; 206 this.pinSubType = resultInfo?.pinSubType; 207 const newType = resultInfo?.type && resultInfo?.type.map(item => { 208 if (item === Constants.noticeTypePin) { 209 return userAuth.UserAuthType.PIN; 210 } else if (item === Constants.noticeTypeFinger) { 211 return userAuth.UserAuthType.FINGERPRINT; 212 } else if (item === Constants.noticeTypeFace) { 213 return userAuth.UserAuthType.FACE; 214 } else { 215 return userAuth.UserAuthType.PIN; 216 } 217 }) 218 AppStorage.setOrCreate('widgetContextId', resultInfo?.widgetContextIdStr); 219 this.authType = newType; 220 this.type = resultInfo?.type; 221 this.windowModeType = resultInfo?.windowModeType; 222 this.dialogType = FuncUtils.getDialogType(newType); 223 this.cmdData = resultInfo?.cmd || []; 224 this.handleIsUnder(resultInfo?.cmd || []); 225 } 226 227 build() { 228 Column() { 229 if (this.isLandscape && this.underFingerPrint) { 230 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.End }) { 231 Column() { 232 Text((AppStorage.get('context') as common.ExtensionContext)?.resourceManager 233 .getStringSync($r('app.string.unified_authwidget_tip_verify_in_portrait_mode').id)) 234 .draggable(false) 235 .fontColor($r('sys.color.ohos_id_color_text_primary_contrary')) 236 .fontSize($r('sys.float.ohos_id_text_size_body2')) 237 .fontWeight(FontWeight.Regular) 238 } 239 .backgroundColor($r('sys.color.ohos_id_color_instant_tip_bg')) 240 .borderRadius($r('sys.float.ohos_id_corner_radius_default_l')) 241 .padding({ 242 left: $r('app.float.padding_16'), 243 top: $r('app.float.padding_8'), 244 right: $r('app.float.padding_16'), 245 bottom: $r('app.float.padding_8') 246 }) 247 .margin({ bottom: $r('app.float.margin_64') }) 248 } 249 .width(Constants.fullContainerWidth) 250 .height(Constants.fullContainerHeight) 251 } else if (this.loadFlag) { 252 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) { 253 if ('DIALOG_BOX' === this.windowModeType) { 254 if (this.authType.includes(userAuth.UserAuthType.FACE)) { 255 FaceAuth({ 256 type: $windowModeType, 257 pinSubType: $pinSubType, 258 dialogType: $dialogType, 259 cmdData: $cmdData, 260 skipLockedBiometricAuth: $skipLockedBiometricAuth 261 }) 262 } else if (this.authType.includes(userAuth.UserAuthType.FINGERPRINT)) { 263 FingerprintAuth({ 264 type: $windowModeType, 265 pinSubType: $pinSubType, 266 dialogType: $dialogType, 267 cmdData: $cmdData, 268 skipLockedBiometricAuth: $skipLockedBiometricAuth 269 }) 270 } else { 271 PasswordAuth({ 272 pinSubType: $pinSubType, 273 cmdData: $cmdData 274 }) 275 } 276 } else { 277 // full screen PIN 278 CustomPassword({ 279 authType: $authType, 280 pinSubType: $pinSubType, 281 cmdData: $cmdData, 282 }) 283 } 284 } 285 } 286 } 287 } 288}