Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google committed Mar 6, 2023
1 parent 08a3e36 commit 4f0de24
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import java.util.logging.Logger;

public final class PairOnNetworkLongImInvokeCommand extends PairingCommand {
private static final Logger logger =
Logger.getLogger(PairOnNetworkLongImInvokeCommand.class.getName());
private static final int MATTER_PORT = 5540;
private long devicePointer;
private static final int CLUSTER_ID_IDENTIFY = 0x0003;
private static final int IDENTIFY_COMMAND = 0;
private static Logger logger = Logger.getLogger(PairOnNetworkLongImInvokeCommand.class.getName());
private long devicePointer;

private void setDevicePointer(long devicePointer) {
this.devicePointer = devicePointer;
Expand Down Expand Up @@ -67,7 +68,7 @@ protected void runCommand() {
byte[] intTLV = {0x15, 0x24, 0x00, 0x01, 0x18};
InvokeElement element =
InvokeElement.newInstance(
/* endpointId= */ 0, CLUSTER_ID_IDENTIFY, IDENTIFY_COMMAND, intTLV);
/* endpointId= */ 0, CLUSTER_ID_IDENTIFY, IDENTIFY_COMMAND, intTLV, null);

currentCommissioner()
.pairDeviceWithAddress(
Expand Down
95 changes: 36 additions & 59 deletions src/controller/java/AndroidCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,28 +422,6 @@ CHIP_ERROR CreateChipAttributePath(const app::ConcreteDataAttributePath & aPath,
return err;
}

CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath & aPath, jobject & outObj)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
CHIP_ERROR err = CHIP_NO_ERROR;

jclass invokeElementCls = nullptr;
err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/model/InvokeElement", invokeElementCls);
ReturnErrorOnFailure(err);
JniClass invokeElementJniCls(invokeElementCls);

jmethodID invokeElementCtor =
env->GetStaticMethodID(invokeElementCls, "newInstance", "(JJJ)Lchip/devicecontroller/model/InvokeElement;");
VerifyOrReturnError(!env->ExceptionCheck(), CHIP_JNI_ERROR_EXCEPTION_THROWN);
VerifyOrReturnError(invokeElementCtor != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND);

outObj =
env->CallStaticObjectMethod(invokeElementCls, invokeElementCtor, aPath.mEndpointId, aPath.mClusterId, aPath.mCommandId);
VerifyOrReturnError(outObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT);

return err;
}

CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath & aPath, TLV::TLVReader * apData, jobject & outObj)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
Expand All @@ -459,34 +437,41 @@ CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath &
VerifyOrReturnError(!env->ExceptionCheck(), CHIP_JNI_ERROR_EXCEPTION_THROWN);
VerifyOrReturnError(invokeElementCtor != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND);

TLV::TLVReader readerForJavaTLV;
TLV::TLVReader readerForJson;
readerForJavaTLV.Init(*apData);
readerForJson.Init(*apData);

// Create TLV byte array to pass to Java layer
size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
uint32_t size = 0;
// The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
// a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
// at the end.)
TLV::TLVWriter writer;
writer.Init(buffer.get(), bufferLen);
err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
ReturnErrorOnFailure(err);
size = writer.GetLengthWritten();
chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), size);

// Convert TLV to JSON
Json::Value json;
err = TlvToJson(readerForJson, json);
ReturnErrorOnFailure(err);

UtfString jsonString(env, JsonToString(json).c_str());

outObj = env->CallStaticObjectMethod(invokeElementCls, invokeElementCtor, aPath.mEndpointId, aPath.mClusterId, aPath.mCommandId,
jniByteArray.jniValue(), jsonString.jniValue());
if (apData != nullptr)
{
TLV::TLVReader readerForJavaTLV;
TLV::TLVReader readerForJson;
readerForJavaTLV.Init(*apData);
readerForJson.Init(*apData);

// Create TLV byte array to pass to Java layer
size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
uint32_t size = 0;
// The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
// a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
// at the end.)
TLV::TLVWriter writer;
writer.Init(buffer.get(), bufferLen);
err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
ReturnErrorOnFailure(err);
size = writer.GetLengthWritten();
chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), size);

