• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}