1/** 2 * Copyright (c) 2021-2023 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 common from '@ohos.app.ability.common'; 17import Audio from '@ohos.multimedia.audio'; 18import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; 19import DataShareExtensionAbility from '@ohos.application.DataShareExtensionAbility'; 20import rpc from '@ohos.rpc'; 21import process from '@ohos.process'; 22import settings from '@ohos.settings'; 23import relationalStore from '@ohos.data.relationalStore'; 24import Want from '@ohos.app.ability.Want'; 25import dataSharePredicates from '@ohos.data.dataSharePredicates'; 26import { AsyncCallback, BusinessError } from '@ohos.base'; 27import SettingsDataConfig from '../Utils/SettingsDataConfig'; 28import SettingsDBHelper from '../Utils/SettingsDBHelper'; 29import { Log } from '../Utils/Log'; 30import { GlobalContext} from '../Utils/GlobalContext'; 31 32 33interface IRequest { 34 operation:string ; 35 columns:string[]; 36 predicates:dataSharePredicates.DataSharePredicates|relationalStore.RdbPredicates|null; 37 value:relationalStore.ValuesBucket|null 38} 39let rdbStore:relationalStore.RdbStore|undefined = undefined; 40let requests:IRequest[] = []; 41let SETTINGS_AUDIO_RINGTONE = "settings.audio.ringtone" 42let SETTINGS_AUDIO_MEDIA = "settings.audio.media" 43let SETTINGS_AUDIO_VOICE_CALL = "settings.audio.voicecall" 44let trustList: Array<String> = [ 45settings.display.SCREEN_BRIGHTNESS_STATUS, 46settings.display.AUTO_SCREEN_BRIGHTNESS, 47settings.display.SCREEN_OFF_TIMEOUT 48]; 49let ret:number = 0; 50let err:BusinessError = {"code":-1} as BusinessError; 51 52export default class DataExtAbility extends DataShareExtensionAbility { 53 onCreate(want: Want) { 54 GlobalContext.thisContext = this.context; 55 this.onInitialized(); 56 Log.info('onCreate context'+ JSON.stringify(this.context)); 57 } 58 59 onInitialized() { 60 Log.info('onInitialize start'); 61 let context = GlobalContext.thisContext as common.Context; 62 Log.info('onInitialize start context: '+ JSON.stringify(this.context)); 63 if (context !== undefined) { 64 SettingsDBHelper.getInstance().getRdbStore().then((rdb: relationalStore.RdbStore|undefined) => { 65 rdbStore = rdb; 66 for (let i = 0; i < requests.length; i++) { 67 let opt: string = requests[i].operation; 68 let columns: string[] = requests[i].columns; 69 let predicates = (requests[i].predicates) as dataSharePredicates.DataSharePredicates; 70 71 let value: relationalStore.ValuesBucket|null = requests[i].value; 72 if (opt == "insert") { 73 if(value){ 74 rdbStore?.insert(SettingsDataConfig.TABLE_NAME, value, (err, ret) => { 75 Log.info('onInitialized insert ret: ' + ret); 76 }); 77 } 78 } else if (opt == "query") { 79 if(predicates){ 80 rdbStore?.query(SettingsDataConfig.TABLE_NAME, predicates, columns, (err: BusinessError, resultSet: relationalStore.ResultSet) => { 81 Log.info('onInitialized query ret: ' + JSON.stringify(resultSet)); 82 }); 83 } 84 85 } else if (opt == "update") { 86 if(value){ 87 rdbStore?.update(SettingsDataConfig.TABLE_NAME, value, predicates, (err, ret) => { 88 Log.info('onInitialized update ret: ' + ret); 89 }); 90 } 91 } 92 } 93 }).catch((err: Error) => { 94 Log.error('onInitialize failed:' + JSON.stringify(err)); 95 }) 96 } else { 97 Log.info('onInitialize context error!'); 98 } 99 Log.info('onInitialize end'); 100 } 101 102 insert(uri: string, value: relationalStore.ValuesBucket, callback : AsyncCallback<number>) { 103 Log.info('insert keyword = ' + value[SettingsDataConfig.FIELD_KEYWORD] + ' start:' + uri); 104 let rdbInsert = (GrantStatus: boolean) => { 105 if (!GrantStatus) { 106 callback(err, ret); 107 return; 108 } 109 this.DoSystemSetting(value[SettingsDataConfig.FIELD_KEYWORD]?.toString(), value[SettingsDataConfig.FIELD_VALUE]?.toString()); 110 111 if (rdbStore == null) { 112 let request: IRequest= { 113 operation: "insert", columns: [], predicates: null, value: value 114 }; 115 Log.info('insert request = ' + JSON.stringify(request)); 116 requests.push(request); 117 callback(err, ret); 118 } else { 119 rdbStore.insert(SettingsDataConfig.TABLE_NAME, value, (err, ret) => { 120 callback(err, ret); 121 Log.info('insert result: ' + ret); 122 }); 123 } 124 } 125 126 try { 127 Log.info('Start to verify permissions.'); 128 this.verifyPermission(value, rdbInsert); 129 } catch (err) { 130 Log.error('Insert Data error:' + JSON.stringify(err)); 131 callback(err, ret); 132 } 133 } 134 135 136 update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value:relationalStore.ValuesBucket, callback: AsyncCallback<number>) { 137 Log.info('update keyword = ' + value[SettingsDataConfig.FIELD_KEYWORD] + ' start:' + uri); 138 let rdbUpData = (GrantStatus:boolean) => { 139 if (!GrantStatus) { 140 callback(err, ret); 141 return; 142 } 143 this.DoSystemSetting(value[SettingsDataConfig.FIELD_KEYWORD]?.toString(), value[SettingsDataConfig.FIELD_VALUE]?.toString()); 144 if (rdbStore == null) { 145 let request : IRequest= { 146 operation: "update", columns: [], predicates: predicates, value: value 147 }; 148 Log.info('update request = ' + JSON.stringify(request)); 149 requests.push(request); 150 callback(err, ret); 151 } else { 152 rdbStore.update(SettingsDataConfig.TABLE_NAME, value, predicates , (err, ret)=> { 153 callback(err, ret); 154 Log.info('update result: ' + ret); 155 }); 156 } 157 } 158 try { 159 Log.info('Start to verify permissions.'); 160 this.verifyPermission(value, rdbUpData); 161 } catch (err) { 162 Log.error('upData error:' + JSON.stringify(err)); 163 callback(err, ret); 164 } 165 } 166 167 delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback<number>) { 168 Log.info('nothing to do'); 169 } 170 171 query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: string[], callback: AsyncCallback<Object>) { 172 Log.info( 'query start uri:' + uri); 173 if (rdbStore == null) { 174 let request: IRequest= {operation:"query", columns : columns, predicates : predicates, value:null}; 175 Log.info('query request = '+ JSON.stringify(request)); 176 requests.push(request); 177 callback(err, {"_napiwrapper":{}}); 178 } else { 179 rdbStore.query(SettingsDataConfig.TABLE_NAME, predicates, columns, (err:BusinessError, resultSet:relationalStore.ResultSet)=> { 180 callback(err, resultSet); 181 Log.info('query result: '+ JSON.stringify(resultSet.rowCount) +'columnNames'+ JSON.stringify(resultSet.columnNames)); 182 }) 183 } 184 } 185 186 private DoSystemSetting(settingsKey: string|undefined, settingsValue: string|undefined) { 187 switch (settingsKey) { 188 case SETTINGS_AUDIO_RINGTONE: 189 try { 190 let volumeType = Audio.AudioVolumeType.RINGTONE; 191 Audio.getAudioManager().setVolume(volumeType, Number(settingsValue)).then(() => { 192 Log.info('settings Promise returned to indicate a successful RINGTONE setting.') 193 }); 194 } catch (err) { 195 Log.info('settings RINGTONE failed error = ' + JSON.stringify(err)); 196 } 197 break 198 case SETTINGS_AUDIO_MEDIA: 199 try { 200 let volumeType = Audio.AudioVolumeType.MEDIA; 201 Audio.getAudioManager().setVolume(volumeType, Number(settingsValue)).then(() => { 202 Log.info('settings Promise returned to indicate a successful MEDIA setting.') 203 }); 204 } catch (err) { 205 Log.info('settings MEDIA failed error = ' + JSON.stringify(err)); 206 } 207 break 208 case SETTINGS_AUDIO_VOICE_CALL: 209 try { 210 let volumeType = Audio.AudioVolumeType.VOICE_CALL; 211 Audio.getAudioManager().setVolume(volumeType, Number(settingsValue)).then(() => { 212 Log.info('settings Promise returned to indicate a successful VOICE_CALL setting.') 213 }); 214 } catch (err) { 215 Log.info('settings VOICE_CALL failed error = ' + JSON.stringify(err)); 216 } 217 break 218 default: 219 Log.info(settingsKey + ' key is not audio'); 220 break 221 } 222 } 223 224 private verifyPermission(value: relationalStore.ValuesBucket, callBack: (GrantStatus: boolean) => void ) { 225 if (this.isTrustList(value[SettingsDataConfig.FIELD_KEYWORD] as string) || process.uid == rpc.IPCSkeleton.getCallingUid()) { 226 callBack(true); 227 return; 228 } 229 try { 230 let tokenID = rpc.IPCSkeleton.getCallingTokenId(); 231 Log.info('tokenID = ' + tokenID); 232 let grantStatus = abilityAccessCtrl.createAtManager().verifyAccessToken(tokenID, "ohos.permission.MANAGE_SECURE_SETTINGS"); 233 grantStatus.then(data => { 234 if (data == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { 235 Log.info('MANAGE_SECURE_SETTINGS active'); 236 callBack(true); 237 } else { 238 Log.warn('MANAGE_SECURE_SETTINGS grantStatus= ' + JSON.stringify(data)); 239 callBack(false); 240 } 241 }).catch((err: BusinessError) => { 242 Log.error('tokenID = ' + tokenID + ' verifyAccessToken is failed: ' + JSON.stringify(err)); 243 callBack(false); 244 }) 245 } catch (err) { 246 Log.error('err = ' + JSON.stringify(err)); 247 callBack(false); 248 } 249 } 250 251 private isTrustList(keyWord: string): boolean { 252 return trustList.includes(keyWord) 253 } 254}