// Convert TLV to JSON
Json::Value json;
err = TlvToJson(readerForJson, json);
ReturnErrorOnFailure(err);

UtfString jsonString(env, JsonToString(json).c_str());
outObj = env->CallStaticObjectMethod(invokeElementCls, invokeElementCtor, aPath.mEndpointId, aPath.mClusterId,
aPath.mCommandId, jniByteArray.jniValue(), jsonString.jniValue());
}
else
{
outObj = env->CallStaticObjectMethod(invokeElementCls, invokeElementCtor, aPath.mEndpointId, aPath.mClusterId,
aPath.mCommandId, nullptr, nullptr);
}
VerifyOrReturnError(outObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT);

return err;
Expand Down Expand Up @@ -980,15 +965,7 @@ void InvokeCallback::OnResponse(app::CommandSender * apCommandSender, const app:
jobject invokeElementObj = nullptr;
jmethodID onResponseMethod;

if (apData != nullptr)
{
err = CreateInvokeElement(aPath, apData, invokeElementObj);
}
else
{
err = CreateInvokeElement(aPath, invokeElementObj);
}

err = CreateInvokeElement(aPath, apData, invokeElementObj);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java InvokeElement: %s", ErrorStr(err)));
err = JniReferences::GetInstance().FindMethod(env, mJavaCallbackRef, "onResponse",
"(Lchip/devicecontroller/model/InvokeElement;J)V", &onResponseMethod);
Expand Down
1 change: 0 additions & 1 deletion src/controller/java/AndroidCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ struct InvokeCallback : public app::CommandSender::Callback

void OnDone(app::CommandSender * apCommandSender) override;

CHIP_ERROR CreateInvokeElement(const app::ConcreteCommandPath & aPath, jobject & outObj);
CHIP_ERROR CreateInvokeElement(const app::ConcreteCommandPath & aPath, TLV::TLVReader * apData, jobject & outObj);
void ReportError(CHIP_ERROR err);
void ReportError(Protocols::InteractionModel::Status status);
Expand Down
7 changes: 0 additions & 7 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,6 @@ JNI_METHOD(void, invoke)
jmethodID getEndpointIdMethod = nullptr;
jmethodID getClusterIdMethod = nullptr;
jmethodID getCommandIdMethod = nullptr;
jmethodID hasTlvMethod = nullptr;
jmethodID getTlvByteArrayMethod = nullptr;
jobject endpointIdObj = nullptr;
jobject clusterIdObj = nullptr;
Expand All @@ -1510,7 +1509,6 @@ JNI_METHOD(void, invoke)
jsize length = 0;
TLV::TLVReader reader;
TLV::TLVWriter * writer = nullptr;
bool hasTlv = false;

ChipLogDetail(Controller, "IM invoke() called");

Expand All @@ -1526,7 +1524,6 @@ JNI_METHOD(void, invoke)
"()Lchip/devicecontroller/model/ChipPathId;", &getClusterIdMethod));
SuccessOrExit(err = JniReferences::GetInstance().FindMethod(env, invokeElement, "getCommandId",
"()Lchip/devicecontroller/model/ChipPathId;", &getCommandIdMethod));
SuccessOrExit(err = JniReferences::GetInstance().FindMethod(env, invokeElement, "hasTlv", "()Z", &hasTlvMethod));
SuccessOrExit(JniReferences::GetInstance().FindMethod(env, invokeElement, "getTlvByteArray", "()[B", &getTlvByteArrayMethod));

