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 */ 15 16import AccountManager from "@ohos.account.osAccount"; 17import Log from "./Log"; 18import getSingleInstance from "./SingleInstanceHelper"; 19 20const TAG = "SwitchUserManager"; 21const SUBSCRIBE_KEY = "SystemUiAccount"; 22const USER_CHANGE_EVENT = "activate"; 23const DELAY_TIME = 3 * 1000; 24export const INVALID_USER_ID = -1; 25 26type AccountInfo = { 27 localId: number; 28 localName: string; 29 photo: string; 30}; 31export type UserChangeListener = { 32 userChange: (data: UserInfo) => void; 33}; 34 35export class UserInfo { 36 userId: number = INVALID_USER_ID; 37 userName: string = ""; 38 userIcon: string | Resource = ""; 39 [key: string]: any; 40} 41 42async function getCurrentAccountInfo(): Promise<AccountInfo> { 43 let accountInfos = await AccountManager.getAccountManager().queryAllCreatedOsAccounts(); 44 for (let accountInfo of accountInfos) { 45 Log.showDebug(TAG, `accountInfo: ${accountInfo.localId}, isActive: ${accountInfo.isActived}`); 46 if (accountInfo.isActived) { 47 return accountInfo; 48 } 49 } 50 return { localId: INVALID_USER_ID, localName: "", photo: "" }; 51} 52 53function parseAccountInfo(accountInfo: AccountInfo): UserInfo { 54 return { 55 userId: accountInfo.localId, 56 userName: accountInfo.localName, 57 userIcon: accountInfo.photo, 58 }; 59} 60 61export default class SwitchUserManager { 62 mUserInfo: UserInfo = new UserInfo(); 63 mListeners = new Set<UserChangeListener>(); 64 mHasWait: boolean = false; 65 66 static getInstance(): SwitchUserManager { 67 return getSingleInstance(SwitchUserManager, TAG); 68 } 69 70 constructor() { 71 Log.showDebug(TAG, `SwitchUserManager constructor`); 72 try { 73 AccountManager.getAccountManager().on(USER_CHANGE_EVENT, SUBSCRIBE_KEY, this.handleUserChange.bind(this)); 74 } catch (err) { 75 Log.showError(TAG, `AccountManager.getAccountManager().on error: ${JSON.stringify(err)}`); 76 } 77 } 78 79 public async getCurrentUserInfo(): Promise<UserInfo> { 80 if (this.mUserInfo.userId == INVALID_USER_ID) { 81 this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo()); 82 while (!this.mHasWait && this.mUserInfo.userId == INVALID_USER_ID) { 83 await new Promise((resolve) => setTimeout(resolve, DELAY_TIME)); 84 this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo()); 85 } 86 this.mHasWait = true; 87 this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo()); 88 } 89 Log.showDebug(TAG, `getCurrentUserInfo userId: ${this.mUserInfo.userId}`); 90 return this.mUserInfo; 91 } 92 93 public registerListener(listener: UserChangeListener) { 94 this.mListeners.add(listener); 95 } 96 97 public unregisterListener(listener: UserChangeListener) { 98 this.mListeners.delete(listener); 99 } 100 101 handleUserChange(accountId: number): void { 102 AccountManager.getAccountManager() 103 .queryOsAccountById(accountId) 104 .then((accountInfo) => { 105 Log.showInfo(TAG, `userChange, localId: ${accountInfo?.localId}`); 106 this.mUserInfo = parseAccountInfo(accountInfo); 107 this.notifyUserChange(); 108 }) 109 .catch((err) => Log.showError(TAG, `Can't query account by ${accountId}, err: ${err}`)); 110 } 111 112 notifyUserChange() { 113 this.mListeners.forEach((listener) => listener.userChange(this.mUserInfo)); 114 } 115} 116