From a17288210dc91252ed76154bcdf9944690f67263 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Fri, 7 Aug 2026 16:51:49 +1000 Subject: [PATCH] Expose the pro auto-renewing config key to Kotlin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libsession PR #121 adds the `A` / auto_renewing user-profile key, but it is core-only — this wrapper had no binding for it, so clients could not read or write it. Adds the JNI pair and the Kotlin declarations, following the existing ProAccessExpiry shape. The accessor is presence-only and the doc comment says so at the API boundary rather than only at the call site: set_pro_auto_renewing(false) ERASES the key, so `false` and "never written" are the same state through this getter. That is #121's encoding surfacing here, not something introduced by the binding, and it is where the next reader will meet it. Pins the libsession-util submodule to 8e5634b8, the head of #121, which is UNMERGED — so this commit cannot merge until #121 does. It is also not the identically-subjected pro-auto-renewing-config-pfs commit, which rebases the same change onto the PFS track. Verified in the built APK across all four ABIs rather than by a successful compile: a JNI signature mismatch is invisible at compile time and only traps at runtime. --- library/src/main/cpp/user_profile.cpp | 19 +++++++++++++++++++ .../loki/messenger/libsession_util/Config.kt | 12 ++++++++++++ .../messenger/libsession_util/UserProfile.kt | 2 ++ libsession-util | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/library/src/main/cpp/user_profile.cpp b/library/src/main/cpp/user_profile.cpp index 593bfdc..80800c9 100644 --- a/library/src/main/cpp/user_profile.cpp +++ b/library/src/main/cpp/user_profile.cpp @@ -180,6 +180,25 @@ Java_network_loki_messenger_libsession_1util_UserProfile_removeProAccessExpiry(J ptrToProfile(env, thiz)->set_pro_access_expiry(std::nullopt); } +extern "C" +JNIEXPORT jboolean JNICALL +Java_network_loki_messenger_libsession_1util_UserProfile_getProAutoRenewing(JNIEnv *env, + jobject thiz) { + return static_cast(ptrToProfile(env, thiz)->get_pro_auto_renewing()); +} + +extern "C" +JNIEXPORT void JNICALL +Java_network_loki_messenger_libsession_1util_UserProfile_setProAutoRenewing(JNIEnv *env, + jobject thiz, + jboolean auto_renewing) { + // Presence-only upstream: set_pro_auto_renewing uses set_nonzero_int, so writing false ERASES + // the key rather than storing it. Absent therefore means "terminal/unknown", and a caller + // cannot distinguish it from an explicit false through this binding — which is the whole of + // libsession PR #121's tri-state limitation, not something introduced here. + ptrToProfile(env, thiz)->set_pro_auto_renewing(auto_renewing); +} + extern "C" JNIEXPORT jlong JNICALL Java_network_loki_messenger_libsession_1util_UserProfile_getProFeaturesRaw(JNIEnv *env, diff --git a/library/src/main/java/network/loki/messenger/libsession_util/Config.kt b/library/src/main/java/network/loki/messenger/libsession_util/Config.kt index 98385bd..c609a10 100644 --- a/library/src/main/java/network/loki/messenger/libsession_util/Config.kt +++ b/library/src/main/java/network/loki/messenger/libsession_util/Config.kt @@ -87,6 +87,15 @@ interface ReadableUserProfile: ReadableConfig { fun getProConfig(): ProConfig? fun getProAccessExpiry(): Long? + /** + * Whether the subscription is auto-renewing, from synced config (key `A`, libsession #121). + * + * **Presence-only.** `setProAutoRenewing(false)` ERASES the key, so `false` here means either + * "not auto-renewing" or "never written" — absent reads as terminal/unknown. Callers that need + * to tell those apart cannot, through this API. + */ + fun getProAutoRenewing(): Boolean + /** When a refund was requested (unix seconds), or null if none (values >1 week old read as null). */ fun getRefundRequested(): Long? @@ -123,6 +132,9 @@ interface MutableUserProfile : ReadableUserProfile, MutableConfig { fun setProAccessExpiry(epochSeconds: Long) fun removeProAccessExpiry() + /** See [getProAutoRenewing] — writing `false` erases the key rather than storing it. */ + fun setProAutoRenewing(autoRenewing: Boolean) + /** Record (epochSeconds) or clear (null) the "refund requested" flag; synced across devices. */ fun setRefundRequested(epochSeconds: Long?) diff --git a/library/src/main/java/network/loki/messenger/libsession_util/UserProfile.kt b/library/src/main/java/network/loki/messenger/libsession_util/UserProfile.kt index 92aa47a..78d4936 100644 --- a/library/src/main/java/network/loki/messenger/libsession_util/UserProfile.kt +++ b/library/src/main/java/network/loki/messenger/libsession_util/UserProfile.kt @@ -47,6 +47,8 @@ class UserProfile private constructor(pointer: Long) : ConfigBase(pointer), Muta external override fun setAnimatedAvatar(animatedAvatar: Boolean) external override fun setProAccessExpiry(epochSeconds: Long) external override fun removeProAccessExpiry() + external override fun getProAutoRenewing(): Boolean + external override fun setProAutoRenewing(autoRenewing: Boolean) private external fun getProFeaturesRaw(): Long override fun getProFeatures(): ProProfileFeatures = ProProfileFeatures(getProFeaturesRaw()) external override fun getProConfig(): ProConfig? diff --git a/libsession-util b/libsession-util index e241a48..8e5634b 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit e241a489fde5385a3677e8f3401627095c23eed6 +Subproject commit 8e5634b81acadb23203cb7fb8474c96db3a406ee