/*
* Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { LogDomain, LogHelper } from '@ohos/basicutils';
import { HiDfxEventUtil } from '@ohos/frameworkwrapper';
import { SCBScreenSessionManager, SCBSceneSessionManager, UserSwitchEventType } from '@ohos/windowscene';
import { AbstractObserverManager } from '../base/AbstractObserverManager';
import commonEventMonitor from '../base/CommonEventMonitor';
import { IUserData } from '../bean/IUserData';
import CommonConstants from '../constants/CommonConstants';
import { AccountHelper, SwitchEventData } from '../utils/AccountHelper';
import { PowerUtils } from '../utils/PowerUtils';
import { SlServerHelper } from '../utils/SlServerHelper';
import { ScreenOnOffService } from './ScreenOnOffService';
const TAG = 'UserSwitchService';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.KG, TAG);
/**
* 用户切换事件监听
*/
export interface UserSwitchListener {
/**
* 切换中事件通知
*
* @param switchEventData 切换事件数据
*/
onSwitching?: (switchEventData: SwitchEventData) => void;
/**
* 切换完成事件通知
*
* @param switchEventData 切换事件数据
*/
onSwitched?: (switchEventData: SwitchEventData) => void;
/**
* 用户激活状态变化通知
*
* @param isCurrentUserActive 当前用户是否激活
*/
onUserActiveChanged?: (isCurrentUserActive: boolean) => void;
}
/**
* 用户切换服务
*/
export class UserSwitchService extends AbstractObserverManager<UserSwitchListener> {
private static sInstance: UserSwitchService;
public static getInstance(): UserSwitchService {
if (UserSwitchService.sInstance == null) {
UserSwitchService.sInstance = new UserSwitchService();
}
return UserSwitchService.sInstance;
}
private _currentUserActive: boolean = true;
private _isUserSwitching: boolean = false;
private constructor() {
super();
}
public get isCurrentUserActive(): boolean {
return this._currentUserActive;
}
private set isCurrentUserActive(currentUserActive: boolean) {
if (this._currentUserActive !== currentUserActive) {
this._currentUserActive = currentUserActive;
SlServerHelper.getInstance().setCurrentUserActive(currentUserActive);
this.broadcastDataChange(observer => observer?.onUserActiveChanged?.(this._currentUserActive));
}
}
public get isUserSwitching(): boolean {
return this._isUserSwitching;
}
public set isUserSwitching(isUserSwitching: boolean) {
if (this._isUserSwitching !== isUserSwitching) {
this._isUserSwitching = isUserSwitching;
}
}
protected doInit(): void {
log.showInfo('doInit');
AccountHelper.getInstance().registerUserSwitchListener('switching', this.handleSwitchingEvent.bind(this));
AccountHelper.getInstance().registerUserSwitchListener('switched', this.handleSwitchedEvent.bind(this));
commonEventMonitor.init();
AccountHelper.getInstance().isForegroundUser((isForegroundUser: boolean): void => {
if (isForegroundUser) {
log.showInfo('is current user active.');
this.isCurrentUserActive = true;
SlServerHelper.getInstance().onSystemEvent();
} else {
log.showInfo('is current user not active.');
this.isCurrentUserActive = false;
}
});
}
protected doRelease(): void {
log.showInfo('doRelease');
AccountHelper.getInstance().unRegisterUserSwitchListener('switching', this.handleSwitchingEvent.bind(this));
AccountHelper.getInstance().unRegisterUserSwitchListener('switched', this.handleSwitchedEvent.bind(this));
commonEventMonitor.destroy();
}
private handleSwitchingEvent(switchData: SwitchEventData): void {
log.showWarn(`receive user switching, <${switchData?.fromAccountId} -> ${switchData?.toAccountId}>`);
if (!switchData) {
log.showWarn('handleSwitchingEvent invalid switchData.');
return;
}
if (switchData.fromAccountId === switchData.toAccountId) {
log.showInfo('handleSwitchingEvent user not change.');
return;
}
this.isUserSwitching = true;
SCBSceneSessionManager.getInstance().handleUserSwitchEvent(UserSwitchEventType.SWITCHING, switchData.toAccountId);
let currentUser: IUserData | undefined = AppStorage.get<IUserData>(CommonConstants.CURRENT_USER_KEY);
HiDfxEventUtil.reportUserSwitchEvent(currentUser?.type);
if (AccountHelper.getInstance().currentLocalId === switchData.toAccountId) {
log.showInfo('current user to active.');
// 锁屏服务端只支持单个注册,因此需要重新激活
this.isCurrentUserActive = true;
SlServerHelper.getInstance().onSystemEvent();
} else {
// 如果是非当前用户将激活,则不处理
log.showInfo(`not current user ${AccountHelper.getInstance().currentLocalId} to active.`);
if (ScreenOnOffService.getInstance().isIntoSleep) {
SCBScreenSessionManager.getInstance().notifyScreenLockEvent(PowerUtils.MSG_NOTIFY_CANCEL_OFF_SCREEN);
PowerUtils.asyncWakeupDevice(PowerUtils.WAKEUP_DETAIL_FINGER_AUTH_SUCCESS);
}
if (!PowerUtils.isActive()) {
PowerUtils.asyncWakeupDevice(PowerUtils.WAKEUP_DETAIL_FINGER_AUTH_SUCCESS);
}
this.isCurrentUserActive = false;
}
this.broadcastDataChange(observer => observer.onSwitching?.(switchData));
}
private handleSwitchedEvent(switchData: SwitchEventData): void {
log.showWarn(`receive user switched, <${switchData?.fromAccountId} -> ${switchData?.toAccountId}>`);
if (!switchData) {
log.showWarn('handleSwitchedEvent invalid switchData.');
return;
}
if (switchData.fromAccountId === switchData.toAccountId) {
log.showInfo('handleSwitchedEvent user not change.');
return;
}
this.isUserSwitching = false;
// notify wms to handle user switched event
SCBSceneSessionManager.getInstance().handleUserSwitchEvent(UserSwitchEventType.SWITCHED, switchData.toAccountId);
this.broadcastDataChange(observer => observer.onSwitched?.(switchData));
}
}