diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f7ec8692d6..e34082fa20 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -26,6 +26,16 @@ jobs: distribution: "temurin" java-version: "17" + # Add verbose log code check + - name: Check for verbose logs + run: | + if [[ "${{ github.ref_name }}" == release/* ]]; then + if grep -rE "Log.v" .; then + echo "❌ Debug code detected. Remove verbose logging before merging." + exit 1 + fi + fi + # Clean should essentially be a no-op, but make sure that it works. - name: Clean run: make clean diff --git a/android/src/main/java/com/tailscale/ipn/ui/localapi/Client.kt b/android/src/main/java/com/tailscale/ipn/ui/localapi/Client.kt index 5b12338b35..2a30db4e5c 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/localapi/Client.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/localapi/Client.kt @@ -4,6 +4,7 @@ package com.tailscale.ipn.ui.localapi import android.content.Context +import com.tailscale.ipn.App import com.tailscale.ipn.ui.model.BugReportID import com.tailscale.ipn.ui.model.Errors import com.tailscale.ipn.ui.model.Ipn @@ -13,7 +14,6 @@ import com.tailscale.ipn.ui.model.StableNodeID import com.tailscale.ipn.ui.model.Tailcfg import com.tailscale.ipn.ui.util.InputStreamAdapter import com.tailscale.ipn.util.TSLog -import com.tailscale.ipn.App import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -69,9 +69,7 @@ class Client(private val scope: CoroutineScope) { private val TAG = Client::class.simpleName // Access libtailscale.Application lazily - private val app: libtailscale.Application by lazy { - App.get().getLibtailscaleApp() -} + private val app: libtailscale.Application by lazy { App.get().getLibtailscaleApp() } fun start(options: Ipn.Options, responseHandler: (Result) -> Unit) { val body = Json.encodeToString(options).toByteArray() @@ -102,6 +100,14 @@ class Client(private val scope: CoroutineScope) { } fun editPrefs(prefs: Ipn.MaskedPrefs, responseHandler: (Result) -> Unit) { + // Log the stack trace for debugging purposes for + // https://github.com/tailscale/tailscale/issues/14125 + val stackTrace = + Thread.currentThread().stackTrace.joinToString("\n") { element -> + "at ${element.className}.${element.methodName}(${element.fileName}:${element.lineNumber})" + } + TSLog.v("editPrefs", "Called editPrefs with prefs: $prefs\nStack trace:\n$stackTrace") + val body = Json.encodeToString(prefs).toByteArray() return patch(Endpoint.PREFS, body, responseHandler = responseHandler) } diff --git a/android/src/main/java/com/tailscale/ipn/util/TSLog.kt b/android/src/main/java/com/tailscale/ipn/util/TSLog.kt index 4394574fab..7c44187b4d 100644 --- a/android/src/main/java/com/tailscale/ipn/util/TSLog.kt +++ b/android/src/main/java/com/tailscale/ipn/util/TSLog.kt @@ -18,6 +18,11 @@ object TSLog { libtailscaleWrapper.sendLog(tag, message) } + fun v(tag: String?, message: String) { + Log.v(tag, message) + libtailscaleWrapper.sendLog(tag, message) + } + // Overloaded function without Throwable because Java does not support default parameters @JvmStatic fun e(tag: String?, message: String) {