diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp index 5278c59dad5d030f0f5283c9b10200d2d1c39361..5e2fcc07197faf635e21a21467fbdac56eebfca9 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp @@ -153,7 +153,7 @@ Status DistributedKvDataManager::CloseAllKvStore(const AppId &appId) return Status::SERVER_UNAVAILABLE; } -Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId &storeId) +Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId &storeId, const std::string &path) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); @@ -173,7 +173,7 @@ Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId return Status::SERVER_UNAVAILABLE; } -Status DistributedKvDataManager::DeleteAllKvStore(const AppId &appId) +Status DistributedKvDataManager::DeleteAllKvStore(const AppId &appId, const std::string &path) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp index 3dce5cf00db127f429d8d13f0731dca3a96f8f9c..dba8e235f51b5048f9c932fd4ac8cebf15cf09bf 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/ikvstore_data_service.cpp @@ -59,7 +59,6 @@ Status KvStoreDataServiceProxy::GetSingleKvStore(const Options &options, const A optionsIpc.syncPolicy = options.syncPolicy; optionsIpc.kvStoreType = options.kvStoreType; optionsIpc.syncable = options.syncable; - optionsIpc.dataOwnership = true; // set default value std::string schemaString = options.schema; if (!data.WriteBuffer(&optionsIpc, sizeof(OptionsIpc)) || @@ -515,7 +514,6 @@ int32_t KvStoreDataServiceStub::GetSingleKvStoreOnRemote(MessageParcel &data, Me options.syncPolicy = optionsIpc.syncPolicy; options.kvStoreType = optionsIpc.kvStoreType; options.syncable = optionsIpc.syncable; - options.dataOwnership = optionsIpc.dataOwnership; options.schema = data.ReadString(); sptr proxyTmp; Status status = GetSingleKvStore(options, appId, storeId, diff --git a/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp b/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp index 20c1a811d3af5d5105f452bb9e93eb65c5da7dcb..e1b46f8dbbe64bb50428beea5d0a43392abfd756 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/src/itypes_util.cpp @@ -348,11 +348,11 @@ bool ITypesUtil::Marshalling(const Options &input, MessageParcel &data) target->persistent = input.persistent; target->backup = input.backup; target->autoSync = input.autoSync; + target->syncable = input.syncable; target->securityLevel = input.securityLevel; + target->area = input.area; target->syncPolicy = input.syncPolicy; target->kvStoreType = input.kvStoreType; - target->syncable = input.syncable; - target->dataOwnership = input.dataOwnership; return data.WriteRawData(buffer.get(), sizeof(input)); } @@ -372,10 +372,10 @@ bool ITypesUtil::Unmarshalling(Options &output, MessageParcel &data) output.backup = source->backup; output.autoSync = source->autoSync; output.securityLevel = source->securityLevel; + output.area = source->area; output.syncPolicy = source->syncPolicy; output.kvStoreType = source->kvStoreType; output.syncable = source->syncable; - output.dataOwnership = source->dataOwnership; return true; } diff --git a/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index 76551654c8257891e33c6dc616bcf3944fed8524..3d0e3dcea0b1cef49f7a24ffe1175b2b9040af10 100644 --- a/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -89,7 +89,6 @@ void DistributedKvDataManagerTest::SetUpTestCase(void) noCreate.createIfMissing = false; noCreate.encrypt = false; noCreate.autoSync = true; - noCreate.dataOwnership = true; noCreate.kvStoreType = SINGLE_VERSION; userId.userId = "account0"; diff --git a/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h b/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h index cb42aea52b4262948e2c7be930ce992d1b8d5973..35ef01dbaddd021d9b667b7a2c96041c0585b6ab 100644 --- a/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h +++ b/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h @@ -18,6 +18,7 @@ #include "kv_store_nb_delegate.h" #include "kv_store_observer.h" #include "kvstore_observer.h" +#include "kvstore_observer_client.h" #include "visibility.h" namespace OHOS::DistributedKv { class IKvStoreObserver; @@ -36,6 +37,16 @@ public: void OnChange(const DBChangedData &data) override; private: + class ObserverClient : public KvStoreObserverClient { + public: + ObserverClient(std::shared_ptr observer, Convert &convert); + void OnChange(const ChangeNotification &changeNotification) override; + + private: + std::vector ConvertDB(const std::vector &dbEntries, std::string &deviceId) const; + Convert &convert_; + }; + std::vector ConvertDB(const std::list &dbEntries, std::string &deviceId) const; AppId appId_; StoreId storeId_; diff --git a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp index 17505a1d3fd9affdba809ecd2e908b04631963be..755b720da66e99382e38c5888e99e1a4c3faeb19 100644 --- a/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp @@ -45,7 +45,7 @@ Status ObserverBridge::RegisterRemoteObserver() return SERVER_UNAVAILABLE; } - remote_ = new (std::nothrow) KvStoreObserverClient(observer_); + remote_ = new (std::nothrow) ObserverClient(observer_, convert_); return service->Subscribe(appId_, storeId_, remote_); } @@ -68,12 +68,47 @@ Status ObserverBridge::UnregisterRemoteObserver() void ObserverBridge::OnChange(const DBChangedData &data) { std::string deviceId; - ChangeNotification notice(ConvertDB(data.GetEntriesInserted(), deviceId), - ConvertDB(data.GetEntriesUpdated(), deviceId), ConvertDB(data.GetEntriesDeleted(), deviceId), deviceId, false); - + auto inserted = ConvertDB(data.GetEntriesInserted(), deviceId); + auto updated = ConvertDB(data.GetEntriesUpdated(), deviceId); + auto deleted = ConvertDB(data.GetEntriesDeleted(), deviceId); + ChangeNotification notice(std::move(inserted), std::move(updated), std::move(deleted), deviceId, false); observer_->OnChange(notice); } +ObserverBridge::ObserverClient::ObserverClient(std::shared_ptr observer, Convert &convert) + : KvStoreObserverClient(observer), convert_(convert) +{ +} + +void ObserverBridge::ObserverClient::OnChange(const ChangeNotification &data) +{ + if (convert_ == nullptr) { + KvStoreObserverClient::OnChange(data); + return; + } + + std::string deviceId; + auto inserted = ConvertDB(data.GetInsertEntries(), deviceId); + auto updated = ConvertDB(data.GetInsertEntries(), deviceId); + auto deleted = ConvertDB(data.GetInsertEntries(), deviceId); + ChangeNotification notice(std::move(inserted), std::move(updated), std::move(deleted), deviceId, false); + KvStoreObserverClient::OnChange(notice); +} + +std::vector ObserverBridge::ObserverClient::ConvertDB(const std::vector &dbEntries, + std::string &deviceId) const +{ + std::vector entries(dbEntries.size()); + auto it = entries.begin(); + for (const auto &dbEntry : dbEntries) { + Entry &entry = *it; + entry.key = convert_ ? convert_(dbEntry.key, deviceId) : Key(dbEntry.key); + entry.value = dbEntry.value; + ++it; + } + return entries; +} + std::vector ObserverBridge::ConvertDB(const std::list &dbEntries, std::string &deviceId) const { std::vector entries(dbEntries.size()); diff --git a/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index f74c3fbcd6414ef965c4eff7950565f49b704789..e649708129ebfc6b808caa7773c7346c0ee72966 100644 --- a/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -664,10 +664,7 @@ std::vector SingleStoreImpl::GetPrefix(const DataQuery &query) const SingleStoreImpl::Convert SingleStoreImpl::GetConvert() const { - return [](const DBKey &key, std::string &deviceId) { - deviceId = ""; - return Key(key); - }; + return nullptr; } Status SingleStoreImpl::DoSync(const SyncInfo &syncInfo, std::shared_ptr observer) diff --git a/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 61b571a643b48f88b0a55bfa62588188ac0cfb21..745d1355caf2393eee2cf4116520da24f186a453 100644 --- a/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -138,7 +138,7 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D } dbOption.schema = options.schema; - dbOption.createDirByStoreIdOnly = options.dataOwnership; + dbOption.createDirByStoreIdOnly = true; dbOption.secOption = StoreUtil::GetDBSecurity(options.securityLevel); return dbOption; } diff --git a/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h b/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h index d2456a4628e97b66c0e6a3fe4a34c275e57c5396..1f644da9d91fffdcc7db0f619db6c400809248e0 100644 --- a/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h +++ b/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h @@ -90,10 +90,10 @@ public: // Parameters: // appId: the name of the application. // storeId: the name of the kvstore. - API_EXPORT Status DeleteKvStore(const AppId &appId, const StoreId &storeId); + API_EXPORT Status DeleteKvStore(const AppId &appId, const StoreId &storeId, const std::string &path = ""); // delete all kvstore. - API_EXPORT Status DeleteAllKvStore(const AppId &appId); + API_EXPORT Status DeleteAllKvStore(const AppId &appId, const std::string &path = ""); API_EXPORT void RegisterKvStoreServiceDeathRecipient(std::shared_ptr deathRecipient); diff --git a/interfaces/innerkits/distributeddata/include/types.h b/interfaces/innerkits/distributeddata/include/types.h index c6828bf183782d49d681ca685f17b5ec18bc1f89..90cfcfc2414897913ca2d86745e798a7e14b12d3 100644 --- a/interfaces/innerkits/distributeddata/include/types.h +++ b/interfaces/innerkits/distributeddata/include/types.h @@ -242,13 +242,13 @@ struct Options { bool persistent = true; bool backup = true; bool autoSync = true; + bool syncable = true; // let bms delete first int32_t securityLevel = NO_LABEL; int32_t area = EL1; SyncPolicy syncPolicy = SyncPolicy::HIGH; KvStoreType kvStoreType = DEVICE_COLLABORATION; - bool syncable = true; // let bms delete first std::string schema = ""; - bool dataOwnership = true; // true indicates the ownership of distributed data is DEVICE, otherwise, ACCOUNT + std::string baseDir = ""; inline bool IsValidType() const { diff --git a/services/distributeddataservice/app/src/dump_helper.h b/services/distributeddataservice/app/src/dump_helper.h index 77de756b3491557af5ea16aefb7f48121e0bd34a..c5fb314cf366531737ce94604b3ca7b9cc1ba848 100644 --- a/services/distributeddataservice/app/src/dump_helper.h +++ b/services/distributeddataservice/app/src/dump_helper.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "store_errno.h" #include "singleton.h" diff --git a/services/distributeddataservice/app/src/kvstore_app_manager.cpp b/services/distributeddataservice/app/src/kvstore_app_manager.cpp index 95d0571d29cdd0b57fa4b9c64769adffe6f3f6b1..9853927970d08a0ed5387dc77ce3c8ee1346b6f4 100644 --- a/services/distributeddataservice/app/src/kvstore_app_manager.cpp +++ b/services/distributeddataservice/app/src/kvstore_app_manager.cpp @@ -298,7 +298,7 @@ Status KvStoreAppManager::InitNbDbOption(const Options &options, const std::vect } dbOption.schema = options.schema; - dbOption.createDirByStoreIdOnly = options.dataOwnership; + dbOption.createDirByStoreIdOnly = true; dbOption.secOption = ConvertSecurity(options.securityLevel); return Status::SUCCESS; } diff --git a/services/distributeddataservice/app/src/kvstore_data_service.cpp b/services/distributeddataservice/app/src/kvstore_data_service.cpp index 89370e6903501cf22d72929aeac992902e7b00be..cae5b6c83250f18a81da21a87f653acd87c9afee 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -875,7 +875,11 @@ void KvStoreDataService::StartService() } auto autoLaunchRequestCallback = [this](const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) -> bool { - return ResolveAutoLaunchParamByIdentifier(identifier, param); + auto status = ResolveAutoLaunchParamByIdentifier(identifier, param); + if (kvdbService_) { + kvdbService_->ResolveAutoLaunch(identifier, param); + } + return status; }; KvStoreDelegateManager::SetAutoLaunchRequestCallback(autoLaunchRequestCallback); @@ -996,7 +1000,6 @@ void KvStoreDataService::ResolveAutoLaunchCompatible(const MetaData &meta, const .autoSync = storeMeta.isAutoSync, .securityLevel = storeMeta.securityLevel, .kvStoreType = static_cast(storeMeta.kvStoreType), - .dataOwnership = true, }; DistributedDB::KvStoreNbDelegate::Option dbOptions; KvStoreAppManager::InitNbDbOption(options, meta.secretKeyMetaData.secretKey, dbOptions); diff --git a/services/distributeddataservice/app/src/kvstore_meta_manager.h b/services/distributeddataservice/app/src/kvstore_meta_manager.h index a9ce153ac2ec090e6d2e0174d6e11596e1dfa652..58ef4d36432006b3e170810adab080e76fc9a29e 100644 --- a/services/distributeddataservice/app/src/kvstore_meta_manager.h +++ b/services/distributeddataservice/app/src/kvstore_meta_manager.h @@ -200,12 +200,10 @@ public: Status WriteSecretKeyToFile(const std::string &secretKeyFile, const std::vector &key); - Status - RemoveSecretKey(pid_t uid, const std::string &bundleName, const std::string &storeId); + Status RemoveSecretKey(pid_t uid, const std::string &bundleName, const std::string &storeId); - Status - RecoverSecretKeyFromFile(const std::string &secretKeyFile, const std::vector &metaSecretKey, - std::vector &key, bool &outdated); + Status RecoverSecretKeyFromFile(const std::string &secretKeyFile, const std::vector &metaSecretKey, + std::vector &key, bool &outdated); void ReKey(const std::string &userId, const std::string &bundleName, const std::string &storeId, int32_t pathType, sptr store); diff --git a/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp b/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp index 0d22e3dbbde75de4965763be5e5b00193ec32746..911194817fd9905e6bb5747b6001406d2071e746 100644 --- a/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp +++ b/services/distributeddataservice/app/src/kvstore_resultset_impl.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #define LOG_TAG "KvStoreResultsetImpl" +#include "kvstore_resultset_impl.h" #include + #include "dds_trace.h" #include "log_print.h" -#include "kvstore_resultset_impl.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedDataDfx; diff --git a/services/distributeddataservice/app/src/single_kvstore_impl.cpp b/services/distributeddataservice/app/src/single_kvstore_impl.cpp index f834e850744a8526298b3b80b166c991e1f551f0..1513ce44fbfb3f723002b425f282c38b01a09c9f 100644 --- a/services/distributeddataservice/app/src/single_kvstore_impl.cpp +++ b/services/distributeddataservice/app/src/single_kvstore_impl.cpp @@ -12,28 +12,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #define LOG_TAG "SingleKvStoreImpl" - #include "single_kvstore_impl.h" #include -#include "account_delegate.h" #include "auth_delegate.h" #include "backup_handler.h" #include "checker/checker_manager.h" #include "constant.h" #include "dds_trace.h" #include "device_kvstore_impl.h" -#include "kvstore_data_service.h" -#include "kvstore_utils.h" #include "ipc_skeleton.h" +#include "kvstore_utils.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" #include "permission_validator.h" #include "query_helper.h" +#include "dump_helper.h" #include "reporter.h" #include "upgrade_manager.h" -#include "metadata/meta_data_manager.h" - #define DEFAUL_RETRACT " " namespace OHOS::DistributedKv { diff --git a/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp b/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp index 406de4f4d70b9f6697b1eb0cfead46dd1ed8c691..bfbb15ecc9108a6e0cd0337e496e42df8cacb902 100644 --- a/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp +++ b/services/distributeddataservice/app/test/unittest/kvstore_backup_test.cpp @@ -85,8 +85,7 @@ void KvStoreBackupTest::TearDown(void) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest001, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup1" }; StoreId storeId = { "store1" }; KvStoreDataService kvDataService; @@ -107,8 +106,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest001, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest002, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION }; AppId appId = { "backup2" }; StoreId storeId = { "store2" }; @@ -155,8 +153,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest002, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest004, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup4" }; StoreId storeId = { "store4" }; @@ -209,8 +206,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest004, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest005, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S0, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S0, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup5" }; StoreId storeId = { "store5" }; @@ -257,8 +253,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest005, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest006, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S2, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S2, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup6" }; StoreId storeId = { "store6" }; @@ -305,8 +300,7 @@ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest006, TestSize.Level1) */ HWTEST_F(KvStoreBackupTest, KvStoreBackupTest007, TestSize.Level1) { - Options options = { .createIfMissing = true, .encrypt = false, .backup = true, .autoSync = true, - .securityLevel = SecurityLevel::S4, .kvStoreType = KvStoreType::SINGLE_VERSION, .dataOwnership = true }; + Options options = { .securityLevel = SecurityLevel::S4, .kvStoreType = KvStoreType::SINGLE_VERSION}; AppId appId = { "backup7" }; StoreId storeId = { "store7" }; diff --git a/services/distributeddataservice/framework/include/utils/constant.h b/services/distributeddataservice/framework/include/utils/constant.h index 41e391eb69a53f9242e94fa0a99a27408fee9361..6d94dd3633e1c789b2e524e438d876d7b96b6f54 100644 --- a/services/distributeddataservice/framework/include/utils/constant.h +++ b/services/distributeddataservice/framework/include/utils/constant.h @@ -35,6 +35,8 @@ public: API_EXPORT static std::string Join( const std::string &prefix, const std::string &separator, std::initializer_list params); + API_EXPORT static bool IsBackground(pid_t pid); + // delete left bland in s by reference. template static void LeftTrim(T &s); diff --git a/services/distributeddataservice/framework/utils/constant.cpp b/services/distributeddataservice/framework/utils/constant.cpp index d693692dfb5105d569508825762aba01dcba133a..b6b777c4c5bb32224c7bd5425e945575ff026a6f 100644 --- a/services/distributeddataservice/framework/utils/constant.cpp +++ b/services/distributeddataservice/framework/utils/constant.cpp @@ -12,16 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "Constant" #include "utils/constant.h" + +#include #include +#include #include -#include +#include "log_print.h" namespace OHOS { namespace DistributedData { constexpr const char *Constant::KEY_SEPARATOR; - std::string Constant::Concatenate(std::initializer_list stringList) { std::string result; @@ -36,8 +38,8 @@ std::string Constant::Concatenate(std::initializer_list stringList) return result; } -std::string Constant::Join( - const std::string &prefix, const std::string &separator, std::initializer_list params) +std::string Constant::Join(const std::string &prefix, const std::string &separator, + std::initializer_list params) { std::string::size_type size = prefix.size(); for (const std::string ¶m : params) { @@ -51,5 +53,27 @@ std::string Constant::Join( } return result; } -} // namespace DistributedData -} // namespace OHOS + +bool Constant::IsBackground(pid_t pid) +{ + std::ifstream ifs("/proc/" + std::to_string(pid) + "/cgroup", std::ios::in); + ZLOGD("pid %d open %d", pid, ifs.good()); + if (!ifs.good()) { + return false; + } + + while (!ifs.eof()) { + const int MAX_LEN = 256; // enough + char buffer[MAX_LEN] = { 0 }; + ifs.getline(buffer, sizeof(buffer)); + std::string line = buffer; + + size_t pos = line.find("background"); + if (pos != std::string::npos) { + return true; + } + } + return false; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/services/distributeddataservice/service/BUILD.gn b/services/distributeddataservice/service/BUILD.gn index 5b067b6b81d556befaff9fa544bb95853ca6ca4c..5acbfdc4dfb202f1ffa2b99a965eeee7d61c0adc 100644 --- a/services/distributeddataservice/service/BUILD.gn +++ b/services/distributeddataservice/service/BUILD.gn @@ -21,6 +21,7 @@ config("module_public_config") { include_dirs = [ "bootstrap/include", "config/include", + "crypto/include", "directory/include", "kvdb", "rdb", @@ -46,6 +47,7 @@ ohos_shared_library("distributeddatasvc") { "config/src/model/global_config.cpp", "config/src/model/network_config.cpp", "config/src/model/protocol_config.cpp", + "crypto/src/crypto_manager.cpp", "directory/src/directory_manager.cpp", "kvdb/auth_delegate.cpp", "kvdb/executor_factory.cpp", @@ -53,6 +55,7 @@ ohos_shared_library("distributeddatasvc") { "kvdb/kvdb_service_stub.cpp", "kvdb/kvstore_sync_manager.cpp", "kvdb/query_helper.cpp", + "kvdb/store_cache.cpp", "kvdb/user_delegate.cpp", "object/object_manager.cpp", "object/object_service_impl.cpp", @@ -80,6 +83,7 @@ ohos_shared_library("distributeddatasvc") { "access_token:libaccesstoken_sdk", "deviceauth_standard:deviceauth_sdk", "hiviewdfx_hilog_native:libhilog", + "huks:libhukssdk", "ipc:ipc_core", ] subsystem_name = "distributeddatamgr" diff --git a/services/distributeddataservice/service/crypto/include/crypto_manager.h b/services/distributeddataservice/service/crypto/include/crypto_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..db049ee785c4a7f995e68808fffa63a34c680975 --- /dev/null +++ b/services/distributeddataservice/service/crypto/include/crypto_manager.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#include +#include +namespace OHOS::DistributedData { +class CryptoManager { +public: + static CryptoManager &GetInstance(); + int32_t GenerateRootKey(); + bool IsExistRootKey(); + std::vector Encrypt(const std::vector &key); + bool Decrypt(std::vector &source, std::vector &key); + +private: + static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; + static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; + static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; + static constexpr const char *ROOT_KEY_GENERATED = "RootKeyGenerated"; + static constexpr int KEY_SIZE = 32; + static constexpr int HOURS_PER_YEAR = (24 * 365); + CryptoManager(); + ~CryptoManager(); + std::vector vecRootKeyAlias_{}; + std::vector vecNonce_{}; + std::vector vecAad_{}; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H diff --git a/services/distributeddataservice/service/crypto/src/crypto_manager.cpp b/services/distributeddataservice/service/crypto/src/crypto_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97a0c758fc495b0ed8a27776e6bec99908157521 --- /dev/null +++ b/services/distributeddataservice/service/crypto/src/crypto_manager.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "CryptoManager" +#include "crypto_manager.h" + +#include + +#include "hks_api.h" +#include "hks_param.h" +#include "log_print.h" +#include "securec.h" +namespace OHOS::DistributedData { +CryptoManager::CryptoManager() +{ + vecRootKeyAlias_ = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); + vecNonce_ = std::vector(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE)); + vecAad_ = std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); +} +CryptoManager::~CryptoManager() +{ +} + +CryptoManager &CryptoManager::GetInstance() +{ + static CryptoManager instance; + return instance; +} + +int32_t CryptoManager::GenerateRootKey() +{ + ZLOGI("GenerateRootKey."); + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *param = nullptr; + int32_t ret = HksInitParamSet(¶m); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return ret; + } + + struct HksParam genKeyParams[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + }; + + ret = HksAddParams(param, genKeyParams, sizeof(genKeyParams) / sizeof(genKeyParams[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + + ret = HksBuildParamSet(¶m); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + + ret = HksGenerateKey(&rootKeyName, param, nullptr); + if (ret != HKS_SUCCESS) { + ZLOGE("HksGenerateKey failed with error %{public}d", ret); + HksFreeParamSet(¶m); + return ret; + } + HksFreeParamSet(¶m); + ZLOGI("GenerateRootKey Succeed."); + return HKS_SUCCESS; +} + +bool CryptoManager::IsExistRootKey() +{ + return false; +} + +std::vector CryptoManager::Encrypt(const std::vector &key) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + struct HksParam param[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + }; + ret = HksAddParams(params, param, sizeof(param) / sizeof(param[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + if (ret != HKS_SUCCESS) { + ZLOGE("HksEncrypt failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + (void)HksFreeParamSet(¶ms); + std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); + (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + return encryptedKey; +} + +bool CryptoManager::Decrypt(std::vector &source, std::vector &key) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; + struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; + + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + return false; + } + struct HksParam param[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + }; + ret = HksAddParams(params, param, sizeof(param) / sizeof(param[0])); + if (ret != HKS_SUCCESS) { + ZLOGE("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + ZLOGE("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + uint8_t plainBuf[256] = { 0 }; + struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); + if (ret != HKS_SUCCESS) { + ZLOGW("HksDecrypt failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + (void)HksFreeParamSet(¶ms); + + key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index d0d425d27ebabf83f757745ce6606e5250401f28..fdf55f555660789bdf9f35a96e235f6c3a639353 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -15,21 +15,25 @@ #define LOG_TAG "KVDBServiceImpl" #include "kvdb_service_impl.h" +#include + #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" #include "communication_provider.h" +#include "crypto_manager.h" #include "directory_manager.h" #include "ipc_skeleton.h" -#include "kvstore_sync_manager.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" +#include "utils/constant.h" #include "utils/converter.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using namespace OHOS::AppDistributedKv; using namespace OHOS::Security::AccessToken; +using system_clock = std::chrono::system_clock; KVDBServiceImpl::KVDBServiceImpl() { } @@ -58,6 +62,17 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId) return ILLEGAL_STATE; } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId](auto &key, SyncAgent &syncAgent) { + if (syncAgent.pid_ != IPCSkeleton::GetCallingPid()) { + return true; + } + syncAgent.delayTimes_.erase(storeId); + syncAgent.observers_.erase(storeId); + syncAgent.conditions_.erase(storeId); + return true; + }); + MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); auto key = SecretKeyMetaData::GetKey({ metaData.user, "default", metaData.bundleName, metaData.storeId }); MetaDataManager::GetInstance().DelMeta(key, true); @@ -66,21 +81,36 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId) Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { - return NOT_SUPPORT; + StoreMetaData metaData = GetStoreMetaData(appId, storeId); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + auto delay = GetSyncDelayTime(syncInfo.delay, storeId); + return KvStoreSyncManager::GetInstance()->AddSyncOperation(reinterpret_cast(this), delay, + std::bind(&KVDBServiceImpl::DoSync, this, metaData, syncInfo, std::placeholders::_1), + std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, std::placeholders::_1)); } Status KVDBServiceImpl::RegisterSyncCallback(const AppId &appId, sptr callback) { - syncAgents_.InsertOrAssign(IPCSkeleton::GetCallingTokenID(), std::pair{ IPCSkeleton::GetCallingPid(), callback }); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, callback](const auto &, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.callback_ = callback; + return true; + }); return SUCCESS; } Status KVDBServiceImpl::UnregisterSyncCallback(const AppId &appId) { - syncAgents_.ComputeIfPresent( - IPCSkeleton::GetCallingTokenID(), [](const auto &key, std::pair> &value) { - return !(value.first == IPCSkeleton::GetCallingPid()); - }); + syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [](const auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + value.callback_ = nullptr; + return true; + }); return SUCCESS; } @@ -92,24 +122,31 @@ Status KVDBServiceImpl::SetSyncParam(const AppId &appId, const StoreId &storeId, if (syncParam.allowedDelayMs > KvStoreSyncManager::SYNC_MAX_DELAY_MS) { return Status::INVALID_ARGUMENT; } - delayTimes_.Compute( - IPCSkeleton::GetCallingTokenID(), [&storeId, &syncParam](auto &key, std::map &values) { - values[storeId] = syncParam.allowedDelayMs; - return !values.empty(); - }); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &syncParam](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.delayTimes_[storeId] = syncParam.allowedDelayMs; + return true; + }); return SUCCESS; } Status KVDBServiceImpl::GetSyncParam(const AppId &appId, const StoreId &storeId, KvSyncParam &syncParam) { - delayTimes_.ComputeIfPresent( - IPCSkeleton::GetCallingTokenID(), [&storeId, &syncParam](auto &key, std::map &values) { - auto it = values.find(storeId); - if (it != values.end()) { - syncParam.allowedDelayMs = it->second; - } - return !values.empty(); - }); + syncParam.allowedDelayMs = 0; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId, &syncParam](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + auto it = value.delayTimes_.find(storeId); + if (it != value.delayTimes_.end()) { + syncParam.allowedDelayMs = it->second; + } + return true; + }); return SUCCESS; } @@ -151,25 +188,64 @@ Status KVDBServiceImpl::SetCapability(const AppId &appId, const StoreId &storeId return SUCCESS; } -Status KVDBServiceImpl::AddSubscribeInfo( - const AppId &appId, const StoreId &storeId, const std::vector &devices, const std::string &query) +Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &storeId, + const std::vector &devices, const std::string &query) { - return NOT_SUPPORT; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &devices, &query](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.conditions_[storeId] = { devices, query }; + return true; + }); + return SUCCESS; } -Status KVDBServiceImpl::RmvSubscribeInfo( - const AppId &appId, const StoreId &storeId, const std::vector &devices, const std::string &query) +Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, + const std::vector &devices, const std::string &query) { - return NOT_SUPPORT; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &devices, &query](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + value.conditions_.erase(storeId); + return true; + }); + return SUCCESS; } Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [&appId, &storeId, &observer](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + value.ReInit(IPCSkeleton::GetCallingPid(), appId); + } + auto it = value.observers_.find(storeId); + if (it == value.observers_.end()) { + value.observers_[storeId] = std::make_shared(); + } + value.observers_[storeId]->insert(observer); + return true; + }); return SUCCESS; } Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.ComputeIfPresent(tokenId, [&storeId, &observer](auto &key, SyncAgent &value) { + if (value.pid_ != IPCSkeleton::GetCallingPid()) { + return false; + } + auto it = value.observers_.find(storeId); + if (it != value.observers_.end()) { + it->second->erase(observer); + } + return true; + }); return SUCCESS; } @@ -178,28 +254,72 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, return SUCCESS; } -Status KVDBServiceImpl::AfterCreate( - const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) +Status KVDBServiceImpl::AfterCreate(const AppId &appId, const StoreId &storeId, const Options &options, + const std::vector &password) { if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { return INVALID_ARGUMENT; } StoreMetaData metaData = GetStoreMetaData(appId, storeId); + AddOptions(options, metaData); StoreMetaData oldMeta; MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta); if (oldMeta == metaData) { return SUCCESS; } - AddOptions(options, metaData); - return NOT_SUPPORT; + // implement update + + MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + if (metaData.isEncrypt) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(password); + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + auto storeKey = SecretKeyMetaData::GetKey({ metaData.user, "default", metaData.bundleName, metaData.storeId }); + MetaDataManager::GetInstance().SaveMeta(storeKey, secretKey, true); + } + return SUCCESS; } Status KVDBServiceImpl::AppExit(pid_t uid, pid_t pid, uint32_t tokenId, const AppId &appId) { - dataObservers_.ComputeIfPresent(tokenId, [pid](const auto &, auto &value) { return !(value.first == pid); }); - syncAgents_.ComputeIfPresent(tokenId, [pid](const auto &, auto &value) { return !(value.first == pid); }); - delayTimes_.Erase(tokenId); + syncAgents_.ComputeIfPresent(tokenId, [pid](auto &, auto &value) { return (value.pid_ == pid); }); + return SUCCESS; +} + +Status KVDBServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m) +{ + std::vector metaData; + auto prefix = StoreMetaData::GetPrefix( + { AppDistributedKv::CommunicationProvider::GetInstance().GetLocalDevice().uuid, param.userId, "default" }); + if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) { + ZLOGE("There is no store"); + return STORE_NOT_FOUND; + } + + for (const auto &storeMeta : metaData) { + auto storeIdentifier = DBManager::GetKvStoreIdentifier("", storeMeta.appId, storeMeta.storeId, true); + if (identifier != storeIdentifier) { + continue; + } + std::shared_ptr observers; + syncAgents_.ComputeIfPresent(storeMeta.tokenId, [&storeMeta, &observers](auto, SyncAgent &agent) { + auto it = agent.observers_.find(storeMeta.storeId); + if (it != agent.observers_.end()) { + observers = it->second; + } + return true; + }); + + if (observers == nullptr || observers->empty()) { + continue; + } + + DBStatus status; + storeCache_.GetStore(storeMeta, observers, status); + } return SUCCESS; } @@ -254,4 +374,120 @@ int32_t KVDBServiceImpl::GetInstIndex(uint32_t tokenId, const AppId &appId) } return tokenInfo.instIndex; } + +Status KVDBServiceImpl::DoSync(const StoreMetaData &metaData, const SyncInfo &syncInfo, const SyncEnd &complete) +{ + ZLOGD("start."); + std::vector uuids; + if (syncInfo.devices.empty()) { + auto remotes = AppDistributedKv::CommunicationProvider::GetInstance().GetRemoteDevices(); + for (auto &remote : remotes) { + uuids.push_back(std::move(remote.uuid)); + } + } + for (const auto &networkId : syncInfo.devices) { + auto uuid = AppDistributedKv::CommunicationProvider::GetInstance().GetDeviceInfo(networkId).uuid; + if (!uuid.empty()) { + uuids.push_back(std::move(uuid)); + } + } + if (uuids.empty()) { + ZLOGE("not found deviceIds."); + return Status::ERROR; + } + DistributedDB::DBStatus status; + auto store = storeCache_.GetStore(metaData, nullptr, status); + if (store == nullptr) { + return ConvertDbStatus(status); + } + status = store->Sync(uuids, static_cast(syncInfo.mode), complete); + return ConvertDbStatus(status); +} + +Status KVDBServiceImpl::DoComplete(const StoreMetaData &metaData, const SyncInfo &syncInfo, const DBResult &dbResult) +{ + if (syncInfo.seqId == std::numeric_limits::max()) { + return SUCCESS; + } + sptr callback; + syncAgents_.ComputeIfPresent(metaData.tokenId, [&callback](auto &key, SyncAgent &agent) { + callback = agent.callback_; + return true; + }); + if (callback == nullptr) { + return SUCCESS; + } + + std::map result; + for (auto &[key, status] : dbResult) { + result[key] = ConvertDbStatus(status); + } + callback->SyncCompleted(result, syncInfo.seqId); + return SUCCESS; +} + +uint32_t KVDBServiceImpl::GetSyncDelayTime(uint32_t delay, const StoreId &storeId) +{ + if (delay == 0) { + bool isBackground = Constant::IsBackground(IPCSkeleton::GetCallingPid()); + if (isBackground) { + delay = KvStoreSyncManager::SYNC_DEFAULT_DELAY_MS; + syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), + [&delay, &storeId](auto &key, SyncAgent &agent) { + auto it = agent.delayTimes_.find(storeId); + if (it != agent.delayTimes_.end() && it->second != 0) { + delay = it->second; + } + return true; + }); + } + } else { + if (delay < KvStoreSyncManager::SYNC_MIN_DELAY_MS) { + delay = KvStoreSyncManager::SYNC_MIN_DELAY_MS; + } + if (delay > KvStoreSyncManager::SYNC_MAX_DELAY_MS) { + delay = KvStoreSyncManager::SYNC_MAX_DELAY_MS; + } + } + return delay; +} + +Status KVDBServiceImpl::ConvertDbStatus(DBStatus status) +{ + switch (status) { + case DBStatus::BUSY: // fallthrough + case DBStatus::DB_ERROR: + return Status::DB_ERROR; + case DBStatus::OK: + return Status::SUCCESS; + case DBStatus::INVALID_ARGS: + return Status::INVALID_ARGUMENT; + case DBStatus::NOT_FOUND: + return Status::KEY_NOT_FOUND; + case DBStatus::INVALID_VALUE_FIELDS: + return Status::INVALID_VALUE_FIELDS; + case DBStatus::INVALID_FIELD_TYPE: + return Status::INVALID_FIELD_TYPE; + case DBStatus::CONSTRAIN_VIOLATION: + return Status::CONSTRAIN_VIOLATION; + case DBStatus::INVALID_FORMAT: + return Status::INVALID_FORMAT; + case DBStatus::INVALID_QUERY_FORMAT: + return Status::INVALID_QUERY_FORMAT; + case DBStatus::INVALID_QUERY_FIELD: + return Status::INVALID_QUERY_FIELD; + case DBStatus::NOT_SUPPORT: + return Status::NOT_SUPPORT; + case DBStatus::TIME_OUT: + return Status::TIME_OUT; + case DBStatus::OVER_MAX_LIMITS: + return Status::OVER_MAX_SUBSCRIBE_LIMITS; + case DBStatus::EKEYREVOKED_ERROR: // fallthrough + case DBStatus::SECURITY_OPTION_CHECK_ERROR: + return Status::SECURITY_LEVEL_ERROR; + default: + break; + } + return Status::ERROR; +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 681d27b4b6a9f51fec4e7dda758f85f0f95ffc96..c0ee477702d9146b21f342406214bb6b78b4e62b 100644 --- a/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -15,13 +15,20 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H #define OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H +#include +#include + #include "concurrent_map.h" +#include "kv_store_nb_delegate.h" #include "kvdb_service_stub.h" +#include "kvstore_sync_manager.h" #include "metadata/store_meta_data.h" #include "metadata/strategy_meta_data.h" +#include "store_cache.h" namespace OHOS::DistributedKv { class API_EXPORT KVDBServiceImpl final : public KVDBServiceStub { public: + using DBLaunchParam = DistributedDB::AutoLaunchParam; API_EXPORT KVDBServiceImpl(); virtual ~KVDBServiceImpl(); Status GetStoreIds(const AppId &appId, std::vector &storeIds) override; @@ -45,18 +52,44 @@ public: Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status AppExit(pid_t uid, pid_t pid, uint32_t tokenId, const AppId &appId); + Status ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m); private: using StoreMetaData = OHOS::DistributedData::StoreMetaData; using StrategyMeta = OHOS::DistributedData::StrategyMeta; + using DBStore = DistributedDB::KvStoreNbDelegate; + using DBManager = DistributedDB::KvStoreDelegateManager; + using SyncEnd = KvStoreSyncManager::SyncEnd; + using DBResult = std::map; + using DBStatus = DistributedDB::DBStatus; void AddOptions(const Options &options, StoreMetaData &metaData); StoreMetaData GetStoreMetaData(const AppId &appId, const StoreId &storeId); StrategyMeta GetStrategyMeta(const AppId &appId, const StoreId &storeId); int32_t GetInstIndex(uint32_t tokenId, const AppId &appId); + Status DoSync(const StoreMetaData &metaData, const SyncInfo &syncInfo, const SyncEnd &complete); + Status DoComplete(const StoreMetaData &metaData, const SyncInfo &syncInfo, const DBResult &dbResult); + uint32_t GetSyncDelayTime(uint32_t delay, const StoreId &storeId); + Status ConvertDbStatus(DBStatus status); - ConcurrentMap>> syncAgents_; - ConcurrentMap>> dataObservers_; - ConcurrentMap> delayTimes_; + struct SyncAgent { + pid_t pid_ = 0; + AppId appId_; + sptr callback_; + std::map delayTimes_; + std::map> observers_; + std::map, std::string>> conditions_; + void ReInit(pid_t pid, const AppId &appId) + { + pid_ = pid; + appId_ = appId; + callback_ = nullptr; + delayTimes_.clear(); + observers_.clear(); + conditions_.clear(); + } + }; + ConcurrentMap syncAgents_; + StoreCache storeCache_; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICES_KVDB_SERVICE_IMPL_H diff --git a/services/distributeddataservice/service/kvdb/store_cache.cpp b/services/distributeddataservice/service/kvdb/store_cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95ee5d1e5419d006d1774870ce6b4adcfb9e8a5b --- /dev/null +++ b/services/distributeddataservice/service/kvdb/store_cache.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "store_cache.h" + +#include "crypto_manager.h" +#include "directory_manager.h" +#include "metadata/meta_data_manager.h" +#include "metadata/secret_key_meta_data.h" +#include "types.h" +namespace OHOS::DistributedKv { +using namespace OHOS::DistributedData; +constexpr int64_t StoreCache::INTERVAL; +constexpr size_t StoreCache::TIME_TASK_NUM; +StoreCache::DBStore *StoreCache::GetStore(const StoreMetaData &data, std::shared_ptr observers, + DBStatus &status) +{ + DBStore *store = nullptr; + status = DBStatus::NOT_FOUND; + stores_.Compute(data.tokenId, [this, &store, &data, &status, &observers](auto &key, auto &stores) { + auto it = stores.find(data.storeId); + if (it != stores.end()) { + it->second.SetObservers(observers); + store = it->second; + return true; + } + + DBManager manager(data.appId, data.user); + manager.SetKvStoreConfig({ DirectoryManager::GetInstance().GetStorePath(data) }); + manager.GetKvStore(data.storeId, GetDBOption(data), [&status, &store](auto dbStatus, auto *tmpStore) { + status = dbStatus; + store = tmpStore; + }); + + if (store != nullptr) { + stores.emplace(std::piecewise_construct, std::forward_as_tuple(data.storeId), + std::forward_as_tuple(store, observers)); + } + return !stores.empty(); + }); + + scheduler_.At(std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL), + std::bind(&StoreCache::CollectGarbage, this)); + + return store; +} + +void StoreCache::CollectGarbage() +{ + DBManager manager("", ""); + auto current = std::chrono::system_clock::now(); + stores_.EraseIf([&manager, ¤t](auto &key, std::map &delegates) { + for (auto it = delegates.begin(); it != delegates.end();) { + // if the kv store is BUSY we wait more INTERVAL minutes again + if ((it->second < current) || !it->second.Close(manager)) { + ++it; + } else { + it = delegates.erase(it); + } + } + return delegates.empty(); + }); + + if (!stores_.Empty()) { + scheduler_.At(current + std::chrono::minutes(INTERVAL), std::bind(&StoreCache::CollectGarbage, this)); + } +} + +StoreCache::DBOption StoreCache::GetDBOption(const StoreMetaData &data) const +{ + DBOption dbOption; + dbOption.syncDualTupleMode = true; // tuple of (appid+storeid) + dbOption.createIfNecessary = false; + dbOption.isMemoryDb = false; + dbOption.isEncryptedDb = data.isEncrypt; + if (data.isEncrypt) { + dbOption.cipher = DistributedDB::CipherType::AES_256_GCM; + SecretKeyMetaData secretKey; + secretKey.storeType = data.storeType; + auto storeKey = SecretKeyMetaData::GetKey({ data.user, "default", data.bundleName, data.storeId }); + MetaDataManager::GetInstance().SaveMeta(storeKey, secretKey, true); + std::vector password; + CryptoManager::GetInstance().Decrypt(secretKey.sKey, password); + dbOption.passwd.SetValue(password.data(), password.size()); + password.assign(password.size(), 0); + } + + if (data.storeType == KvStoreType::SINGLE_VERSION) { + dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN; + } else if (data.storeType == KvStoreType::DEVICE_COLLABORATION) { + dbOption.conflictResolvePolicy = DistributedDB::DEVICE_COLLABORATION; + } + + dbOption.schema = data.schema; + dbOption.createDirByStoreIdOnly = true; + dbOption.secOption = GetDBSecurity(data.securityLevel); + return dbOption; +} + +StoreCache::DBSecurity StoreCache::GetDBSecurity(int32_t secLevel) const +{ + if (secLevel < SecurityLevel::NO_LABEL || secLevel > SecurityLevel::S4) { + return { DistributedDB::NOT_SET, DistributedDB::ECE }; + } + if (secLevel == SecurityLevel::S3) { + return { DistributedDB::S3, DistributedDB::SECE }; + } + if (secLevel == SecurityLevel::S4) { + return { DistributedDB::S4, DistributedDB::ECE }; + } + return { secLevel, DistributedDB::ECE }; +} + +StoreCache::DBStoreDelegate::DBStoreDelegate(DBStore *delegate, std::shared_ptr observers) + : delegate_(delegate), observers_(std::move(observers)) +{ + time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); + if (observers_ != nullptr && !observers_->empty()) { + delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_FOREIGN, this); + } +} + +StoreCache::DBStoreDelegate::~DBStoreDelegate() +{ + delegate_ = nullptr; +} + +StoreCache::DBStoreDelegate::operator DBStore *() +{ + time_ = std::chrono::system_clock::now() + std::chrono::minutes(INTERVAL); + if (observers_ != nullptr && !observers_->empty()) { + delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_FOREIGN, this); + } + return delegate_; +} + +bool StoreCache::DBStoreDelegate::operator<(const Time &time) const +{ + return time_ < time; +} + +bool StoreCache::DBStoreDelegate::Close(DBManager &manager) +{ + if (delegate_ != nullptr) { + delegate_->UnRegisterObserver(this); + } + + auto status = manager.CloseKvStore(delegate_); + if (status == DBStatus::BUSY) { + return false; + } + delegate_ = nullptr; + return true; +} + +void StoreCache::DBStoreDelegate::OnChange(const DistributedDB::KvStoreChangedData &data) +{ + if (observers_ == nullptr) { + return; + } + + const auto &dbInserts = data.GetEntriesInserted(); + const auto &dbUpdates = data.GetEntriesUpdated(); + const auto &dbDeletes = data.GetEntriesDeleted(); + ChangeNotification change(Convert(dbInserts), Convert(dbUpdates), Convert(dbDeletes), std::string(), false); + for (auto &observer : *observers_) { + observer->OnChange(change); + } +} + +void StoreCache::DBStoreDelegate::SetObservers(std::shared_ptr observers) +{ + if (observers_ != observers && observers != nullptr) { + observers_ = observers; + } +} +std::vector StoreCache::DBStoreDelegate::Convert(const std::list &dbEntries) +{ + std::vector entries; + for (const auto &entry : dbEntries) { + Entry tmpEntry; + tmpEntry.key = entry.key; + tmpEntry.value = entry.value; + entries.push_back(tmpEntry); + } + return entries; +} +}; // namespace OHOS::DistributedKv diff --git a/services/distributeddataservice/service/kvdb/store_cache.h b/services/distributeddataservice/service/kvdb/store_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..44c142f12236827e595f83e99ce44df18a745d73 --- /dev/null +++ b/services/distributeddataservice/service/kvdb/store_cache.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H +#include + +#include +#include + +#include "concurrent_map.h" +#include "kv_scheduler.h" +#include "kv_store_nb_delegate.h" +#include "metadata/store_meta_data.h" +#include "refbase.h" +#include "ikvstore_observer.h" +namespace OHOS::DistributedKv { +class StoreCache { +public: + template + struct Less { + public: + bool operator()(const sptr &__x, const sptr &__y) const + { + return __x.GetRefPtr() < __y.GetRefPtr(); + } + }; + using DBStatus = DistributedDB::DBStatus; + using DBStore = DistributedDB::KvStoreNbDelegate; + using DBManager = DistributedDB::KvStoreDelegateManager; + using DBObserver = DistributedDB::KvStoreObserver; + using DBChangeData = DistributedDB::KvStoreChangedData; + using DBEntry = DistributedDB::Entry; + using Observers = std::set, Less>; + using StoreMetaData = OHOS::DistributedData::StoreMetaData; + using Time = std::chrono::system_clock::time_point; + + struct DBStoreDelegate : public DBObserver { + DBStoreDelegate(DBStore *delegate, std::shared_ptr observers); + ~DBStoreDelegate(); + operator DBStore *(); + bool operator<(const Time &time) const; + bool Close(DBManager &manager); + void OnChange(const DBChangeData &data) override; + void SetObservers(std::shared_ptr observers); + + private: + std::vector Convert(const std::list &dbEntries); + mutable Time time_; + DBStore *delegate_; + std::shared_ptr observers_; + }; + + DBStore *GetStore(const StoreMetaData &data, std::shared_ptr observers, DBStatus &status); + +private: + using DBOption = DistributedDB::KvStoreNbDelegate::Option; + using DBSecurity = DistributedDB::SecurityOption; + void CollectGarbage(); + DBOption GetDBOption(const StoreMetaData &data) const; + DBSecurity GetDBSecurity(int32_t secLevel) const; + static constexpr int64_t INTERVAL = 1; + static constexpr size_t TIME_TASK_NUM = 1; + ConcurrentMap> stores_; + KvScheduler scheduler_{ TIME_TASK_NUM }; +}; +} // namespace OHOS::DistributedKv +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_KVDB_STORE_CACHE_H