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 "ipc/cloud_sync_service.h"
16
17 #include <memory>
18
19 #include "system_ability_definition.h"
20
21 #include "dfs_error.h"
22 #include "dfsu_access_token_helper.h"
23 #include "ipc/cloud_sync_callback_manager.h"
24 #include "meta_file.h"
25 #include "sync_rule/battery_status.h"
26 #include "sync_rule/cloud_status.h"
27 #include "sync_rule/net_conn_callback_observer.h"
28 #include "sync_rule/network_status.h"
29 #include "utils_log.h"
30 #include "directory_ex.h"
31 #include "sdk_helper.h"
32
33 namespace OHOS::FileManagement::CloudSync {
34 using namespace std;
35 using namespace OHOS;
36
37 const string GALLERY_BUNDLE_NAME = "com.ohos.photos";
38
39 REGISTER_SYSTEM_ABILITY_BY_ID(CloudSyncService, FILEMANAGEMENT_CLOUD_SYNC_SERVICE_SA_ID, false);
40
CloudSyncService(int32_t saID,bool runOnCreate)41 CloudSyncService::CloudSyncService(int32_t saID, bool runOnCreate) : SystemAbility(saID, runOnCreate)
42 {
43 dataSyncManager_ = make_shared<DataSyncManager>();
44 batteryStatusListener_ = make_shared<BatteryStatusListener>(dataSyncManager_);
45 }
46
PublishSA()47 void CloudSyncService::PublishSA()
48 {
49 LOGI("Begin to init");
50 if (!SystemAbility::Publish(this)) {
51 throw runtime_error(" Failed to publish the daemon");
52 }
53 LOGI("Init finished successfully");
54 }
55
Init()56 void CloudSyncService::Init()
57 {
58 NetworkStatus::InitNetwork(dataSyncManager_);
59 /* Get Init Charging status */
60 BatteryStatus::GetInitChargingStatus();
61 }
62
GetHmdfsPath(const std::string & uri,int32_t userId)63 std::string CloudSyncService::GetHmdfsPath(const std::string &uri, int32_t userId)
64 {
65 const std::string HMDFS_DIR = "/mnt/hmdfs/";
66 const std::string DATA_DIR = "/account/device_view/local/data/";
67 const std::string FILE_DIR = "data/storage/el2/distributedfiles/";
68 const std::string URI_PREFIX = "://";
69 if (uri.empty()) {
70 return "";
71 }
72
73 std::string bundleName;
74 size_t uriPrefixPos = uri.find(URI_PREFIX);
75 if (uriPrefixPos == std::string::npos) {
76 return "";
77 }
78 uriPrefixPos += URI_PREFIX.length();
79 size_t bundleNameEndPos = uri.find('/', uriPrefixPos);
80 if (bundleNameEndPos == std::string::npos) {
81 return "";
82 }
83 bundleName = uri.substr(uriPrefixPos, bundleNameEndPos - uriPrefixPos);
84
85 std::string relativePath;
86 size_t fileDirPos = uri.find(FILE_DIR);
87 if (fileDirPos == std::string::npos) {
88 return "";
89 }
90 fileDirPos += FILE_DIR.length();
91 relativePath = uri.substr(fileDirPos);
92
93 std::string outputPath = HMDFS_DIR + std::to_string(userId) + DATA_DIR + bundleName + "/" + relativePath;
94 std::string dir = outputPath.substr(0, outputPath.find_last_of('/'));
95
96 ForceCreateDirectory(dir);
97 return outputPath;
98 }
99
OnStart()100 void CloudSyncService::OnStart()
101 {
102 Init();
103 LOGI("Begin to start service");
104 try {
105 PublishSA();
106 AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
107 } catch (const exception &e) {
108 LOGE("%{public}s", e.what());
109 }
110 LOGI("Start service successfully");
111 }
112
OnStop()113 void CloudSyncService::OnStop()
114 {
115 LOGI("Stop finished successfully");
116 }
117
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)118 void CloudSyncService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
119 {
120 LOGI("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId);
121 batteryStatusListener_->Start();
122 }
123
UnRegisterCallbackInner()124 int32_t CloudSyncService::UnRegisterCallbackInner()
125 {
126 string bundleName;
127 if (DfsuAccessTokenHelper::GetCallerBundleName(bundleName)) {
128 return E_INVAL_ARG;
129 }
130
131 CloudSyncCallbackManager::GetInstance().RemoveCallback(bundleName);
132 return E_OK;
133 }
134
RegisterCallbackInner(const sptr<IRemoteObject> & remoteObject)135 int32_t CloudSyncService::RegisterCallbackInner(const sptr<IRemoteObject> &remoteObject)
136 {
137 if (remoteObject == nullptr) {
138 LOGE("remoteObject is nullptr");
139 return E_INVAL_ARG;
140 }
141
142 string bundleName;
143 if (DfsuAccessTokenHelper::GetCallerBundleName(bundleName)) {
144 return E_INVAL_ARG;
145 }
146
147 auto callback = iface_cast<ICloudSyncCallback>(remoteObject);
148 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
149 CloudSyncCallbackManager::GetInstance().AddCallback(bundleName, callerUserId, callback);
150 dataSyncManager_->RegisterCloudSyncCallback(GALLERY_BUNDLE_NAME, callerUserId);
151 return E_OK;
152 }
153
StartSyncInner(bool forceFlag)154 int32_t CloudSyncService::StartSyncInner(bool forceFlag)
155 {
156 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
157 return dataSyncManager_->TriggerStartSync(GALLERY_BUNDLE_NAME, callerUserId, forceFlag,
158 SyncTriggerType::APP_TRIGGER);
159 }
160
StopSyncInner()161 int32_t CloudSyncService::StopSyncInner()
162 {
163 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
164 return dataSyncManager_->TriggerStopSync(GALLERY_BUNDLE_NAME, callerUserId, SyncTriggerType::APP_TRIGGER);
165 }
166
ChangeAppSwitch(const std::string & accoutId,const std::string & bundleName,bool status)167 int32_t CloudSyncService::ChangeAppSwitch(const std::string &accoutId, const std::string &bundleName, bool status)
168 {
169 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
170
171 /* update app switch status */
172 auto ret = CloudStatus::ChangeAppSwitch(bundleName, callerUserId, status);
173 if (ret != E_OK) {
174 return ret;
175 }
176
177 if (status) {
178 return dataSyncManager_->TriggerStartSync(bundleName, callerUserId, false, SyncTriggerType::CLOUD_TRIGGER);
179 }
180 return dataSyncManager_->TriggerStopSync(bundleName, callerUserId, SyncTriggerType::CLOUD_TRIGGER);
181 }
182
NotifyDataChange(const std::string & accoutId,const std::string & bundleName)183 int32_t CloudSyncService::NotifyDataChange(const std::string &accoutId, const std::string &bundleName)
184 {
185 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
186 return dataSyncManager_->TriggerStartSync(bundleName, callerUserId, false, SyncTriggerType::CLOUD_TRIGGER);
187 }
188
DisableCloud(const std::string & accoutId)189 int32_t CloudSyncService::DisableCloud(const std::string &accoutId)
190 {
191 return E_OK;
192 }
193
EnableCloud(const std::string & accoutId,const SwitchDataObj & switchData)194 int32_t CloudSyncService::EnableCloud(const std::string &accoutId, const SwitchDataObj &switchData)
195 {
196 return E_OK;
197 }
198
Clean(const std::string & accountId,const CleanOptions & cleanOptions)199 int32_t CloudSyncService::Clean(const std::string &accountId, const CleanOptions &cleanOptions)
200 {
201 LOGD("Clean accountId is: %{public}s", accountId.c_str());
202 for (auto &iter : cleanOptions.appActionsData) {
203 LOGD("Clean key is: %s, value is: %d", iter.first.c_str(), iter.second);
204 }
205
206 MetaFileMgr::GetInstance().ClearAll();
207 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
208 LOGD("Clean callerUserId is: %{public}d", callerUserId);
209 for (auto iter = cleanOptions.appActionsData.begin(); iter != cleanOptions.appActionsData.end(); ++iter) {
210 dataSyncManager_->CleanCloudFile(callerUserId, iter->first, iter->second);
211 }
212
213 return E_OK;
214 }
215
216 constexpr int TEST_MAIN_USR_ID = 100;
StartDownloadFile(const std::string & path)217 int32_t CloudSyncService::StartDownloadFile(const std::string &path)
218 {
219 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
220 LOGI("start StartDownloadFile");
221 if (callerUserId == 0) {
222 callerUserId = TEST_MAIN_USR_ID; // for root user change id to main user for test
223 }
224 return dataSyncManager_->StartDownloadFile(GALLERY_BUNDLE_NAME, callerUserId, path);
225 }
226
StopDownloadFile(const std::string & path)227 int32_t CloudSyncService::StopDownloadFile(const std::string &path)
228 {
229 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
230 LOGI("start StopDownloadFile");
231 if (callerUserId == 0) {
232 callerUserId = TEST_MAIN_USR_ID; // for root user change id to main user for test
233 }
234 return dataSyncManager_->StopDownloadFile(GALLERY_BUNDLE_NAME, callerUserId, path);
235 }
236
RegisterDownloadFileCallback(const sptr<IRemoteObject> & downloadCallback)237 int32_t CloudSyncService::RegisterDownloadFileCallback(const sptr<IRemoteObject> &downloadCallback)
238 {
239 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
240 auto downloadCb = iface_cast<ICloudDownloadCallback>(downloadCallback);
241 LOGI("start RegisterDownloadFileCallback");
242 if (callerUserId == 0) {
243 callerUserId = TEST_MAIN_USR_ID; // for root user change id to main user for test
244 }
245 return dataSyncManager_->RegisterDownloadFileCallback(GALLERY_BUNDLE_NAME, callerUserId, downloadCb);
246 }
247
UnregisterDownloadFileCallback()248 int32_t CloudSyncService::UnregisterDownloadFileCallback()
249 {
250 auto callerUserId = DfsuAccessTokenHelper::GetUserId();
251 LOGI("start UnregisterDownloadFileCallback");
252 if (callerUserId == 0) {
253 callerUserId = TEST_MAIN_USR_ID; // for root user change id to main user for test
254 }
255 return dataSyncManager_->UnregisterDownloadFileCallback(GALLERY_BUNDLE_NAME, callerUserId);
256 }
257
UploadAsset(const int32_t userId,const std::string & request,std::string & result)258 int32_t CloudSyncService::UploadAsset(const int32_t userId, const std::string &request, std::string &result)
259 {
260 auto driveKit = DriveKit::DriveKitNative::GetInstance(userId);
261 if (driveKit == nullptr) {
262 LOGE("uploadAsset get drive kit instance err");
263 return E_CLOUD_SDK;
264 }
265 return driveKit->OnUploadAsset(request, result);
266 }
267
DownloadFile(const int32_t userId,const std::string & bundleName,AssetInfoObj & assetInfoObj)268 int32_t CloudSyncService::DownloadFile(const int32_t userId, const std::string &bundleName, AssetInfoObj &assetInfoObj)
269 {
270 auto sdkHelper = std::make_shared<SdkHelper>();
271 auto ret = sdkHelper->Init(userId, bundleName);
272 if (ret != E_OK) {
273 LOGE("get sdk helper err %{public}d", ret);
274 return ret;
275 }
276
277 DriveKit::DKAsset asset;
278 asset.assetName = assetInfoObj.assetName;
279
280 asset.uri = GetHmdfsPath(assetInfoObj.uri, userId);
281 if (asset.uri.empty()) {
282 LOGE("fail to get download path from %{public}s", assetInfoObj.uri.c_str());
283 return E_INVAL_ARG;
284 }
285
286 // Not to pass the assetinfo.fieldkey
287 DriveKit::DKDownloadAsset assetsToDownload{assetInfoObj.recordType, assetInfoObj.recordId, {}, asset, {}};
288 return sdkHelper->DownloadAssets(assetsToDownload);
289 }
290 } // namespace OHOS::FileManagement::CloudSync
291