1 /*
2  * Copyright (C) 2021 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 #define MLOG_TAG "Distributed"
16 
17 #include <map>
18 
19 #include "medialibrary_device_operations.h"
20 #include "media_device_column.h"
21 #include "media_file_utils.h"
22 #include "media_log.h"
23 #include "medialibrary_errno.h"
24 #include "result_set_utils.h"
25 #include "media_column.h"
26 
27 using namespace std;
28 using namespace OHOS::NativeRdb;
29 
30 namespace OHOS {
31 namespace Media {
32 static const int64_t AGING_DEVICE_INTERVAL = 14 * 24 * 60 * 60LL;
33 
34 static const map<string, string> TABLE_SYNC_STATUS_MAP = {
35     { MEDIALIBRARY_TABLE, DEVICE_DB_SYNC_STATUS },
36     { PhotoColumn::PHOTOS_TABLE, DEVICE_DB_PHOTO_SYNC_STATUS }
37     // AudiosTable and DocumentsTable is not synchronized yet
38 };
39 
InsertDeviceInfo(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const OHOS::Media::MediaLibraryDeviceInfo & deviceInfo,const std::string & bundleName)40 bool MediaLibraryDeviceOperations::InsertDeviceInfo(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
41     const OHOS::Media::MediaLibraryDeviceInfo &deviceInfo, const std::string &bundleName)
42 {
43     if (rdbStore == nullptr) {
44         MEDIA_ERR_LOG("rdbstore is nullptr");
45         return false;
46     }
47     std::vector<std::string> columns;
48     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
49     absPredDevice.EqualTo(DEVICE_DB_UDID, deviceInfo.deviceUdid);
50     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
51 
52     auto count = 0;
53     auto ret = queryResultSet->GetRowCount(count);
54     MEDIA_INFO_LOG("MediaLibraryDeviceOperations::InsertDeviceInfo ret = %{public}d, count = %{public}d", ret, count);
55     if (ret == NativeRdb::E_OK) {
56         if (count > 0) {
57             // 更新数据库
58             ValuesBucket valuesBucket;
59             valuesBucket.PutString(DEVICE_DB_UDID, deviceInfo.deviceUdid);
60             valuesBucket.PutString(DEVICE_DB_NETWORK_ID, deviceInfo.networkId);
61             valuesBucket.PutInt(DEVICE_DB_SYNC_STATUS, 0);
62             valuesBucket.PutInt(DEVICE_DB_PHOTO_SYNC_STATUS, 0);
63             valuesBucket.PutLong(DEVICE_DB_DATE_MODIFIED, 0);
64             return MediaLibraryDeviceDb::UpdateDeviceInfo(valuesBucket, rdbStore) == E_SUCCESS;
65         } else {
66             // 插入数据库
67             ValuesBucket valuesBucket;
68             valuesBucket.PutString(DEVICE_DB_UDID, deviceInfo.deviceUdid);
69             valuesBucket.PutString(DEVICE_DB_NETWORK_ID, deviceInfo.networkId);
70             valuesBucket.PutString(DEVICE_DB_NAME, deviceInfo.deviceName);
71             valuesBucket.PutString(DEVICE_DB_IP, std::string());
72             valuesBucket.PutString(DEVICE_DB_SELF_ID, deviceInfo.selfId);
73             valuesBucket.PutInt(DEVICE_DB_TYPE, (int32_t) deviceInfo.deviceTypeId);
74             valuesBucket.PutString(DEVICE_DB_PREPATH, std::string());
75             int64_t now = MediaFileUtils::UTCTimeSeconds();
76             valuesBucket.PutLong(DEVICE_DB_DATE_ADDED, now);
77             return MediaLibraryDeviceDb::InsertDeviceInfo(valuesBucket, rdbStore) >= 0;
78         }
79     }
80     return false;
81 }
82 
UpdateDeviceInfo(const shared_ptr<MediaLibraryRdbStore> rdbStore,const OHOS::Media::MediaLibraryDeviceInfo & deviceInfo,const std::string & bundleName)83 bool MediaLibraryDeviceOperations::UpdateDeviceInfo(const shared_ptr<MediaLibraryRdbStore> rdbStore,
84     const OHOS::Media::MediaLibraryDeviceInfo &deviceInfo, const std::string &bundleName)
85 {
86     std::vector<std::string> columns;
87     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
88     absPredDevice.EqualTo(DEVICE_DB_UDID, deviceInfo.deviceUdid);
89     MEDIA_INFO_LOG("MediaLibraryDeviceOperations::UpdateDeviceInfo dev");
90     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
91 
92     auto count = 0;
93     auto ret = queryResultSet->GetRowCount(count);
94     if (ret == NativeRdb::E_OK) {
95         if (count > 0) {
96             // 更新数据库
97             ValuesBucket valuesBucket;
98             valuesBucket.PutString(DEVICE_DB_UDID, deviceInfo.deviceUdid);
99             valuesBucket.PutString(DEVICE_DB_NETWORK_ID, deviceInfo.networkId);
100             int idx = -1;
101             ret = queryResultSet->GoToFirstRow();
102             if (ret != NativeRdb::E_OK) {
103                 return false;
104             }
105 
106             ret = queryResultSet->GetColumnIndex(DEVICE_DB_DATE_MODIFIED, idx);
107             if (ret != NativeRdb::E_OK) {
108                 return false;
109             }
110 
111             int64_t modifiedTime = 0;
112             queryResultSet->GetLong(idx, modifiedTime);
113             if (modifiedTime == 0) {
114                 int64_t now = MediaFileUtils::UTCTimeSeconds();
115                 valuesBucket.PutLong(DEVICE_DB_DATE_MODIFIED, now);
116             }
117             return MediaLibraryDeviceDb::UpdateDeviceInfo(valuesBucket, rdbStore) == E_SUCCESS;
118         }
119     }
120     return false;
121 }
122 
DeleteDeviceInfo(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & udid)123 bool MediaLibraryDeviceOperations::DeleteDeviceInfo(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
124     const std::string &udid)
125 {
126     return MediaLibraryDeviceDb::DeleteDeviceInfo(udid, rdbStore);
127 }
128 
UpdateSyncStatus(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & tableName,const std::string & udid,int32_t syncStatus)129 bool MediaLibraryDeviceOperations::UpdateSyncStatus(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
130     const std::string &tableName, const std::string &udid, int32_t syncStatus)
131 {
132     std::vector<std::string> columns;
133     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
134 
135     absPredDevice.EqualTo(DEVICE_DB_UDID, udid);
136     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
137 
138     auto count = 0;
139     auto ret = queryResultSet->GetRowCount(count);
140     if (ret == NativeRdb::E_OK) {
141         if (count > 0) {
142             // 更新数据库
143             ValuesBucket valuesBucket;
144             valuesBucket.PutString(DEVICE_DB_UDID, udid);
145             if (TABLE_SYNC_STATUS_MAP.find(tableName) != TABLE_SYNC_STATUS_MAP.end()) {
146                 valuesBucket.PutInt(TABLE_SYNC_STATUS_MAP.at(tableName), syncStatus);
147             }
148             MEDIA_INFO_LOG("MediaLibraryDeviceOperations::UpdateSyncStatus");
149             return MediaLibraryDeviceDb::UpdateDeviceInfo(valuesBucket, rdbStore) == E_SUCCESS;
150         }
151     }
152     return false;
153 }
154 
GetSyncStatusById(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,const std::string & udid,const std::string & table,int32_t & syncStatus)155 bool MediaLibraryDeviceOperations::GetSyncStatusById(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
156     const std::string &udid, const std::string &table, int32_t &syncStatus)
157 {
158     std::vector<std::string> columns;
159     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
160 
161     absPredDevice.EqualTo(DEVICE_DB_UDID, udid);
162     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
163     if (queryResultSet == nullptr || queryResultSet->GoToFirstRow() != NativeRdb::E_OK) {
164         MEDIA_ERR_LOG("Query device by udid failed");
165         return false;
166     }
167 
168     if (TABLE_SYNC_STATUS_MAP.find(table) != TABLE_SYNC_STATUS_MAP.end()) {
169         int32_t columnIndexId = 0;
170         queryResultSet->GetColumnIndex(TABLE_SYNC_STATUS_MAP.at(table), columnIndexId);
171         queryResultSet->GetInt(columnIndexId, syncStatus);
172     } else {
173         for (const auto &iter : TABLE_SYNC_STATUS_MAP) {
174             int32_t columnIndexId = 0;
175             queryResultSet->GetColumnIndex(iter.second, columnIndexId);
176             queryResultSet->GetInt(columnIndexId, syncStatus);
177             if (syncStatus == DEVICE_SYNCSTATUSING) {
178                 break;
179             }
180         }
181     }
182 
183     MEDIA_INFO_LOG("MediaLibraryDeviceOperations::GetSyncStatusById syncStatus = %{public}d", syncStatus);
184     return true;
185 }
186 
QueryDeviceTable(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,std::map<std::string,std::set<int>> & excludeMap)187 bool MediaLibraryDeviceOperations::QueryDeviceTable(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
188     std::map<std::string, std::set<int>> &excludeMap)
189 {
190     const int SHORT_UDID_LEN = 8;
191     std::vector<std::string> columns;
192     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
193     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
194     if (queryResultSet == nullptr) {
195         MEDIA_ERR_LOG("MediaLibraryDeviceOperations::QueryDeviceTable fail");
196         return false;
197     }
198 
199     if (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
200         int32_t columnIndexId;
201         std::string selfId;
202         queryResultSet->GetColumnIndex(DEVICE_DB_SELF_ID, columnIndexId);
203         queryResultSet->GetString(columnIndexId, selfId);
204         if (selfId.length() > SHORT_UDID_LEN) {
205             std::string shortUdid = selfId.substr(0, SHORT_UDID_LEN);
206             std::string randNumber = selfId.substr(SHORT_UDID_LEN);
207             if (!randNumber.empty()) {
208                 auto &data = excludeMap[shortUdid];
209                 data.insert(atoi(randNumber.c_str()));
210             }
211         }
212     }
213     return true;
214 }
215 
GetAllDeviceData(const std::shared_ptr<NativeRdb::RdbStore> & rdbStore,vector<MediaLibraryDeviceInfo> & outDeviceList)216 bool MediaLibraryDeviceOperations::GetAllDeviceData(const std::shared_ptr<NativeRdb::RdbStore> &rdbStore,
217     vector<MediaLibraryDeviceInfo> &outDeviceList)
218 {
219     std::vector<std::string> columns;
220     AbsRdbPredicates absPredDevice(DEVICE_TABLE);
221     auto queryResultSet = rdbStore->QueryByStep(absPredDevice, columns);
222     if (queryResultSet == nullptr) {
223         MEDIA_ERR_LOG("MediaLibraryDeviceOperations::GetAllDeviceData fail");
224         return false;
225     }
226 
227     while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
228         MediaLibraryDeviceInfo deviceInfo;
229         deviceInfo.networkId = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_NETWORK_ID, queryResultSet,
230             TYPE_STRING));
231         deviceInfo.deviceTypeId = static_cast<DistributedHardware::DmDeviceType>(get<int32_t>(
232             ResultSetUtils::GetValFromColumn(DEVICE_DB_TYPE, queryResultSet, TYPE_INT32)));
233         deviceInfo.deviceUdid = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_UDID, queryResultSet,
234             TYPE_STRING));
235         deviceInfo.selfId = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_SELF_ID, queryResultSet,
236             TYPE_STRING));
237         outDeviceList.push_back(deviceInfo);
238     }
239     return true;
240 }
241 
GetAgingDeviceData(const shared_ptr<RdbStore> & rdbStore,vector<MediaLibraryDeviceInfo> & outDeviceList)242 bool MediaLibraryDeviceOperations::GetAgingDeviceData(const shared_ptr<RdbStore> &rdbStore,
243     vector<MediaLibraryDeviceInfo> &outDeviceList)
244 {
245     vector<string> columns;
246     int64_t agingTime = MediaFileUtils::UTCTimeSeconds() - AGING_DEVICE_INTERVAL;
247 
248     MEDIA_INFO_LOG("GetAgingDeviceData less than %{public}" PRId64, agingTime);
249     AbsRdbPredicates absPredevice(DEVICE_TABLE);
250     absPredevice.GreaterThan(DEVICE_DB_DATE_MODIFIED, to_string(0))->And()->
251         LessThan(DEVICE_DB_DATE_MODIFIED, to_string(agingTime));
252     auto queryResultSet = rdbStore->QueryByStep(absPredevice, columns);
253     if (queryResultSet == nullptr) {
254         MEDIA_ERR_LOG("GetAgingDeviceData fail");
255         return false;
256     }
257     auto ret = queryResultSet->GoToFirstRow();
258     if (ret != NativeRdb::E_OK) {
259         MEDIA_ERR_LOG("Failed to fetch first record, ret = %{public}d", ret);
260         return false;
261     }
262 
263     MediaLibraryDeviceInfo deviceInfo;
264     do {
265         deviceInfo.networkId = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_NETWORK_ID, queryResultSet,
266             TYPE_STRING));
267         deviceInfo.deviceTypeId = (DistributedHardware::DmDeviceType)(get<int32_t>(ResultSetUtils::GetValFromColumn(
268             DEVICE_DB_TYPE, queryResultSet, TYPE_INT32)));
269         deviceInfo.deviceUdid = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_UDID, queryResultSet,
270             TYPE_STRING));
271         deviceInfo.selfId = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_SELF_ID, queryResultSet,
272             TYPE_STRING));
273         outDeviceList.push_back(deviceInfo);
274     } while (queryResultSet->GoToNextRow() == NativeRdb::E_OK);
275 
276     MEDIA_ERR_LOG("GetAgingDeviceData OUT, deviceSize = %{public}d", static_cast<int>(outDeviceList.size()));
277     return true;
278 }
279 
GetAllDeviceUdid(const shared_ptr<RdbStore> & rdbStore,vector<string> & deviceUdids)280 bool MediaLibraryDeviceOperations::GetAllDeviceUdid(const shared_ptr<RdbStore> &rdbStore,
281     vector<string> &deviceUdids)
282 {
283     vector<string> columns;
284     AbsRdbPredicates absPreDevice(DEVICE_TABLE);
285     auto queryResultSet = rdbStore->QueryByStep(absPreDevice, columns);
286     if (queryResultSet == nullptr) {
287         MEDIA_ERR_LOG("MediaLibraryDeviceOperations::GetAllDeviceUdid fail");
288         return false;
289     }
290     auto ret = queryResultSet->GoToFirstRow();
291     if (ret != NativeRdb::E_OK) {
292         return true;
293     }
294     do {
295         string udid = get<string>(ResultSetUtils::GetValFromColumn(DEVICE_DB_UDID, queryResultSet,
296             TYPE_STRING));
297         deviceUdids.push_back(udid);
298     } while (queryResultSet->GoToNextRow() == NativeRdb::E_OK);
299 
300     MEDIA_DEBUG_LOG("MediaLibraryDeviceOperations::GetAllDeviceUdid OUT");
301     return true;
302 }
303 } // namespace Media
304 } // namespace OHOS
305