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 #include "timer_database.h"
16 #include "time_hilog.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";
TimeDatabase()53 TimeDatabase::TimeDatabase()
54 {
55 int errCode = OHOS::NativeRdb::E_OK;
56 OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
57 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
58 config.SetEncryptStatus(false);
59 config.SetReadConSize(1);
60 TimeDBOpenCallback timeDBOpenCallback;
61 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDBOpenCallback, errCode);
62 TIME_HILOGI(TIME_MODULE_SERVICE, "Gets time database, ret: %{public}d", errCode);
63 if (errCode == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
64 auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
65 if (ret != OHOS::NativeRdb::E_OK) {
66 TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
67 return;
68 }
69 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDBOpenCallback, errCode);
70 }
71 }
72
GetInstance()73 TimeDatabase &TimeDatabase::GetInstance()
74 {
75 static TimeDatabase timeDatabase;
76 return timeDatabase;
77 }
78
RecoverDataBase()79 bool TimeDatabase::RecoverDataBase()
80 {
81 OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
82 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
83 config.SetEncryptStatus(false);
84 config.SetReadConSize(1);
85 auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
86 if (ret != OHOS::NativeRdb::E_OK) {
87 TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
88 return false;
89 }
90 TimeDBOpenCallback timeDbOpenCallback;
91 int errCode;
92 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_3, timeDbOpenCallback, errCode);
93 return true;
94 }
95
GetInt(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)96 int GetInt(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
97 {
98 int value = 0;
99 resultSet->GetInt(line, value);
100 return value;
101 }
102
GetLong(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)103 int64_t GetLong(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
104 {
105 int64_t value = 0;
106 resultSet->GetLong(line, value);
107 return value;
108 }
109
GetString(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,int line)110 std::string GetString(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
111 {
112 std::string value = "";
113 resultSet->GetString(line, value);
114 return value;
115 }
116
Insert(const std::string & table,const OHOS::NativeRdb::ValuesBucket & insertValues)117 bool TimeDatabase::Insert(const std::string &table, const OHOS::NativeRdb::ValuesBucket &insertValues)
118 {
119 if (store_ == nullptr) {
120 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
121 return false;
122 }
123
124 int64_t outRowId = 0;
125 int ret = store_->Insert(outRowId, table, insertValues);
126 if (ret != OHOS::NativeRdb::E_OK) {
127 TIME_HILOGE(TIME_MODULE_SERVICE, "insert values failed, ret: %{public}d", ret);
128 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
129 return false;
130 }
131 if (!RecoverDataBase()) {
132 return false;
133 }
134 ret = store_->Insert(outRowId, table, insertValues);
135 if (ret != OHOS::NativeRdb::E_OK) {
136 TIME_HILOGE(TIME_MODULE_SERVICE, "Insert values after RecoverDataBase failed, ret: %{public}d", ret);
137 }
138 }
139 return true;
140 }
141
Update(const OHOS::NativeRdb::ValuesBucket values,const OHOS::NativeRdb::AbsRdbPredicates & predicates)142 bool TimeDatabase::Update(
143 const OHOS::NativeRdb::ValuesBucket values, const OHOS::NativeRdb::AbsRdbPredicates &predicates)
144 {
145 if (store_ == nullptr) {
146 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
147 return false;
148 }
149
150 int changedRows = 0;
151 int ret = store_->Update(changedRows, values, predicates);
152 if (ret != OHOS::NativeRdb::E_OK) {
153 TIME_HILOGE(TIME_MODULE_SERVICE, "update values failed, ret: %{public}d", ret);
154 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
155 return false;
156 }
157 if (!RecoverDataBase()) {
158 return false;
159 }
160 ret = store_->Update(changedRows, values, predicates);
161 if (ret != OHOS::NativeRdb::E_OK) {
162 TIME_HILOGE(TIME_MODULE_SERVICE, "Update values after RecoverDataBase failed, ret: %{public}d", ret);
163 }
164 }
165 return true;
166 }
167
Query(const OHOS::NativeRdb::AbsRdbPredicates & predicates,const std::vector<std::string> & columns)168 std::shared_ptr<OHOS::NativeRdb::ResultSet> TimeDatabase::Query(
169 const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
170 {
171 if (store_ == nullptr) {
172 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
173 return nullptr;
174 }
175 auto result = store_->Query(predicates, columns);
176 int count;
177 if (result->GetRowCount(count) == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
178 RecoverDataBase();
179 return nullptr;
180 }
181 return result;
182 }
183
Delete(const OHOS::NativeRdb::AbsRdbPredicates & predicates)184 bool TimeDatabase::Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates)
185 {
186 if (store_ == nullptr) {
187 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
188 return false;
189 }
190
191 int deletedRows = 0;
192 int ret = store_->Delete(deletedRows, predicates);
193 if (ret != OHOS::NativeRdb::E_OK) {
194 TIME_HILOGE(TIME_MODULE_SERVICE, "delete values failed, ret: %{public}d", ret);
195 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
196 return false;
197 }
198 if (!RecoverDataBase()) {
199 return false;
200 }
201 ret = store_->Delete(deletedRows, predicates);
202 if (ret != OHOS::NativeRdb::E_OK) {
203 TIME_HILOGE(TIME_MODULE_SERVICE, "Delete values after RecoverDataBase failed, ret: %{public}d", ret);
204 }
205 }
206 return true;
207 }
208
ClearDropOnReboot()209 void TimeDatabase::ClearDropOnReboot()
210 {
211 TIME_HILOGI(TIME_MODULE_SERVICE, "Clears drop_on_reboot table");
212 if (store_ == nullptr) {
213 TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
214 return;
215 }
216 int ret = store_->ExecuteSql("DELETE FROM drop_on_reboot");
217 if (ret != OHOS::NativeRdb::E_OK) {
218 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears drop_on_reboot table failed");
219 if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
220 return;
221 }
222 if (!RecoverDataBase()) {
223 return;
224 }
225 ret = store_->ExecuteSql("DELETE FROM drop_on_reboot");
226 if (ret != OHOS::NativeRdb::E_OK) {
227 TIME_HILOGE(TIME_MODULE_SERVICE, "Clears after RecoverDataBase failed, ret: %{public}d", ret);
228 }
229 }
230 }
231
TimeDBCreateTables(OHOS::NativeRdb::RdbStore & store)232 int TimeDBCreateTables(OHOS::NativeRdb::RdbStore &store)
233 {
234 TIME_HILOGI(TIME_MODULE_SERVICE, "Creates hold_on_reboot table");
235 // Creates hold_on_reboot table.
236 int ret = store.ExecuteSql(CREATE_TIME_TIMER_HOLD_ON_REBOOT);
237 if (ret != OHOS::NativeRdb::E_OK) {
238 TIME_HILOGE(TIME_MODULE_SERVICE, "Creates hold_on_reboot table failed, ret: %{public}d", ret);
239 return ret;
240 }
241
242 TIME_HILOGI(TIME_MODULE_SERVICE, "Creates drop_on_reboot table");
243 // Creates drop_on_reboot table.
244 ret = store.ExecuteSql(CREATE_TIME_TIMER_DROP_ON_REBOOT);
245 if (ret != OHOS::NativeRdb::E_OK) {
246 TIME_HILOGE(TIME_MODULE_SERVICE, "Creates drop_on_reboot table failed, ret: %{public}d", ret);
247 return ret;
248 }
249 return ret;
250 }
251
OnCreate(OHOS::NativeRdb::RdbStore & store)252 int TimeDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
253 {
254 TIME_HILOGI(TIME_MODULE_SERVICE, "OnCreate");
255 auto initRet = TimeDBCreateTables(store);
256 if (initRet != OHOS::NativeRdb::E_OK) {
257 TIME_HILOGE(TIME_MODULE_SERVICE, "Init database failed: %{public}d", initRet);
258 return initRet;
259 }
260 return OHOS::NativeRdb::E_OK;
261 }
262
OnOpen(OHOS::NativeRdb::RdbStore & store)263 int TimeDBOpenCallback::OnOpen(OHOS::NativeRdb::RdbStore &store)
264 {
265 return OHOS::NativeRdb::E_OK;
266 }
267
OnUpgrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)268 int TimeDBOpenCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
269 {
270 if (oldVersion < DATABASE_OPEN_VERSION_2 && newVersion >= DATABASE_OPEN_VERSION_2) {
271 int ret = store.ExecuteSql(HOLD_ON_REBOOT_ADD_PID_COLUMN);
272 if (ret != OHOS::NativeRdb::E_OK) {
273 TIME_HILOGE(TIME_MODULE_SERVICE, "hold_on_reboot add column failed, ret: %{public}d", ret);
274 return ret;
275 }
276 ret = store.ExecuteSql(DROP_ON_REBOOT_ADD_PID_COLUMN);
277 if (ret != OHOS::NativeRdb::E_OK) {
278 TIME_HILOGE(TIME_MODULE_SERVICE, "drop_on_reboot add column failed, ret: %{public}d", ret);
279 return ret;
280 }
281 }
282 if (oldVersion < DATABASE_OPEN_VERSION_3 && newVersion >= DATABASE_OPEN_VERSION_3) {
283 int ret = store.ExecuteSql(HOLD_ON_REBOOT_ADD_NAME_COLUMN);
284 if (ret != OHOS::NativeRdb::E_OK) {
285 TIME_HILOGE(TIME_MODULE_SERVICE, "hold_on_reboot add column failed, ret: %{public}d", ret);
286 return ret;
287 }
288 ret = store.ExecuteSql(DROP_ON_REBOOT_ADD_NAME_COLUMN);
289 if (ret != OHOS::NativeRdb::E_OK) {
290 TIME_HILOGE(TIME_MODULE_SERVICE, "drop_on_reboot add column failed, ret: %{public}d", ret);
291 return ret;
292 }
293 }
294 return OHOS::NativeRdb::E_OK;
295 }
296
OnDowngrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)297 int TimeDBOpenCallback::OnDowngrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
298 {
299 return OHOS::NativeRdb::E_OK;
300 }
301 }
302 }