1 /*
2 * Copyright (c) 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
16 #include "timer_database.h"
17 #include "time_common.h"
18
19 namespace OHOS {
20 namespace MiscServices {
21 constexpr const char *CREATE_TIME_TIMER_HOLD_ON_REBOOT = "CREATE TABLE IF NOT EXISTS hold_on_reboot "
22 "(timerId INTEGER PRIMARY KEY, "
23 "type INTEGER, "
24 "flag INTEGER, "
25 "windowLength INTEGER, "
26 "interval INTEGER, "
27 "uid INTEGER, "
28 "bundleName TEXT, "
29 "wantAgent TEXT, "
30 "state INTEGER, "
31 "triggerTime INTEGER, "
32 "pid INTEGER, "
33 "name TEXT)";
34
35 constexpr const char *CREATE_TIME_TIMER_DROP_ON_REBOOT = "CREATE TABLE IF NOT EXISTS drop_on_reboot "
36 "(timerId INTEGER PRIMARY KEY, "
37 "type INTEGER, "
38 "flag INTEGER, "
39 "windowLength INTEGER, "
40 "interval INTEGER, "
41 "uid INTEGER, "
42 "bundleName TEXT, "
43 "wantAgent TEXT, "
44 "state INTEGER, "
45 "triggerTime INTEGER, "
46 "pid INTEGER, "
47 "name TEXT)";
48
49 constexpr const char *HOLD_ON_REBOOT_ADD_PID_COLUMN = "ALTER TABLE hold_on_reboot ADD COLUMN pid INTEGER";
50 constexpr const char *HOLD_ON_REBOOT_ADD_NAME_COLUMN = "ALTER TABLE hold_on_reboot ADD COLUMN name TEXT";
51 constexpr const char *DROP_ON_REBOOT_ADD_PID_COLUMN = "ALTER TABLE drop_on_reboot ADD COLUMN pid INTEGER";
52 constexpr const char *DROP_ON_REBOOT_ADD_NAME_COLUMN = "ALTER TABLE drop_on_reboot ADD COLUMN name TEXT";
53 constexpr const char *DB_NAME = "/data/service/el1/public/database/time/time.db";
54 constexpr int DATABASE_OPEN_VERSION_2 = 2;
55 constexpr int DATABASE_OPEN_VERSION_3 = 3;
TimeDatabase()56 TimeDatabase::TimeDatabase()
57 {
58 int errCode = OHOS::NativeRdb::E_OK;
59 OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
60 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
61 config.SetEncryptStatus(false);
62 config.SetReadConSize(1);
63 TimeDBOpenCallback timeDBOpenCallback;
64 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDBOpenCallback, errCode);
65 TIME_HILOGI(TIME_MODULE_SERVICE, "Gets time database, ret: %{public}d", errCode);
66 if (errCode == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
67 auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
68 if (ret != OHOS::NativeRdb::E_OK) {
69 TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
70 return;
71 }
72 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDBOpenCallback, errCode);
73 }
74 }
75
GetInstance()76 TimeDatabase &TimeDatabase::GetInstance()
77 {
78 static TimeDatabase timeDatabase;
79 return timeDatabase;
80 }
81
RecoverDataBase()82 bool TimeDatabase::RecoverDataBase()
83 {
84 OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
85 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
86 config.SetEncryptStatus(false);
87 config.SetReadConSize(1);
88 auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
89 if (ret != OHOS::NativeRdb::E_OK) {
90 TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
91 return false;
92 }
93 TimeDBOpenCallback timeDbOpenCallback;
94 int errCode;
95 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDbOpenCallback, errCode);
96 if (store_ == nullptr) {
97 return false;
98 }
99 return true;
100 }
101
GetInt(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)102 int GetInt(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
103 {
104 int value = 0;
105 resultSet->GetInt(line, value);
106 return value;
107 }
108
GetLong(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)109 int64_t GetLong(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
110 {
111 int64_t value = 0;
112 resultSet->GetLong(line, value);
113 return value;
114 }
115
GetString(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)116 std::string GetString(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
117 {
118 std::string value = "";
119 resultSet->GetString(line, value);
120 return value;
121 }
122
Insert(const std::string & table,const OHOS::NativeRdb::ValuesBucket & insertValues)123 bool TimeDatabase::Insert(const std::string &table, const OHOS::NativeRdb::ValuesBucket &insertValues)
124 {
125 auto store = store_;
126 if (store == nullptr) {
127 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
128 return false;
129 }
130
131 int64_t outRowId = 0;
132 auto ret = store->Insert(outRowId, table, insertValues);
133 if (ret != OHOS::NativeRdb::E_OK) {
134 TIME_HILOGE(TIME_MODULE_SERVICE, "insert values failed, ret: %{public}d", ret);
135 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
136 return false;
137 }
138 if (!RecoverDataBase()) {
139 return false;
140 }
141 store = store_;
142 if (store == nullptr) {
143 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
144 return false;
145 }
146 ret = store->Insert(outRowId, table, insertValues);
147 if (ret != OHOS::NativeRdb::E_OK) {
148 TIME_HILOGE(TIME_MODULE_SERVICE, "Insert values after RecoverDataBase failed, ret: %{public}d", ret);
149 }
150 }
151 return true;
152 }
153
Update(const OHOS::NativeRdb::ValuesBucket values,const OHOS::NativeRdb::AbsRdbPredicates & predicates)154 bool TimeDatabase::Update(
155 const OHOS::NativeRdb::ValuesBucket values, const OHOS::NativeRdb::AbsRdbPredicates &predicates)
156 {
157 auto store = store_;
158 if (store == nullptr) {
159 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
160 return false;
161 }
162
163 int changedRows = 0;
164 auto ret = store->Update(changedRows, values, predicates);
165 if (ret != OHOS::NativeRdb::E_OK) {
166 TIME_HILOGE(TIME_MODULE_SERVICE, "update values failed, ret: %{public}d", ret);
167 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
168 return false;
169 }
170 if (!RecoverDataBase()) {
171 return false;
172 }
173 store = store_;
174 if (store == nullptr) {
175 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
176 return false;
177 }
178 ret = store->Update(changedRows, values, predicates);
179 if (ret != OHOS::NativeRdb::E_OK) {
180 TIME_HILOGE(TIME_MODULE_SERVICE, "Update values after RecoverDataBase failed, ret: %{public}d", ret);
181 }
182 }
183 return true;
184 }
185
Query(const OHOS::NativeRdb::AbsRdbPredicates & predicates,const std::vector<std::string> & columns)186 std::shared_ptr<OHOS::NativeRdb::ResultSet> TimeDatabase::Query(
187 const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
188 {
189 auto store = store_;
190 if (store == nullptr) {
191 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
192 return nullptr;
193 }
194 auto result = store->Query(predicates, columns);
195 if (result == nullptr) {
196 TIME_HILOGE(TIME_MODULE_SERVICE, "result is nullptr");
197 return nullptr;
198 }
199 int count;
200 if (result->GetRowCount(count) == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
201 RecoverDataBase();
202 result->Close();
203 return nullptr;
204 }
205 return result;
206 }
207
Delete(const OHOS::NativeRdb::AbsRdbPredicates & predicates)208 bool TimeDatabase::Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates)
209 {
210 auto store = store_;
211 if (store == nullptr) {
212 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
213 return false;
214 }
215
216 int deletedRows = 0;
217 auto ret = store->Delete(deletedRows, predicates);
218 if (ret != OHOS::NativeRdb::E_OK) {
219 TIME_HILOGE(TIME_MODULE_SERVICE, "delete values failed, ret: %{public}d", ret);
220 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
221 return false;
222 }
223 if (!RecoverDataBase()) {
224 return false;
225 }
226 store = store_;
227 if (store == nullptr) {
228 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
229 return false;
230 }
231 ret = store->Delete(deletedRows, predicates);
232 if (ret != OHOS::NativeRdb::E_OK) {
233 TIME_HILOGE(TIME_MODULE_SERVICE, "Delete values after RecoverDataBase failed, ret: %{public}d", ret);
234 }
235 }
236 return true;
237 }
238
ClearDropOnReboot()239 void TimeDatabase::ClearDropOnReboot()
240 {
241 TIME_HILOGI(TIME_MODULE_SERVICE, "Clears drop_on_reboot table");
242 auto store = store_;
243 if (store == nullptr) {
244 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
245 return;
246 }
247 auto ret = store->ExecuteSql("DELETE FROM drop_on_reboot");
248 if (ret != OHOS::NativeRdb::E_OK) {
249 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears drop_on_reboot table failed");
250 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
251 return;
252 }
253 if (!RecoverDataBase()) {
254 return;
255 }
256 store = store_;
257 if (store == nullptr) {
258 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
259 return;
260 }
261 ret = store->ExecuteSql("DELETE FROM drop_on_reboot");
262 if (ret != OHOS::NativeRdb::E_OK) {
263 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears after RecoverDataBase failed, ret: %{public}d", ret);
264 }
265 }
266 }
267
ClearInvaildDataInHoldOnReboot()268 void TimeDatabase::ClearInvaildDataInHoldOnReboot()
269 {
270 TIME_HILOGI(TIME_MODULE_SERVICE, "Clears hold_on_reboot table");
271 auto store = store_;
272 if (store == nullptr) {
273 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
274 return;
275 }
276 auto ret = store->ExecuteSql("DELETE FROM hold_on_reboot WHERE state = 0 OR type = 2 OR type = 3");
277 if (ret != OHOS::NativeRdb::E_OK) {
278 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears hold_on_reboot table failed");
279 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
280 return;
281 }
282 if (!RecoverDataBase()) {
283 return;
284 }
285 store = store_;
286 if (store == nullptr) {
287 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
288 return;
289 }
290 ret = store->ExecuteSql("DELETE FROM hold_on_reboot WHERE state = 0 OR type = 2 OR type = 3");
291 if (ret != OHOS::NativeRdb::E_OK) {
292 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears after RecoverDataBase failed, ret: %{public}d", ret);
293 }
294 }
295 }
296
TimeDBCreateTables(OHOS::NativeRdb::RdbStore & store)297 int TimeDBCreateTables(OHOS::NativeRdb::RdbStore &store)
298 {
299 TIME_HILOGI(TIME_MODULE_SERVICE, "Creates hold_on_reboot table");
300 // Creates hold_on_reboot table.
301 int ret = store.ExecuteSql(CREATE_TIME_TIMER_HOLD_ON_REBOOT);
302 if (ret != OHOS::NativeRdb::E_OK) {
303 TIME_HILOGE(TIME_MODULE_SERVICE, "Creates hold_on_reboot table failed, ret: %{public}d", ret);
304 return ret;
305 }
306
307 TIME_HILOGI(TIME_MODULE_SERVICE, "Creates drop_on_reboot table");
308 // Creates drop_on_reboot table.
309 ret = store.ExecuteSql(CREATE_TIME_TIMER_DROP_ON_REBOOT);
310 if (ret != OHOS::NativeRdb::E_OK) {
311 TIME_HILOGE(TIME_MODULE_SERVICE, "Creates drop_on_reboot table failed, ret: %{public}d", ret);
312 return ret;
313 }
314 return ret;
315 }
316
OnCreate(OHOS::NativeRdb::RdbStore & store)317 int TimeDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
318 {
319 TIME_HILOGI(TIME_MODULE_SERVICE, "OnCreate");
320 auto initRet = TimeDBCreateTables(store);
321 if (initRet != OHOS::NativeRdb::E_OK) {
322 TIME_HILOGE(TIME_MODULE_SERVICE, "Init database failed: %{public}d", initRet);
323 return initRet;
324 }
325 return OHOS::NativeRdb::E_OK;
326 }
327
OnOpen(OHOS::NativeRdb::RdbStore & store)328 int TimeDBOpenCallback::OnOpen(OHOS::NativeRdb::RdbStore &store)
329 {
330 return OHOS::NativeRdb::E_OK;
331 }
332
OnUpgrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)333 int TimeDBOpenCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
334 {
335 if (oldVersion < DATABASE_OPEN_VERSION_2 && newVersion >= DATABASE_OPEN_VERSION_2) {
336 int ret = store.ExecuteSql(HOLD_ON_REBOOT_ADD_PID_COLUMN);
337 if (ret != OHOS::NativeRdb::E_OK) {
338 TIME_HILOGE(TIME_MODULE_SERVICE, "hold_on_reboot add column failed, ret: %{public}d", ret);
339 return ret;
340 }
341 ret = store.ExecuteSql(DROP_ON_REBOOT_ADD_PID_COLUMN);
342 if (ret != OHOS::NativeRdb::E_OK) {
343 TIME_HILOGE(TIME_MODULE_SERVICE, "drop_on_reboot add column failed, ret: %{public}d", ret);
344 return ret;
345 }
346 }
347 if (oldVersion < DATABASE_OPEN_VERSION_3 && newVersion >= DATABASE_OPEN_VERSION_3) {
348 int ret = store.ExecuteSql(HOLD_ON_REBOOT_ADD_NAME_COLUMN);
349 if (ret != OHOS::NativeRdb::E_OK) {
350 TIME_HILOGE(TIME_MODULE_SERVICE, "hold_on_reboot add column failed, ret: %{public}d", ret);
351 return ret;
352 }
353 ret = store.ExecuteSql(DROP_ON_REBOOT_ADD_NAME_COLUMN);
354 if (ret != OHOS::NativeRdb::E_OK) {
355 TIME_HILOGE(TIME_MODULE_SERVICE, "drop_on_reboot add column failed, ret: %{public}d", ret);
356 return ret;
357 }
358 }
359 return OHOS::NativeRdb::E_OK;
360 }
361
OnDowngrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)362 int TimeDBOpenCallback::OnDowngrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
363 {
364 return OHOS::NativeRdb::E_OK;
365 }
366 }
367 }
368