diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.java b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.java index e664d0f6117e35..6195b8fff690fa 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.java +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.java @@ -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; @@ -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( diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index f20ef1900c2551..f8b113a768b0d1 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -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(); @@ -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 buffer = std::unique_ptr(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(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 buffer = std::unique_ptr(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(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; @@ -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); diff --git a/src/controller/java/AndroidCallbacks.h b/src/controller/java/AndroidCallbacks.h index 37a4d536eca54a..cd058eae43fe56 100644 --- a/src/controller/java/AndroidCallbacks.h +++ b/src/controller/java/AndroidCallbacks.h @@ -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); diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index f448aac62eb7df..566832d59e5020 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -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; @@ -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"); @@ -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); @@ -1545,10 +1542,6 @@ JNI_METHOD(void, invoke) SuccessOrExit(err = GetChipPathIdValue(clusterIdObj, kInvalidClusterId, clusterId)); SuccessOrExit(err = GetChipPathIdValue(commandIdObj, kInvalidCommandId, commandId)); - hasTlv = static_cast(env->CallBooleanMethod(invokeElement, hasTlvMethod)); - VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); - VerifyOrExit(hasTlv, err = CHIP_ERROR_INVALID_ARGUMENT); - tlvBytesObj = static_cast(env->CallObjectMethod(invokeElement, getTlvByteArrayMethod)); VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); VerifyOrExit(tlvBytesObj != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/controller/java/src/chip/devicecontroller/InvokeCallback.java b/src/controller/java/src/chip/devicecontroller/InvokeCallback.java index efde7746118b3f..0d4fccda025b0d 100644 --- a/src/controller/java/src/chip/devicecontroller/InvokeCallback.java +++ b/src/controller/java/src/chip/devicecontroller/InvokeCallback.java @@ -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); @@ -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); diff --git a/src/controller/java/src/chip/devicecontroller/InvokeCallbackJni.java b/src/controller/java/src/chip/devicecontroller/InvokeCallbackJni.java index a287fdabb5131f..926aa0088c21bb 100644 --- a/src/controller/java/src/chip/devicecontroller/InvokeCallbackJni.java +++ b/src/controller/java/src/chip/devicecontroller/InvokeCallbackJni.java @@ -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; diff --git a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java index fb7d7136ed0572..38f98c3201103a 100644 --- a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java +++ b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java @@ -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; diff --git a/src/controller/java/src/chip/devicecontroller/model/InvokeElement.java b/src/controller/java/src/chip/devicecontroller/model/InvokeElement.java index 23fb208eecaeab..e61f09fffc23f9 100644 --- a/src/controller/java/src/chip/devicecontroller/model/InvokeElement.java +++ b/src/controller/java/src/chip/devicecontroller/model/InvokeElement.java @@ -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 tlv; - private final Optional 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 tlv, - Optional 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() { @@ -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. @@ -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); } }