1/* 2 * Copyright (c) 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 extension from '@ohos.app.ability.ServiceExtensionAbility'; 17import window from '@ohos.window'; 18import display from '@ohos.display'; 19import { GlobalContext } from '../common/utils/globalContext'; 20import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit'; 21import { camera } from '@kit.CameraKit'; 22import { audio } from '@kit.AudioKit'; 23 24const TAG = 'PermissionManager_Log:'; 25const BG_COLOR = '#00000000'; 26 27export default class GlobalExtensionAbility extends extension { 28 /** 29 * Lifecycle function, called back when a service extension is started for initialization. 30 */ 31 onCreate(want): void { 32 console.info(TAG + 'ServiceExtensionAbility onCreate, ability name is ' + want.abilityName); 33 console.info(TAG + 'want: ' + JSON.stringify(want)); 34 35 GlobalContext.store('globalState', want.parameters['ohos.sensitive.resource']); 36 GlobalContext.store('context', this.context); 37 38 if (!this.permissionCheck()) { 39 this.context?.terminateSelf(); 40 return; 41 } 42 43 if (!this.statusCheck(want.parameters['ohos.sensitive.resource'])) { 44 this.context?.terminateSelf(); 45 return; 46 } 47 48 try { 49 let dis = display.getDefaultDisplaySync(); 50 let navigationBarRect = { 51 left: 0, 52 top: 0, 53 width: dis.width, 54 height: dis.height 55 }; 56 this.createWindow('globalDialog', window.WindowType.TYPE_VOICE_INTERACTION, navigationBarRect); 57 } catch (exception) { 58 console.error(TAG + 'Failed to obtain the default display object. Code: ' + JSON.stringify(exception)); 59 }; 60 } 61 62 /** 63 * Lifecycle function, called back when a service extension is started or recall. 64 */ 65 onRequest(want, startId): void { 66 console.info(TAG + 'ServiceExtensionAbility onRequest. start id is ' + startId); 67 } 68 69 /** 70 * Lifecycle function, called back before a service extension is destroyed. 71 */ 72 onDestroy(): void { 73 console.info(TAG + 'ServiceExtensionAbility onDestroy.'); 74 let win = GlobalContext.load('globalWin'); 75 win?.destroyWindow(); 76 } 77 78 private permissionCheck(): boolean { 79 try { 80 let flag = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; 81 let bundleInfo = bundleManager.getBundleInfoForSelfSync(flag); 82 let atManager = abilityAccessCtrl.createAtManager(); 83 let status = 84 atManager.verifyAccessTokenSync(bundleInfo.appInfo.accessTokenId, 'ohos.permission.MICROPHONE_CONTROL'); 85 if (status === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { 86 console.log(TAG + 'permission status is denied.'); 87 return false; 88 } 89 return true; 90 } catch (err) { 91 console.error(TAG + 'verifyAccessTokenSync failed.'); 92 return false; 93 } 94 } 95 96 private statusCheck(resource: string): boolean { 97 switch (resource) { 98 case 'microphone': 99 if (this.microphoneStatus()) { 100 return true; 101 } else { 102 console.log(TAG + 'The microphone is not disabled on this device.'); 103 return false; 104 } 105 case 'camera': 106 if (this.cameraStatus()) { 107 return true; 108 } else { 109 console.log(TAG + 'The camera is not disabled on this device.'); 110 return false; 111 } 112 default: 113 if (this.microphoneStatus() && this.cameraStatus()) { 114 return true; 115 } else { 116 console.log(TAG + 'The microphone and camera is not disabled on this device.'); 117 return false; 118 } 119 } 120 } 121 122 private microphoneStatus(): boolean { 123 try { 124 let audioManager = audio.getAudioManager(); 125 let audioVolumeManager = audioManager.getVolumeManager(); 126 let groupId = audio.DEFAULT_VOLUME_GROUP_ID; 127 let audioVolumeGroupManager = audioVolumeManager.getVolumeGroupManagerSync(groupId); 128 let muteState = audioVolumeGroupManager.isPersistentMicMute(); 129 console.log(TAG + 'microphoneStatus: ' + muteState); 130 return muteState; 131 } catch (err) { 132 console.error(TAG + 'Failed to obtain the microphone disabled status.'); 133 return false; 134 } 135 } 136 137 private cameraStatus(): boolean { 138 try { 139 let cameraManager = camera.getCameraManager(this.context); 140 let isMuteSupported = cameraManager.isCameraMuteSupported(); 141 if (!isMuteSupported) { 142 console.log(TAG + 'The current device does not support disabling the camera.'); 143 return false; 144 } 145 let muteState = cameraManager.isCameraMuted(); 146 console.log(TAG + 'cameraStatus: ' + muteState); 147 return muteState; 148 } catch (err) { 149 console.error(TAG + 'Failed to obtain the camera disabled status.'); 150 return false; 151 } 152 } 153 154 private async createWindow(name: string, windowType: number, rect): Promise<void> { 155 console.info(TAG + 'create window'); 156 try { 157 const win = await window.createWindow({ ctx: this.context, name, windowType }); 158 GlobalContext.store('globalWin', win); 159 await win.moveWindowTo(rect.left, rect.top); 160 await win.resize(rect.width, rect.height); 161 await win.setUIContent('pages/globalSwitch'); 162 win.setWindowBackgroundColor(BG_COLOR); 163 await win.showWindow(); 164 } catch { 165 console.info(TAG + 'window create failed!'); 166 } 167 } 168};