endpointIdObj = env->CallObjectMethod(invokeElement, getEndpointIdMethod);
Expand All @@ -1545,10 +1542,6 @@ JNI_METHOD(void, invoke)
SuccessOrExit(err = GetChipPathIdValue(clusterIdObj, kInvalidClusterId, clusterId));
SuccessOrExit(err = GetChipPathIdValue(commandIdObj, kInvalidCommandId, commandId));

hasTlv = static_cast<bool>(env->CallBooleanMethod(invokeElement, hasTlvMethod));
VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
VerifyOrExit(hasTlv, err = CHIP_ERROR_INVALID_ARGUMENT);

tlvBytesObj = static_cast<jbyteArray>(env->CallObjectMethod(invokeElement, getTlvByteArrayMethod));
VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
VerifyOrExit(tlvBytesObj != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
Expand Down
17 changes: 7 additions & 10 deletions src/controller/java/src/chip/devicecontroller/InvokeCallback.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ public interface InvokeCallback {
* OnError will be called when an error occurs after failing to call
*
* @param Exception The IllegalStateException which encapsulated the error message, the possible
* chip error could be
* - CHIP_ERROR_TIMEOUT: A response was not received within the expected response timeout.
* - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from
* the server.
* - CHIP_ERROR encapsulating the converted error from the StatusIB: If we got a non-path-specific
* status response from the server.
* - CHIP_ERROR*: All other cases.
* chip error could be - CHIP_ERROR_TIMEOUT: A response was not received within the expected
* response timeout. - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from
* the server. - CHIP_ERROR encapsulating the converted error from the StatusIB: If we got a
* non-path-specific status response from the server. - CHIP_ERROR*: All other cases.
*/
void onError(Exception e);

Expand All @@ -42,9 +39,9 @@ public interface InvokeCallback {
*
* @param invokeElement The invoke element in invoke response that could have null or nonNull tlv
* data
* @param successCode If data in InvokeElment is null, successCode can be any success status, including
* possibly a cluster-specific one. If data in InvokeElement is not null, successCode will always
* be a generic SUCCESS(0) with no-cluster specific information
* @param successCode If data in InvokeElment is null, successCode can be any success status,
* including possibly a cluster-specific one. If data in InvokeElement is not null,
* successCode will always be a generic SUCCESS(0) with no-cluster specific information
*/
void onResponse(InvokeElement invokeElement, long successCode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package chip.devicecontroller;

/** JNI wrapper callback class for {@link InvokeCallback}. */
public class InvokeCallbackJni {
public final class InvokeCallbackJni {
private final InvokeCallback wrappedInvokeCallback;
private long callbackHandle;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package chip.devicecontroller;

/** JNI wrapper callback class for {@link WriteAttributesCallback}. */
public class WriteAttributesCallbackJni {
public final class WriteAttributesCallbackJni {
private final WriteAttributesCallback wrappedWriteAttributesCallback;
private long callbackHandle;

Expand Down
104 changes: 26 additions & 78 deletions src/controller/java/src/chip/devicecontroller/model/InvokeElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,45 @@

import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;

/** An invoke element that should be used for interaction model invoke request and response. */
public final class InvokeElement {
private static final Logger logger = Logger.getLogger(InvokeElement.class.getName());
private final ChipPathId endpointId, clusterId, commandId;
private final Optional<byte[]> tlv;
private final Optional<JSONObject> json;
private static Logger logger = Logger.getLogger(InvokeElement.class.getName());
@Nullable private final byte[] tlv;
@Nullable private final JSONObject json;

private InvokeElement(
ChipPathId endpointId,
ChipPathId clusterId,
ChipPathId commandId,
Optional<byte[]> tlv,
Optional<String> jsonString) {
@Nullable byte[] tlv,
@Nullable String jsonString) {
this.endpointId = endpointId;
this.clusterId = clusterId;
this.commandId = commandId;
if (tlv.isPresent()) {
this.tlv = Optional.of(tlv.get().clone());

if (tlv != null) {
this.tlv = tlv.clone();
} else {
this.tlv = Optional.empty();
this.tlv = null;
}

JSONObject jsonObject = null;
if (jsonString.isPresent()) {
if (jsonString != null) {
try {
jsonObject = new JSONObject(jsonString.get());
jsonObject = new JSONObject(jsonString);
} catch (JSONException ex) {
logger.log(Level.SEVERE, "Error parsing JSON string", ex);
}
}

this.json = Optional.ofNullable(jsonObject);
;
this.json = jsonObject;
}

public ChipPathId getEndpointId() {
Expand All @@ -72,20 +72,17 @@ public ChipPathId getCommandId() {
return commandId;
}

public boolean hasTlv() {
return tlv.isPresent();
}

public boolean hasJson() {
return json.isPresent();
}

@Nullable
public byte[] getTlvByteArray() {
return tlv.get().clone();
if (tlv != null) {
return tlv.clone();
}
return null;
}

@Nullable
public JSONObject getJson() {
return json.get();
return json;
}

// check whether the current InvokeElement has same path as others.
Expand Down Expand Up @@ -115,68 +112,19 @@ public static InvokeElement newInstance(
ChipPathId endpointId,
ChipPathId clusterId,
ChipPathId commandId,
byte[] tlv,
String jsonString) {
return new InvokeElement(
endpointId, clusterId, commandId, Optional.of(tlv), Optional.of(jsonString));
}

/** Create a new {@link InvokeElement} with only concrete ids. */
public static InvokeElement newInstance(
long endpointId, long clusterId, long commandId, byte[] tlv, String jsonString) {
return new InvokeElement(
ChipPathId.forId(endpointId),
ChipPathId.forId(clusterId),
ChipPathId.forId(commandId),
Optional.of(tlv),
Optional.of(jsonString));
}

public static InvokeElement newInstance(
ChipPathId endpointId, ChipPathId clusterId, ChipPathId commandId, byte[] tlv) {
return new InvokeElement(endpointId, clusterId, commandId, Optional.of(tlv), Optional.empty());
}

/** Create a new {@link InvokeElement} with only concrete ids. */
public static InvokeElement newInstance(
long endpointId, long clusterId, long commandId, byte[] tlv) {
return new InvokeElement(
ChipPathId.forId(endpointId),
ChipPathId.forId(clusterId),
ChipPathId.forId(commandId),
Optional.of(tlv),
Optional.empty());
}

public static InvokeElement newInstance(
ChipPathId endpointId, ChipPathId clusterId, ChipPathId commandId, String jsonString) {
return new InvokeElement(
endpointId, clusterId, commandId, Optional.empty(), Optional.of(jsonString));
@Nullable byte[] tlv,
@Nullable String jsonString) {
return new InvokeElement(endpointId, clusterId, commandId, tlv, jsonString);
}

/** Create a new {@link InvokeElement} with only concrete ids. */
public static InvokeElement newInstance(
long endpointId, long clusterId, long commandId, String jsonString) {
return new InvokeElement(
ChipPathId.forId(endpointId),
ChipPathId.forId(clusterId),
ChipPathId.forId(commandId),
Optional.empty(),
Optional.of(jsonString));
}

public static InvokeElement newInstance(
ChipPathId endpointId, ChipPathId clusterId, ChipPathId commandId) {
return new InvokeElement(endpointId, clusterId, commandId, Optional.empty(), Optional.empty());
}

/** Create a new {@link InvokeElement} with only concrete ids. */
public static InvokeElement newInstance(long endpointId, long clusterId, long commandId) {
long endpointId, long clusterId, long commandId, @Nullable byte[] tlv, @Nullable String jsonString) {
return new InvokeElement(
ChipPathId.forId(endpointId),
ChipPathId.forId(clusterId),
ChipPathId.forId(commandId),
Optional.empty(),
Optional.empty());
tlv,
jsonString);
}
}

0 comments on commit 4f0de24

Please sign in to comment.