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