Use device specific API for linked devices updating capabilities.

This commit is contained in:
Cody Henthorne
2026-06-30 16:21:48 -04:00
committed by Michelle Tang
parent ee11d1fd3b
commit c4faafa9ae
6 changed files with 61 additions and 5 deletions
@@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.net.SignalNetwork;
import org.thoughtcrime.securesms.registration.data.RegistrationRepository;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.NetworkResultUtil;
import org.whispersystems.signalservice.api.RequestResultUtil;
import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
@@ -95,12 +96,26 @@ public class RefreshAttributesJob extends BaseJob {
return;
}
SvrValues svrValues = SignalStore.svr();
AccountAttributes.Capabilities capabilities = AppCapabilities.getCapabilities(svrValues.hasPin() && !svrValues.hasOptedOut());
if (SignalStore.account().isPrimaryDevice()) {
setPrimaryDeviceAttributes(svrValues, capabilities);
} else {
Log.i(TAG, "Linked device, refreshing device capabilities only. Capabilities: " + capabilities);
RequestResultUtil.successOrThrow(SignalNetwork.account().setCapabilities(capabilities));
}
hasRefreshedThisAppCycle = true;
}
private void setPrimaryDeviceAttributes(@NonNull SvrValues svrValues, @NonNull AccountAttributes.Capabilities capabilities) throws IOException {
int registrationId = SignalStore.account().getRegistrationId();
boolean fetchesMessages = !SignalStore.account().isFcmEnabled() || SignalStore.settings().getForceWebsocketMode().isEnabled();
byte[] unidentifiedAccessKey = UnidentifiedAccess.deriveAccessKeyFrom(ProfileKeyUtil.getSelfProfileKey());
boolean universalUnidentifiedAccess = TextSecurePreferences.isUniversalUnidentifiedAccess(context);
String registrationLockV2 = null;
SvrValues svrValues = SignalStore.svr();
int pniRegistrationId = RegistrationRepository.getPniRegistrationId();
String recoveryPassword = svrValues.getMasterKey().deriveRegistrationRecoveryPassword();
@@ -113,7 +128,6 @@ public class RefreshAttributesJob extends BaseJob {
String deviceName = SignalStore.account().getDeviceName();
byte[] encryptedDeviceName = (deviceName == null) ? null : DeviceNameCipher.encryptDeviceName(deviceName.getBytes(StandardCharsets.UTF_8), SignalStore.account().getAciIdentityKey());
AccountAttributes.Capabilities capabilities = AppCapabilities.getCapabilities(svrValues.hasPin() && !svrValues.hasOptedOut());
Log.i(TAG, "Calling setAccountAttributes() reglockV2? " + !TextUtils.isEmpty(registrationLockV2) + ", pin? " + svrValues.hasPin() + ", restoredAEP? " + SignalStore.account().restoredAccountEntropyPool() +
"\n Recovery password? " + !TextUtils.isEmpty(recoveryPassword) +
"\n Phone number discoverable : " + phoneNumberDiscoverable +
@@ -135,8 +149,6 @@ public class RefreshAttributesJob extends BaseJob {
);
NetworkResultUtil.toBasicLegacy(SignalNetwork.account().setAccountAttributes(accountAttributes));
hasRefreshedThisAppCycle = true;
}
@Override
@@ -72,6 +72,11 @@ class ResetSvrGuessCountJob private constructor(
override fun getFactoryKey(): String = KEY
override fun run(): Result {
if (SignalStore.account.isLinkedDevice) {
Log.i(TAG, "Not primary device. Skipping.")
return Result.success()
}
SvrRepository.operationLock.withLock {
val pin = SignalStore.svr.pin
@@ -52,6 +52,11 @@ class Svr3MirrorJob private constructor(parameters: Parameters, private var seri
override fun getFactoryKey(): String = KEY
override fun run(): Result {
if (SignalStore.account.isLinkedDevice) {
Log.i(TAG, "Not primary device. Skipping.")
return Result.success()
}
if (!Svr3Migration.shouldWriteToSvr3) {
Log.w(TAG, "Writes to SVR3 are disabled. Skipping.")
return Result.success()
@@ -260,7 +260,7 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
data.registrationLockEnabled,
data.accountEntropyPool.isNotEmpty()
)
} else if (data.pinOptedOut) {
} else if (data.pinOptedOut && data.linkedDeviceData == null) {
Log.i(TAG, "[commitRegistrationData] User opted out of creating a PIN. Applying opt-out.")
SvrRepository.optOutOfPin(rotateAep = false)
}