-
-
Notifications
You must be signed in to change notification settings - Fork 6k
/
RefreshAttributesJob.java
148 lines (120 loc) · 5.84 KB
/
RefreshAttributesJob.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package org.thoughtcrime.securesms.jobs;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.AppCapabilities;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SvrValues;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.registration.RegistrationRepository;
import org.thoughtcrime.securesms.registration.secondary.DeviceNameCipher;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
import org.signal.core.util.Base64;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
public class RefreshAttributesJob extends BaseJob {
public static final String KEY = "RefreshAttributesJob";
private static final String TAG = Log.tag(RefreshAttributesJob.class);
private static final String KEY_FORCED = "forced";
private static volatile boolean hasRefreshedThisAppCycle;
private final boolean forced;
public RefreshAttributesJob() {
this(true);
}
/**
* @param forced True if you want this job to run no matter what. False if you only want this job
* to run if it hasn't run yet this app cycle.
*/
public RefreshAttributesJob(boolean forced) {
this(new Job.Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setQueue("RefreshAttributesJob")
.setMaxInstancesForFactory(2)
.setLifespan(TimeUnit.DAYS.toMillis(30))
.setMaxAttempts(Parameters.UNLIMITED)
.build(),
forced);
}
private RefreshAttributesJob(@NonNull Job.Parameters parameters, boolean forced) {
super(parameters);
this.forced = forced;
}
@Override
public @Nullable byte[] serialize() {
return new JsonJobData.Builder().putBoolean(KEY_FORCED, forced).serialize();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun() throws IOException {
if (!SignalStore.account().isRegistered() || SignalStore.account().getE164() == null) {
Log.w(TAG, "Not yet registered. Skipping.");
return;
}
if (!forced && hasRefreshedThisAppCycle) {
Log.d(TAG, "Already refreshed this app cycle. Skipping.");
return;
}
int registrationId = SignalStore.account().getRegistrationId();
boolean fetchesMessages = !SignalStore.account().isFcmEnabled() || SignalStore.internalValues().isWebsocketModeForced();
byte[] unidentifiedAccessKey = UnidentifiedAccess.deriveAccessKeyFrom(ProfileKeyUtil.getSelfProfileKey());
boolean universalUnidentifiedAccess = TextSecurePreferences.isUniversalUnidentifiedAccess(context);
String registrationLockV2 = null;
SvrValues svrValues = SignalStore.svr();
int pniRegistrationId = new RegistrationRepository(ApplicationDependencies.getApplication()).getPniRegistrationId();
String recoveryPassword = svrValues.getRecoveryPassword();
if (svrValues.isRegistrationLockEnabled()) {
registrationLockV2 = svrValues.getRegistrationLockToken();
}
boolean phoneNumberDiscoverable = SignalStore.phoneNumberPrivacy().getPhoneNumberDiscoverabilityMode().isDiscoverable();
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() +
"\n Recovery password? " + !TextUtils.isEmpty(recoveryPassword) +
"\n Phone number discoverable : " + phoneNumberDiscoverable +
"\n Device Name : " + (encryptedDeviceName != null) +
"\n Capabilities: " + capabilities);
AccountAttributes accountAttributes = new AccountAttributes(
null,
registrationId,
fetchesMessages,
registrationLockV2,
unidentifiedAccessKey,
universalUnidentifiedAccess,
capabilities,
phoneNumberDiscoverable,
(encryptedDeviceName == null) ? null : Base64.encodeWithPadding(encryptedDeviceName),
pniRegistrationId,
recoveryPassword
);
ApplicationDependencies.getSignalServiceAccountManager().setAccountAttributes(accountAttributes);
hasRefreshedThisAppCycle = true;
}
@Override
public boolean onShouldRetry(@NonNull Exception e) {
return e instanceof NetworkFailureException;
}
@Override
public void onFailure() {
Log.w(TAG, "Failed to update account attributes!");
}
public static class Factory implements Job.Factory<RefreshAttributesJob> {
@Override
public @NonNull RefreshAttributesJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
JsonJobData data = JsonJobData.deserialize(serializedData);
return new RefreshAttributesJob(parameters, data.getBooleanOrDefault(KEY_FORCED, true));
}
}
}