diff --git a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java index 4a9bf2bb..b708c3aa 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/http/GetRequest.java @@ -17,6 +17,7 @@ import java.util.Map; public class GetRequest extends ApiRequest { public static final String URI_CONFIG = "/rest/system/config"; + public static final String URI_DEBUG = "/rest/system/debug"; public static final String URI_VERSION = "/rest/system/version"; public static final String URI_SYSTEM = "/rest/system/status"; public static final String URI_CONNECTIONS = "/rest/system/connections"; diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java index d8cad799..24342e34 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java @@ -23,6 +23,12 @@ public class Constants { public static final String PREF_SOCKS_PROXY_ADDRESS = "socks_proxy_address"; public static final String PREF_HTTP_PROXY_ADDRESS = "http_proxy_address"; + /** + * Available options cache for preference {@link app_settings#sttrace} + * Read via REST API call in {@link RestApi#updateDebugFacilitiesCache} after first successful binary startup. + */ + public static final String PREF_STTRACE_AVAILABLE_OPTIONS = "sttrace_available_options"; + /** * On Android 8.1, ACCESS_COARSE_LOCATION is required to access WiFi SSID. * This is the request code used when requesting the permission. diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java index 41251676..8f3f49cc 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java @@ -33,15 +33,18 @@ import com.nutomic.syncthingandroid.model.FolderStatus; import com.nutomic.syncthingandroid.model.Options; import com.nutomic.syncthingandroid.model.SystemInfo; import com.nutomic.syncthingandroid.model.SystemVersion; +import com.nutomic.syncthingandroid.service.Constants; import java.lang.reflect.Type; import java.net.URL; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import javax.inject.Inject; @@ -145,6 +148,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener { mVersion = json.get("version").getAsString(); Log.i(TAG, "Syncthing version is " + mVersion); tryIsAvailable(); + updateDebugFacilitiesCache(); }); new GetRequest(mContext, mUrl, GetRequest.URI_CONFIG, mApiKey, null, result -> { onReloadConfigComplete(result); @@ -171,6 +175,40 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener { mCompletion.updateFromConfig(getDevices(true), getFolders()); } + /** + * Queries debug facilities available from the currently running syncthing binary + * if the syncthing binary version changed. First launch of the binary is also + * considered as a version change. + * Precondition: {@link #mVersion} read from REST + */ + private void updateDebugFacilitiesCache() { + final String PREF_LAST_BINARY_VERSION = "lastBinaryVersion"; + if (!mVersion.equals(PreferenceManager.getDefaultSharedPreferences(mContext).getString(PREF_LAST_BINARY_VERSION, ""))) { + // First binary launch or binary upgraded case. + new GetRequest(mContext, mUrl, GetRequest.URI_DEBUG, mApiKey, null, result -> { + try { + Set facilitiesToStore = new HashSet(); + JsonObject json = new JsonParser().parse(result).getAsJsonObject(); + JsonObject jsonFacilities = json.getAsJsonObject("facilities"); + for (String facilityName : jsonFacilities.keySet()) { + facilitiesToStore.add(facilityName); + } + PreferenceManager.getDefaultSharedPreferences(mContext).edit() + .putStringSet(Constants.PREF_STTRACE_AVAILABLE_OPTIONS, facilitiesToStore) + .apply(); + + // Store current binary version so we will only store this information again + // after a binary update. + PreferenceManager.getDefaultSharedPreferences(mContext).edit() + .putString(PREF_LAST_BINARY_VERSION, mVersion) + .apply(); + } catch (Exception e) { + Log.w(TAG, "updateDebugFacilitiesCache: Failed to get debug facilities. result=" + result); + } + }); + } + } + /** * Increments mAvailableCount by one, and, if it reached TOTAL_STARTUP_CALLS, * calls {@link SyncthingService#onApiChange}. diff --git a/app/src/main/java/com/nutomic/syncthingandroid/views/SttracePreference.java b/app/src/main/java/com/nutomic/syncthingandroid/views/SttracePreference.java index fd8ebc3d..c13113f8 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/views/SttracePreference.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/views/SttracePreference.java @@ -8,6 +8,9 @@ import android.preference.MultiSelectListPreference; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; +import android.util.Log; + +import com.nutomic.syncthingandroid.service.Constants; import java.util.ArrayList; import java.util.Arrays; @@ -30,6 +33,8 @@ import java.util.TreeSet; */ public class SttracePreference extends MultiSelectListPreference { + private final String TAG = "SttracePreference"; + public SttracePreference(Context context, AttributeSet attrs) { super(context, attrs); setDefaultValue(new TreeSet()); @@ -69,32 +74,46 @@ public class SttracePreference extends MultiSelectListPreference { * Returns all debug facilities available in the currently syncthing version. */ private CharSequence[] getDebugFacilities() { - // Syncthing v0.14.47 debug facilities. - List debugFacilities = new ArrayList(); - debugFacilities.add("beacon"); - debugFacilities.add("config"); - debugFacilities.add("connections"); - debugFacilities.add("db"); - debugFacilities.add("dialer"); - debugFacilities.add("discover"); - debugFacilities.add("events"); - debugFacilities.add("fs"); - debugFacilities.add("http"); - debugFacilities.add("main"); - debugFacilities.add("model"); - debugFacilities.add("nat"); - debugFacilities.add("pmp"); - debugFacilities.add("protocol"); - debugFacilities.add("scanner"); - debugFacilities.add("sha256"); - debugFacilities.add("stats"); - debugFacilities.add("sync"); - debugFacilities.add("upgrade"); - debugFacilities.add("upnp"); - debugFacilities.add("versioner"); - debugFacilities.add("walkfs"); - debugFacilities.add("watchaggregator"); - return debugFacilities.toArray(new CharSequence[debugFacilities.size()]); + List retDebugFacilities = new ArrayList(); + Set availableDebugFacilities = getSharedPreferences().getStringSet(Constants.PREF_STTRACE_AVAILABLE_OPTIONS, new HashSet<>()); + // from JavaDoc: Note that you must not modify the set instance returned by this call. + // therefore required to make a defensive copy of the elements + availableDebugFacilities = new HashSet<>(availableDebugFacilities); + if (!availableDebugFacilities.isEmpty()) { + for (String facilityName : availableDebugFacilities) { + retDebugFacilities.add(facilityName); + } + } else { + Log.w(TAG, "getDebugFacilities: Failed to get facilities from prefs, falling back to hardcoded list."); + + // Syncthing v0.14.47 debug facilities. + retDebugFacilities.add("beacon"); + retDebugFacilities.add("config"); + retDebugFacilities.add("connections"); + retDebugFacilities.add("db"); + retDebugFacilities.add("dialer"); + retDebugFacilities.add("discover"); + retDebugFacilities.add("events"); + retDebugFacilities.add("fs"); + retDebugFacilities.add("http"); + retDebugFacilities.add("main"); + retDebugFacilities.add("model"); + retDebugFacilities.add("nat"); + retDebugFacilities.add("pmp"); + retDebugFacilities.add("protocol"); + retDebugFacilities.add("scanner"); + retDebugFacilities.add("sha256"); + retDebugFacilities.add("stats"); + retDebugFacilities.add("sync"); + retDebugFacilities.add("upgrade"); + retDebugFacilities.add("upnp"); + retDebugFacilities.add("versioner"); + retDebugFacilities.add("walkfs"); + retDebugFacilities.add("watchaggregator"); + } + CharSequence[] retDebugFacilitiesArray = retDebugFacilities.toArray(new CharSequence[retDebugFacilities.size()]); + Arrays.sort(retDebugFacilitiesArray); + return retDebugFacilitiesArray; } }