Signal-Android/app/src/main/java/org/thoughtcrime/securesms/jobs/PnpInitializeDevicesJob.kt

109 wiersze
3.7 KiB
Kotlin

package org.thoughtcrime.securesms.jobs
import org.signal.core.util.concurrent.safeBlockingGet
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.components.settings.app.changenumber.ChangeNumberRepository
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobmanager.Data
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.VerifyAccountResponseWithoutKbs
import org.thoughtcrime.securesms.util.TextSecurePreferences
import java.io.IOException
/**
* To be run when all clients support PNP and we need to initialize all linked devices with appropriate PNP data.
*
* We reuse the change number flow as it already support distributing the necessary data in a way linked devices can understand.
*/
class PnpInitializeDevicesJob private constructor(parameters: Parameters) : BaseJob(parameters) {
companion object {
const val KEY = "PnpInitializeDevicesJob"
private val TAG = Log.tag(PnpInitializeDevicesJob::class.java)
private const val PLACEHOLDER_CODE = "123456"
@JvmStatic
fun enqueueIfNecessary() {
if (SignalStore.misc().hasPniInitializedDevices() || !SignalStore.account().isRegistered || SignalStore.account().aci == null || Recipient.self().pnpCapability != Recipient.Capability.SUPPORTED) {
return
}
ApplicationDependencies.getJobManager().add(PnpInitializeDevicesJob())
}
}
constructor() : this(Parameters.Builder().addConstraint(NetworkConstraint.KEY).build())
override fun serialize(): Data {
return Data.EMPTY
}
override fun getFactoryKey(): String {
return KEY
}
override fun onFailure() = Unit
@Throws(Exception::class)
public override fun onRun() {
if (!SignalStore.account().isRegistered || SignalStore.account().aci == null) {
Log.w(TAG, "Not registered! Skipping, as it wouldn't do anything.")
return
}
if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device, aborting...")
SignalStore.misc().setPniInitializedDevices(true)
return
}
if (SignalStore.account().isLinkedDevice) {
Log.i(TAG, "Not primary device, aborting...")
SignalStore.misc().setPniInitializedDevices(true)
return
}
ChangeNumberRepository.CHANGE_NUMBER_LOCK.lock()
try {
if (SignalStore.misc().hasPniInitializedDevices()) {
Log.w(TAG, "We found out that things have been initialized after we got the lock! No need to do anything else.")
return
}
val changeNumberRepository = ChangeNumberRepository()
val e164 = SignalStore.account().requireE164()
try {
Log.i(TAG, "Calling change number with our current number to distribute PNI messages")
changeNumberRepository
.changeNumber(code = PLACEHOLDER_CODE, newE164 = e164, pniUpdateMode = true)
.map(::VerifyAccountResponseWithoutKbs)
.safeBlockingGet()
.resultOrThrow
} catch (e: InterruptedException) {
throw IOException("Retry", e)
} catch (t: Throwable) {
Log.w(TAG, "Unable to initialize PNI for linked devices", t)
throw t
}
SignalStore.misc().setPniInitializedDevices(true)
} finally {
ChangeNumberRepository.CHANGE_NUMBER_LOCK.unlock()
}
}
override fun onShouldRetry(e: Exception): Boolean {
return e is IOException
}
class Factory : Job.Factory<PnpInitializeDevicesJob?> {
override fun create(parameters: Parameters, data: Data): PnpInitializeDevicesJob {
return PnpInitializeDevicesJob(parameters)
}
}
}