Skip to content

Commit

Permalink
Split KeyValueStoreManager.java into interface and impl, and add Set(…
Browse files Browse the repository at this point in the history
…) in JNI. (#8046)
  • Loading branch information
austinh0 authored and pull[bot] committed Sep 8, 2021
1 parent b2e9919 commit 1542827
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import chip.devicecontroller.ChipDeviceController
import chip.setuppayload.SetupPayloadParser.UnrecognizedQrCodeException
import com.google.chip.chiptool.attestation.AttestationTestFragment
import com.google.chip.chiptool.clusterclient.OnOffClientFragment
Expand All @@ -36,7 +37,7 @@ import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment
import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceDetailsFragment
import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo
import com.google.chip.chiptool.setuppayloadscanner.QrCodeInfo
import chip.devicecontroller.KeyValueStoreManager
import chip.devicecontroller.PreferencesKeyValueStoreManager
import chip.setuppayload.SetupPayload
import chip.setuppayload.SetupPayloadParser

Expand All @@ -52,9 +53,8 @@ class CHIPToolActivity :
super.onCreate(savedInstanceState)
setContentView(R.layout.top_activity)

KeyValueStoreManager.initialize(this);

if (savedInstanceState == null) {
ChipDeviceController.setKeyValueStoreManager(PreferencesKeyValueStoreManager(this))
val fragment = SelectActionFragment.newInstance()
supportFragmentManager
.beginTransaction()
Expand Down
37 changes: 17 additions & 20 deletions src/controller/java/AndroidKeyValueStoreManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <memory>
#include <string.h>

#include "AndroidKeyValueStoreManagerImpl.h"
#include "CHIPJNIError.h"
#include "JniReferences.h"
#include "JniTypeWrappers.h"
Expand All @@ -28,11 +29,11 @@
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>

using namespace chip::Controller;

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

using namespace chip::Controller;
namespace {

constexpr size_t kMaxKvsValueBytes = 4096;
Expand All @@ -45,7 +46,7 @@ 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(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mKeyValueStoreManagerObject == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mGetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(offset != 0, CHIP_ERROR_INVALID_ARGUMENT);

Expand All @@ -54,7 +55,7 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t

UtfString javaKey(env, key);

jobject javaValue = env->CallStaticObjectMethod(mKeyValueStoreManagerClass, mGetMethod, javaKey.jniValue());
jobject javaValue = env->CallObjectMethod(mKeyValueStoreManagerObject, mGetMethod, javaKey.jniValue());
if (env->ExceptionCheck())
{
ChipLogError(DeviceLayer, "Java exception in KVS::Get");
Expand Down Expand Up @@ -99,15 +100,15 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
ReturnErrorCodeIf(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mKeyValueStoreManagerObject == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mDeleteMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);

JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
ReturnErrorCodeIf(env == nullptr, CHIP_ERROR_INTERNAL);

UtfString javaKey(env, key);

env->CallStaticVoidMethod(mKeyValueStoreManagerClass, mDeleteMethod, javaKey.jniValue());
env->CallVoidMethod(mKeyValueStoreManagerObject, mDeleteMethod, javaKey.jniValue());

if (env->ExceptionCheck())
{
Expand All @@ -122,7 +123,7 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
ReturnErrorCodeIf(mKeyValueStoreManagerClass == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mKeyValueStoreManagerObject == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(mSetMethod == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(value_size > kMaxKvsValueBytes, CHIP_ERROR_INVALID_ARGUMENT);

Expand All @@ -137,7 +138,7 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value,
UtfString utfKey(env, key);
UtfString utfBase64Value(env, buffer.get());

env->CallStaticVoidMethod(mKeyValueStoreManagerClass, mSetMethod, utfKey.jniValue(), utfBase64Value.jniValue());
env->CallVoidMethod(mKeyValueStoreManagerObject, mSetMethod, utfKey.jniValue(), utfBase64Value.jniValue());

if (env->ExceptionCheck())
{
Expand All @@ -150,33 +151,29 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value,
return CHIP_NO_ERROR;
}

void KeyValueStoreManagerImpl::InitializeMethodForward(JavaVM * vm, JNIEnv * env)
void KeyValueStoreManagerImpl::InitializeWithObject(jobject managerObject)
{
mJvm = vm;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
mKeyValueStoreManagerObject = env->NewGlobalRef(managerObject);
jclass keyValueStoreManagerClass = env->GetObjectClass(mKeyValueStoreManagerObject);

CHIP_ERROR err =
JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/KeyValueStoreManager", mKeyValueStoreManagerClass);
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to get reference to KeyValueStoreManager");
return;
}
VerifyOrReturn(keyValueStoreManagerClass != nullptr, ChipLogError(DeviceLayer, "Failed to get KVS Java class"));

mGetMethod = env->GetStaticMethodID(mKeyValueStoreManagerClass, "get", "(Ljava/lang/String;)Ljava/lang/String;");
mGetMethod = env->GetMethodID(keyValueStoreManagerClass, "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");
mSetMethod = env->GetMethodID(keyValueStoreManagerClass, "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");
mDeleteMethod = env->GetMethodID(keyValueStoreManagerClass, "delete", "(Ljava/lang/String;)V");
if (mDeleteMethod == nullptr)
{
ChipLogError(DeviceLayer, "Failed to access KVS 'delete' method");
Expand Down
13 changes: 10 additions & 3 deletions src/controller/java/AndroidKeyValueStoreManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,31 @@

#pragma once

#include "JniReferences.h"

#include <jni.h>

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

using namespace chip::Controller;

class KeyValueStoreManagerImpl : public KeyValueStoreManager
{
public:
~KeyValueStoreManagerImpl()
{
JniReferences::GetInstance().GetEnvForCurrentThread()->DeleteGlobalRef(mKeyValueStoreManagerObject);
}
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(JavaVM * vm, JNIEnv * env);
void InitializeWithObject(jobject managerObject);

private:
JavaVM * mJvm = nullptr;
jclass mKeyValueStoreManagerClass = nullptr;
jobject mKeyValueStoreManagerObject = nullptr;

jmethodID mSetMethod = nullptr;
jmethodID mGetMethod = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ android_library("java") {
"src/chip/devicecontroller/ChipDeviceController.java",
"src/chip/devicecontroller/ChipDeviceControllerException.java",
"src/chip/devicecontroller/KeyValueStoreManager.java",
"src/chip/devicecontroller/PreferencesKeyValueStoreManager.java",
]

javac_flags = [ "-Xlint:deprecation" ]
Expand Down
10 changes: 7 additions & 3 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ jint JNI_OnLoad(JavaVM * jvm, void * reserved)
env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);

chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().InitializeMethodForward(sJVM, env);

ChipLogProgress(Controller, "Loading Java class references.");

// Get various class references need by the API.
Expand Down Expand Up @@ -257,6 +255,12 @@ JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self)
return result;
}

JNI_METHOD(void, setKeyValueStoreManager)(JNIEnv * env, jclass self, jobject manager)
{
StackLockGuard lock(JniReferences::GetInstance().GetStackLock());
chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().InitializeWithObject(manager);
}

JNI_METHOD(void, pairDevice)
(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jint connObj, jlong pinCode, jbyteArray csrNonce)
{
Expand All @@ -275,7 +279,7 @@ JNI_METHOD(void, pairDevice)
if (csrNonce != nullptr)
{
JniByteArray jniCsrNonce(env, csrNonce);
params = params.SetCSRNonce(jniCsrNonce.byteSpan());
params.SetCSRNonce(jniCsrNonce.byteSpan());
}
err = wrapper->Controller()->PairDevice(deviceId, params);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ private native void enableThreadNetwork(

private native boolean isActive(long deviceControllerPtr, long deviceId);

public static native void setKeyValueStoreManager(KeyValueStoreManager manager);

static {
System.loadLibrary("CHIPController");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,15 @@
*/
package chip.devicecontroller;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

/**
* Java implementation of a key/value store.
* Java interface for a key/value store.
*
* <p>Exposes get/set/delete methods to be used by the native C++ JNI Layer.
*/
public class KeyValueStoreManager {
private static final String TAG = KeyValueStoreManager.class.getSimpleName();
private static SharedPreferences preferences;
private static final String PREFERENCE_FILE_KEY = "com.google.chip.KeyValueStore";

public static String get(String key) {
String value = preferences.getString(key, null);
if (value == null) {
Log.d(TAG, "Key '" + key + "' not found in shared preferences");
}
return value;
}

public static void set(String key, String value) {
preferences.edit().putString(key, value).apply();
}
public interface KeyValueStoreManager {
public String get(String key);

public static void delete(String key) {
preferences.edit().remove(key).apply();
}
public void set(String key, String value);

/** Initialization MUST be done before any of get/set/delete work. */
public static void initialize(Context context) {
preferences = context.getSharedPreferences(PREFERENCE_FILE_KEY, Context.MODE_PRIVATE);
}
public void delete(String key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.
*
*/
package chip.devicecontroller;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

/** Android implementation of a key/value store using SharedPreferences. */
public class PreferencesKeyValueStoreManager implements KeyValueStoreManager {
private final String TAG = KeyValueStoreManager.class.getSimpleName();
private final String PREFERENCE_FILE_KEY = "com.google.chip.KeyValueStore";
private SharedPreferences preferences;

public PreferencesKeyValueStoreManager(Context context) {
preferences = context.getSharedPreferences(PREFERENCE_FILE_KEY, Context.MODE_PRIVATE);
}

@Override
public String get(String key) {
String value = preferences.getString(key, null);
if (value == null) {
Log.d(TAG, "Key '" + key + "' not found in shared preferences");
}
return value;
}

@Override
public void set(String key, String value) {
preferences.edit().putString(key, value).apply();
}

@Override
public void delete(String key) {
preferences.edit().remove(key).apply();
}
}

0 comments on commit 1542827

Please sign in to comment.