Commit b8dd0b8a authored by Edward Wang's avatar Edward Wang
Browse files

Add a feature to easily retrieve debug logs

No tools like adb, Android SDK, aLogcat, etc needed

This will make it much easier to extract logs out of users on the forum, who don't know how to use the Android SDK or other tools.
parent f2d274ef
......@@ -62,6 +62,9 @@
android:name=".gui.BrowserActivity"
android:label="@string/mediafiles"
android:theme="@android:style/Theme" />
<activity
android:name=".gui.DebugLogActivity"
android:theme="@android:style/Theme.NoTitleBar" />
<activity
android:name=".gui.video.VideoGridFragment"
android:theme="@style/Theme.VLC"/>
......
......@@ -206,6 +206,7 @@ static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
JavaVM *myVm;
static jobject eventManagerInstance = NULL;
static jobject debugBufferInstance = NULL;
static pthread_mutex_t vout_android_lock;
static void *vout_android_surf = NULL;
......@@ -390,8 +391,48 @@ static void debug_log(void *data, int level, const char *fmt, va_list ap)
__android_log_vprint(prio, "VLC", fmt, ap);
}
static void debug_buffer_log(void *data, int level, const char *fmt, va_list ap)
{
bool isAttached = false;
JNIEnv *env = NULL;
JavaVM *myVm = (JavaVM*)data;
int status = (*myVm)->GetEnv(myVm, (void**) &env, JNI_VERSION_1_2);
if (status < 0) {
status = (*myVm)->AttachCurrentThread(myVm, &env, NULL);
if (status < 0)
return;
isAttached = true;
}
/* Prepare message string */
char* psz_fmt_newline = malloc(strlen(fmt) + 2);
if(!psz_fmt_newline)
return;
strcpy(psz_fmt_newline, fmt);
strcat(psz_fmt_newline, "\n");
char* psz_msg = NULL;
int res = vasprintf(&psz_msg, psz_fmt_newline, ap);
free(psz_fmt_newline);
if(res < 0)
return;
jobject buffer = debugBufferInstance;
jclass buffer_class = (*env)->FindClass(env, "java/lang/StringBuffer");
jmethodID bufferAppendID = (*env)->GetMethodID(env, buffer_class, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
jstring message = (*env)->NewStringUTF(env, psz_msg);
(*env)->CallObjectMethod(env, buffer, bufferAppendID, message);
(*env)->DeleteLocalRef(env, message);
free(psz_msg);
if (isAttached)
(*myVm)->DetachCurrentThread(myVm);
}
static libvlc_log_subscriber_t debug_subscriber;
static bool verbosity;
static libvlc_log_subscriber_t debug_buffer_subscriber;
void Java_org_videolan_vlc_LibVLC_changeVerbosity(JNIEnv *env, jobject thiz, jboolean verbose)
{
......@@ -400,6 +441,43 @@ void Java_org_videolan_vlc_LibVLC_changeVerbosity(JNIEnv *env, jobject thiz, jbo
libvlc_log_subscribe(&debug_subscriber, debug_log, &verbosity);
}
void Java_org_videolan_vlc_LibVLC_startDebugBuffer(JNIEnv *env, jobject thiz)
{
jclass libVLC_class = (*env)->FindClass(env, "org/videolan/vlc/LibVLC");
jmethodID getInstance = (*env)->GetStaticMethodID(env, libVLC_class, "getInstance", "()Lorg/videolan/vlc/LibVLC;");
jobject libvlcj = (*env)->CallStaticObjectMethod(env, libVLC_class, getInstance);
jfieldID bufferID = (*env)->GetFieldID(env, libVLC_class, "mDebugLogBuffer", "Ljava/lang/StringBuffer;");
jobject buffer = (*env)->GetObjectField(env, libvlcj, bufferID);
debugBufferInstance = (*env)->NewGlobalRef(env, buffer);
(*env)->DeleteLocalRef(env, buffer);
jfieldID buffer_flag = (*env)->GetFieldID(env, libVLC_class, "mIsBufferingLog", "Z");
(*env)->SetBooleanField(env, libvlcj, buffer_flag, JNI_TRUE);
(*env)->DeleteLocalRef(env, libVLC_class);
(*env)->DeleteLocalRef(env, libvlcj);
libvlc_log_subscribe(&debug_buffer_subscriber, debug_buffer_log, myVm);
}
void Java_org_videolan_vlc_LibVLC_stopDebugBuffer(JNIEnv *env, jobject thiz)
{
libvlc_log_unsubscribe(&debug_buffer_subscriber);
jclass libVLC_class = (*env)->FindClass(env, "org/videolan/vlc/LibVLC");
jmethodID getInstance = (*env)->GetStaticMethodID(env, libVLC_class, "getInstance", "()Lorg/videolan/vlc/LibVLC;");
jobject libvlcj = (*env)->CallStaticObjectMethod(env, libVLC_class, getInstance);
(*env)->DeleteGlobalRef(env, debugBufferInstance);
jfieldID buffer_flag = (*env)->GetFieldID(env, libVLC_class, "mIsBufferingLog", "Z");
(*env)->SetBooleanField(env, libvlcj, buffer_flag, JNI_FALSE);
(*env)->DeleteLocalRef(env, libVLC_class);
(*env)->DeleteLocalRef(env, libvlcj);
}
void Java_org_videolan_vlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz, jboolean verbose)
{
//only use OpenSLES if java side says we can
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/start_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:text="@string/start_logging" />
<Button
android:id="@+id/stop_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:text="@string/stop_logging" />
</LinearLayout>
<Button
android:id="@+id/clear_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/clear_log" />
<Button
android:id="@+id/copy_to_clipboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="@string/copy_to_clipboard" />
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:textIsSelectable="true" />
</LinearLayout>
\ No newline at end of file
......@@ -188,6 +188,13 @@
<string name="clear_media_db">Clear media database</string>
<string name="media_db_cleared">Media database cleared!</string>
<string name="subtitles_text_encoding">Subtitle text encoding</string>
<string name="start_logging">Start logging</string>
<string name="stop_logging">Stop logging</string>
<string name="clear_log">Clear log</string>
<string name="copy_to_clipboard">Copy to clipboard</string>
<string name="copied_to_clipboard">Copied log to clipboard.</string>
<string name="advanced_prefs_category">Advanced</string>
<string name="advanced_debugging">Advanced debugging</string>
<string name="aout">Audio output</string>
......
......@@ -71,6 +71,9 @@
android:enabled="true"
android:key="clear_media_db"
android:title="@string/clear_media_db" />
<PreferenceScreen
android:key="debug_logs"
android:title="Debug logs" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/advanced_prefs_category">
<CheckBoxPreference
......
......@@ -48,6 +48,10 @@ public class LibVLC {
/** libvlc_media_list_t pointer */
private long mMediaListInstance = 0; // Read-only, reserved for JNI
/** Buffer for VLC messages */
private StringBuffer mDebugLogBuffer;
private boolean mIsBufferingLog = false;
private Aout mAout;
/** Keep screen bright */
......@@ -191,6 +195,7 @@ public class LibVLC {
*/
private void init() throws LibVlcException {
Log.v(TAG, "Initializing LibVLC");
mDebugLogBuffer = new StringBuffer();
if (!mIsInitialized) {
if(!Util.hasCompatibleCPU()) {
Log.e(TAG, Util.getErrorMsg());
......@@ -330,6 +335,23 @@ public class LibVLC {
*/
private native void nativeDestroy();
/**
* Start buffering to the mDebugLogBuffer.
*/
public native void startDebugBuffer();
public native void stopDebugBuffer();
public String getBufferContent() {
return mDebugLogBuffer.toString();
}
public void clearBuffer() {
mDebugLogBuffer.setLength(0);
}
public boolean isDebugBuffering() {
return mIsBufferingLog;
}
/**
* Read a media
* @param instance: the instance of libVLC
......
......@@ -167,6 +167,18 @@ public class PreferencesActivity extends PreferenceActivity implements OnSharedP
}
});
// Debug log activity
Preference debugLogsPref = findPreference("debug_logs");
debugLogsPref
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(getApplicationContext(), DebugLogActivity.class);
startActivity(intent);
return true;
}
});
/*** Attach debugging items **/
Preference quitAppPref = findPreference("quit_app");
quitAppPref.setOnPreferenceClickListener(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment