-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
KVS implementation for Android (#5738)
* Starting to add an android version of a key store manager * Add KVS include path via platform build config * Add Key value store manager java class and initialization * Added a key-value-store implementation * Restyle fixes * Remove file that was not intended to be added (idea compiler.xml)
- Loading branch information
Showing
10 changed files
with
454 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 178 additions & 0 deletions
178
src/controller/java/AndroidKeyValueStoreManagerImpl.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
/* | ||
* | ||
* Copyright (c) 2021 Project CHIP Authors | ||
* | ||
* 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 <platform/KeyValueStoreManager.h> | ||
|
||
#include <algorithm> | ||
#include <string.h> | ||
|
||
#include "CHIPJNIError.h" | ||
#include "JniReferences.h" | ||
#include "JniTypeWrappers.h" | ||
|
||
#include <support/Base64.h> | ||
#include <support/CodeUtils.h> | ||
#include <support/logging/CHIPLogging.h> | ||
|
||
namespace chip { | ||
namespace DeviceLayer { | ||
namespace PersistedStorage { | ||
namespace { | ||
|
||
constexpr size_t kMaxKvsValueBytes = 1024; | ||
constexpr size_t kMaxKvsValueEncodedChars = BASE64_ENCODED_LEN(kMaxKvsValueBytes) + 1; | ||
|
||
} // namespace | ||
|
||
KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; | ||
|
||
CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, | ||
size_t offset) | ||
{ | ||
ReturnErrorCodeIf(mEnv == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mGetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(offset != 0, CHIP_ERROR_INVALID_ARGUMENT); | ||
|
||
UtfString javaKey(mEnv, key); | ||
|
||
jobject javaValue = mEnv->CallStaticObjectMethod(mKeyValueStoreManagerClass, mGetMethod, javaKey.jniValue()); | ||
if (mEnv->ExceptionCheck()) | ||
{ | ||
ChipLogError(DeviceLayer, "Java exception in KVS::Get"); | ||
mEnv->ExceptionDescribe(); | ||
return CHIP_JNI_ERROR_EXCEPTION_THROWN; | ||
} | ||
|
||
if (javaValue == nullptr) | ||
{ | ||
return CHIP_ERROR_KEY_NOT_FOUND; | ||
} | ||
|
||
JniUtfString utfValue(mEnv, (jstring) javaValue); | ||
if (strlen(utfValue.c_str()) > kMaxKvsValueEncodedChars) | ||
{ | ||
ChipLogError(DeviceLayer, "Unexpected large value received from KVS"); | ||
return CHIP_ERROR_NO_MEMORY; | ||
} | ||
|
||
uint8_t buffer[kMaxKvsValueBytes]; | ||
uint16_t decodedLength = chip::Base64Decode(utfValue.c_str(), strlen(utfValue.c_str()), buffer); | ||
if (decodedLength == UINT16_MAX) | ||
{ | ||
ChipLogError(DeviceLayer, "KVS base64 decoding failed"); | ||
return CHIP_ERROR_INTEGRITY_CHECK_FAILED; | ||
} | ||
|
||
if (read_bytes_size != nullptr) | ||
{ | ||
*read_bytes_size = decodedLength; | ||
} | ||
|
||
if (value != nullptr) | ||
{ | ||
memcpy(value, buffer, std::min<size_t>(value_size, decodedLength)); | ||
} | ||
|
||
return CHIP_NO_ERROR; | ||
} | ||
|
||
CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) | ||
{ | ||
ReturnErrorCodeIf(mEnv == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mDeleteMethod == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
|
||
UtfString javaKey(mEnv, key); | ||
|
||
mEnv->CallStaticVoidMethod(mKeyValueStoreManagerClass, mDeleteMethod, javaKey.jniValue()); | ||
|
||
if (mEnv->ExceptionCheck()) | ||
{ | ||
ChipLogError(DeviceLayer, "Java exception in KVS::Delete"); | ||
mEnv->ExceptionDescribe(); | ||
mEnv->ExceptionClear(); | ||
return CHIP_JNI_ERROR_EXCEPTION_THROWN; | ||
} | ||
|
||
return CHIP_NO_ERROR; | ||
} | ||
|
||
CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) | ||
{ | ||
ReturnErrorCodeIf(mEnv == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(mSetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE); | ||
ReturnErrorCodeIf(value_size > kMaxKvsValueBytes, CHIP_ERROR_INVALID_ARGUMENT); | ||
|
||
char base64Buffer[kMaxKvsValueEncodedChars]; | ||
|
||
size_t length = chip::Base64Encode(static_cast<const uint8_t *>(value), value_size, base64Buffer); | ||
|
||
base64Buffer[length] = 0; | ||
|
||
UtfString utfKey(mEnv, key); | ||
UtfString utfBase64Value(mEnv, base64Buffer); | ||
|
||
mEnv->CallStaticVoidMethod(mKeyValueStoreManagerClass, mSetMethod, utfKey.jniValue(), utfBase64Value.jniValue()); | ||
|
||
if (mEnv->ExceptionCheck()) | ||
{ | ||
ChipLogError(DeviceLayer, "Java exception in KVS::Delete"); | ||
mEnv->ExceptionDescribe(); | ||
mEnv->ExceptionClear(); | ||
return CHIP_JNI_ERROR_EXCEPTION_THROWN; | ||
} | ||
|
||
return CHIP_NO_ERROR; | ||
} | ||
|
||
void KeyValueStoreManagerImpl::InitializeMethodForward(JNIEnv * env) | ||
{ | ||
mEnv = env; | ||
|
||
CHIP_ERROR err = GetClassRef(env, "chip/devicecontroller/KeyValueStoreManager", mKeyValueStoreManagerClass); | ||
if (err != CHIP_NO_ERROR) | ||
{ | ||
ChipLogError(DeviceLayer, "Failed to get reference to KeyValueStoreManager"); | ||
return; | ||
} | ||
|
||
mGetMethod = env->GetStaticMethodID(mKeyValueStoreManagerClass, "get", "(Ljava/lang/String;)Ljava/lang/String;"); | ||
if (mGetMethod == nullptr) | ||
{ | ||
ChipLogError(DeviceLayer, "Failed to access KVS 'get' method"); | ||
env->ExceptionClear(); | ||
} | ||
|
||
mSetMethod = env->GetStaticMethodID(mKeyValueStoreManagerClass, "set", "(Ljava/lang/String;Ljava/lang/String;)V"); | ||
if (mSetMethod == nullptr) | ||
{ | ||
ChipLogError(DeviceLayer, "Failed to access KVS 'set' method"); | ||
env->ExceptionClear(); | ||
} | ||
|
||
mDeleteMethod = env->GetStaticMethodID(mKeyValueStoreManagerClass, "delete", "(Ljava/lang/String;)V"); | ||
if (mDeleteMethod == nullptr) | ||
{ | ||
ChipLogError(DeviceLayer, "Failed to access KVS 'delete' method"); | ||
env->ExceptionClear(); | ||
} | ||
} | ||
|
||
} // namespace PersistedStorage | ||
} // namespace DeviceLayer | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* | ||
* Copyright (c) 2021 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* 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. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <jni.h> | ||
|
||
namespace chip { | ||
namespace DeviceLayer { | ||
namespace PersistedStorage { | ||
|
||
class KeyValueStoreManagerImpl : public KeyValueStoreManager | ||
{ | ||
public: | ||
CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0); | ||
CHIP_ERROR _Delete(const char * key); | ||
CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); | ||
|
||
void InitializeMethodForward(JNIEnv * env); | ||
|
||
private: | ||
JNIEnv * mEnv = nullptr; | ||
jclass mKeyValueStoreManagerClass = nullptr; | ||
|
||
jmethodID mSetMethod = nullptr; | ||
jmethodID mGetMethod = nullptr; | ||
jmethodID mDeleteMethod = nullptr; | ||
|
||
// ===== Members for internal use by the following friends. | ||
friend KeyValueStoreManager & KeyValueStoreMgr(); | ||
friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); | ||
|
||
static KeyValueStoreManagerImpl sInstance; | ||
}; | ||
|
||
/** | ||
* Returns the public interface of the KeyValueStoreManager singleton object. | ||
* | ||
* Chip applications should use this to access features of the KeyValueStoreManager object | ||
* that are common to all platforms. | ||
*/ | ||
inline KeyValueStoreManager & KeyValueStoreMgr() | ||
{ | ||
return KeyValueStoreManagerImpl::sInstance; | ||
} | ||
|
||
/** | ||
* Returns the platform-specific implementation of the KeyValueStoreManager singleton object. | ||
* | ||
* Chip applications can use this to gain access to features of the KeyValueStoreManager | ||
* that are specific to the ESP32 platform. | ||
*/ | ||
inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl() | ||
{ | ||
return KeyValueStoreManagerImpl::sInstance; | ||
} | ||
|
||
} // namespace PersistedStorage | ||
} // namespace DeviceLayer | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.