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