1/* 2 * Copyright (c) 2025 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 { BaseModel } from '../common/base/BaseModel'; 17import { audio } from '@kit.AudioKit'; 18import { camera } from '@kit.CameraKit'; 19import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit'; 20import { Log } from '../common/utils/utils'; 21import { PermissionGroup } from '../common/model/definition'; 22import { PermissionApplications } from '../common/model/typedef'; 23import { GlobalDialogViewState } from './GlobalDialogViewState'; 24import window from '@ohos.window'; 25import display from '@ohos.display'; 26import common from '@ohos.app.ability.common'; 27 28const BG_COLOR = '#00000000'; 29const CAMERA = 'camera'; 30const MICROPHONE = 'microphone'; 31 32export class GlobalDialogModel extends BaseModel { 33 private static instance: GlobalDialogModel; 34 35 public static getInstance(): GlobalDialogModel { 36 if (!GlobalDialogModel.instance) { 37 GlobalDialogModel.instance = new GlobalDialogModel(); 38 } 39 return GlobalDialogModel.instance; 40 } 41 42 /** 43 * 判断麦克风全局状态 44 * return boolean 45 */ 46 private microphoneStatus(): boolean { 47 try { 48 let audioManager = audio.getAudioManager(); 49 let audioVolumeManager = audioManager.getVolumeManager(); 50 let groupId = audio.DEFAULT_VOLUME_GROUP_ID; 51 let audioVolumeGroupManager = audioVolumeManager.getVolumeGroupManagerSync(groupId); 52 let muteState = audioVolumeGroupManager.isPersistentMicMute(); 53 Log.info(`microphoneStatus: ${muteState}.`); 54 return muteState; 55 } catch (err) { 56 Log.error('Failed to obtain the microphone disabled status.'); 57 return false; 58 } 59 } 60 61 /** 62 * 判断相机全局状态 63 * @param context ServiceExtensionContext 64 * return boolean 65 */ 66 private cameraStatus(context: Context): boolean { 67 try { 68 let cameraManager = camera.getCameraManager(context); 69 let isMuteSupported = cameraManager.isCameraMuteSupported(); 70 if (!isMuteSupported) { 71 Log.info('The current device does not support disabling the camera.'); 72 return false; 73 } 74 let muteState = cameraManager.isCameraMuted(); 75 Log.info(`cameraStatus: ${muteState}.`); 76 return muteState; 77 } catch (err) { 78 Log.error('Failed to obtain the camera disabled status.'); 79 return false; 80 } 81 } 82 83 /** 84 * 判断弹窗申请权限的全局状态 85 * @param context ServiceExtensionContext 86 * @param resource 弹窗申请的权限 87 * return boolean 88 */ 89 public statusCheck(context: Context, resource: string): boolean { 90 switch (resource) { 91 case 'microphone': 92 if (this.microphoneStatus()) { 93 return true; 94 } else { 95 Log.info('The microphone is not disabled on this device.'); 96 return false; 97 } 98 case 'camera': 99 if (this.cameraStatus(context)) { 100 return true; 101 } else { 102 Log.info('The camera is not disabled on this device.'); 103 return false; 104 } 105 default: 106 if (this.microphoneStatus() && this.cameraStatus(context)) { 107 return true; 108 } else { 109 Log.info('The microphone and camera is not disabled on this device.'); 110 return false; 111 } 112 } 113 } 114 115 /** 116 * 判断是否拥有控制全局开关的权限 117 * return boolean 118 */ 119 public permissionCheck(): boolean { 120 try { 121 let flag = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; 122 let bundleInfo = bundleManager.getBundleInfoForSelfSync(flag); 123 let atManager = abilityAccessCtrl.createAtManager(); 124 let status = 125 atManager.verifyAccessTokenSync(bundleInfo.appInfo.accessTokenId, 'ohos.permission.MICROPHONE_CONTROL'); 126 if (status === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { 127 Log.info('permission status is denied.'); 128 return false; 129 } 130 return true; 131 } catch (err) { 132 Log.error('verifyAccessTokenSync failed.'); 133 return false; 134 } 135 } 136 137 /** 138 * 创建全局弹窗 139 * @param context ServiceExtensionContext 140 * @param rect 窗口大小及位置 141 * @param storage 数据管理 142 * return 创建的窗口 143 */ 144 public async createWindow( 145 context: Context, rect: display.Rect, storage: LocalStorage 146 ): Promise<window.Window | null> { 147 try { 148 Log.info('create window'); 149 let configuration: window.Configuration = { 150 ctx: context, 151 name: 'globalDialog', 152 windowType: window.WindowType.TYPE_VOICE_INTERACTION 153 } 154 const win = await window.createWindow(configuration); 155 await win.moveWindowTo(rect.left, rect.top); 156 await win.resize(rect.width, rect.height); 157 await win.loadContent('pages/globalSwitch', storage); 158 win.setWindowBackgroundColor(BG_COLOR); 159 await win.showWindow(); 160 return win; 161 } catch (error) { 162 Log.error(`window create failed, code: ${error.code}, message: ${error.message}.`); 163 return null; 164 } 165 } 166 167 public initViewState(type: string): GlobalDialogViewState { 168 let viewState = new GlobalDialogViewState(); 169 if (type === MICROPHONE) { 170 viewState.title = $r('app.string.global_title_microphone'); 171 viewState.text = $r('app.string.global_desc_microphone'); 172 } else if (type === CAMERA) { 173 viewState.title = $r('app.string.global_title_camera'); 174 viewState.text = $r('app.string.global_desc_camera'); 175 } else { 176 viewState.title = $r('app.string.global_title_camera_and_microphone'); 177 viewState.text = $r('app.string.global_desc_camera_and_microphone'); 178 } 179 return viewState; 180 } 181 182 /** 183 * 获取全局开关状态 184 * @param context UIAbilityContext 185 * @param type 全局开关类型 186 * @param backTitle 标题 187 * @param list 应用列表 188 * return 189 */ 190 public getMuteStateAndGoto( 191 context: UIContext, 192 type: PermissionGroup, 193 backTitle: ResourceStr, 194 list: PermissionApplications[] 195 ): void { 196 try { 197 if (type == PermissionGroup.MICROPHONE) { 198 let audioManager = audio.getAudioManager(); 199 let audioVolumeManager = audioManager.getVolumeManager(); 200 let audioVolumeGroupManager = audioVolumeManager.getVolumeGroupManagerSync(audio.DEFAULT_VOLUME_GROUP_ID); 201 let muteState = audioVolumeGroupManager.isPersistentMicMute(); 202 Log.info(`get muteState success: ${muteState}.`); 203 context.getRouter().pushUrl({ 204 url: 'pages/authority-tertiary-groups', 205 params: { list, backTitle, globalIsOn: !muteState, isMuteSupported: true } 206 }) 207 } else { 208 let cameraManager = camera.getCameraManager(context.getHostContext()); 209 let mute = cameraManager.isCameraMuted(); 210 let isCameraMuteSupported = cameraManager.isCameraMuteSupported(); 211 Log.info(`get muteState success: ${mute}.`); 212 context.getRouter().pushUrl({ 213 url: 'pages/authority-tertiary-groups', 214 params: { list, backTitle, globalIsOn: !mute, isMuteSupported: isCameraMuteSupported } 215 }) 216 } 217 } catch (error) { 218 Log.error(`getMuteStateAndGoto failed, code: ${error.code}, message: ${error.message}.`); 219 } 220 } 221 222 /** 223 * 设置麦克风全局开关 224 * @param context ServiceExtensionContext | UIAbilityContext 225 * @param flag 全局开关状态 226 * @param isKill 是否销毁ability 227 * return 228 */ 229 private setMicrophoneMute( 230 context: common.ServiceExtensionContext | common.UIAbilityContext, flag: boolean, isKill: boolean 231 ): void { 232 try { 233 let audioManager = audio.getAudioManager(); 234 let audioVolumeManager = audioManager.getVolumeManager(); 235 let audioVolumeGroupManager = audioVolumeManager.getVolumeGroupManagerSync(audio.DEFAULT_VOLUME_GROUP_ID); 236 audioVolumeGroupManager.setMicMutePersistent(flag, audio.PolicyType.PRIVACY).then(() => { 237 Log.info(`setMicMutePersistent success, mute: ${flag}.`); 238 isKill ? context.terminateSelf() : null; 239 }) 240 } catch (error) { 241 Log.error(`setMicrophoneMute failed, code: ${error.code}, message: ${error.message}.`); 242 } 243 } 244 245 /** 246 * 设置相机全局开关 247 * @param context ServiceExtensionContext | UIAbilityContext 248 * @param flag 全局开关状态 249 * @param isKill 是否销毁ability 250 * return 251 */ 252 private setCameraMute( 253 context: common.ServiceExtensionContext | common.UIAbilityContext, flag: boolean, isKill: boolean 254 ): void { 255 try { 256 let cameraManager = camera.getCameraManager(context); 257 cameraManager.muteCameraPersistent(flag, camera.PolicyType.PRIVACY); 258 Log.info(`muteCameraPersistent success, mute: ${flag}.`); 259 isKill ? context.terminateSelf() : null; 260 } catch (error) { 261 Log.error(`setCameraMute failed, code: ${error.code}, message: ${error.message}.`); 262 } 263 } 264 265 /** 266 * 设置全局开关状态 267 * @param context ServiceExtensionContext | UIAbilityContext 268 * @param type 全局开关类型 269 * @param flag 全局开关状态 270 * @param isKill 是否销毁ability 271 * return 272 */ 273 public setMuteState( 274 context: common.ServiceExtensionContext | common.UIAbilityContext, type: string, flag: boolean, isKill: boolean 275 ): void { 276 if (type === MICROPHONE || type === PermissionGroup.MICROPHONE) { 277 this.setMicrophoneMute(context, flag, isKill); 278 } else if (type === CAMERA || type === PermissionGroup.CAMERA) { 279 this.setCameraMute(context, flag, isKill); 280 } else { 281 this.setCameraMute(context, flag, false); 282 this.setMicrophoneMute(context, flag, isKill); 283 } 284 } 285 286}