Skip to content

Commit 5dd517c

Browse files
authored
Enhance Android Logging with setLogCallback API (project-chip#35254)
* Enhance Android Logging with setLogCallback API This change adds the setLogCallback API to the AndroidChipLogging class of the Matter SDK, enhancing its logging capabilities. With this API, developers can customize logging behavior and integrate it with Android's logging system, allowing for more flexible and comprehensive logging. An example of usage in Kotlin is as follows: ChipDeviceController.loadJni() AndroidChipLogging.setLogCallback { module, priority, message -> when (priority) { Log.ERROR -> Log.e(module, message) Log.INFO -> Log.i(module, message) Log.DEBUG -> Log.d(module, message) } } Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Add s prefix for global variables Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Do not call onLogMessage callback when msg is null Handle the case where jMsg is null due to UTF decode errors in buffer. Don't call the callback when the string is null. Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Return logRedirectCallback when env is nullptr Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Use JniLocalReferenceScope instead of DeleteLocalRef Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Change type of global ref to JniGlobalReference Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Use CharToStringUTF instead of NewStringUTF Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Use VerifyOrReturn for CharToStringUTF Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> --------- Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com>
1 parent 7f33e09 commit 5dd517c

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/platform/android/AndroidChipPlatform-JNI.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ static bool JavaBytesToUUID(JNIEnv * env, jbyteArray value, chip::Ble::ChipBleUU
6060
namespace {
6161
JavaVM * sJVM = nullptr;
6262
JniGlobalReference sAndroidChipPlatformExceptionCls;
63+
jmethodID sOnLogMessageMethod = nullptr;
64+
JniGlobalReference sJavaLogCallbackObject;
6365
} // namespace
6466

6567
CHIP_ERROR AndroidChipPlatformJNI_OnLoad(JavaVM * jvm, void * reserved)
@@ -274,6 +276,76 @@ JNI_LOGGING_METHOD(void, setLogFilter)(JNIEnv * env, jclass clazz, jint level)
274276
SetLogFilter(category);
275277
}
276278

279+
static void ENFORCE_FORMAT(3, 0) logRedirectCallback(const char * module, uint8_t category, const char * msg, va_list args)
280+
{
281+
using namespace chip::Logging;
282+
283+
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
284+
VerifyOrReturn(env != nullptr);
285+
VerifyOrReturn(sJavaLogCallbackObject.HasValidObjectRef());
286+
VerifyOrReturn(sOnLogMessageMethod != nullptr);
287+
288+
JniLocalReferenceScope scope(env);
289+
int priority = ANDROID_LOG_DEBUG;
290+
switch (category)
291+
{
292+
case kLogCategory_Error:
293+
priority = ANDROID_LOG_ERROR;
294+
break;
295+
case kLogCategory_Progress:
296+
priority = ANDROID_LOG_INFO;
297+
break;
298+
case kLogCategory_Detail:
299+
priority = ANDROID_LOG_DEBUG;
300+
break;
301+
default:
302+
break;
303+
}
304+
305+
jint jPriority = static_cast<jint>(priority);
306+
jobject jModule;
307+
VerifyOrReturn(JniReferences::GetInstance().CharToStringUTF(CharSpan::fromCharString(module), jModule) == CHIP_NO_ERROR);
308+
VerifyOrReturn(jModule != nullptr);
309+
310+
char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
311+
vsnprintf(buffer, sizeof(buffer), msg, args);
312+
jobject jMsg;
313+
VerifyOrReturn(JniReferences::GetInstance().CharToStringUTF(CharSpan::fromCharString(buffer), jMsg) == CHIP_NO_ERROR);
314+
VerifyOrReturn(jMsg != nullptr);
315+
316+
env->CallVoidMethod(sJavaLogCallbackObject.ObjectRef(), sOnLogMessageMethod, static_cast<jstring>(jModule), jPriority,
317+
static_cast<jstring>(jMsg));
318+
}
319+
320+
JNI_LOGGING_METHOD(void, setLogCallback)(JNIEnv * env, jclass clazz, jobject callback)
321+
{
322+
using namespace chip::Logging;
323+
324+
if (sOnLogMessageMethod == nullptr)
325+
{
326+
jclass callbackClass = env->GetObjectClass(callback);
327+
sOnLogMessageMethod = env->GetMethodID(callbackClass, "onLogMessage", "(Ljava/lang/String;ILjava/lang/String;)V");
328+
}
329+
VerifyOrReturn(sOnLogMessageMethod != nullptr,
330+
ChipLogError(DeviceLayer, "Failed to access AndroidChipLogging.LogCallback 'onLogMessage' method"));
331+
332+
if (sJavaLogCallbackObject.HasValidObjectRef())
333+
{
334+
sJavaLogCallbackObject.Reset();
335+
}
336+
337+
if (env->IsSameObject(callback, NULL))
338+
{
339+
SetLogRedirectCallback(nullptr);
340+
}
341+
else
342+
{
343+
VerifyOrReturn(sJavaLogCallbackObject.Init(callback) == CHIP_NO_ERROR,
344+
ChipLogError(DeviceLayer, "Failed to init sJavaLogCallbackObject"));
345+
SetLogRedirectCallback(logRedirectCallback);
346+
}
347+
}
348+
277349
JNI_MDNSCALLBACK_METHOD(void, handleServiceResolve)
278350
(JNIEnv * env, jclass self, jstring instanceName, jstring serviceType, jstring hostName, jstring address, jint port,
279351
jobject attributes, jlong callbackHandle, jlong contextHandle)

src/platform/android/java/chip/platform/AndroidChipLogging.java

+7
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,11 @@
2020
public class AndroidChipLogging {
2121
// logging level is in android.util.Log class
2222
public static native void setLogFilter(int level);
23+
24+
// This must be called after System.loadLibrary
25+
public static native void setLogCallback(LogCallback callback);
26+
27+
public interface LogCallback {
28+
void onLogMessage(String module, int priority, String message);
29+
}
2330
}

0 commit comments

Comments
 (0)