From 7b0c0147917655c88782e21eb0321ab16671ad78 Mon Sep 17 00:00:00 2001
From: SzBenedek2006 <95222597+SzBenedek2006@users.noreply.github.com>
Date: Thu, 13 Apr 2023 02:40:32 +0200
Subject: [PATCH 01/83] Fix hungarian translations (#1140)
---
app/src/main/res/values-hu-rHU/strings.xml | 31 +++++++++++-----------
app/src/main/res/values-hu/strings.xml | 31 +++++++++++-----------
2 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml
index 3c8b4a54c8..517efa5604 100644
--- a/app/src/main/res/values-hu-rHU/strings.xml
+++ b/app/src/main/res/values-hu-rHU/strings.xml
@@ -92,7 +92,8 @@
- Ez végelegesen törölni fogja a kiválasztott üzenetet.
- Ez véglegesen törölni fogja mind a(z) %1$d db kiválasztott üzenetet.
- Tiltja ezt a felhasználót?
+ Hívás engedély szükséges
+ Tiltod ezt a felhasználót?
Mentés tárolóra?
- A média mentése a tárolóra lehetővé teszi bármelyik másik alkalmazásnak a készülékeden, hogy hozzáférjen.\n\nFolytatod?
@@ -206,7 +207,7 @@
Hívott téged
Nem fogadott hívás
Média üzenet
- %s a Session-on van!
+ %s elérhető a Session-on!
Eltűnő üzenetek letiltva
Eltűnő üzenet ideje beállítva erre: %s
%s készített egy képernyőképet.
@@ -236,7 +237,7 @@
Te
Nem támogatott médiatípus
Piszkozat
- A Session- nek szüksége van fájlhozzáférési engedélyekhez, hogy menteni tudjon külső tárhelyre, de ezt az engedélyt megtagadták. Kérjük, hogy a készüléke beállításaiban engedélyezze a \"fájlok és média\" opciót a Session számára.
+ A Session- nek szüksége van fájlhozzáférési engedélyekhez, hogy menteni tudjon külső tárhelyre. Kérlek, hogy a rendszerbeállításokban engedélyezd a \"fájlok és média\" opciót a Session számára.
Nem lehet engedély nélkül menteni a külső tárolóra
Törlöd az üzenetet?
Ez véglegesen törölni fogja ezt az üzenetet.
@@ -250,8 +251,8 @@
Összes megjelölése olvasottként
Olvasottnak jelöl
Válasz
- Függő Session üzenetek
- Függő Session üzeneteid vannak, koppints a megnyitáshoz és letöltéshez
+ Függőben lévő Session üzenetek
+ Függőben lévő Session üzeneteid vannak, koppints a megnyitáshoz és letöltéshez
%1$s %2$s
Névjegy
@@ -275,7 +276,7 @@
Érvénytelen parancsikon
- Ülés
+ Session
Új üzenet
@@ -530,17 +531,17 @@
Megosztás
Érvénytelen Session azonosító
Mégse
- Az ön Session azonosítója
- Az ön Session-ja itt kezdődik...
+ A session azonosítód
+ A Session itt kezdődik...
Session azonosító létrehozása
- Folytassa az ülését
+ Session azonosító helyreállítása
Mi az a Session?
Ez egy decentralizált, titkosított üzenetküldő alkalmazás
Tehát nem gyűjti a személyes adataimat vagy a beszélgetés metaadatait? Hogyan működik?
- Fejlett névtelen útválasztási és end-to-end titkosítási technológiák kombinációjának használata.
- A barátok nem engedik, hogy a barátok kompromittált hírnököket használjanak. Szívesen.
+ Fejlett anonim útválasztási és végponttól-végpontig titkosítási technológiák használatával.
+ A barátként nem engedhetem, hogy megbízhatatlan üzenetküldő appokat használj. Szívesen.
Ismerd meg a Session ID-d
- Az üles azonosító az az egyedi cím, amelyet az emberek használhatnak, hogy kapcsolatba lépjenek Önnel az Ülés során. Mivel nincs kapcsolat a valódi személyazonosságával, az Ülés azonosító teljesen névtelen, és privát.
+ A Session azonosító az az egyedi cím, amelyet az emberek használhatnak, hogy kapcsolatba lépjenek Önnel a Sessionon. Mivel nincs kapcsolat a valódi személyazonosságával, az Session azonosító teljesen névtelen, és privát.
Fiók visszaállítása
Írja be azt a helyreállítási kifejezést, amelyet a fiók visszaállításához regisztrálásakor kapott.
Írja be a helyreállítási kifejezést
@@ -552,7 +553,7 @@
Ajánlott
Kérjük, válasszon egy lehetőséget
Még nincsenek névjegyei
- Indítson el egy ülést
+ Indítson el egy beszélgetést
Biztosan elhagyja ezt a csoportot?
"Nem sikerült kilépni a csoportból"
Biztosan törli ezt a beszélgetést?
@@ -573,8 +574,8 @@
Célállomás
Tudj meg többet
Feloldás...
- Új Ülés
- Adja meg az Ülés azonosítóját
+ Új Session
+ Adja meg a Session azonosítóját
QR kód beolvasása
A beszélgetés elindításához olvassa be a felhasználó QR kódját. A QR kód a fiókbeállításokban található a QR kód ikonra koppintva.
Írja be Session azonosítóját vagy ONS nevét
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 3c8b4a54c8..517efa5604 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -92,7 +92,8 @@
- Ez végelegesen törölni fogja a kiválasztott üzenetet.
- Ez véglegesen törölni fogja mind a(z) %1$d db kiválasztott üzenetet.
- Tiltja ezt a felhasználót?
+ Hívás engedély szükséges
+ Tiltod ezt a felhasználót?
Mentés tárolóra?
- A média mentése a tárolóra lehetővé teszi bármelyik másik alkalmazásnak a készülékeden, hogy hozzáférjen.\n\nFolytatod?
@@ -206,7 +207,7 @@
Hívott téged
Nem fogadott hívás
Média üzenet
- %s a Session-on van!
+ %s elérhető a Session-on!
Eltűnő üzenetek letiltva
Eltűnő üzenet ideje beállítva erre: %s
%s készített egy képernyőképet.
@@ -236,7 +237,7 @@
Te
Nem támogatott médiatípus
Piszkozat
- A Session- nek szüksége van fájlhozzáférési engedélyekhez, hogy menteni tudjon külső tárhelyre, de ezt az engedélyt megtagadták. Kérjük, hogy a készüléke beállításaiban engedélyezze a \"fájlok és média\" opciót a Session számára.
+ A Session- nek szüksége van fájlhozzáférési engedélyekhez, hogy menteni tudjon külső tárhelyre. Kérlek, hogy a rendszerbeállításokban engedélyezd a \"fájlok és média\" opciót a Session számára.
Nem lehet engedély nélkül menteni a külső tárolóra
Törlöd az üzenetet?
Ez véglegesen törölni fogja ezt az üzenetet.
@@ -250,8 +251,8 @@
Összes megjelölése olvasottként
Olvasottnak jelöl
Válasz
- Függő Session üzenetek
- Függő Session üzeneteid vannak, koppints a megnyitáshoz és letöltéshez
+ Függőben lévő Session üzenetek
+ Függőben lévő Session üzeneteid vannak, koppints a megnyitáshoz és letöltéshez
%1$s %2$s
Névjegy
@@ -275,7 +276,7 @@
Érvénytelen parancsikon
- Ülés
+ Session
Új üzenet
@@ -530,17 +531,17 @@
Megosztás
Érvénytelen Session azonosító
Mégse
- Az ön Session azonosítója
- Az ön Session-ja itt kezdődik...
+ A session azonosítód
+ A Session itt kezdődik...
Session azonosító létrehozása
- Folytassa az ülését
+ Session azonosító helyreállítása
Mi az a Session?
Ez egy decentralizált, titkosított üzenetküldő alkalmazás
Tehát nem gyűjti a személyes adataimat vagy a beszélgetés metaadatait? Hogyan működik?
- Fejlett névtelen útválasztási és end-to-end titkosítási technológiák kombinációjának használata.
- A barátok nem engedik, hogy a barátok kompromittált hírnököket használjanak. Szívesen.
+ Fejlett anonim útválasztási és végponttól-végpontig titkosítási technológiák használatával.
+ A barátként nem engedhetem, hogy megbízhatatlan üzenetküldő appokat használj. Szívesen.
Ismerd meg a Session ID-d
- Az üles azonosító az az egyedi cím, amelyet az emberek használhatnak, hogy kapcsolatba lépjenek Önnel az Ülés során. Mivel nincs kapcsolat a valódi személyazonosságával, az Ülés azonosító teljesen névtelen, és privát.
+ A Session azonosító az az egyedi cím, amelyet az emberek használhatnak, hogy kapcsolatba lépjenek Önnel a Sessionon. Mivel nincs kapcsolat a valódi személyazonosságával, az Session azonosító teljesen névtelen, és privát.
Fiók visszaállítása
Írja be azt a helyreállítási kifejezést, amelyet a fiók visszaállításához regisztrálásakor kapott.
Írja be a helyreállítási kifejezést
@@ -552,7 +553,7 @@
Ajánlott
Kérjük, válasszon egy lehetőséget
Még nincsenek névjegyei
- Indítson el egy ülést
+ Indítson el egy beszélgetést
Biztosan elhagyja ezt a csoportot?
"Nem sikerült kilépni a csoportból"
Biztosan törli ezt a beszélgetést?
@@ -573,8 +574,8 @@
Célállomás
Tudj meg többet
Feloldás...
- Új Ülés
- Adja meg az Ülés azonosítóját
+ Új Session
+ Adja meg a Session azonosítóját
QR kód beolvasása
A beszélgetés elindításához olvassa be a felhasználó QR kódját. A QR kód a fiókbeállításokban található a QR kód ikonra koppintva.
Írja be Session azonosítóját vagy ONS nevét
From 51856138e3ae23606c7f5ad04756a6db89ee5390 Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 24 Apr 2023 15:38:06 +1000
Subject: [PATCH 02/83] refactor on SignalAudioManager
---
.../securesms/service/WebRtcCallService.kt | 1 +
.../securesms/webrtc/CallManager.kt | 4 +
.../webrtc/audio/SignalAudioManager.kt | 99 +++++++++----------
.../libsignal/utilities/ThreadUtils.kt | 9 +-
4 files changed, 53 insertions(+), 60 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt
index b5e9b78a74..3ae3d30f01 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt
@@ -799,6 +799,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
wantsToAnswerReceiver?.let { receiver ->
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
}
+ callManager.shutDownAudioManager()
powerButtonReceiver = null
wiredHeadsetStateReceiver = null
networkChangedReceiver = null
diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt
index 07e73bedd2..d96de5eedb 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt
@@ -93,6 +93,10 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
peerConnectionObservers.remove(listener)
}
+ fun shutDownAudioManager() {
+ signalAudioManager.shutdown()
+ }
+
private val _audioEvents = MutableStateFlow(AudioEnabled(false))
val audioEvents = _audioEvents.asSharedFlow()
private val _videoEvents = MutableStateFlow(VideoEnabled(false))
diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
index 67514c58be..6eb1304430 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
@@ -9,6 +9,7 @@ import android.media.SoundPool
import android.os.HandlerThread
import network.loki.messenger.R
import org.session.libsignal.utilities.Log
+import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
import org.thoughtcrime.securesms.webrtc.audio.SignalBluetoothManager.State as BState
@@ -32,10 +33,10 @@ class SignalAudioManager(private val context: Context,
private val eventListener: EventListener?,
private val androidAudioManager: AudioManagerCompat) {
- private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio").apply { start() }
- private var handler: SignalAudioHandler? = null
+ private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio", ThreadUtils.PRIORITY_IMPORTANT_BACKGROUND_THREAD).apply { start() }
+ private var handler: SignalAudioHandler? = SignalAudioHandler(commandAndControlThread!!.looper)
- private var signalBluetoothManager: SignalBluetoothManager? = null
+ private var signalBluetoothManager: SignalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!)
private var state: State = State.UNINITIALIZED
@@ -62,12 +63,9 @@ class SignalAudioManager(private val context: Context,
private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null
fun handleCommand(command: AudioManagerCommand) {
- if (command == AudioManagerCommand.Initialize) {
- initialize()
- return
- }
handler?.post {
when (command) {
+ is AudioManagerCommand.Initialize -> initialize()
is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState()
is AudioManagerCommand.Start -> start()
is AudioManagerCommand.Stop -> stop(command.playDisconnect)
@@ -84,34 +82,37 @@ class SignalAudioManager(private val context: Context,
Log.i(TAG, "Initializing audio manager state: $state")
if (state == State.UNINITIALIZED) {
- commandAndControlThread = HandlerThread("call-audio").apply { start() }
- handler = SignalAudioHandler(commandAndControlThread!!.looper)
+ savedAudioMode = androidAudioManager.mode
+ savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn
+ savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute
+ hasWiredHeadset = androidAudioManager.isWiredHeadsetOn
- signalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!)
+ androidAudioManager.requestCallAudioFocus()
- handler!!.post {
+ setMicrophoneMute(false)
- savedAudioMode = androidAudioManager.mode
- savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn
- savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute
- hasWiredHeadset = androidAudioManager.isWiredHeadsetOn
+ audioDevices.clear()
- androidAudioManager.requestCallAudioFocus()
+ signalBluetoothManager.start()
- setMicrophoneMute(false)
+ updateAudioDeviceState()
- audioDevices.clear()
+ wiredHeadsetReceiver = WiredHeadsetReceiver()
+ context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG))
- signalBluetoothManager!!.start()
+ state = State.PREINITIALIZED
- updateAudioDeviceState()
+ Log.d(TAG, "Initialized")
+ }
+ }
- wiredHeadsetReceiver = WiredHeadsetReceiver()
- context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG))
-
- state = State.PREINITIALIZED
-
- Log.d(TAG, "Initialized")
+ fun shutdown() {
+ handler!!.post {
+ stop(false)
+ if (commandAndControlThread != null) {
+ Log.i(TAG, "Shutting down command and control")
+ commandAndControlThread?.quitSafely()
+ commandAndControlThread = null
}
}
}
@@ -138,23 +139,11 @@ class SignalAudioManager(private val context: Context,
private fun stop(playDisconnect: Boolean) {
Log.d(TAG, "Stopping. state: $state")
- if (state == State.UNINITIALIZED) {
- Log.i(TAG, "Trying to stop AudioManager in incorrect state: $state")
- return
- }
- handler?.post {
- incomingRinger.stop()
- outgoingRinger.stop()
- stop(false)
- if (commandAndControlThread != null) {
- Log.i(TAG, "Shutting down command and control")
- commandAndControlThread?.quitSafely()
- commandAndControlThread = null
- }
- }
+ incomingRinger.stop()
+ outgoingRinger.stop()
- if (playDisconnect) {
+ if (playDisconnect && state != State.UNINITIALIZED) {
val volume: Float = androidAudioManager.ringVolumeWithMinimum()
soundPool.play(disconnectedSoundId, volume, volume, 0, 0, 1.0f)
}
@@ -170,7 +159,7 @@ class SignalAudioManager(private val context: Context,
}
wiredHeadsetReceiver = null
- signalBluetoothManager?.stop()
+ signalBluetoothManager.stop()
setSpeakerphoneOn(savedIsSpeakerPhoneOn)
setMicrophoneMute(savedIsMicrophoneMute)
@@ -189,19 +178,19 @@ class SignalAudioManager(private val context: Context,
TAG,
"updateAudioDeviceState(): " +
"wired: $hasWiredHeadset " +
- "bt: ${signalBluetoothManager!!.state} " +
+ "bt: ${signalBluetoothManager.state} " +
"available: $audioDevices " +
"selected: $selectedAudioDevice " +
"userSelected: $userSelectedAudioDevice"
)
- if (signalBluetoothManager!!.state.shouldUpdate()) {
- signalBluetoothManager!!.updateDevice()
+ if (signalBluetoothManager.state.shouldUpdate()) {
+ signalBluetoothManager.updateDevice()
}
val newAudioDevices = mutableSetOf(AudioDevice.SPEAKER_PHONE)
- if (signalBluetoothManager!!.state.hasDevice()) {
+ if (signalBluetoothManager.state.hasDevice()) {
newAudioDevices += AudioDevice.BLUETOOTH
}
@@ -217,7 +206,7 @@ class SignalAudioManager(private val context: Context,
var audioDeviceSetUpdated = audioDevices != newAudioDevices
audioDevices = newAudioDevices
- if (signalBluetoothManager!!.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
+ if (signalBluetoothManager.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
userSelectedAudioDevice = AudioDevice.NONE
}
@@ -230,7 +219,7 @@ class SignalAudioManager(private val context: Context,
userSelectedAudioDevice = AudioDevice.NONE
}
- val btState = signalBluetoothManager!!.state
+ val btState = signalBluetoothManager.state
val needBluetoothAudioStart = btState == BState.AVAILABLE &&
(userSelectedAudioDevice == AudioDevice.NONE || userSelectedAudioDevice == AudioDevice.BLUETOOTH || autoSwitchToBluetooth)
@@ -238,27 +227,27 @@ class SignalAudioManager(private val context: Context,
(userSelectedAudioDevice != AudioDevice.NONE && userSelectedAudioDevice != AudioDevice.BLUETOOTH)
if (btState.hasDevice()) {
- Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager!!.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop")
+ Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop")
}
if (needBluetoothAudioStop) {
- signalBluetoothManager!!.stopScoAudio()
- signalBluetoothManager!!.updateDevice()
+ signalBluetoothManager.stopScoAudio()
+ signalBluetoothManager.updateDevice()
}
- if (!autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.UNAVAILABLE) {
+ if (!autoSwitchToBluetooth && signalBluetoothManager.state == BState.UNAVAILABLE) {
autoSwitchToBluetooth = true
}
- if (needBluetoothAudioStart && !needBluetoothAudioStop) {
- if (!signalBluetoothManager!!.startScoAudio()) {
+ if (!needBluetoothAudioStop && needBluetoothAudioStart) {
+ if (!signalBluetoothManager.startScoAudio()) {
Log.e(TAG,"Failed to start sco audio")
audioDevices.remove(AudioDevice.BLUETOOTH)
audioDeviceSetUpdated = true
}
}
- if (autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.CONNECTED) {
+ if (autoSwitchToBluetooth && signalBluetoothManager.state == BState.CONNECTED) {
userSelectedAudioDevice = AudioDevice.BLUETOOTH
autoSwitchToBluetooth = false
}
diff --git a/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt b/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt
index 0700d01f66..ac81564bd1 100644
--- a/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt
+++ b/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt
@@ -1,13 +1,12 @@
package org.session.libsignal.utilities
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-import java.util.concurrent.LinkedBlockingQueue
-import java.util.concurrent.ThreadPoolExecutor
-import java.util.concurrent.TimeUnit
+import android.os.Process
+import java.util.concurrent.*
object ThreadUtils {
+ const val PRIORITY_IMPORTANT_BACKGROUND_THREAD = Process.THREAD_PRIORITY_DEFAULT + Process.THREAD_PRIORITY_LESS_FAVORABLE
+
val executorPool: ExecutorService = Executors.newCachedThreadPool()
@JvmStatic
From c7bbdb778b93fb97bad93dad020240055c6507c8 Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 24 Apr 2023 15:50:53 +1000
Subject: [PATCH 03/83] minor refactor
---
.../securesms/webrtc/audio/SignalAudioHandler.kt | 2 +-
.../securesms/webrtc/audio/SignalAudioManager.kt | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt
index 89eba2a3aa..7ca44f46dc 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt
@@ -15,7 +15,7 @@ class SignalAudioHandler(looper: Looper) : Handler(looper) {
}
}
- fun isOnHandler(): Boolean {
+ private fun isOnHandler(): Boolean {
return Looper.myLooper() == looper
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
index 6eb1304430..229cbd13dd 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt
@@ -34,9 +34,9 @@ class SignalAudioManager(private val context: Context,
private val androidAudioManager: AudioManagerCompat) {
private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio", ThreadUtils.PRIORITY_IMPORTANT_BACKGROUND_THREAD).apply { start() }
- private var handler: SignalAudioHandler? = SignalAudioHandler(commandAndControlThread!!.looper)
+ private var handler: SignalAudioHandler = SignalAudioHandler(commandAndControlThread!!.looper)
- private var signalBluetoothManager: SignalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!)
+ private var signalBluetoothManager: SignalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler)
private var state: State = State.UNINITIALIZED
@@ -63,7 +63,7 @@ class SignalAudioManager(private val context: Context,
private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null
fun handleCommand(command: AudioManagerCommand) {
- handler?.post {
+ handler.post {
when (command) {
is AudioManagerCommand.Initialize -> initialize()
is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState()
@@ -107,7 +107,7 @@ class SignalAudioManager(private val context: Context,
}
fun shutdown() {
- handler!!.post {
+ handler.post {
stop(false)
if (commandAndControlThread != null) {
Log.i(TAG, "Shutting down command and control")
@@ -172,7 +172,7 @@ class SignalAudioManager(private val context: Context,
}
private fun updateAudioDeviceState() {
- handler!!.assertHandlerThread()
+ handler.assertHandlerThread()
Log.i(
TAG,
@@ -362,7 +362,7 @@ class SignalAudioManager(private val context: Context,
val pluggedIn = intent.getIntExtra("state", 0) == 1
val hasMic = intent.getIntExtra("microphone", 0) == 1
- handler?.post { onWiredHeadsetChange(pluggedIn, hasMic) }
+ handler.post { onWiredHeadsetChange(pluggedIn, hasMic) }
}
}
From 7d33177e065099d1709045b97d820c624a92707b Mon Sep 17 00:00:00 2001
From: Andrew Gallasch
Date: Wed, 26 Apr 2023 14:18:34 +0930
Subject: [PATCH 04/83] Fix status and nav bar colors (#1165)
---
.../org/thoughtcrime/securesms/BaseActionBarActivity.java | 7 +++++++
app/src/main/res/values-v27/colors.xml | 5 +++++
app/src/main/res/values/colors.xml | 3 +++
app/src/main/res/values/themes.xml | 8 ++++----
4 files changed, 19 insertions(+), 4 deletions(-)
create mode 100644 app/src/main/res/values-v27/colors.xml
diff --git a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
index 7d82c760cc..51f66ec323 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms;
+import static android.os.Build.VERSION.SDK_INT;
import static org.session.libsession.utilities.TextSecurePreferences.SELECTED_ACCENT_COLOR;
import android.app.ActivityManager;
@@ -18,6 +19,7 @@ import androidx.appcompat.app.AppCompatActivity;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
+import org.thoughtcrime.securesms.conversation.v2.WindowUtil;
import org.thoughtcrime.securesms.util.ActivityUtilitiesKt;
import org.thoughtcrime.securesms.util.ThemeState;
import org.thoughtcrime.securesms.util.UiModeUtilities;
@@ -92,6 +94,11 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
if (!currentThemeState.equals(ActivityUtilitiesKt.themeState(getPreferences()))) {
recreate();
}
+
+ // apply lightStatusBar manually as API 26 does not update properly via applyTheme
+ // https://issuetracker.google.com/issues/65883460?pli=1
+ if (SDK_INT >= 26 && SDK_INT <= 27) WindowUtil.setLightStatusBarFromTheme(this);
+ if (SDK_INT == 27) WindowUtil.setLightNavigationBarFromTheme(this);
}
@Override
diff --git a/app/src/main/res/values-v27/colors.xml b/app/src/main/res/values-v27/colors.xml
new file mode 100644
index 0000000000..5c5e9494f1
--- /dev/null
+++ b/app/src/main/res/values-v27/colors.xml
@@ -0,0 +1,5 @@
+
+
+ @color/classic_light_6
+ @color/ocean_light_7
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index d3b9d9b255..196e587cdc 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -60,6 +60,9 @@
#40ffffff
#aaffffff
+ @color/compose_view_background
+ @color/navigation_bar
+ @color/navigation_bar
@color/gray65
#22000000
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 2874d42972..43d06ee7ad 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -326,7 +326,7 @@
- ?android:textColorPrimary
- @color/gray27
- ?colorPrimary
- - @color/compose_view_background
+ - @color/navigation_bar
- @color/classic_dark_1
- @style/Classic.Dark.BottomSheet
- ?android:textColorPrimary
@@ -404,7 +404,7 @@
- ?android:textColorPrimary
- @color/gray27
- ?colorPrimary
- - ?colorPrimary
+ - @color/classic_light_navigation_bar
- @color/classic_light_6
- @color/classic_light_5
- @color/classic_light_3
@@ -490,7 +490,7 @@
- @color/ocean_dark_5
- ?colorPrimary
- @color/default_background_start
- - @color/compose_view_background
+ - @color/navigation_bar
- ?colorPrimary
- ?colorPrimaryDark
- @color/ocean_dark_3
@@ -570,7 +570,7 @@
- @color/ocean_light_2
- ?android:textColorPrimary
- @color/ocean_light_6
- - @color/ocean_light_7
+ - @color/ocean_light_navigation_bar
- ?colorPrimary
- @color/default_background_start
- @color/ocean_light_7
From 716fc1f4fa840efee4e4dfb3c6596273c083aa62 Mon Sep 17 00:00:00 2001
From: Andrew Gallasch
Date: Wed, 26 Apr 2023 14:24:54 +0930
Subject: [PATCH 05/83] Add SafeViewPager to fix touch exception in
MediaPreviewActivity (#1166)
---
.../securesms/components/SafeViewPager.kt | 30 +++++++++++++++++++
.../res/layout/media_preview_activity.xml | 2 +-
2 files changed, 31 insertions(+), 1 deletion(-)
create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt b/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt
new file mode 100644
index 0000000000..6748478736
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt
@@ -0,0 +1,30 @@
+package org.thoughtcrime.securesms.components
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import androidx.viewpager.widget.ViewPager
+
+/**
+ * An extension of ViewPager to swallow erroneous multi-touch exceptions.
+ *
+ * @see https://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch
+ */
+class SafeViewPager @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null
+) : ViewPager(context, attrs) {
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onTouchEvent(event: MotionEvent?): Boolean = try {
+ super.onTouchEvent(event)
+ } catch (e: IllegalArgumentException) {
+ false
+ }
+
+ override fun onInterceptTouchEvent(event: MotionEvent?): Boolean = try {
+ super.onInterceptTouchEvent(event)
+ } catch (e: IllegalArgumentException) {
+ false
+ }
+}
diff --git a/app/src/main/res/layout/media_preview_activity.xml b/app/src/main/res/layout/media_preview_activity.xml
index 2f6aaff454..78327b6cc3 100644
--- a/app/src/main/res/layout/media_preview_activity.xml
+++ b/app/src/main/res/layout/media_preview_activity.xml
@@ -22,7 +22,7 @@
-
Date: Wed, 26 Apr 2023 14:26:00 +0930
Subject: [PATCH 06/83] Remove unnecessary api version checks in WindowUtil
(#1163)
---
.../securesms/conversation/v2/WindowUtil.java | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java
index 4bff4e76aa..6083bb267c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java
@@ -38,14 +38,10 @@ public final class WindowUtil {
}
public static void setNavigationBarColor(@NonNull Window window, @ColorInt int color) {
- if (Build.VERSION.SDK_INT < 21) return;
-
window.setNavigationBarColor(color);
}
public static void setLightStatusBarFromTheme(@NonNull Activity activity) {
- if (Build.VERSION.SDK_INT < 23) return;
-
final boolean isLightStatusBar = ThemeUtil.getThemedBoolean(activity, android.R.attr.windowLightStatusBar);
if (isLightStatusBar) setLightStatusBar(activity.getWindow());
@@ -53,20 +49,14 @@ public final class WindowUtil {
}
public static void clearLightStatusBar(@NonNull Window window) {
- if (Build.VERSION.SDK_INT < 23) return;
-
clearSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
public static void setLightStatusBar(@NonNull Window window) {
- if (Build.VERSION.SDK_INT < 23) return;
-
setSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
public static void setStatusBarColor(@NonNull Window window, @ColorInt int color) {
- if (Build.VERSION.SDK_INT < 21) return;
-
window.setStatusBarColor(color);
}
From ffef98ecc93780e367ebe08cb8a621e51cd86cf8 Mon Sep 17 00:00:00 2001
From: Andrew Gallasch
Date: Wed, 26 Apr 2023 14:29:32 +0930
Subject: [PATCH 07/83] Fix LandingActivity textColor (#1159)
---
app/src/main/res/values/styles.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5f9ee03168..1cf88c0c06 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -228,11 +228,13 @@
From 58e532f0ec0be0f34434113ce782b91958e803a9 Mon Sep 17 00:00:00 2001
From: andrew
Date: Wed, 26 Apr 2023 16:31:28 +0930
Subject: [PATCH 08/83] Swallow screenshot exceptions
---
.../attachments/ScreenshotObserver.kt | 78 +++++++++++--------
1 file changed, 45 insertions(+), 33 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt
index 84a9b6cfc3..9c7ca21e8b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt
@@ -7,6 +7,10 @@ import android.os.Build
import android.os.Handler
import android.provider.MediaStore
import androidx.annotation.RequiresApi
+import org.session.libsignal.utilities.Log
+import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer
+
+private const val TAG = "ScreenshotObserver"
class ScreenshotObserver(private val context: Context, handler: Handler, private val screenshotTriggered: ()->Unit): ContentObserver(handler) {
@@ -31,22 +35,26 @@ class ScreenshotObserver(private val context: Context, handler: Handler, private
val projection = arrayOf(
MediaStore.Images.Media.DATA
)
- context.contentResolver.query(
- uri,
- projection,
- null,
- null,
- null
- )?.use { cursor ->
- val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
- while (cursor.moveToNext()) {
- val path = cursor.getString(dataColumn)
- if (path.contains("screenshot", true)) {
- if (cache.add(uri.hashCode())) {
- screenshotTriggered()
+ try {
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
+ while (cursor.moveToNext()) {
+ val path = cursor.getString(dataColumn)
+ if (path.contains("screenshot", true)) {
+ if (cache.add(uri.hashCode())) {
+ screenshotTriggered()
+ }
}
}
}
+ } catch (e: SecurityException) {
+ Log.e(TAG, e)
}
}
@@ -56,28 +64,32 @@ class ScreenshotObserver(private val context: Context, handler: Handler, private
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.RELATIVE_PATH
)
- context.contentResolver.query(
- uri,
- projection,
- null,
- null,
- null
- )?.use { cursor ->
- val relativePathColumn =
- cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH)
- val displayNameColumn =
- cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
- while (cursor.moveToNext()) {
- val name = cursor.getString(displayNameColumn)
- val relativePath = cursor.getString(relativePathColumn)
- if (name.contains("screenshot", true) or
- relativePath.contains("screenshot", true)) {
- if (cache.add(uri.hashCode())) {
- screenshotTriggered()
+
+ try {
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val relativePathColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH)
+ val displayNameColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
+ while (cursor.moveToNext()) {
+ val name = cursor.getString(displayNameColumn)
+ val relativePath = cursor.getString(relativePathColumn)
+ if (name.contains("screenshot", true) or
+ relativePath.contains("screenshot", true)) {
+ if (cache.add(uri.hashCode())) {
+ screenshotTriggered()
+ }
}
}
}
+ } catch (e: IllegalStateException) {
+ Log.e(TAG, e)
}
}
-
-}
\ No newline at end of file
+}
From 2630c97a4efe34ffad3d43b5bd72a39ee2357bc9 Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 1 May 2023 17:01:57 +1000
Subject: [PATCH 09/83] add where clause for marking all jobs pending to reduce
the time for writing to db
---
.../org/thoughtcrime/securesms/database/JobDatabase.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
index ef4746923b..21719df20b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
@@ -138,7 +138,10 @@ public class JobDatabase extends Database {
ContentValues contentValues = new ContentValues();
contentValues.put(Jobs.IS_RUNNING, 0);
- databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, null, null);
+ String query = Jobs.IS_RUNNING + " = ?";
+ String[] args = new String[] { "1" };
+
+ databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, query, args);
}
public synchronized void deleteJobs(@NonNull List jobIds) {
From 70aab2994b51896472e08de0d892f64f00b946a4 Mon Sep 17 00:00:00 2001
From: Andrew
Date: Mon, 1 May 2023 16:46:48 +0930
Subject: [PATCH 10/83] Refactor MmsDatabase (#1169)
---
.../securesms/database/MmsDatabase.kt | 155 +++++-------------
.../thoughtcrime/securesms/util/CursorUtil.kt | 6 +
2 files changed, 43 insertions(+), 118 deletions(-)
create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
index 90d3cad454..3a4b35ad17 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
@@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.database.model.Quote
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
import org.thoughtcrime.securesms.mms.MmsException
import org.thoughtcrime.securesms.mms.SlideDeck
+import org.thoughtcrime.securesms.util.asSequence
import java.io.Closeable
import java.io.IOException
import java.security.SecureRandom
@@ -91,54 +92,22 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
return 0
}
- fun addFailures(messageId: Long, failure: List) {
- try {
- addToDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java)
- } catch (e: IOException) {
- Log.w(TAG, e)
+ fun isOutgoingMessage(timestamp: Long): Boolean =
+ databaseHelper.writableDatabase.query(
+ TABLE_NAME,
+ arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS),
+ DATE_SENT + " = ?",
+ arrayOf(timestamp.toString()),
+ null,
+ null,
+ null,
+ null
+ ).use { cursor ->
+ cursor.asSequence()
+ .map { cursor.getColumnIndexOrThrow(MESSAGE_BOX) }
+ .map(cursor::getLong)
+ .any { MmsSmsColumns.Types.isOutgoingMessageType(it) }
}
- }
-
- fun removeFailure(messageId: Long, failure: NetworkFailure?) {
- try {
- removeFromDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java)
- } catch (e: IOException) {
- Log.w(TAG, e)
- }
- }
-
- fun isOutgoingMessage(timestamp: Long): Boolean {
- val database = databaseHelper.writableDatabase
- var cursor: Cursor? = null
- var isOutgoing = false
- try {
- cursor = database.query(
- TABLE_NAME,
- arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS),
- DATE_SENT + " = ?",
- arrayOf(timestamp.toString()),
- null,
- null,
- null,
- null
- )
- while (cursor.moveToNext()) {
- if (MmsSmsColumns.Types.isOutgoingMessageType(
- cursor.getLong(
- cursor.getColumnIndexOrThrow(
- MESSAGE_BOX
- )
- )
- )
- ) {
- isOutgoing = true
- }
- }
- } finally {
- cursor?.close()
- }
- return isOutgoing
- }
fun incrementReceiptCount(
messageId: SyncMessageId,
@@ -254,15 +223,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
}
}
- private fun getThreadIdFor(notification: NotificationInd): Long {
- val fromString =
- if (notification.from != null && notification.from.textString != null) toIsoString(
- notification.from.textString
- ) else ""
- val recipient = Recipient.from(context, fromExternal(context, fromString), false)
- return get(context).threadDatabase().getOrCreateThreadIdFor(recipient)
- }
-
private fun rawQuery(where: String, arguments: Array?): Cursor {
val database = databaseHelper.readableDatabase
return database.rawQuery(
@@ -273,10 +233,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
)
}
- fun getMessages(idsAsString: String): Cursor {
- return rawQuery(idsAsString, null)
- }
-
fun getMessage(messageId: Long): Cursor {
val cursor = rawQuery(RAW_ID_WHERE, arrayOf(messageId.toString()))
setNotifyConverationListeners(cursor, getThreadIdForMessage(messageId))
@@ -306,48 +262,30 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
}
}
- fun markAsPendingInsecureSmsFallback(messageId: Long) {
- val threadId = getThreadIdForMessage(messageId)
+ private fun markAs(
+ messageId: Long,
+ baseType: Long,
+ threadId: Long = getThreadIdForMessage(messageId)
+ ) {
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
- MmsSmsColumns.Types.BASE_PENDING_INSECURE_SMS_FALLBACK,
+ baseType,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
}
fun markAsSending(messageId: Long) {
- val threadId = getThreadIdForMessage(messageId)
- updateMailboxBitmask(
- messageId,
- MmsSmsColumns.Types.BASE_TYPE_MASK,
- MmsSmsColumns.Types.BASE_SENDING_TYPE,
- Optional.of(threadId)
- )
- notifyConversationListeners(threadId)
+ markAs(messageId, MmsSmsColumns.Types.BASE_SENDING_TYPE)
}
fun markAsSentFailed(messageId: Long) {
- val threadId = getThreadIdForMessage(messageId)
- updateMailboxBitmask(
- messageId,
- MmsSmsColumns.Types.BASE_TYPE_MASK,
- MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE,
- Optional.of(threadId)
- )
- notifyConversationListeners(threadId)
+ markAs(messageId, MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE)
}
override fun markAsSent(messageId: Long, secure: Boolean) {
- val threadId = getThreadIdForMessage(messageId)
- updateMailboxBitmask(
- messageId,
- MmsSmsColumns.Types.BASE_TYPE_MASK,
- MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0,
- Optional.of(threadId)
- )
- notifyConversationListeners(threadId)
+ markAs(messageId, MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0)
}
override fun markUnidentified(messageId: Long, unidentified: Boolean) {
@@ -371,13 +309,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
val mentionChange = if (hasMention) { 1 } else { 0 }
get(context).threadDatabase().decrementUnread(threadId, 1, mentionChange)
}
- updateMailboxBitmask(
- messageId,
- MmsSmsColumns.Types.BASE_TYPE_MASK,
- MmsSmsColumns.Types.BASE_DELETED_TYPE,
- Optional.of(threadId)
- )
- notifyConversationListeners(threadId)
+ markAs(messageId, MmsSmsColumns.Types.BASE_DELETED_TYPE, threadId)
}
override fun markExpireStarted(messageId: Long) {
@@ -407,10 +339,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
)
}
- fun setAllMessagesRead(): List {
- return setMessagesRead(READ + " = 0", null)
- }
-
private fun setMessagesRead(where: String, arguments: Array?): List {
val database = databaseHelper.writableDatabase
val result: MutableList = LinkedList()
@@ -419,7 +347,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
try {
cursor = database.query(
TABLE_NAME,
- arrayOf(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED),
+ arrayOf(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED),
where,
arguments,
null,
@@ -1400,25 +1328,16 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
val attachments = get(context).attachmentDatabase().getAttachment(
cursor
)
- val contacts: List = getSharedContacts(
- cursor, attachments
- )
- val contactAttachments =
- contacts.map { obj: Contact? -> obj!!.avatarAttachment }
- .filter { a: Attachment? -> a != null }
- .toSet()
- val previews: List = getLinkPreviews(
- cursor, attachments
- )
- val previewAttachments =
- previews.filter { lp: LinkPreview? -> lp!!.getThumbnail().isPresent }
- .map { lp: LinkPreview? -> lp!!.getThumbnail().get() }
- .toSet()
+ val contacts: List = getSharedContacts(cursor, attachments)
+ val contactAttachments: Set =
+ contacts.mapNotNull { it?.avatarAttachment }.toSet()
+ val previews: List = getLinkPreviews(cursor, attachments)
+ val previewAttachments: Set =
+ previews.mapNotNull { it?.getThumbnail()?.orNull() }.toSet()
val slideDeck = getSlideDeck(
- Stream.of(attachments)
- .filterNot { o: DatabaseAttachment? -> contactAttachments.contains(o) }
- .filterNot { o: DatabaseAttachment? -> previewAttachments.contains(o) }
- .toList()
+ attachments
+ .filterNot { o: DatabaseAttachment? -> o in contactAttachments }
+ .filterNot { o: DatabaseAttachment? -> o in previewAttachments }
)
val quote = getQuote(cursor)
val reactions = get(context).reactionDatabase().getReactions(cursor)
@@ -1623,4 +1542,4 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
const val CREATE_REACTIONS_LAST_SEEN_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $REACTIONS_LAST_SEEN INTEGER DEFAULT 0;"
const val CREATE_HAS_MENTION_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $HAS_MENTION INTEGER DEFAULT 0;"
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt
new file mode 100644
index 0000000000..9cff8c77bc
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt
@@ -0,0 +1,6 @@
+package org.thoughtcrime.securesms.util
+
+import android.database.Cursor
+
+fun Cursor.asSequence(): Sequence =
+ generateSequence { if (moveToNext()) this else null }
From a934c5c2e2e73ad6fb245b3dc88adbcdd15264db Mon Sep 17 00:00:00 2001
From: Andrew
Date: Mon, 1 May 2023 16:49:01 +0930
Subject: [PATCH 11/83] Fix missing media progress (#1151)
---
.../securesms/conversation/v2/utilities/ThumbnailView.kt | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt
index e9a085dad9..4a9986d6ec 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt
@@ -126,10 +126,9 @@ open class ThumbnailView: FrameLayout {
buildThumbnailGlideRequest(glide, slide).into(GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result))
}
slide.hasPlaceholder() -> {
- buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result))
+ buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, null, result))
}
else -> {
- binding.thumbnailLoadIndicator.isVisible = false
glide.clear(binding.thumbnailImage)
result.set(false)
}
From 83b6002a270bca19b98826be0ec0b9d98885c890 Mon Sep 17 00:00:00 2001
From: Andrew
Date: Mon, 1 May 2023 16:49:13 +0930
Subject: [PATCH 12/83] Fix emoji misalignment (#1155)
---
.../v2/ConversationReactionOverlay.java | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
index b3c151690f..1d81325e03 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
@@ -203,10 +203,11 @@ public final class ConversationReactionOverlay extends FrameLayout {
boolean isMessageOnLeft) {
contextMenu = new ConversationContextMenu(dropdownAnchor, getMenuActionItems(messageRecord));
- float itemX = isMessageOnLeft ? scrubberHorizontalMargin :
+ float endX = isMessageOnLeft ? scrubberHorizontalMargin :
selectedConversationModel.getBubbleX() - conversationItem.getWidth() + selectedConversationModel.getBubbleWidth();
- conversationItem.setX(itemX);
- conversationItem.setY(selectedConversationModel.getBubbleY() - statusBarHeight);
+ float endY = selectedConversationModel.getBubbleY() - statusBarHeight;
+ conversationItem.setX(endX);
+ conversationItem.setY(endY);
Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap();
boolean isWideLayout = contextMenu.getMaxWidth() + scrubberWidth < getWidth();
@@ -214,8 +215,6 @@ public final class ConversationReactionOverlay extends FrameLayout {
int overlayHeight = getHeight();
int bubbleWidth = selectedConversationModel.getBubbleWidth();
- float endX = itemX;
- float endY = conversationItem.getY();
float endApparentTop = endY;
float endScale = 1f;
@@ -265,9 +264,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
}
} else {
endY = overlayHeight - contextMenu.getMaxHeight() - menuPadding - conversationItemSnapshot.getHeight();
-
- float contextMenuTop = endY + conversationItemSnapshot.getHeight();
- reactionBarBackgroundY = getReactionBarOffsetForTouch(selectedConversationModel.getBubbleY(), contextMenuTop, menuPadding, reactionBarOffset, reactionBarHeight, reactionBarTopPadding, endY);
+ reactionBarBackgroundY = endY - reactionBarHeight - menuPadding;
}
endApparentTop = endY;
From 99cb10f5befe288a61e56804207808b9972db200 Mon Sep 17 00:00:00 2001
From: Andrew
Date: Mon, 1 May 2023 16:49:19 +0930
Subject: [PATCH 13/83] Add send approval message (#1157)
---
.../conversation/v2/ConversationActivityV2.kt | 8 ++++++++
.../main/res/layout/activity_conversation_v2.xml | 14 +++++++++++++-
app/src/main/res/values/strings.xml | 1 +
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index b5f1b96fd7..cabb583085 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -22,6 +22,7 @@ import androidx.activity.viewModels
import androidx.annotation.DimenRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.drawToBitmap
+import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
@@ -344,6 +345,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
updateSubtitle()
setUpBlockedBanner()
binding!!.searchBottomBar.setEventListener(this)
+ updateSendAfterApprovalText()
showOrHideInputIfNeeded()
setUpMessageRequestsBar()
@@ -653,7 +655,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
setUpMessageRequestsBar()
invalidateOptionsMenu()
updateSubtitle()
+ updateSendAfterApprovalText()
showOrHideInputIfNeeded()
+
binding?.toolbarContent?.profilePictureView?.root?.update(threadRecipient)
binding?.toolbarContent?.conversationTitleView?.text = when {
threadRecipient.isLocalNumber -> getString(R.string.note_to_self)
@@ -662,6 +666,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
}
+ private fun updateSendAfterApprovalText() {
+ binding?.textSendAfterApproval?.isGone = viewModel.recipient?.hasApprovedMe() ?: true
+ }
+
private fun showOrHideInputIfNeeded() {
val recipient = viewModel.recipient
if (recipient != null && recipient.isClosedGroupRecipient) {
diff --git a/app/src/main/res/layout/activity_conversation_v2.xml b/app/src/main/res/layout/activity_conversation_v2.xml
index 4ec4666d7f..d2696a45ec 100644
--- a/app/src/main/res/layout/activity_conversation_v2.xml
+++ b/app/src/main/res/layout/activity_conversation_v2.xml
@@ -35,7 +35,7 @@
android:layout_width="match_parent"
android:layout_height="36dp"
android:visibility="gone"
- android:layout_above="@+id/messageRequestBar"
+ android:layout_above="@+id/textSendAfterApproval"
/>
+
+
%1$d of %2$d
Call Permissions Required
You can enable the \'Voice and video calls\' permission in the Privacy Settings.
+ You will be able to send voice messages and attachments once the recipient has approved this message request
- Delete selected message?
From d868021f0ac5f3f1770b6c0aad2f841f7df9eb3b Mon Sep 17 00:00:00 2001
From: ryanzhao
Date: Thu, 4 May 2023 15:30:09 +1000
Subject: [PATCH 14/83] move job running status from database to memory
---
.../securesms/database/JobDatabase.java | 33 +++++++++----------
.../securesms/database/SessionJobDatabase.kt | 2 +-
.../securesms/database/Storage.kt | 2 +-
.../securesms/jobs/FastJobStorageTest.java | 10 ------
4 files changed, 17 insertions(+), 30 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
index 21719df20b..5e84d5e23a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java
@@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -22,6 +23,8 @@ public class JobDatabase extends Database {
Constraints.CREATE_TABLE,
Dependencies.CREATE_TABLE };
+ private static final ArrayList runningJobs = new ArrayList<>();
+
public static final class Jobs {
public static final String TABLE_NAME = "job_spec";
private static final String ID = "_id";
@@ -113,18 +116,17 @@ public class JobDatabase extends Database {
}
public synchronized void updateJobRunningState(@NonNull String id, boolean isRunning) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(Jobs.IS_RUNNING, isRunning ? 1 : 0);
-
- String query = Jobs.JOB_SPEC_ID + " = ?";
- String[] args = new String[]{ id };
-
- databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, query, args);
+ if (!isRunning) {
+ JobDatabase.runningJobs.remove(id);
+ } else if (!JobDatabase.runningJobs.contains(id)) {
+ JobDatabase.runningJobs.add(id);
+ }
}
public synchronized void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime) {
+ updateJobRunningState(id, isRunning);
+
ContentValues contentValues = new ContentValues();
- contentValues.put(Jobs.IS_RUNNING, isRunning ? 1 : 0);
contentValues.put(Jobs.RUN_ATTEMPT, runAttempt);
contentValues.put(Jobs.NEXT_RUN_ATTEMPT_TIME, nextRunAttemptTime);
@@ -135,13 +137,7 @@ public class JobDatabase extends Database {
}
public synchronized void updateAllJobsToBePending() {
- ContentValues contentValues = new ContentValues();
- contentValues.put(Jobs.IS_RUNNING, 0);
-
- String query = Jobs.IS_RUNNING + " = ?";
- String[] args = new String[] { "1" };
-
- databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, query, args);
+ JobDatabase.runningJobs.clear();
}
public synchronized void deleteJobs(@NonNull List jobIds) {
@@ -202,7 +198,7 @@ public class JobDatabase extends Database {
contentValues.put(Jobs.MAX_INSTANCES, job.getMaxInstances());
contentValues.put(Jobs.LIFESPAN, job.getLifespan());
contentValues.put(Jobs.SERIALIZED_DATA, job.getSerializedData());
- contentValues.put(Jobs.IS_RUNNING, job.isRunning() ? 1 : 0);
+ updateJobRunningState(job.getId(), job.isRunning());
db.insertWithOnConflict(Jobs.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE);
}
@@ -226,7 +222,8 @@ public class JobDatabase extends Database {
}
private @NonNull JobSpec jobSpecFromCursor(@NonNull Cursor cursor) {
- return new JobSpec(cursor.getString(cursor.getColumnIndexOrThrow(Jobs.JOB_SPEC_ID)),
+ String jobId = cursor.getString(cursor.getColumnIndexOrThrow(Jobs.JOB_SPEC_ID));
+ return new JobSpec(jobId,
cursor.getString(cursor.getColumnIndexOrThrow(Jobs.FACTORY_KEY)),
cursor.getString(cursor.getColumnIndexOrThrow(Jobs.QUEUE_KEY)),
cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.CREATE_TIME)),
@@ -237,7 +234,7 @@ public class JobDatabase extends Database {
cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.LIFESPAN)),
cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.MAX_INSTANCES)),
cursor.getString(cursor.getColumnIndexOrThrow(Jobs.SERIALIZED_DATA)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.IS_RUNNING)) == 1);
+ JobDatabase.runningJobs.contains(jobId));
}
private @NonNull ConstraintSpec constraintSpecFromCursor(@NonNull Cursor cursor) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt
index 66497d9da8..b081fb007e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt
@@ -46,7 +46,7 @@ class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
databaseHelper.writableDatabase.delete(sessionJobTable, "${Companion.jobID} = ?", arrayOf( jobID ))
}
- fun getAllPendingJobs(type: String): Map {
+ fun getAllJobs(type: String): Map {
val database = databaseHelper.readableDatabase
return database.getAll(sessionJobTable, "$jobType = ?", arrayOf( type )) { cursor ->
val jobID = cursor.getString(jobID)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 076fa57afc..0d7ea3352f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -211,7 +211,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getAllPendingJobs(type: String): Map {
- return DatabaseComponent.get(context).sessionJobDatabase().getAllPendingJobs(type)
+ return DatabaseComponent.get(context).sessionJobDatabase().getAllJobs(type)
}
override fun getAttachmentUploadJob(attachmentID: Long): AttachmentUploadJob? {
diff --git a/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java b/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
index ee1f232b54..a6624189d1 100644
--- a/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
+++ b/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
@@ -74,16 +74,6 @@ public class FastJobStorageTest {
assertEquals(DataSet1.JOB_2, subject.getJobSpec(DataSet1.JOB_2.getId()));
}
- @Test
- public void updateAllJobsToBePending_writesToDatabase() {
- JobDatabase database = noopDatabase();
- FastJobStorage subject = new FastJobStorage(database);
-
- subject.updateAllJobsToBePending();
-
- verify(database).updateAllJobsToBePending();
- }
-
@Test
public void updateAllJobsToBePending_allArePending() {
FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 1, 1, 1, 1, 1, 1, 1, EMPTY_DATA, true),
From 45eb3549f6ba66838ef80b56beb83058510adf72 Mon Sep 17 00:00:00 2001
From: andrew
Date: Thu, 4 May 2023 14:50:51 +0930
Subject: [PATCH 15/83] Add sync status message
---
.../conversation/v2/ConversationActivityV2.kt | 8 ++
.../v2/ConversationReactionOverlay.java | 5 ++
.../menus/ConversationActionModeCallback.kt | 4 +
.../v2/messages/VisibleMessageView.kt | 73 ++++++++++---------
.../v2/utilities/ResendMessageUtilities.kt | 16 +++-
.../securesms/database/MessagingDatabase.java | 8 +-
.../securesms/database/MmsDatabase.kt | 10 +++
.../securesms/database/MmsSmsColumns.java | 17 +++++
.../securesms/database/SmsDatabase.java | 15 ++++
.../securesms/database/Storage.kt | 56 +++++++++++++-
.../database/model/DisplayRecord.java | 12 +++
.../menu/menu_conversation_item_action.xml | 5 ++
app/src/main/res/values/strings.xml | 4 +
.../libsession/database/StorageProtocol.kt | 5 +-
.../messaging/jobs/MessageSendJob.kt | 2 +
.../messaging/messages/Destination.kt | 6 +-
.../messages/visible/VisibleMessage.kt | 28 +++----
.../sending_receiving/MessageSender.kt | 37 ++++++++--
18 files changed, 248 insertions(+), 63 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index cabb583085..18c62a74c9 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -1755,6 +1755,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
endActionMode()
}
+ override fun resyncMessage(messages: Set) {
+ messages.iterator().forEach { messageRecord ->
+ ResendMessageUtilities.resend(this, messageRecord, viewModel.blindedPublicKey, isResync = true)
+ }
+ endActionMode()
+ }
+
override fun resendMessage(messages: Set) {
messages.iterator().forEach { messageRecord ->
ResendMessageUtilities.resend(this, messageRecord, viewModel.blindedPublicKey)
@@ -1915,6 +1922,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
val selectedItems = setOf(message)
when (action) {
ConversationReactionOverlay.Action.REPLY -> reply(selectedItems)
+ ConversationReactionOverlay.Action.RESYNC -> resyncMessage(selectedItems)
ConversationReactionOverlay.Action.RESEND -> resendMessage(selectedItems)
ConversationReactionOverlay.Action.DOWNLOAD -> saveAttachment(selectedItems)
ConversationReactionOverlay.Action.COPY_MESSAGE -> copyMessages(selectedItems)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
index 1d81325e03..8f1fb6a0e5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
@@ -700,6 +700,10 @@ public final class ConversationReactionOverlay extends FrameLayout {
if (message.isFailed()) {
items.add(new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_resend_message), () -> handleActionItemClicked(Action.RESEND)));
}
+ // Resync
+ if (message.isSyncFailed()) {
+ items.add(new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_resync_message), () -> handleActionItemClicked(Action.RESYNC)));
+ }
// Save media
if (message.isMms() && ((MediaMmsMessageRecord)message).containsMediaSlide()) {
items.add(new ActionItem(R.attr.menu_save_icon, getContext().getResources().getString(R.string.conversation_context_image__save_attachment), () -> handleActionItemClicked(Action.DOWNLOAD),
@@ -885,6 +889,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
public enum Action {
REPLY,
RESEND,
+ RESYNC,
DOWNLOAD,
COPY_MESSAGE,
COPY_SESSION_ID,
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
index d475a64448..f86920f90f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
@@ -70,6 +70,8 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
menu.findItem(R.id.menu_message_details).isVisible = (selectedItems.size == 1 && firstMessage.isOutgoing)
// Resend
menu.findItem(R.id.menu_context_resend).isVisible = (selectedItems.size == 1 && firstMessage.isFailed)
+ // Resync
+ menu.findItem(R.id.menu_context_resync).isVisible = (selectedItems.size == 1 && firstMessage.isSyncFailed)
// Save media
menu.findItem(R.id.menu_context_save_attachment).isVisible = (selectedItems.size == 1
&& firstMessage.isMms && (firstMessage as MediaMmsMessageRecord).containsMediaSlide())
@@ -90,6 +92,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
R.id.menu_context_ban_and_delete_all -> delegate?.banAndDeleteAll(selectedItems)
R.id.menu_context_copy -> delegate?.copyMessages(selectedItems)
R.id.menu_context_copy_public_key -> delegate?.copySessionID(selectedItems)
+ R.id.menu_context_resync -> delegate?.resyncMessage(selectedItems)
R.id.menu_context_resend -> delegate?.resendMessage(selectedItems)
R.id.menu_message_details -> delegate?.showMessageDetail(selectedItems)
R.id.menu_context_save_attachment -> delegate?.saveAttachment(selectedItems)
@@ -113,6 +116,7 @@ interface ConversationActionModeCallbackDelegate {
fun banAndDeleteAll(messages: Set)
fun copyMessages(messages: Set)
fun copySessionID(messages: Set)
+ fun resyncMessage(messages: Set)
fun resendMessage(messages: Set)
fun showMessageDetail(messages: Set)
fun saveAttachment(messages: Set)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
index 2c04bcfce3..745c91e910 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
@@ -292,39 +292,46 @@ class VisibleMessageView : LinearLayout {
@StringRes val messageText: Int?,
val contentDescription: String?)
- private fun getMessageStatusImage(message: MessageRecord): MessageStatusInfo {
- return when {
- !message.isOutgoing -> MessageStatusInfo(null,
- null,
- null,
- null)
- message.isFailed ->
- MessageStatusInfo(
- R.drawable.ic_delivery_status_failed,
- resources.getColor(R.color.destructive, context.theme),
- R.string.delivery_status_failed,
- null
- )
- message.isPending ->
- MessageStatusInfo(
- R.drawable.ic_delivery_status_sending,
- context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_sending,
- context.getString(R.string.AccessibilityId_message_sent_status_pending)
- )
- message.isRead ->
- MessageStatusInfo(
- R.drawable.ic_delivery_status_read,
- context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_read,
- null
- )
- else ->
- MessageStatusInfo(
- R.drawable.ic_delivery_status_sent,
- context.getColorFromAttr(R.attr.message_status_color),
- R.string.delivery_status_sent,
- context.getString(R.string.AccessibilityId_message_sent_status_tick)
- )
- }
+ private fun getMessageStatusImage(message: MessageRecord): MessageStatusInfo = when {
+ message.isFailed ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_failed,
+ resources.getColor(R.color.destructive, context.theme),
+ R.string.delivery_status_failed,
+ null
+ )
+ message.isSyncFailed ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_failed,
+ resources.getColor(R.color.destructive, context.theme),
+ R.string.delivery_status_sync_failed,
+ null
+ )
+ message.isPending ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_sending,
+ context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_sending,
+ context.getString(R.string.AccessibilityId_message_sent_status_pending)
+ )
+ message.isResyncing ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_sending,
+ context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_syncing,
+ context.getString(R.string.AccessibilityId_message_sent_status_syncing)
+ )
+ message.isRead ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_read,
+ context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_read,
+ null
+ )
+ else ->
+ MessageStatusInfo(
+ R.drawable.ic_delivery_status_sent,
+ context.getColorFromAttr(R.attr.message_status_color),
+ R.string.delivery_status_sent,
+ context.getString(R.string.AccessibilityId_message_sent_status_tick)
+ )
}
private fun updateExpirationTimer(message: MessageRecord) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
index 80f4cc0bf8..5e6283e1ad 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import org.session.libsession.messaging.MessagingModuleConfiguration
+import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.visible.LinkPreview
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
import org.session.libsession.messaging.messages.visible.Quote
@@ -10,12 +11,16 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
+import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
+private val TAG = ResendMessageUtilities.javaClass.simpleName
+
object ResendMessageUtilities {
- fun resend(context: Context, messageRecord: MessageRecord, userBlindedKey: String?) {
+ fun resend(context: Context, messageRecord: MessageRecord, userBlindedKey: String?, isResync: Boolean = false) {
+ Log.d(TAG, "resend() called with: context = $context, messageRecord = $messageRecord, userBlindedKey = $userBlindedKey, isResync = $isResync")
val recipient: Recipient = messageRecord.recipient
val message = VisibleMessage()
message.id = messageRecord.getId()
@@ -55,8 +60,13 @@ object ResendMessageUtilities {
val sentTimestamp = message.sentTimestamp
val sender = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
if (sentTimestamp != null && sender != null) {
- MessagingModuleConfiguration.shared.storage.markAsSending(sentTimestamp, sender)
+ if (isResync) {
+ MessagingModuleConfiguration.shared.storage.markAsResyncing(sentTimestamp, sender)
+ MessageSender.send(message, Destination.from(recipient.address), isSyncMessage = true)
+ } else {
+ MessagingModuleConfiguration.shared.storage.markAsSending(sentTimestamp, sender)
+ MessageSender.send(message, recipient.address)
+ }
}
- MessageSender.send(message, recipient.address)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java
index d3ba31747d..edc6bc1a6f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java
@@ -37,6 +37,13 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
public abstract void markExpireStarted(long messageId, long startTime);
public abstract void markAsSent(long messageId, boolean secure);
+
+ public abstract void markAsSyncing(long id);
+
+ public abstract void markAsResyncing(long id);
+
+ public abstract void markAsSyncFailed(long id);
+
public abstract void markUnidentified(long messageId, boolean unidentified);
public abstract void markAsDeleted(long messageId, boolean read, boolean hasMention);
@@ -199,7 +206,6 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
contentValues.put(THREAD_ID, newThreadId);
db.update(getTableName(), contentValues, where, args);
}
-
public static class SyncMessageId {
private final Address address;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
index 3a4b35ad17..9e854698f5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
@@ -276,6 +276,16 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
notifyConversationListeners(threadId)
}
+ override fun markAsSyncing(messageId: Long) {
+ markAs(messageId, MmsSmsColumns.Types.BASE_SYNCING_TYPE)
+ }
+ override fun markAsResyncing(messageId: Long) {
+ markAs(messageId, MmsSmsColumns.Types.BASE_RESYNCING_TYPE)
+ }
+ override fun markAsSyncFailed(messageId: Long) {
+ markAs(messageId, MmsSmsColumns.Types.BASE_SYNC_FAILED_TYPE)
+ }
+
fun markAsSending(messageId: Long) {
markAs(messageId, MmsSmsColumns.Types.BASE_SENDING_TYPE)
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java
index f3110a5c79..1e1cc50896 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java
@@ -47,8 +47,13 @@ public interface MmsSmsColumns {
protected static final long BASE_PENDING_INSECURE_SMS_FALLBACK = 26;
public static final long BASE_DRAFT_TYPE = 27;
protected static final long BASE_DELETED_TYPE = 28;
+ protected static final long BASE_SYNCING_TYPE = 29;
+ protected static final long BASE_RESYNCING_TYPE = 30;
+ protected static final long BASE_SYNC_FAILED_TYPE = 31;
protected static final long[] OUTGOING_MESSAGE_TYPES = {BASE_OUTBOX_TYPE, BASE_SENT_TYPE,
+ BASE_SYNCING_TYPE, BASE_RESYNCING_TYPE,
+ BASE_SYNC_FAILED_TYPE,
BASE_SENDING_TYPE, BASE_SENT_FAILED_TYPE,
BASE_PENDING_SECURE_SMS_FALLBACK,
BASE_PENDING_INSECURE_SMS_FALLBACK,
@@ -109,6 +114,18 @@ public interface MmsSmsColumns {
return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
}
+ public static boolean isResyncingType(long type) {
+ return (type & BASE_TYPE_MASK) == BASE_RESYNCING_TYPE;
+ }
+
+ public static boolean isSyncingType(long type) {
+ return (type & BASE_TYPE_MASK) == BASE_SYNCING_TYPE;
+ }
+
+ public static boolean isSyncFailedMessageType(long type) {
+ return (type & BASE_TYPE_MASK) == BASE_SYNC_FAILED_TYPE;
+ }
+
public static boolean isFailedMessageType(long type) {
return (type & BASE_TYPE_MASK) == BASE_SENT_FAILED_TYPE;
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java
index 0d61b26796..42a00ccbb2 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java
@@ -202,6 +202,21 @@ public class SmsDatabase extends MessagingDatabase {
updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SENDING_TYPE);
}
+ @Override
+ public void markAsSyncing(long id) {
+ updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SYNCING_TYPE);
+ }
+
+ @Override
+ public void markAsResyncing(long id) {
+ updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_RESYNCING_TYPE);
+ }
+
+ @Override
+ public void markAsSyncFailed(long id) {
+ updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SYNC_FAILED_TYPE);
+ }
+
@Override
public void markUnidentified(long id, boolean unidentified) {
ContentValues contentValues = new ContentValues(1);
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 076fa57afc..77f616026c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -41,6 +41,7 @@ import org.session.libsignal.messages.SignalServiceAttachmentPointer
import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.KeyHelper
+import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
@@ -53,6 +54,8 @@ import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.security.MessageDigest
+private val TAG = Storage::class.java.simpleName
+
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
override fun getUserPublicKey(): String? {
@@ -356,6 +359,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
openGroupSentTimestamp: Long,
threadId: Long
) {
+ Log.d(TAG, "updateSentTimestamp() called with: messageID = $messageID, isMms = $isMms, openGroupSentTimestamp = $openGroupSentTimestamp, threadId = $threadId")
+
if (isMms) {
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
mmsDb.updateSentTimestamp(messageID, openGroupSentTimestamp, threadId)
@@ -366,6 +371,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun markAsSent(timestamp: Long, author: String) {
+ Log.d(TAG, "markAsSent() called with: timestamp = $timestamp, author = $author")
+
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -377,7 +384,29 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
}
+ override fun markAsSyncing(timestamp: Long, author: String) {
+ Log.d(TAG, "markAsSyncing() called with: timestamp = $timestamp, author = $author")
+
+ DatabaseComponent.get(context).mmsSmsDatabase()
+ .getMessageFor(timestamp, author)
+ ?.run { getMmsDatabaseElseSms(isMms).markAsSyncing(id) }
+ }
+
+ private fun getMmsDatabaseElseSms(isMms: Boolean) =
+ if (isMms) DatabaseComponent.get(context).mmsDatabase()
+ else DatabaseComponent.get(context).smsDatabase()
+
+ override fun markAsResyncing(timestamp: Long, author: String) {
+ Log.d(TAG, "markAsResyncing() called with: timestamp = $timestamp, author = $author")
+
+ DatabaseComponent.get(context).mmsSmsDatabase()
+ .getMessageFor(timestamp, author)
+ ?.run { getMmsDatabaseElseSms(isMms).markAsResyncing(id) }
+ }
+
override fun markAsSending(timestamp: Long, author: String) {
+ Log.d(TAG, "markAsSending() called with: timestamp = $timestamp, author = $author")
+
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -402,7 +431,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
}
- override fun setErrorMessage(timestamp: Long, author: String, error: Exception) {
+ override fun markAsSentFailed(timestamp: Long, author: String, error: Exception) {
+ Log.d(TAG, "markAsSentFailed() called with: timestamp = $timestamp, author = $author, error = $error")
+
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -425,6 +456,28 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
}
+ override fun markAsSyncFailed(timestamp: Long, author: String, error: Exception) {
+ Log.d(TAG, "markAsSyncFailed() called with: timestamp = $timestamp, author = $author, error = $error")
+
+ val database = DatabaseComponent.get(context).mmsSmsDatabase()
+ val messageRecord = database.getMessageFor(timestamp, author) ?: return
+
+ database.getMessageFor(timestamp, author)
+ ?.run { getMmsDatabaseElseSms(isMms).markAsSyncFailed(id) }
+
+ if (error.localizedMessage != null) {
+ val message: String
+ if (error is OnionRequestAPI.HTTPRequestFailedAtDestinationException && error.statusCode == 429) {
+ message = "429: Rate limited."
+ } else {
+ message = error.localizedMessage!!
+ }
+ DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), message)
+ } else {
+ DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), error.javaClass.simpleName)
+ }
+ }
+
override fun clearErrorMessage(messageID: Long) {
val db = DatabaseComponent.get(context).lokiMessageDatabase()
db.clearErrorMessage(messageID)
@@ -983,5 +1036,4 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
return recipientDb.blockedContacts
}
-
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java
index ef0f4b54f3..39fba182aa 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java
@@ -80,6 +80,18 @@ public abstract class DisplayRecord {
return !isFailed() && !isPending();
}
+ public boolean isSyncing() {
+ return MmsSmsColumns.Types.isSyncingType(type);
+ }
+
+ public boolean isResyncing() {
+ return MmsSmsColumns.Types.isResyncingType(type);
+ }
+
+ public boolean isSyncFailed() {
+ return MmsSmsColumns.Types.isSyncFailedMessageType(type);
+ }
+
public boolean isFailed() {
return MmsSmsColumns.Types.isFailedMessageType(type)
|| MmsSmsColumns.Types.isPendingSecureSmsFallbackType(type)
diff --git a/app/src/main/res/menu/menu_conversation_item_action.xml b/app/src/main/res/menu/menu_conversation_item_action.xml
index 8e20939225..ea81685617 100644
--- a/app/src/main/res/menu/menu_conversation_item_action.xml
+++ b/app/src/main/res/menu/menu_conversation_item_action.xml
@@ -32,6 +32,11 @@
android:icon="?menu_copy_icon"
app:showAsAction="always" />
+
+
-
Message sent status: Sent
Message sent status pending
+ Message sent status syncing
Message request has been accepted
Message Body
Voice message
@@ -627,6 +628,7 @@
Delete message
Ban user
Ban and delete all
+ Resync message
Resend message
Reply
Reply to message
@@ -1007,9 +1009,11 @@
Close Dialog
Database Upgrade Failed
Please contact support to report the error.
+ Syncing
Sending
Read
Sent
+ Failed to sync
Failed to send
Search GIFs?
Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.
diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
index d75e209d11..48d15a18ac 100644
--- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
+++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
@@ -106,10 +106,13 @@ interface StorageProtocol {
fun getAttachmentsForMessage(messageID: Long): List
fun getMessageIdInDatabase(timestamp: Long, author: String): Long? // TODO: This is a weird name
fun updateSentTimestamp(messageID: Long, isMms: Boolean, openGroupSentTimestamp: Long, threadId: Long)
+ fun markAsResyncing(timestamp: Long, author: String)
+ fun markAsSyncing(timestamp: Long, author: String)
fun markAsSending(timestamp: Long, author: String)
fun markAsSent(timestamp: Long, author: String)
fun markUnidentified(timestamp: Long, author: String)
- fun setErrorMessage(timestamp: Long, author: String, error: Exception)
+ fun markAsSyncFailed(timestamp: Long, author: String, error: Exception)
+ fun markAsSentFailed(timestamp: Long, author: String, error: Exception)
fun clearErrorMessage(messageID: Long)
fun setMessageServerHash(messageID: Long, serverHash: String)
diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
index 524338592c..4300fe4b61 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
@@ -34,6 +34,8 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
}
override fun execute(dispatcherName: String) {
+ Log.d(TAG, "MessageSendJob#execute() called with: dispatcherName = $dispatcherName")
+
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val message = message as? VisibleMessage
val storage = MessagingModuleConfiguration.shared.storage
diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/Destination.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/Destination.kt
index 3abf0ed3e1..f30c1b9168 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/messages/Destination.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/messages/Destination.kt
@@ -7,13 +7,13 @@ import org.session.libsignal.utilities.toHexString
sealed class Destination {
- class Contact(var publicKey: String) : Destination() {
+ data class Contact(var publicKey: String) : Destination() {
internal constructor(): this("")
}
- class ClosedGroup(var groupPublicKey: String) : Destination() {
+ data class ClosedGroup(var groupPublicKey: String) : Destination() {
internal constructor(): this("")
}
- class LegacyOpenGroup(var roomToken: String, var server: String) : Destination() {
+ data class LegacyOpenGroup(var roomToken: String, var server: String) : Destination() {
internal constructor(): this("", "")
}
diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt
index e66147da18..705fc7ce45 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt
@@ -11,20 +11,22 @@ import org.session.libsignal.protos.SignalServiceProtos
import org.session.libsignal.utilities.Log
import org.session.libsession.messaging.sending_receiving.attachments.Attachment as SignalAttachment
-class VisibleMessage : Message() {
- /** In the case of a sync message, the public key of the person the message was targeted at.
- *
- * **Note:** `nil` if this isn't a sync message.
- */
- var syncTarget: String? = null
- var text: String? = null
- val attachmentIDs: MutableList = mutableListOf()
- var quote: Quote? = null
- var linkPreview: LinkPreview? = null
- var profile: Profile? = null
- var openGroupInvitation: OpenGroupInvitation? = null
- var reaction: Reaction? = null
+/**
+ * @param syncTarget In the case of a sync message, the public key of the person the message was targeted at.
+ *
+ * **Note:** `nil` if this isn't a sync message.
+ */
+class VisibleMessage(
+ var syncTarget: String? = null,
+ var text: String? = null,
+ val attachmentIDs: MutableList = mutableListOf(),
+ var quote: Quote? = null,
+ var linkPreview: LinkPreview? = null,
+ var profile: Profile? = null,
+ var openGroupInvitation: OpenGroupInvitation? = null,
+ var reaction: Reaction? = null,
var hasMention: Boolean = false
+) : Message() {
override val isSelfSendValid: Boolean = true
diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
index eb0d15739b..9da6cd8b14 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
@@ -39,6 +39,8 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview as SignalLinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel as SignalQuote
+private val TAG = MessageSender::class.java.simpleName
+
object MessageSender {
// Error
@@ -61,16 +63,20 @@ object MessageSender {
}
// Convenience
- fun send(message: Message, destination: Destination): Promise {
+ fun send(message: Message, destination: Destination, isSyncMessage: Boolean = false): Promise {
+ Log.d(TAG, "send() called with: message = $message, destination = $destination, isSyncMessage = $isSyncMessage")
+
return if (destination is Destination.LegacyOpenGroup || destination is Destination.OpenGroup || destination is Destination.OpenGroupInbox) {
sendToOpenGroupDestination(destination, message)
} else {
- sendToSnodeDestination(destination, message)
+ sendToSnodeDestination(destination, message, isSyncMessage)
}
}
// One-on-One Chats & Closed Groups
private fun sendToSnodeDestination(destination: Destination, message: Message, isSyncMessage: Boolean = false): Promise {
+ Log.d(TAG, "sendToSnodeDestination() called with: destination = $destination, message = $message, isSyncMessage = $isSyncMessage")
+
val deferred = deferred()
val promise = deferred.promise
val storage = MessagingModuleConfiguration.shared.storage
@@ -86,7 +92,7 @@ object MessageSender {
val isSelfSend = (message.recipient == userPublicKey)
// Set the failure handler (need it here already for precondition failure handling)
fun handleFailure(error: Exception) {
- handleFailedMessageSend(message, error)
+ handleFailedMessageSend(message, error, isSyncMessage)
if (destination is Destination.Contact && message is VisibleMessage && !isSelfSend) {
SnodeModule.shared.broadcaster.broadcast("messageFailed", message.sentTimestamp!!)
}
@@ -220,6 +226,8 @@ object MessageSender {
// Open Groups
private fun sendToOpenGroupDestination(destination: Destination, message: Message): Promise {
+ Log.d(TAG, "sendToOpenGroupDestination() called with: destination = $destination, message = $message")
+
val deferred = deferred()
val storage = MessagingModuleConfiguration.shared.storage
if (message.sentTimestamp == null) {
@@ -318,6 +326,8 @@ object MessageSender {
// Result Handling
fun handleSuccessfulMessageSend(message: Message, destination: Destination, isSyncMessage: Boolean = false, openGroupSentTimestamp: Long = -1) {
+ Log.d(TAG, "handleSuccessfulMessageSend() called with: message = $message, destination = $destination, isSyncMessage = $isSyncMessage, openGroupSentTimestamp = $openGroupSentTimestamp")
+
val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!!
// Ignore future self-sends
@@ -374,21 +384,32 @@ object MessageSender {
// • the destination was a contact
// • we didn't sync it already
if (destination is Destination.Contact && !isSyncMessage) {
- if (message is VisibleMessage) { message.syncTarget = destination.publicKey }
- if (message is ExpirationTimerUpdate) { message.syncTarget = destination.publicKey }
+ if (message is VisibleMessage) message.syncTarget = destination.publicKey
+ if (message is ExpirationTimerUpdate) message.syncTarget = destination.publicKey
+
+ storage.markAsSyncing(message.sentTimestamp!!, userPublicKey)
sendToSnodeDestination(Destination.Contact(userPublicKey), message, true)
}
}
- fun handleFailedMessageSend(message: Message, error: Exception) {
+ fun handleFailedMessageSend(message: Message, error: Exception, isSyncMessage: Boolean = false) {
+ Log.d(TAG, "handleFailedMessageSend() called with: message = $message, error = $error, isSyncMessage = $isSyncMessage")
+
val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!!
- storage.setErrorMessage(message.sentTimestamp!!, message.sender?:userPublicKey, error)
+
+ val timestamp = message.sentTimestamp!!
+ val author = message.sender ?: userPublicKey
+
+ if (isSyncMessage) storage.markAsSyncFailed(timestamp, author, error)
+ else storage.markAsSentFailed(timestamp, author, error)
}
// Convenience
@JvmStatic
fun send(message: VisibleMessage, address: Address, attachments: List, quote: SignalQuote?, linkPreview: SignalLinkPreview?) {
+ Log.d(TAG, "send() called with: message = $message, address = $address, attachments = $attachments, quote = $quote, linkPreview = $linkPreview")
+
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val attachmentIDs = messageDataProvider.getAttachmentIDsFor(message.id!!)
message.attachmentIDs.addAll(attachmentIDs)
@@ -407,6 +428,8 @@ object MessageSender {
@JvmStatic
fun send(message: Message, address: Address) {
+ Log.d(TAG, "send() called with: message = $message, address = $address")
+
val threadID = MessagingModuleConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
From d3ce899a8056c9b9d307f9993845603b0016c058 Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:07:19 +0930
Subject: [PATCH 16/83] Synchronize all Cipher#doFinal
---
.../securesms/backup/FullBackupExporter.kt | 35 +++++++++------
.../session/libsession/utilities/AESGCM.kt | 17 ++++---
.../session/libsignal/crypto/CipherUtil.java | 5 +++
.../session/libsignal/crypto/DiffieHellman.kt | 45 -------------------
.../session/libsignal/crypto/kdf/HKDF.java | 8 +---
.../streams/AttachmentCipherOutputStream.java | 15 ++++---
.../streams/ProfileCipherInputStream.java | 30 +++++++------
.../streams/ProfileCipherOutputStream.java | 16 ++++---
8 files changed, 75 insertions(+), 96 deletions(-)
create mode 100644 libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
delete mode 100644 libsignal/src/main/java/org/session/libsignal/crypto/DiffieHellman.kt
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
index 6b5d47a2e6..783468eee7 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
@@ -14,6 +14,7 @@ import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
import org.session.libsession.utilities.Conversions
import org.session.libsession.utilities.Util
+import org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK
import org.session.libsignal.crypto.kdf.HKDFv3
import org.session.libsignal.utilities.ByteUtil
import org.session.libsignal.utilities.Log
@@ -289,7 +290,7 @@ object FullBackupExporter {
private var counter: Int = 0
- constructor(outputStream: OutputStream, passphrase: String) : super() {
+ private constructor(outputStream: OutputStream, passphrase: String) : super() {
try {
val salt = Util.getSecretBytes(32)
val key = BackupUtil.computeBackupKey(passphrase, salt)
@@ -381,18 +382,24 @@ object FullBackupExporter {
private fun writeStream(inputStream: InputStream) {
try {
Conversions.intToByteArray(iv, 0, counter++)
- cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
- mac.update(iv)
- val buffer = ByteArray(8192)
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- val ciphertext = cipher.update(buffer, 0, read)
- if (ciphertext != null) {
- outputStream.write(ciphertext)
- mac.update(ciphertext)
+ val remainder = synchronized(CIPHER_LOCK) {
+ cipher.init(
+ Cipher.ENCRYPT_MODE,
+ SecretKeySpec(cipherKey, "AES"),
+ IvParameterSpec(iv)
+ )
+ mac.update(iv)
+ val buffer = ByteArray(8192)
+ var read: Int
+ while (inputStream.read(buffer).also { read = it } != -1) {
+ val ciphertext = cipher.update(buffer, 0, read)
+ if (ciphertext != null) {
+ outputStream.write(ciphertext)
+ mac.update(ciphertext)
+ }
}
+ cipher.doFinal()
}
- val remainder = cipher.doFinal()
outputStream.write(remainder)
mac.update(remainder)
val attachmentDigest = mac.doFinal()
@@ -414,8 +421,10 @@ object FullBackupExporter {
private fun write(out: OutputStream, frame: BackupFrame) {
try {
Conversions.intToByteArray(iv, 0, counter++)
- cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
- val frameCiphertext = cipher.doFinal(frame.toByteArray())
+ val frameCiphertext = synchronized(CIPHER_LOCK) {
+ cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
+ cipher.doFinal(frame.toByteArray())
+ }
val frameMac = mac.doFinal(frameCiphertext)
val length = Conversions.intToByteArray(frameCiphertext.size + 10)
out.write(length)
diff --git a/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt b/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt
index 225900b096..4a6a588dc2 100644
--- a/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt
+++ b/libsession/src/main/java/org/session/libsession/utilities/AESGCM.kt
@@ -1,6 +1,7 @@
package org.session.libsession.utilities
import androidx.annotation.WorkerThread
+import org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK
import org.session.libsignal.utilities.ByteUtil
import org.session.libsignal.utilities.Util
import org.session.libsignal.utilities.Hex
@@ -27,9 +28,11 @@ internal object AESGCM {
internal fun decrypt(ivAndCiphertext: ByteArray, symmetricKey: ByteArray): ByteArray {
val iv = ivAndCiphertext.sliceArray(0 until ivSize)
val ciphertext = ivAndCiphertext.sliceArray(ivSize until ivAndCiphertext.count())
- val cipher = Cipher.getInstance("AES/GCM/NoPadding")
- cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(gcmTagSize, iv))
- return cipher.doFinal(ciphertext)
+ synchronized(CIPHER_LOCK) {
+ val cipher = Cipher.getInstance("AES/GCM/NoPadding")
+ cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(gcmTagSize, iv))
+ return cipher.doFinal(ciphertext)
+ }
}
/**
@@ -47,9 +50,11 @@ internal object AESGCM {
*/
internal fun encrypt(plaintext: ByteArray, symmetricKey: ByteArray): ByteArray {
val iv = Util.getSecretBytes(ivSize)
- val cipher = Cipher.getInstance("AES/GCM/NoPadding")
- cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(gcmTagSize, iv))
- return ByteUtil.combine(iv, cipher.doFinal(plaintext))
+ synchronized(CIPHER_LOCK) {
+ val cipher = Cipher.getInstance("AES/GCM/NoPadding")
+ cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(gcmTagSize, iv))
+ return ByteUtil.combine(iv, cipher.doFinal(plaintext))
+ }
}
/**
diff --git a/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java b/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
new file mode 100644
index 0000000000..d3423a0bd4
--- /dev/null
+++ b/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
@@ -0,0 +1,5 @@
+package org.session.libsignal.crypto;
+
+public class CipherUtil {
+ public static final Object CIPHER_LOCK = new Object();
+}
diff --git a/libsignal/src/main/java/org/session/libsignal/crypto/DiffieHellman.kt b/libsignal/src/main/java/org/session/libsignal/crypto/DiffieHellman.kt
deleted file mode 100644
index 2b613247bf..0000000000
--- a/libsignal/src/main/java/org/session/libsignal/crypto/DiffieHellman.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.session.libsignal.crypto
-
-import org.whispersystems.curve25519.Curve25519
-import org.session.libsignal.utilities.Util
-import javax.crypto.Cipher
-import javax.crypto.spec.IvParameterSpec
-import javax.crypto.spec.SecretKeySpec
-
-object DiffieHellman {
- private val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
- private val curve = Curve25519.getInstance(Curve25519.BEST)
- private val ivSize = 16
-
- @JvmStatic @Throws
- fun encrypt(plaintext: ByteArray, symmetricKey: ByteArray): ByteArray {
- val iv = Util.getSecretBytes(ivSize)
- val ivSpec = IvParameterSpec(iv)
- val secretKeySpec = SecretKeySpec(symmetricKey, "AES")
- cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec)
- val ciphertext = cipher.doFinal(plaintext)
- return iv + ciphertext
- }
-
- @JvmStatic @Throws
- fun encrypt(plaintext: ByteArray, publicKey: ByteArray, privateKey: ByteArray): ByteArray {
- val symmetricKey = curve.calculateAgreement(publicKey, privateKey)
- return encrypt(plaintext, symmetricKey)
- }
-
- @JvmStatic @Throws
- fun decrypt(ivAndCiphertext: ByteArray, symmetricKey: ByteArray): ByteArray {
- val iv = ivAndCiphertext.sliceArray(0 until ivSize)
- val ciphertext = ivAndCiphertext.sliceArray(ivSize until ivAndCiphertext.size)
- val ivSpec = IvParameterSpec(iv)
- val secretKeySpec = SecretKeySpec(symmetricKey, "AES")
- cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec)
- return cipher.doFinal(ciphertext)
- }
-
- @JvmStatic @Throws
- fun decrypt(ivAndCiphertext: ByteArray, publicKey: ByteArray, privateKey: ByteArray): ByteArray {
- val symmetricKey = curve.calculateAgreement(publicKey, privateKey)
- return decrypt(ivAndCiphertext, symmetricKey)
- }
-}
diff --git a/libsignal/src/main/java/org/session/libsignal/crypto/kdf/HKDF.java b/libsignal/src/main/java/org/session/libsignal/crypto/kdf/HKDF.java
index 3295f06e52..73c87c075d 100644
--- a/libsignal/src/main/java/org/session/libsignal/crypto/kdf/HKDF.java
+++ b/libsignal/src/main/java/org/session/libsignal/crypto/kdf/HKDF.java
@@ -39,9 +39,7 @@ public abstract class HKDF {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(salt, "HmacSHA256"));
return mac.doFinal(inputKeyMaterial);
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- } catch (InvalidKeyException e) {
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new AssertionError(e);
}
}
@@ -73,9 +71,7 @@ public abstract class HKDF {
}
return results.toByteArray();
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- } catch (InvalidKeyException e) {
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new AssertionError(e);
}
}
diff --git a/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherOutputStream.java b/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherOutputStream.java
index 91c3563700..2f58c84c78 100644
--- a/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherOutputStream.java
+++ b/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherOutputStream.java
@@ -6,6 +6,8 @@
package org.session.libsignal.streams;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import org.session.libsignal.utilities.Util;
import java.io.IOException;
@@ -68,16 +70,17 @@ public class AttachmentCipherOutputStream extends DigestingOutputStream {
@Override
public void flush() throws IOException {
try {
- byte[] ciphertext = cipher.doFinal();
+ byte[] ciphertext;
+ synchronized (CIPHER_LOCK) {
+ ciphertext = cipher.doFinal();
+ }
byte[] auth = mac.doFinal(ciphertext);
super.write(ciphertext);
super.write(auth);
super.flush();
- } catch (IllegalBlockSizeException e) {
- throw new AssertionError(e);
- } catch (BadPaddingException e) {
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
@@ -97,9 +100,7 @@ public class AttachmentCipherOutputStream extends DigestingOutputStream {
private Cipher initializeCipher() {
try {
return Cipher.getInstance("AES/CBC/PKCS5Padding");
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- } catch (NoSuchPaddingException e) {
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new AssertionError(e);
}
}
diff --git a/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherInputStream.java b/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherInputStream.java
index aa15eb00c6..19996c17cb 100644
--- a/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherInputStream.java
+++ b/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherInputStream.java
@@ -1,5 +1,7 @@
package org.session.libsignal.streams;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import org.session.libsignal.utilities.Util;
import java.io.FilterInputStream;
@@ -62,23 +64,23 @@ public class ProfileCipherInputStream extends FilterInputStream {
byte[] ciphertext = new byte[outputLength / 2];
int read = in.read(ciphertext, 0, ciphertext.length);
- if (read == -1) {
- if (cipher.getOutputSize(0) > outputLength) {
- throw new AssertionError("Need: " + cipher.getOutputSize(0) + " but only have: " + outputLength);
- }
+ synchronized (CIPHER_LOCK) {
+ if (read == -1) {
+ if (cipher.getOutputSize(0) > outputLength) {
+ throw new AssertionError("Need: " + cipher.getOutputSize(0) + " but only have: " + outputLength);
+ }
- finished = true;
- return cipher.doFinal(output, outputOffset);
- } else {
- if (cipher.getOutputSize(read) > outputLength) {
- throw new AssertionError("Need: " + cipher.getOutputSize(read) + " but only have: " + outputLength);
- }
+ finished = true;
+ return cipher.doFinal(output, outputOffset);
+ } else {
+ if (cipher.getOutputSize(read) > outputLength) {
+ throw new AssertionError("Need: " + cipher.getOutputSize(read) + " but only have: " + outputLength);
+ }
- return cipher.update(ciphertext, 0, read, output, outputOffset);
+ return cipher.update(ciphertext, 0, read, output, outputOffset);
+ }
}
- } catch (IllegalBlockSizeException e) {
- throw new AssertionError(e);
- } catch(ShortBufferException e) {
+ } catch (IllegalBlockSizeException | ShortBufferException e) {
throw new AssertionError(e);
} catch (BadPaddingException e) {
throw new IOException(e);
diff --git a/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherOutputStream.java b/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherOutputStream.java
index 9d4e13a0c2..f47a5f72b6 100644
--- a/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherOutputStream.java
+++ b/libsignal/src/main/java/org/session/libsignal/streams/ProfileCipherOutputStream.java
@@ -1,5 +1,7 @@
package org.session.libsignal.streams;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
@@ -54,20 +56,24 @@ public class ProfileCipherOutputStream extends DigestingOutputStream {
byte[] input = new byte[1];
input[0] = (byte)b;
- byte[] output = cipher.update(input);
+ byte[] output;
+ synchronized (CIPHER_LOCK) {
+ output = cipher.update(input);
+ }
super.write(output);
}
@Override
public void flush() throws IOException {
try {
- byte[] output = cipher.doFinal();
+ byte[] output;
+ synchronized (CIPHER_LOCK) {
+ output = cipher.doFinal();
+ }
super.write(output);
super.flush();
- } catch (BadPaddingException e) {
- throw new AssertionError(e);
- } catch (IllegalBlockSizeException e) {
+ } catch (BadPaddingException | IllegalBlockSizeException e) {
throw new AssertionError(e);
}
}
From 24741fcc22dabaef7757d723be355654bc70e1b9 Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:10:46 +0930
Subject: [PATCH 17/83] Synchronize Cipher in KeystoreHelper
---
.../securesms/crypto/KeyStoreHelper.java | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
index 43e9865598..45ec9e207f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
@@ -45,44 +45,46 @@ public final class KeyStoreHelper {
private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
private static final String KEY_ALIAS = "SignalSecret";
- @RequiresApi(Build.VERSION_CODES.M)
+ private static final Object lock = new Object();
+
public static SealedData seal(@NonNull byte[] input) {
SecretKey secretKey = getOrCreateKeyStoreEntry();
try {
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ synchronized (lock) {
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
- byte[] iv = cipher.getIV();
- byte[] data = cipher.doFinal(input);
+ byte[] iv = cipher.getIV();
+ byte[] data = cipher.doFinal(input);
- return new SealedData(iv, data);
+ return new SealedData(iv, data);
+ }
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
- @RequiresApi(Build.VERSION_CODES.M)
public static byte[] unseal(@NonNull SealedData sealedData) {
SecretKey secretKey = getKeyStoreEntry();
try {
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
- cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
+ synchronized (lock) {
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
- return cipher.doFinal(sealedData.data);
+ return cipher.doFinal(sealedData.data);
+ }
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey getOrCreateKeyStoreEntry() {
if (hasKeyStoreEntry()) return getKeyStoreEntry();
else return createKeyStoreEntry();
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey createKeyStoreEntry() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
@@ -99,7 +101,6 @@ public final class KeyStoreHelper {
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey getKeyStoreEntry() {
KeyStore keyStore = getKeyStore();
@@ -137,7 +138,6 @@ public final class KeyStoreHelper {
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static boolean hasKeyStoreEntry() {
try {
KeyStore ks = KeyStore.getInstance(ANDROID_KEY_STORE);
From a152250a6007c423bda465f8c8824f1be5b73780 Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:18:39 +0930
Subject: [PATCH 18/83] Add comments
---
.../org/thoughtcrime/securesms/crypto/KeyStoreHelper.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
index 45ec9e207f..001b4fa1a8 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
@@ -51,6 +51,9 @@ public final class KeyStoreHelper {
SecretKey secretKey = getOrCreateKeyStoreEntry();
try {
+ // Cipher operations are not thread-safe so we synchronize over them through doFinal to
+ // prevent crashes with quickly repeated encrypt/decrypt operations
+ // https://github.com/mozilla-mobile/android-components/issues/5342
synchronized (lock) {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
@@ -69,6 +72,9 @@ public final class KeyStoreHelper {
SecretKey secretKey = getKeyStoreEntry();
try {
+ // Cipher operations are not thread-safe so we synchronize over them through doFinal to
+ // prevent crashes with quickly repeated encrypt/decrypt operations
+ // https://github.com/mozilla-mobile/android-components/issues/5342
synchronized (lock) {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
From a9078c8d08939604087b21c73446ba66bfe3248d Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:32:54 +0930
Subject: [PATCH 19/83] ...and the rest
---
.../securesms/backup/FullBackupImporter.kt | 39 ++++++++++++-------
.../securesms/crypto/KeyStoreHelper.java | 30 +++++++-------
.../securesms/logging/LogFile.java | 27 +++++++------
.../streams/AttachmentCipherInputStream.java | 35 +++++++----------
4 files changed, 68 insertions(+), 63 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt
index b40c049bc2..7d2daa910e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt
@@ -12,6 +12,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.Conversions
import org.session.libsession.utilities.Util
+import org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK
import org.session.libsignal.crypto.kdf.HKDFv3
import org.session.libsignal.utilities.ByteUtil
import org.session.libsignal.utilities.Log
@@ -243,7 +244,7 @@ object FullBackupImporter {
val split = ByteUtil.split(derived, 32, 32)
cipherKey = split[0]
macKey = split[1]
- cipher = Cipher.getInstance("AES/CTR/NoPadding")
+ cipher = synchronized(CIPHER_LOCK) { Cipher.getInstance("AES/CTR/NoPadding") }
mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(macKey, "HmacSHA256"))
counter = Conversions.byteArrayToInt(iv)
@@ -269,20 +270,26 @@ object FullBackupImporter {
var length = length
try {
Conversions.intToByteArray(iv, 0, counter++)
- cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
- mac.update(iv)
- val buffer = ByteArray(8192)
- while (length > 0) {
- val read = inputStream.read(buffer, 0, Math.min(buffer.size, length))
- if (read == -1) throw IOException("File ended early!")
- mac.update(buffer, 0, read)
- val plaintext = cipher.update(buffer, 0, read)
- if (plaintext != null) {
- out.write(plaintext, 0, plaintext.size)
+ val plaintext = synchronized(CIPHER_LOCK) {
+ cipher.init(
+ Cipher.DECRYPT_MODE,
+ SecretKeySpec(cipherKey, "AES"),
+ IvParameterSpec(iv)
+ )
+ mac.update(iv)
+ val buffer = ByteArray(8192)
+ while (length > 0) {
+ val read = inputStream.read(buffer, 0, Math.min(buffer.size, length))
+ if (read == -1) throw IOException("File ended early!")
+ mac.update(buffer, 0, read)
+ val plaintext = cipher.update(buffer, 0, read)
+ if (plaintext != null) {
+ out.write(plaintext, 0, plaintext.size)
+ }
+ length -= read
}
- length -= read
+ cipher.doFinal()
}
- val plaintext = cipher.doFinal()
if (plaintext != null) {
out.write(plaintext, 0, plaintext.size)
}
@@ -325,8 +332,10 @@ object FullBackupImporter {
throw IOException("Bad MAC")
}
Conversions.intToByteArray(iv, 0, counter++)
- cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
- val plaintext = cipher.doFinal(frame, 0, frame.size - 10)
+ val plaintext = synchronized(CIPHER_LOCK) {
+ cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv))
+ cipher.doFinal(frame, 0, frame.size - 10)
+ }
BackupFrame.parseFrom(plaintext)
} catch (e: Exception) {
when (e) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
index 43e9865598..c0372cc7f1 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java
@@ -1,6 +1,8 @@
package org.thoughtcrime.securesms.crypto;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
@@ -45,44 +47,44 @@ public final class KeyStoreHelper {
private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
private static final String KEY_ALIAS = "SignalSecret";
- @RequiresApi(Build.VERSION_CODES.M)
public static SealedData seal(@NonNull byte[] input) {
SecretKey secretKey = getOrCreateKeyStoreEntry();
try {
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ synchronized (CIPHER_LOCK) {
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
- byte[] iv = cipher.getIV();
- byte[] data = cipher.doFinal(input);
+ byte[] iv = cipher.getIV();
+ byte[] data = cipher.doFinal(input);
- return new SealedData(iv, data);
+ return new SealedData(iv, data);
+ }
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
- @RequiresApi(Build.VERSION_CODES.M)
public static byte[] unseal(@NonNull SealedData sealedData) {
SecretKey secretKey = getKeyStoreEntry();
try {
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
- cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
+ synchronized (CIPHER_LOCK) {
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
- return cipher.doFinal(sealedData.data);
+ return cipher.doFinal(sealedData.data);
+ }
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey getOrCreateKeyStoreEntry() {
if (hasKeyStoreEntry()) return getKeyStoreEntry();
else return createKeyStoreEntry();
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey createKeyStoreEntry() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
@@ -99,7 +101,6 @@ public final class KeyStoreHelper {
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static SecretKey getKeyStoreEntry() {
KeyStore keyStore = getKeyStore();
@@ -137,7 +138,6 @@ public final class KeyStoreHelper {
}
}
- @RequiresApi(Build.VERSION_CODES.M)
private static boolean hasKeyStoreEntry() {
try {
KeyStore ks = KeyStore.getInstance(ANDROID_KEY_STORE);
@@ -202,7 +202,5 @@ public final class KeyStoreHelper {
return Base64.decode(p.getValueAsString(), Base64.NO_WRAP | Base64.NO_PADDING);
}
}
-
}
-
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java b/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java
index f0c083ca1d..909f19e08c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java
@@ -1,5 +1,7 @@
package org.thoughtcrime.securesms.logging;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import androidx.annotation.NonNull;
import org.session.libsession.utilities.Conversions;
@@ -66,15 +68,17 @@ class LogFile {
byte[] plaintext = entry.getBytes();
try {
- cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer));
+ synchronized (CIPHER_LOCK) {
+ cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer));
- int cipherLength = cipher.getOutputSize(plaintext.length);
- byte[] ciphertext = ciphertextBuffer.get(cipherLength);
- cipherLength = cipher.doFinal(plaintext, 0, plaintext.length, ciphertext);
+ int cipherLength = cipher.getOutputSize(plaintext.length);
+ byte[] ciphertext = ciphertextBuffer.get(cipherLength);
+ cipherLength = cipher.doFinal(plaintext, 0, plaintext.length, ciphertext);
- outputStream.write(ivBuffer);
- outputStream.write(Conversions.intToByteArray(cipherLength));
- outputStream.write(ciphertext, 0, cipherLength);
+ outputStream.write(ivBuffer);
+ outputStream.write(Conversions.intToByteArray(cipherLength));
+ outputStream.write(ciphertext, 0, cipherLength);
+ }
outputStream.flush();
} catch (ShortBufferException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
@@ -134,10 +138,11 @@ class LogFile {
Util.readFully(inputStream, ciphertext, length);
try {
- cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer));
- byte[] plaintext = cipher.doFinal(ciphertext, 0, length);
-
- return new String(plaintext);
+ synchronized (CIPHER_LOCK) {
+ cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer));
+ byte[] plaintext = cipher.doFinal(ciphertext, 0, length);
+ return new String(plaintext);
+ }
} catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
diff --git a/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherInputStream.java b/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherInputStream.java
index 3158d35f73..fd3c8123df 100644
--- a/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherInputStream.java
+++ b/libsignal/src/main/java/org/session/libsignal/streams/AttachmentCipherInputStream.java
@@ -6,6 +6,8 @@
package org.session.libsignal.streams;
+import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
+
import org.session.libsignal.exceptions.InvalidMacException;
import org.session.libsignal.exceptions.InvalidMessageException;
import org.session.libsignal.utilities.Util;
@@ -92,19 +94,15 @@ public class AttachmentCipherInputStream extends FilterInputStream {
byte[] iv = new byte[BLOCK_SIZE];
readFully(iv);
- this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
- this.cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv));
+ synchronized (CIPHER_LOCK) {
+ this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ this.cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv));
+ }
this.done = false;
this.totalRead = 0;
this.totalDataSize = totalDataSize;
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- } catch (InvalidKeyException e) {
- throw new AssertionError(e);
- } catch (NoSuchPaddingException e) {
- throw new AssertionError(e);
- } catch (InvalidAlgorithmParameterException e) {
+ } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException e) {
throw new AssertionError(e);
}
}
@@ -141,15 +139,12 @@ public class AttachmentCipherInputStream extends FilterInputStream {
private int readFinal(byte[] buffer, int offset, int length) throws IOException {
try {
- int flourish = cipher.doFinal(buffer, offset);
-
- done = true;
- return flourish;
- } catch (IllegalBlockSizeException e) {
- throw new IOException(e);
- } catch (BadPaddingException e) {
- throw new IOException(e);
- } catch (ShortBufferException e) {
+ synchronized (CIPHER_LOCK) {
+ int flourish = cipher.doFinal(buffer, offset);
+ done = true;
+ return flourish;
+ }
+ } catch (IllegalBlockSizeException | ShortBufferException | BadPaddingException e) {
throw new IOException(e);
}
}
@@ -234,9 +229,7 @@ public class AttachmentCipherInputStream extends FilterInputStream {
throw new InvalidMacException("Digest doesn't match!");
}
- } catch (IOException e) {
- throw new InvalidMacException(e);
- } catch (ArithmeticException e) {
+ } catch (IOException | ArithmeticException e) {
throw new InvalidMacException(e);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
From 9e6d1e27fc4657170e8dd7c87b64f618f3bd16ff Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:33:50 +0930
Subject: [PATCH 20/83] Add comment
---
.../src/main/java/org/session/libsignal/crypto/CipherUtil.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java b/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
index d3423a0bd4..a6a3808bb4 100644
--- a/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
+++ b/libsignal/src/main/java/org/session/libsignal/crypto/CipherUtil.java
@@ -1,5 +1,8 @@
package org.session.libsignal.crypto;
public class CipherUtil {
+ // Cipher operations are not thread-safe so we synchronize over them through doFinal to
+ // prevent crashes with quickly repeated encrypt/decrypt operations
+ // https://github.com/mozilla-mobile/android-components/issues/5342
public static final Object CIPHER_LOCK = new Object();
}
From 6a5d97a0f063f7385f61d18202352e98ad968cf0 Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 12:37:46 +0930
Subject: [PATCH 21/83] Fix something
---
.../org/thoughtcrime/securesms/backup/FullBackupExporter.kt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
index 783468eee7..5eba9b9945 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
@@ -279,7 +279,7 @@ object FullBackupExporter {
return false
}
- private class BackupFrameOutputStream : Closeable, Flushable {
+ private class BackupFrameOutputStream(outputStream: OutputStream, passphrase: String) : Closeable, Flushable {
private val outputStream: OutputStream
private var cipher: Cipher
@@ -290,7 +290,7 @@ object FullBackupExporter {
private var counter: Int = 0
- private constructor(outputStream: OutputStream, passphrase: String) : super() {
+ init {
try {
val salt = Util.getSecretBytes(32)
val key = BackupUtil.computeBackupKey(passphrase, salt)
From 375815c7190444f0a4d49b304095551866ce0cd5 Mon Sep 17 00:00:00 2001
From: ryanzhao
Date: Fri, 5 May 2023 16:51:44 +1000
Subject: [PATCH 22/83] WIP: refactor on jobs using old job table
---
.../securesms/jobmanager/JobManager.java | 39 ---
.../securesms/jobs/JobManagerFactories.java | 4 +-
.../securesms/jobs/LocalBackupJob.java | 83 ------
.../securesms/jobs/LocalBackupJob.kt | 61 ++++
.../securesms/jobs/UpdateApkJob.java | 271 ------------------
.../securesms/jobs/UpdateApkJob.kt | 200 +++++++++++++
.../service/UpdateApkRefreshListener.java | 2 +
.../sskenvironment/ProfileManager.kt | 1 +
8 files changed, 266 insertions(+), 395 deletions(-)
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
create mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
create mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
index 5906afd292..abb15d9f75 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
@@ -78,35 +78,6 @@ public class JobManager implements ConstraintObserver.Notifier {
new Chain(this, Collections.singletonList(job)).enqueue();
}
- /**
- * Begins the creation of a job chain with a single job.
- * @see Chain
- */
- public Chain startChain(@NonNull Job job) {
- return new Chain(this, Collections.singletonList(job));
- }
-
- /**
- * Begins the creation of a job chain with a set of jobs that can be run in parallel.
- * @see Chain
- */
- public Chain startChain(@NonNull List extends Job> jobs) {
- return new Chain(this, jobs);
- }
-
- /**
- * Retrieves a string representing the state of the job queue. Intended for debugging.
- */
- public @NonNull String getDebugInfo() {
- Future result = executor.submit(jobController::getDebugInfo);
- try {
- return result.get();
- } catch (ExecutionException | InterruptedException e) {
- Log.w(TAG, "Failed to retrieve Job info.", e);
- return "Failed to retrieve Job info.";
- }
- }
-
/**
* Adds a listener to that will be notified when the job queue has been drained.
*/
@@ -261,16 +232,6 @@ public class JobManager implements ConstraintObserver.Notifier {
private Data.Serializer dataSerializer = new JsonDataSerializer();
private JobStorage jobStorage = null;
- public @NonNull Builder setJobThreadCount(int jobThreadCount) {
- this.jobThreadCount = jobThreadCount;
- return this;
- }
-
- public @NonNull Builder setExecutorFactory(@NonNull ExecutorFactory executorFactory) {
- this.executorFactory = executorFactory;
- return this;
- }
-
public @NonNull Builder setJobFactories(@NonNull Map jobFactories) {
this.jobFactories = jobFactories;
return this;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
index ef73325f37..468bf58369 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
@@ -29,9 +29,9 @@ public final class JobManagerFactories {
public static Map getJobFactories(@NonNull Application application) {
HashMap factoryHashMap = new HashMap() {{
put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
- put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
+ put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application));
- put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
+ put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory());
put(PrepareAttachmentAudioExtrasJob.KEY, new PrepareAttachmentAudioExtrasJob.Factory());
}};
factoryKeys.addAll(factoryHashMap.keySet());
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
deleted file mode 100644
index e5715db263..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsignal.utilities.NoExternalStorageException;
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.database.BackupFileRecord;
-import org.thoughtcrime.securesms.notifications.NotificationChannels;
-import org.thoughtcrime.securesms.service.GenericForegroundService;
-import org.thoughtcrime.securesms.util.BackupUtil;
-
-import java.io.IOException;
-import java.util.Collections;
-
-import network.loki.messenger.R;
-
-public class LocalBackupJob extends BaseJob {
-
- public static final String KEY = "LocalBackupJob";
-
- private static final String TAG = LocalBackupJob.class.getSimpleName();
-
- public LocalBackupJob() {
- this(new Job.Parameters.Builder()
- .setQueue("__LOCAL_BACKUP__")
- .setMaxInstances(1)
- .setMaxAttempts(3)
- .build());
- }
-
- private LocalBackupJob(@NonNull Job.Parameters parameters) {
- super(parameters);
- }
-
- @Override
- public @NonNull
- Data serialize() {
- return Data.EMPTY;
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public void onRun() throws NoExternalStorageException, IOException {
- Log.i(TAG, "Executing backup job...");
-
- GenericForegroundService.startForegroundTask(context,
- context.getString(R.string.LocalBackupJob_creating_backup),
- NotificationChannels.BACKUPS,
- R.drawable.ic_launcher_foreground);
-
- // TODO: Maybe create a new backup icon like ic_signal_backup?
-
- try {
- BackupFileRecord record = BackupUtil.createBackupFile(context);
- BackupUtil.deleteAllBackupFiles(context, Collections.singletonList(record));
-
- } finally {
- GenericForegroundService.stopForegroundTask(context);
- }
- }
-
- @Override
- public boolean onShouldRetry(@NonNull Exception e) {
- return false;
- }
-
- @Override
- public void onCanceled() {
- }
-
- public static class Factory implements Job.Factory {
- @Override
- public @NonNull LocalBackupJob create(@NonNull Parameters parameters, @NonNull Data data) {
- return new LocalBackupJob(parameters);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt
new file mode 100644
index 0000000000..8a71760df3
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt
@@ -0,0 +1,61 @@
+package org.thoughtcrime.securesms.jobs
+
+import android.content.Context
+import org.session.libsession.messaging.jobs.Job
+import org.session.libsession.messaging.jobs.JobDelegate
+import org.session.libsession.messaging.utilities.Data
+import org.session.libsignal.utilities.Log
+import org.thoughtcrime.securesms.notifications.NotificationChannels
+import org.thoughtcrime.securesms.service.GenericForegroundService
+import org.thoughtcrime.securesms.util.BackupUtil.createBackupFile
+import org.thoughtcrime.securesms.util.BackupUtil.deleteAllBackupFiles
+
+import network.loki.messenger.R
+
+
+class LocalBackupJob:Job {
+ override var delegate: JobDelegate? = null
+ override var id: String? = null
+ override var failureCount: Int = 0
+ override val maxFailureCount: Int = 0
+
+ lateinit var context: Context
+
+ companion object {
+ val TAG = LocalBackupJob::class.simpleName
+ val KEY: String = "LocalBackupJob"
+ }
+
+ override fun execute(dispatcherName: String) {
+ Log.i(TAG, "Executing backup job...")
+
+ GenericForegroundService.startForegroundTask(
+ context,
+ context.getString(R.string.LocalBackupJob_creating_backup),
+ NotificationChannels.BACKUPS,
+ R.drawable.ic_launcher_foreground
+ )
+
+ // TODO: Maybe create a new backup icon like ic_signal_backup?
+ try {
+ val record = createBackupFile(context)
+ deleteAllBackupFiles(context, listOf(record))
+ } finally {
+ GenericForegroundService.stopForegroundTask(context)
+ }
+ }
+
+ override fun serialize(): Data {
+ return Data.EMPTY
+ }
+
+ override fun getFactoryKey(): String {
+ return KEY
+ }
+
+ class Factory: Job.Factory {
+ override fun create(data: Data): LocalBackupJob {
+ return LocalBackupJob()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
deleted file mode 100644
index 5b4ce8d13c..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-
-import android.app.DownloadManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import org.session.libsession.messaging.utilities.Data;
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.service.UpdateApkReadyListener;
-import org.session.libsession.utilities.FileUtils;
-import org.session.libsignal.utilities.Hex;
-import org.session.libsignal.utilities.JsonUtil;
-import org.session.libsession.utilities.TextSecurePreferences;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-
-import network.loki.messenger.BuildConfig;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-
-public class UpdateApkJob extends BaseJob {
-
- public static final String KEY = "UpdateApkJob";
-
- private static final String TAG = UpdateApkJob.class.getSimpleName();
-
- public UpdateApkJob() {
- this(new Job.Parameters.Builder()
- .setQueue("UpdateApkJob")
- .addConstraint(NetworkConstraint.KEY)
- .setMaxAttempts(3)
- .build());
- }
-
- private UpdateApkJob(@NonNull Job.Parameters parameters) {
- super(parameters);
- }
-
- @Override
- public @NonNull
- Data serialize() {
- return Data.EMPTY;
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public void onRun() throws IOException, PackageManager.NameNotFoundException {
- if (!BuildConfig.PLAY_STORE_DISABLED) return;
-
- Log.i(TAG, "Checking for APK update...");
-
- OkHttpClient client = new OkHttpClient();
- Request request = new Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build();
-
- Response response = client.newCall(request).execute();
-
- if (!response.isSuccessful()) {
- throw new IOException("Bad response: " + response.message());
- }
-
- UpdateDescriptor updateDescriptor = JsonUtil.fromJson(response.body().string(), UpdateDescriptor.class);
- byte[] digest = Hex.fromStringCondensed(updateDescriptor.getDigest());
-
- Log.i(TAG, "Got descriptor: " + updateDescriptor);
-
- if (updateDescriptor.getVersionCode() > getVersionCode()) {
- DownloadStatus downloadStatus = getDownloadStatus(updateDescriptor.getUrl(), digest);
-
- Log.i(TAG, "Download status: " + downloadStatus.getStatus());
-
- if (downloadStatus.getStatus() == DownloadStatus.Status.COMPLETE) {
- Log.i(TAG, "Download status complete, notifying...");
- handleDownloadNotify(downloadStatus.getDownloadId());
- } else if (downloadStatus.getStatus() == DownloadStatus.Status.MISSING) {
- Log.i(TAG, "Download status missing, starting download...");
- handleDownloadStart(updateDescriptor.getUrl(), updateDescriptor.getVersionName(), digest);
- }
- }
- }
-
- @Override
- public boolean onShouldRetry(@NonNull Exception e) {
- return e instanceof IOException;
- }
-
- @Override
- public void onCanceled() {
- Log.w(TAG, "Update check failed");
- }
-
- private int getVersionCode() throws PackageManager.NameNotFoundException {
- PackageManager packageManager = context.getPackageManager();
- PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
-
- return packageInfo.versionCode;
- }
-
- private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) {
- DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- DownloadManager.Query query = new DownloadManager.Query();
-
- query.setFilterByStatus(DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_PENDING | DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_SUCCESSFUL);
-
- long pendingDownloadId = TextSecurePreferences.getUpdateApkDownloadId(context);
- byte[] pendingDigest = getPendingDigest(context);
- Cursor cursor = downloadManager.query(query);
-
- try {
- DownloadStatus status = new DownloadStatus(DownloadStatus.Status.MISSING, -1);
-
- while (cursor != null && cursor.moveToNext()) {
- int jobStatus = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
- String jobRemoteUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI));
- long downloadId = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
- byte[] digest = getDigestForDownloadId(downloadId);
-
- if (jobRemoteUri != null && jobRemoteUri.equals(uri) && downloadId == pendingDownloadId) {
-
- if (jobStatus == DownloadManager.STATUS_SUCCESSFUL &&
- digest != null && pendingDigest != null &&
- MessageDigest.isEqual(pendingDigest, theirDigest) &&
- MessageDigest.isEqual(digest, theirDigest))
- {
- return new DownloadStatus(DownloadStatus.Status.COMPLETE, downloadId);
- } else if (jobStatus != DownloadManager.STATUS_SUCCESSFUL) {
- status = new DownloadStatus(DownloadStatus.Status.PENDING, downloadId);
- }
- }
- }
-
- return status;
- } finally {
- if (cursor != null) cursor.close();
- }
- }
-
- private void handleDownloadStart(String uri, String versionName, byte[] digest) {
- DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri));
-
- downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
- downloadRequest.setTitle("Downloading Signal update");
- downloadRequest.setDescription("Downloading Signal " + versionName);
- downloadRequest.setVisibleInDownloadsUi(false);
- downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk");
- downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
-
- long downloadId = downloadManager.enqueue(downloadRequest);
- TextSecurePreferences.setUpdateApkDownloadId(context, downloadId);
- TextSecurePreferences.setUpdateApkDigest(context, Hex.toStringCondensed(digest));
- }
-
- private void handleDownloadNotify(long downloadId) {
- Intent intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
- intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId);
-
- new UpdateApkReadyListener().onReceive(context, intent);
- }
-
- private @Nullable byte[] getDigestForDownloadId(long downloadId) {
- try {
- DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
- FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor());
- byte[] digest = FileUtils.getFileDigest(fin);
-
- fin.close();
-
- return digest;
- } catch (IOException e) {
- Log.w(TAG, e);
- return null;
- }
- }
-
- private @Nullable byte[] getPendingDigest(Context context) {
- try {
- String encodedDigest = TextSecurePreferences.getUpdateApkDigest(context);
-
- if (encodedDigest == null) return null;
-
- return Hex.fromStringCondensed(encodedDigest);
- } catch (IOException e) {
- Log.w(TAG, e);
- return null;
- }
- }
-
- private static class UpdateDescriptor {
- @JsonProperty
- private int versionCode;
-
- @JsonProperty
- private String versionName;
-
- @JsonProperty
- private String url;
-
- @JsonProperty
- private String sha256sum;
-
-
- public int getVersionCode() {
- return versionCode;
- }
-
- public String getVersionName() {
- return versionName;
- }
-
- public String getUrl() {
- return url;
- }
-
- public @NonNull String toString() {
- return "[" + versionCode + ", " + versionName + ", " + url + "]";
- }
-
- public String getDigest() {
- return sha256sum;
- }
- }
-
- private static class DownloadStatus {
- enum Status {
- PENDING,
- COMPLETE,
- MISSING
- }
-
- private final Status status;
- private final long downloadId;
-
- DownloadStatus(Status status, long downloadId) {
- this.status = status;
- this.downloadId = downloadId;
- }
-
- public Status getStatus() {
- return status;
- }
-
- public long getDownloadId() {
- return downloadId;
- }
- }
-
- public static final class Factory implements Job.Factory {
- @Override
- public @NonNull UpdateApkJob create(@NonNull Parameters parameters, @NonNull Data data) {
- return new UpdateApkJob(parameters);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt
new file mode 100644
index 0000000000..411f01fcde
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt
@@ -0,0 +1,200 @@
+package org.thoughtcrime.securesms.jobs
+
+import androidx.annotation.Nullable
+
+import android.app.DownloadManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.net.Uri
+import com.fasterxml.jackson.annotation.JsonProperty
+import network.loki.messenger.BuildConfig
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import org.session.libsession.messaging.jobs.Job
+import org.session.libsession.messaging.jobs.JobDelegate
+import org.session.libsession.messaging.utilities.Data
+import org.session.libsession.utilities.FileUtils
+import org.session.libsession.utilities.TextSecurePreferences.Companion.getUpdateApkDigest
+import org.session.libsession.utilities.TextSecurePreferences.Companion.getUpdateApkDownloadId
+import org.session.libsession.utilities.TextSecurePreferences.Companion.setUpdateApkDigest
+import org.session.libsession.utilities.TextSecurePreferences.Companion.setUpdateApkDownloadId
+import org.session.libsignal.utilities.Hex
+import org.session.libsignal.utilities.JsonUtil
+import org.session.libsignal.utilities.Log
+import org.thoughtcrime.securesms.service.UpdateApkReadyListener
+import java.io.FileInputStream
+import java.io.IOException
+import java.security.MessageDigest
+
+class UpdateApkJob: Job {
+ override var delegate: JobDelegate? = null
+ override var id: String? = null
+ override var failureCount: Int = 0
+ override val maxFailureCount: Int = 0
+
+ lateinit var context: Context
+
+ companion object {
+ val TAG = UpdateApkJob::class.simpleName
+ val KEY: String = "UpdateApkJob"
+ }
+
+ override fun execute(dispatcherName: String) {
+ if (!BuildConfig.PLAY_STORE_DISABLED) return
+
+ Log.i(TAG, "Checking for APK update...")
+
+ val client = OkHttpClient()
+ val request = Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build()
+ val response = client.newCall(request).execute()
+
+ if (!response.isSuccessful) {
+ throw IOException("Bad response: " + response.message())
+ }
+
+ val updateDescriptor: UpdateDescriptor = JsonUtil.fromJson(
+ response.body()!!.string(),
+ UpdateDescriptor::class.java
+ )
+ val digest = Hex.fromStringCondensed(updateDescriptor.digest)
+
+ Log.i(
+ TAG,
+ "Got descriptor: $updateDescriptor"
+ )
+
+ if (updateDescriptor.versionCode > getVersionCode()) {
+ val downloadStatus: DownloadStatus = getDownloadStatus(updateDescriptor.url, digest)
+ Log.i(TAG, "Download status: " + downloadStatus.status)
+ if (downloadStatus.status == DownloadStatus.Status.COMPLETE) {
+ Log.i(TAG, "Download status complete, notifying...")
+ handleDownloadNotify(downloadStatus.downloadId)
+ } else if (downloadStatus.status == DownloadStatus.Status.MISSING) {
+ Log.i(TAG, "Download status missing, starting download...")
+ handleDownloadStart(
+ updateDescriptor.url,
+ updateDescriptor.versionName,
+ digest
+ )
+ }
+ }
+ }
+
+ @Throws(PackageManager.NameNotFoundException::class)
+ private fun getVersionCode(): Int {
+ val packageManager: PackageManager = context.getPackageManager()
+ val packageInfo: PackageInfo = packageManager.getPackageInfo(context.getPackageName(), 0)
+ return packageInfo.versionCode
+ }
+
+ private fun getDownloadStatus(uri: String, theirDigest: ByteArray): DownloadStatus {
+ val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+ val query = DownloadManager.Query()
+ query.setFilterByStatus(DownloadManager.STATUS_PAUSED or DownloadManager.STATUS_PENDING or DownloadManager.STATUS_RUNNING or DownloadManager.STATUS_SUCCESSFUL)
+ val pendingDownloadId = getUpdateApkDownloadId(context)
+ val pendingDigest = getPendingDigest(context)
+ val cursor = downloadManager.query(query)
+ return try {
+ var status = DownloadStatus(DownloadStatus.Status.MISSING, -1)
+ while (cursor != null && cursor.moveToNext()) {
+ val jobStatus =
+ cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
+ val jobRemoteUri =
+ cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI))
+ val downloadId =
+ cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID))
+ val digest = getDigestForDownloadId(downloadId)
+ if (jobRemoteUri != null && jobRemoteUri == uri && downloadId == pendingDownloadId) {
+ if (jobStatus == DownloadManager.STATUS_SUCCESSFUL && digest != null && pendingDigest != null &&
+ MessageDigest.isEqual(pendingDigest, theirDigest) &&
+ MessageDigest.isEqual(digest, theirDigest)
+ ) {
+ return DownloadStatus(DownloadStatus.Status.COMPLETE, downloadId)
+ } else if (jobStatus != DownloadManager.STATUS_SUCCESSFUL) {
+ status = DownloadStatus(DownloadStatus.Status.PENDING, downloadId)
+ }
+ }
+ }
+ status
+ } finally {
+ cursor?.close()
+ }
+ }
+
+ private fun handleDownloadStart(uri: String, versionName: String, digest: ByteArray) {
+ val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+ val downloadRequest = DownloadManager.Request(Uri.parse(uri))
+ downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
+ downloadRequest.setTitle("Downloading Signal update")
+ downloadRequest.setDescription("Downloading Signal $versionName")
+ downloadRequest.setVisibleInDownloadsUi(false)
+ downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk")
+ downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)
+ val downloadId = downloadManager.enqueue(downloadRequest)
+ setUpdateApkDownloadId(context, downloadId)
+ setUpdateApkDigest(context, Hex.toStringCondensed(digest))
+ }
+
+ private fun handleDownloadNotify(downloadId: Long) {
+ val intent = Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
+ intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId)
+ UpdateApkReadyListener().onReceive(context, intent)
+ }
+
+ private fun getDigestForDownloadId(downloadId: Long): ByteArray? {
+ return try {
+ val downloadManager =
+ context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+ val fin = FileInputStream(downloadManager.openDownloadedFile(downloadId).fileDescriptor)
+ val digest = FileUtils.getFileDigest(fin)
+ fin.close()
+ digest
+ } catch (e: IOException) {
+ Log.w(TAG, e)
+ null
+ }
+ }
+
+ private fun getPendingDigest(context: Context): ByteArray? {
+ return try {
+ val encodedDigest = getUpdateApkDigest(context) ?: return null
+ Hex.fromStringCondensed(encodedDigest)
+ } catch (e: IOException) {
+ Log.w(TAG, e)
+ null
+ }
+ }
+
+ override fun serialize(): Data {
+ return Data.EMPTY
+ }
+
+ override fun getFactoryKey(): String {
+ return KEY
+ }
+
+ private class UpdateDescriptor(
+ @JsonProperty("versionCode") @Nullable val versionCode: Int,
+ @JsonProperty("versionName") @Nullable val versionName: String,
+ @JsonProperty("url") @Nullable val url: String,
+ @JsonProperty("sha256sum") @Nullable val digest: String)
+ {
+ override fun toString(): String {
+ return "[$versionCode, $versionName, $url]"
+ }
+ }
+
+ private class DownloadStatus(val status: Status, val downloadId: Long) {
+ enum class Status {
+ PENDING, COMPLETE, MISSING
+ }
+ }
+
+ class Factory: Job.Factory {
+ override fun create(data: Data): UpdateApkJob {
+ return UpdateApkJob()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
index 187713df95..ef27916ac9 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
@@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.service;
import android.content.Context;
import android.content.Intent;
+
+import org.session.libsession.messaging.jobs.JobQueue;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ApplicationContext;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
index c46f75bff8..2615eff588 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.sskenvironment
import android.content.Context
import org.session.libsession.messaging.contacts.Contact
+import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.ApplicationContext
From e9a15941aef5971c5058a55162d1a6fc868fa368 Mon Sep 17 00:00:00 2001
From: andrew
Date: Fri, 5 May 2023 17:47:36 +0930
Subject: [PATCH 23/83] Fix colors
---
.../securesms/conversation/v2/messages/VisibleMessageView.kt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
index 745c91e910..ce6019e4c6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
@@ -303,7 +303,7 @@ class VisibleMessageView : LinearLayout {
message.isSyncFailed ->
MessageStatusInfo(
R.drawable.ic_delivery_status_failed,
- resources.getColor(R.color.destructive, context.theme),
+ context.getColor(R.color.accent_orange),
R.string.delivery_status_sync_failed,
null
)
@@ -316,7 +316,7 @@ class VisibleMessageView : LinearLayout {
message.isResyncing ->
MessageStatusInfo(
R.drawable.ic_delivery_status_sending,
- context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_syncing,
+ context.getColor(R.color.accent_orange), R.string.delivery_status_syncing,
context.getString(R.string.AccessibilityId_message_sent_status_syncing)
)
message.isRead ->
From ec2abffdccc395bc119bcb3624a55f84734f9a53 Mon Sep 17 00:00:00 2001
From: andrew
Date: Mon, 8 May 2023 10:33:39 +0930
Subject: [PATCH 24/83] Remove logs
---
.../v2/utilities/ResendMessageUtilities.kt | 4 ----
.../thoughtcrime/securesms/database/Storage.kt | 17 -----------------
.../libsession/messaging/jobs/MessageSendJob.kt | 2 --
.../sending_receiving/MessageSender.kt | 16 ----------------
4 files changed, 39 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
index 5e6283e1ad..e01a75b30c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
@@ -11,16 +11,12 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
-import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
-private val TAG = ResendMessageUtilities.javaClass.simpleName
-
object ResendMessageUtilities {
fun resend(context: Context, messageRecord: MessageRecord, userBlindedKey: String?, isResync: Boolean = false) {
- Log.d(TAG, "resend() called with: context = $context, messageRecord = $messageRecord, userBlindedKey = $userBlindedKey, isResync = $isResync")
val recipient: Recipient = messageRecord.recipient
val message = VisibleMessage()
message.id = messageRecord.getId()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 77f616026c..33896803b8 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -41,7 +41,6 @@ import org.session.libsignal.messages.SignalServiceAttachmentPointer
import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.KeyHelper
-import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
@@ -54,8 +53,6 @@ import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.security.MessageDigest
-private val TAG = Storage::class.java.simpleName
-
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
override fun getUserPublicKey(): String? {
@@ -359,8 +356,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
openGroupSentTimestamp: Long,
threadId: Long
) {
- Log.d(TAG, "updateSentTimestamp() called with: messageID = $messageID, isMms = $isMms, openGroupSentTimestamp = $openGroupSentTimestamp, threadId = $threadId")
-
if (isMms) {
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
mmsDb.updateSentTimestamp(messageID, openGroupSentTimestamp, threadId)
@@ -371,8 +366,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun markAsSent(timestamp: Long, author: String) {
- Log.d(TAG, "markAsSent() called with: timestamp = $timestamp, author = $author")
-
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -385,8 +378,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun markAsSyncing(timestamp: Long, author: String) {
- Log.d(TAG, "markAsSyncing() called with: timestamp = $timestamp, author = $author")
-
DatabaseComponent.get(context).mmsSmsDatabase()
.getMessageFor(timestamp, author)
?.run { getMmsDatabaseElseSms(isMms).markAsSyncing(id) }
@@ -397,16 +388,12 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
else DatabaseComponent.get(context).smsDatabase()
override fun markAsResyncing(timestamp: Long, author: String) {
- Log.d(TAG, "markAsResyncing() called with: timestamp = $timestamp, author = $author")
-
DatabaseComponent.get(context).mmsSmsDatabase()
.getMessageFor(timestamp, author)
?.run { getMmsDatabaseElseSms(isMms).markAsResyncing(id) }
}
override fun markAsSending(timestamp: Long, author: String) {
- Log.d(TAG, "markAsSending() called with: timestamp = $timestamp, author = $author")
-
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -432,8 +419,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun markAsSentFailed(timestamp: Long, author: String, error: Exception) {
- Log.d(TAG, "markAsSentFailed() called with: timestamp = $timestamp, author = $author, error = $error")
-
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
@@ -457,8 +442,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun markAsSyncFailed(timestamp: Long, author: String, error: Exception) {
- Log.d(TAG, "markAsSyncFailed() called with: timestamp = $timestamp, author = $author, error = $error")
-
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
index 4300fe4b61..524338592c 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt
@@ -34,8 +34,6 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
}
override fun execute(dispatcherName: String) {
- Log.d(TAG, "MessageSendJob#execute() called with: dispatcherName = $dispatcherName")
-
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val message = message as? VisibleMessage
val storage = MessagingModuleConfiguration.shared.storage
diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
index 9da6cd8b14..fa0a49a647 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
@@ -39,8 +39,6 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview as SignalLinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel as SignalQuote
-private val TAG = MessageSender::class.java.simpleName
-
object MessageSender {
// Error
@@ -64,8 +62,6 @@ object MessageSender {
// Convenience
fun send(message: Message, destination: Destination, isSyncMessage: Boolean = false): Promise {
- Log.d(TAG, "send() called with: message = $message, destination = $destination, isSyncMessage = $isSyncMessage")
-
return if (destination is Destination.LegacyOpenGroup || destination is Destination.OpenGroup || destination is Destination.OpenGroupInbox) {
sendToOpenGroupDestination(destination, message)
} else {
@@ -75,8 +71,6 @@ object MessageSender {
// One-on-One Chats & Closed Groups
private fun sendToSnodeDestination(destination: Destination, message: Message, isSyncMessage: Boolean = false): Promise {
- Log.d(TAG, "sendToSnodeDestination() called with: destination = $destination, message = $message, isSyncMessage = $isSyncMessage")
-
val deferred = deferred()
val promise = deferred.promise
val storage = MessagingModuleConfiguration.shared.storage
@@ -226,8 +220,6 @@ object MessageSender {
// Open Groups
private fun sendToOpenGroupDestination(destination: Destination, message: Message): Promise {
- Log.d(TAG, "sendToOpenGroupDestination() called with: destination = $destination, message = $message")
-
val deferred = deferred()
val storage = MessagingModuleConfiguration.shared.storage
if (message.sentTimestamp == null) {
@@ -326,8 +318,6 @@ object MessageSender {
// Result Handling
fun handleSuccessfulMessageSend(message: Message, destination: Destination, isSyncMessage: Boolean = false, openGroupSentTimestamp: Long = -1) {
- Log.d(TAG, "handleSuccessfulMessageSend() called with: message = $message, destination = $destination, isSyncMessage = $isSyncMessage, openGroupSentTimestamp = $openGroupSentTimestamp")
-
val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!!
// Ignore future self-sends
@@ -393,8 +383,6 @@ object MessageSender {
}
fun handleFailedMessageSend(message: Message, error: Exception, isSyncMessage: Boolean = false) {
- Log.d(TAG, "handleFailedMessageSend() called with: message = $message, error = $error, isSyncMessage = $isSyncMessage")
-
val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!!
@@ -408,8 +396,6 @@ object MessageSender {
// Convenience
@JvmStatic
fun send(message: VisibleMessage, address: Address, attachments: List, quote: SignalQuote?, linkPreview: SignalLinkPreview?) {
- Log.d(TAG, "send() called with: message = $message, address = $address, attachments = $attachments, quote = $quote, linkPreview = $linkPreview")
-
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val attachmentIDs = messageDataProvider.getAttachmentIDsFor(message.id!!)
message.attachmentIDs.addAll(attachmentIDs)
@@ -428,8 +414,6 @@ object MessageSender {
@JvmStatic
fun send(message: Message, address: Address) {
- Log.d(TAG, "send() called with: message = $message, address = $address")
-
val threadID = MessagingModuleConfiguration.shared.storage.getOrCreateThreadIdFor(address)
message.threadID = threadID
val destination = Destination.from(address)
From 2b48b52df0b819f39558d792fc05aee3261f4f2a Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 8 May 2023 11:18:33 +1000
Subject: [PATCH 25/83] remove unused jobs and wrap up old job refactoring
---
.../securesms/ApplicationContext.java | 2 +-
.../securesms/jobs/AvatarDownloadJob.java | 133 ----------------
.../securesms/jobs/JobManagerFactories.java | 10 +-
.../jobs/PrepareAttachmentAudioExtrasJob.kt | 133 ----------------
.../jobs/RetrieveProfileAvatarJob.java | 144 ------------------
.../jobs/RetrieveProfileAvatarJob.kt | 99 ++++++++++++
6 files changed, 104 insertions(+), 417 deletions(-)
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
create mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
index a605a84922..b398d021c5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
@@ -355,7 +355,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private void initializeJobManager() {
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
.setDataSerializer(new JsonDataSerializer())
- .setJobFactories(JobManagerFactories.getJobFactories(this))
+ .setJobFactories(JobManagerFactories.getJobFactories())
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
.setJobStorage(new FastJobStorage(jobDatabase))
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
deleted file mode 100644
index 0bf7ea24e4..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.graphics.Bitmap;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsession.utilities.DownloadUtilities;
-import org.session.libsession.utilities.GroupRecord;
-import org.session.libsignal.exceptions.InvalidMessageException;
-import org.session.libsignal.exceptions.NonSuccessfulResponseCodeException;
-import org.session.libsignal.messages.SignalServiceAttachmentPointer;
-import org.session.libsignal.streams.AttachmentCipherInputStream;
-import org.session.libsignal.utilities.Hex;
-import org.session.libsignal.utilities.Log;
-import org.session.libsignal.utilities.guava.Optional;
-import org.thoughtcrime.securesms.database.GroupDatabase;
-import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
-import org.thoughtcrime.securesms.util.BitmapDecodingException;
-import org.thoughtcrime.securesms.util.BitmapUtil;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class AvatarDownloadJob extends BaseJob {
-
- public static final String KEY = "AvatarDownloadJob";
-
- private static final String TAG = AvatarDownloadJob.class.getSimpleName();
-
- private static final int MAX_AVATAR_SIZE = 20 * 1024 * 1024;
-
- private static final String KEY_GROUP_ID = "group_id";
-
- private String groupId;
-
- public AvatarDownloadJob(@NonNull String groupId) {
- this(new Job.Parameters.Builder()
- .addConstraint(NetworkConstraint.KEY)
- .setMaxAttempts(10)
- .build(),
- groupId);
- }
-
- private AvatarDownloadJob(@NonNull Job.Parameters parameters, @NonNull String groupId) {
- super(parameters);
- this.groupId = groupId;
- }
-
- @Override
- public @NonNull Data serialize() {
- return new Data.Builder().putString(KEY_GROUP_ID, groupId).build();
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public void onRun() throws IOException {
- GroupDatabase database = DatabaseComponent.get(context).groupDatabase();
- Optional record = database.getGroup(groupId);
- File attachment = null;
-
- try {
- if (record.isPresent()) {
- long avatarId = record.get().getAvatarId();
- String contentType = record.get().getAvatarContentType();
- byte[] key = record.get().getAvatarKey();
- String relay = record.get().getRelay();
- Optional digest = Optional.fromNullable(record.get().getAvatarDigest());
- Optional fileName = Optional.absent();
- String url = record.get().getUrl();
-
- if (avatarId == -1 || key == null || url.isEmpty()) {
- return;
- }
-
- if (digest.isPresent()) {
- Log.i(TAG, "Downloading group avatar with digest: " + Hex.toString(digest.get()));
- }
-
- attachment = File.createTempFile("avatar", "tmp", context.getCacheDir());
- attachment.deleteOnExit();
-
- SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url);
-
- if (pointer.getUrl().isEmpty()) throw new InvalidMessageException("Missing attachment URL.");
- DownloadUtilities.downloadFile(attachment, pointer.getUrl());
-
- // Assume we're retrieving an attachment for an open group server if the digest is not set
- InputStream inputStream;
- if (!pointer.getDigest().isPresent()) {
- inputStream = new FileInputStream(attachment);
- } else {
- inputStream = AttachmentCipherInputStream.createForAttachment(attachment, pointer.getSize().or(0), pointer.getKey(), pointer.getDigest().get());
- }
-
- Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key, 0, digest), 500, 500);
-
- database.updateProfilePicture(groupId, avatar);
- inputStream.close();
- }
- } catch (BitmapDecodingException | NonSuccessfulResponseCodeException | InvalidMessageException e) {
- Log.w(TAG, e);
- } finally {
- if (attachment != null)
- attachment.delete();
- }
- }
-
- @Override
- public void onCanceled() {}
-
- @Override
- public boolean onShouldRetry(@NonNull Exception exception) {
- if (exception instanceof IOException) return true;
- return false;
- }
-
- public static final class Factory implements Job.Factory {
- @Override
- public @NonNull AvatarDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) {
- return new AvatarDownloadJob(parameters, data.getString(KEY_GROUP_ID));
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
index 468bf58369..910a9c09be 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
@@ -4,9 +4,9 @@ import android.app.Application;
import androidx.annotation.NonNull;
+import org.session.libsession.messaging.jobs.Job;
import org.thoughtcrime.securesms.jobmanager.Constraint;
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
-import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
@@ -28,11 +28,9 @@ public final class JobManagerFactories {
public static Map getJobFactories(@NonNull Application application) {
HashMap factoryHashMap = new HashMap() {{
- put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
- put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
- put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application));
- put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory());
- put(PrepareAttachmentAudioExtrasJob.KEY, new PrepareAttachmentAudioExtrasJob.Factory());
+ put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
+ put(RetrieveProfileAvatarJob.Companion.getKEY(), new RetrieveProfileAvatarJob.Factory());
+ put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory());
}};
factoryKeys.addAll(factoryHashMap.keySet());
return factoryHashMap;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt
deleted file mode 100644
index 69794d41bd..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.thoughtcrime.securesms.jobs
-
-import android.os.Build
-import org.greenrobot.eventbus.EventBus
-import org.session.libsession.messaging.sending_receiving.attachments.Attachment
-import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
-import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachmentAudioExtras
-import org.session.libsession.messaging.utilities.Data
-import org.session.libsession.utilities.DecodedAudio
-import org.session.libsession.utilities.InputStreamMediaDataSource
-import org.session.libsignal.utilities.Log
-import org.thoughtcrime.securesms.dependencies.DatabaseComponent
-import org.thoughtcrime.securesms.jobmanager.Job
-import org.thoughtcrime.securesms.jobs.PrepareAttachmentAudioExtrasJob.AudioExtrasUpdatedEvent
-import org.thoughtcrime.securesms.mms.PartAuthority
-import java.util.*
-import java.util.concurrent.TimeUnit
-
-/**
- * Decodes the audio content of the related attachment entry
- * and caches the result with [DatabaseAttachmentAudioExtras] data.
- *
- * It only process attachments with "audio" mime types.
- *
- * Due to [DecodedAudio] implementation limitations, it only works for API 23+.
- * For any lower targets fake data will be generated.
- *
- * You can subscribe to [AudioExtrasUpdatedEvent] to be notified about the successful result.
- */
-//TODO AC: Rewrite to WorkManager API when
-// https://github.com/loki-project/session-android/pull/354 is merged.
-class PrepareAttachmentAudioExtrasJob : BaseJob {
-
- companion object {
- private const val TAG = "AttachAudioExtrasJob"
-
- const val KEY = "PrepareAttachmentAudioExtrasJob"
- const val DATA_ATTACH_ID = "attachment_id"
-
- const val VISUAL_RMS_FRAMES = 32 // The amount of values to be computed for the visualization.
- }
-
- private val attachmentId: AttachmentId
-
- constructor(attachmentId: AttachmentId) : this(Parameters.Builder()
- .setQueue(KEY)
- .setLifespan(TimeUnit.DAYS.toMillis(1))
- .build(),
- attachmentId)
-
- private constructor(parameters: Parameters, attachmentId: AttachmentId) : super(parameters) {
- this.attachmentId = attachmentId
- }
-
- override fun serialize(): Data {
- return Data.Builder().putParcelable(DATA_ATTACH_ID, attachmentId).build();
- }
-
- override fun getFactoryKey(): String { return KEY
- }
-
- override fun onShouldRetry(e: Exception): Boolean {
- return false
- }
-
- override fun onCanceled() { }
-
- override fun onRun() {
- Log.v(TAG, "Processing attachment: $attachmentId")
-
- val attachDb = DatabaseComponent.get(context).attachmentDatabase()
- val attachment = attachDb.getAttachment(attachmentId)
-
- if (attachment == null) {
- throw IllegalStateException("Cannot find attachment with the ID $attachmentId")
- }
- if (!attachment.contentType.startsWith("audio/")) {
- throw IllegalStateException("Attachment $attachmentId is not of audio type.")
- }
-
- // Check if the audio extras already exist.
- if (attachDb.getAttachmentAudioExtras(attachmentId) != null) return
-
- fun extractAttachmentRandomSeed(attachment: Attachment): Int {
- return when {
- attachment.digest != null -> attachment.digest!!.sum()
- attachment.fileName != null -> attachment.fileName.hashCode()
- else -> attachment.hashCode()
- }
- }
-
- fun generateFakeRms(seed: Int, frames: Int = VISUAL_RMS_FRAMES): ByteArray {
- return ByteArray(frames).apply { Random(seed.toLong()).nextBytes(this) }
- }
-
- var rmsValues: ByteArray
- var totalDurationMs: Long = DatabaseAttachmentAudioExtras.DURATION_UNDEFINED
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
- // Due to API version incompatibility, we just display some random waveform for older API.
- rmsValues = generateFakeRms(extractAttachmentRandomSeed(attachment))
- } else {
- try {
- @Suppress("BlockingMethodInNonBlockingContext")
- val decodedAudio = PartAuthority.getAttachmentStream(context, attachment.dataUri!!).use {
- DecodedAudio.create(InputStreamMediaDataSource(it))
- }
- rmsValues = decodedAudio.calculateRms(VISUAL_RMS_FRAMES)
- totalDurationMs = (decodedAudio.totalDuration / 1000.0).toLong()
- } catch (e: Exception) {
- Log.w(TAG, "Failed to decode sample values for the audio attachment \"${attachment.fileName}\".", e)
- rmsValues = generateFakeRms(extractAttachmentRandomSeed(attachment))
- }
- }
-
- attachDb.setAttachmentAudioExtras(DatabaseAttachmentAudioExtras(
- attachmentId,
- rmsValues,
- totalDurationMs
- ))
-
- EventBus.getDefault().post(AudioExtrasUpdatedEvent(attachmentId))
- }
-
- class Factory : Job.Factory {
- override fun create(parameters: Parameters, data: Data): PrepareAttachmentAudioExtrasJob {
- return PrepareAttachmentAudioExtrasJob(parameters, data.getParcelable(DATA_ATTACH_ID, AttachmentId.CREATOR))
- }
- }
-
- /** Gets dispatched once the audio extras have been updated. */
- data class AudioExtrasUpdatedEvent(val attachmentId: AttachmentId)
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
deleted file mode 100644
index 39b7753035..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.app.Application;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsession.avatars.AvatarHelper;
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsession.utilities.Address;
-import org.session.libsession.utilities.DownloadUtilities;
-import org.session.libsession.utilities.TextSecurePreferences;
-import org.session.libsession.utilities.Util;
-import org.session.libsession.utilities.recipients.Recipient;
-import org.session.libsignal.exceptions.PushNetworkException;
-import org.session.libsignal.streams.ProfileCipherInputStream;
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.database.RecipientDatabase;
-import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.SecureRandom;
-import java.util.concurrent.TimeUnit;
-
-public class RetrieveProfileAvatarJob extends BaseJob {
-
- public static final String KEY = "RetrieveProfileAvatarJob";
-
- private static final String TAG = RetrieveProfileAvatarJob.class.getSimpleName();
-
- private static final int MAX_PROFILE_SIZE_BYTES = 10 * 1024 * 1024;
-
- private static final String KEY_PROFILE_AVATAR = "profile_avatar";
- private static final String KEY_ADDRESS = "address";
-
-
- private String profileAvatar;
- private Recipient recipient;
-
- public RetrieveProfileAvatarJob(Recipient recipient, String profileAvatar) {
- this(new Job.Parameters.Builder()
- .setQueue("RetrieveProfileAvatarJob" + recipient.getAddress().serialize())
- .addConstraint(NetworkConstraint.KEY)
- .setLifespan(TimeUnit.HOURS.toMillis(1))
- .setMaxAttempts(2)
- .setMaxInstances(1)
- .build(),
- recipient,
- profileAvatar);
- }
-
- private RetrieveProfileAvatarJob(@NonNull Job.Parameters parameters, @NonNull Recipient recipient, String profileAvatar) {
- super(parameters);
- this.recipient = recipient;
- this.profileAvatar = profileAvatar;
- }
-
- @Override
- public @NonNull
- Data serialize() {
- return new Data.Builder()
- .putString(KEY_PROFILE_AVATAR, profileAvatar)
- .putString(KEY_ADDRESS, recipient.getAddress().serialize())
- .build();
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public void onRun() throws IOException {
- RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
- byte[] profileKey = recipient.resolve().getProfileKey();
-
- if (profileKey == null || (profileKey.length != 32 && profileKey.length != 16)) {
- Log.w(TAG, "Recipient profile key is gone!");
- return;
- }
-
- if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
- Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar);
- return;
- }
-
- if (TextUtils.isEmpty(profileAvatar)) {
- Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize());
- AvatarHelper.delete(context, recipient.getAddress());
- database.setProfileAvatar(recipient, profileAvatar);
- return;
- }
-
- File downloadDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
-
- try {
- DownloadUtilities.downloadFile(downloadDestination, profileAvatar);
- InputStream avatarStream = new ProfileCipherInputStream(new FileInputStream(downloadDestination), profileKey);
- File decryptDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir());
-
- Util.copy(avatarStream, new FileOutputStream(decryptDestination));
- decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.getAddress()));
- } finally {
- if (downloadDestination != null) downloadDestination.delete();
- }
-
- if (recipient.isLocalNumber()) {
- TextSecurePreferences.setProfileAvatarId(context, new SecureRandom().nextInt());
- }
- database.setProfileAvatar(recipient, profileAvatar);
- }
-
- @Override
- public boolean onShouldRetry(@NonNull Exception e) {
- if (e instanceof PushNetworkException) return true;
- return false;
- }
-
- @Override
- public void onCanceled() {
- }
-
- public static final class Factory implements Job.Factory {
-
- private final Application application;
-
- public Factory(Application application) {
- this.application = application;
- }
-
- @Override
- public @NonNull RetrieveProfileAvatarJob create(@NonNull Parameters parameters, @NonNull Data data) {
- return new RetrieveProfileAvatarJob(parameters,
- Recipient.from(application, Address.fromSerialized(data.getString(KEY_ADDRESS)), true),
- data.getString(KEY_PROFILE_AVATAR));
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt
new file mode 100644
index 0000000000..a5b0fce2df
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt
@@ -0,0 +1,99 @@
+package org.thoughtcrime.securesms.jobs
+
+import android.content.Context
+import android.text.TextUtils
+import org.session.libsession.avatars.AvatarHelper
+import org.session.libsession.messaging.jobs.Job
+import org.session.libsession.messaging.jobs.JobDelegate
+import org.session.libsession.messaging.utilities.Data
+import org.session.libsession.utilities.DownloadUtilities.downloadFile
+import org.session.libsession.utilities.TextSecurePreferences.Companion.setProfileAvatarId
+import org.session.libsession.utilities.Util.copy
+import org.session.libsession.utilities.Util.equals
+import org.session.libsession.utilities.Address
+import org.session.libsession.utilities.recipients.Recipient
+import org.session.libsignal.streams.ProfileCipherInputStream
+import org.session.libsignal.utilities.Log
+import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.security.SecureRandom
+
+class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress: Address): Job {
+ override var delegate: JobDelegate? = null
+ override var id: String? = null
+ override var failureCount: Int = 0
+ override val maxFailureCount: Int = 0
+
+ lateinit var context: Context
+
+ companion object {
+ val TAG = RetrieveProfileAvatarJob::class.simpleName
+ val KEY: String = "RetrieveProfileAvatarJob"
+
+ // Keys used for database storage
+ private val PROFILE_AVATAR_KEY = "profileAvatar"
+ private val RECEIPIENT_ADDRESS_KEY = "recipient"
+ }
+
+ override fun execute(dispatcherName: String) {
+ val recipient = Recipient.from(context, recipientAddress, true)
+ val database = get(context).recipientDatabase()
+ val profileKey = recipient.resolve().profileKey
+
+ if (profileKey == null || (profileKey.size != 32 && profileKey.size != 16)) {
+ Log.w(TAG, "Recipient profile key is gone!")
+ return
+ }
+
+ if (AvatarHelper.avatarFileExists(context, recipient.resolve().address) && equals(profileAvatar, recipient.resolve().profileAvatar)) {
+ Log.w(TAG, "Already retrieved profile avatar: $profileAvatar")
+ return
+ }
+
+ if (TextUtils.isEmpty(profileAvatar)) {
+ Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
+ AvatarHelper.delete(context, recipient.address)
+ database.setProfileAvatar(recipient, profileAvatar)
+ return
+ }
+
+ val downloadDestination = File.createTempFile("avatar", ".jpg", context.cacheDir)
+
+ try {
+ downloadFile(downloadDestination, profileAvatar)
+ val avatarStream: InputStream = ProfileCipherInputStream(FileInputStream(downloadDestination), profileKey)
+ val decryptDestination = File.createTempFile("avatar", ".jpg", context.cacheDir)
+ copy(avatarStream, FileOutputStream(decryptDestination))
+ decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.address))
+ } finally {
+ downloadDestination.delete()
+ }
+
+ if (recipient.isLocalNumber) {
+ setProfileAvatarId(context, SecureRandom().nextInt())
+ }
+ database.setProfileAvatar(recipient, profileAvatar)
+ }
+
+ override fun serialize(): Data {
+ return Data.Builder()
+ .putString(PROFILE_AVATAR_KEY, profileAvatar)
+ .putString(RECEIPIENT_ADDRESS_KEY, recipientAddress.serialize())
+ .build()
+ }
+
+ override fun getFactoryKey(): String {
+ return KEY
+ }
+
+ class Factory: Job.Factory {
+ override fun create(data: Data): RetrieveProfileAvatarJob {
+ val profileAvatar = data.getString(PROFILE_AVATAR_KEY)
+ val recipientAddress = Address.fromSerialized(data.getString(RECEIPIENT_ADDRESS_KEY))
+ return RetrieveProfileAvatarJob(profileAvatar, recipientAddress)
+ }
+ }
+}
\ No newline at end of file
From 2ceb9e2bf448bf37e7f855de43be87637b4d6607 Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 8 May 2023 12:29:21 +1000
Subject: [PATCH 26/83] clean up old job manager
---
app/src/main/AndroidManifest.xml | 8 -
.../securesms/ApplicationContext.java | 6 -
.../securesms/database/Storage.kt | 3 +-
.../jobmanager/AlarmManagerScheduler.java | 69 ----
.../jobmanager/CompositeScheduler.java | 22 --
.../jobmanager/ConstraintInstantiator.java | 23 --
.../jobmanager/DependencyInjector.java | 24 --
.../securesms/jobmanager/InAppScheduler.java | 49 ---
.../securesms/jobmanager/Job.java | 286 --------------
.../securesms/jobmanager/JobController.java | 354 ------------------
.../securesms/jobmanager/JobInstantiator.java | 5 +-
.../securesms/jobmanager/JobLogger.java | 24 --
.../securesms/jobmanager/JobManager.java | 167 +--------
.../securesms/jobmanager/JobRunner.java | 110 ------
.../jobmanager/JobSchedulerScheduler.java | 90 -----
.../securesms/jobmanager/Scheduler.java | 9 -
.../thoughtcrime/securesms/jobs/BaseJob.java | 41 --
.../securesms/jobs/FastJobStorage.java | 261 -------------
.../securesms/jobs/JobManagerFactories.java | 2 +-
.../service/LocalBackupListener.java | 5 +-
.../service/UpdateApkRefreshListener.java | 6 +-
.../sskenvironment/ProfileManager.kt | 6 +-
.../securesms/jobs/FastJobStorageTest.java | 350 -----------------
23 files changed, 20 insertions(+), 1900 deletions(-)
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java
delete mode 100644 app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6755addc03..da3be785c3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -446,17 +446,9 @@
-
-
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
index b398d021c5..0d5e57352e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
@@ -66,9 +66,7 @@ import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.jobmanager.JobManager;
-import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-import org.thoughtcrime.securesms.jobs.FastJobStorage;
import org.thoughtcrime.securesms.jobs.JobManagerFactories;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
@@ -354,11 +352,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private void initializeJobManager() {
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
- .setDataSerializer(new JsonDataSerializer())
- .setJobFactories(JobManagerFactories.getJobFactories())
- .setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
- .setJobStorage(new FastJobStorage(jobDatabase))
.build());
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 0d7ea3352f..891df6be87 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -75,8 +75,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
Recipient.from(context, it, false)
}
TextSecurePreferences.setProfilePictureURL(context, newValue)
- RetrieveProfileAvatarJob(ourRecipient, newValue)
- ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(ourRecipient, newValue))
+ JobQueue.shared.add(RetrieveProfileAvatarJob(newValue, ourRecipient.address))
}
override fun getOrGenerateRegistrationID(): Int {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java
deleted file mode 100644
index dc1d2afcf1..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.app.AlarmManager;
-import android.app.Application;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-import androidx.annotation.NonNull;
-
-import com.annimon.stream.Stream;
-
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.ApplicationContext;
-
-import java.util.List;
-import java.util.UUID;
-
-import network.loki.messenger.BuildConfig;
-
-/**
- * Schedules tasks using the {@link AlarmManager}.
- *
- * Given that this scheduler is only used when {@link KeepAliveService} is also used (which keeps
- * all of the {@link ConstraintObserver}s running), this only needs to schedule future runs in
- * situations where all constraints are already met. Otherwise, the {@link ConstraintObserver}s will
- * trigger future runs when the constraints are met.
- *
- * For the same reason, this class also doesn't have to schedule jobs that don't have delays.
- *
- * Important: Only use on API < 26.
- */
-public class AlarmManagerScheduler implements Scheduler {
-
- private static final String TAG = AlarmManagerScheduler.class.getSimpleName();
-
- private final Application application;
-
- AlarmManagerScheduler(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public void schedule(long delay, @NonNull List constraints) {
- if (delay > 0 && Stream.of(constraints).allMatch(Constraint::isMet)) {
- setUniqueAlarm(application, System.currentTimeMillis() + delay);
- }
- }
-
- private void setUniqueAlarm(@NonNull Context context, long time) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- Intent intent = new Intent(context, RetryReceiver.class);
-
- intent.setAction(BuildConfig.APPLICATION_ID + UUID.randomUUID().toString());
- alarmManager.set(AlarmManager.RTC_WAKEUP, time, PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
-
- Log.i(TAG, "Set an alarm to retry a job in " + (time - System.currentTimeMillis()) + " ms.");
- }
-
- public static class RetryReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i(TAG, "Received an alarm to retry a job.");
- ApplicationContext.getInstance(context).getJobManager().wakeUp();
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java
deleted file mode 100644
index 322366f4f4..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-
-import java.util.Arrays;
-import java.util.List;
-
-class CompositeScheduler implements Scheduler {
-
- private final List schedulers;
-
- CompositeScheduler(@NonNull Scheduler... schedulers) {
- this.schedulers = Arrays.asList(schedulers);
- }
-
- @Override
- public void schedule(long delay, @NonNull List constraints) {
- for (Scheduler scheduler : schedulers) {
- scheduler.schedule(delay, constraints);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java
deleted file mode 100644
index b0a67e3d19..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class ConstraintInstantiator {
-
- private final Map constraintFactories;
-
- ConstraintInstantiator(@NonNull Map constraintFactories) {
- this.constraintFactories = new HashMap<>(constraintFactories);
- }
-
- public @NonNull Constraint instantiate(@NonNull String constraintFactoryKey) {
- if (constraintFactories.containsKey(constraintFactoryKey)) {
- return constraintFactories.get(constraintFactoryKey).create();
- } else {
- throw new IllegalStateException("Tried to instantiate a constraint with key '" + constraintFactoryKey + "', but no matching factory was found.");
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java
deleted file mode 100644
index c8a266bd87..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager;
-
-/**
- * Interface responsible for injecting dependencies into Jobs.
- */
-public interface DependencyInjector {
- void injectDependencies(Object object);
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java
deleted file mode 100644
index b0f314eaa6..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import androidx.annotation.NonNull;
-
-import com.annimon.stream.Stream;
-
-import org.session.libsignal.utilities.Log;
-
-import java.util.List;
-
-/**
- * Schedules future runs on an in-app handler. Intended to be used in combination with a persistent
- * {@link Scheduler} to improve responsiveness when the app is open.
- *
- * This should only schedule runs when all constraints are met. Because this only works when the
- * app is foregrounded, jobs that don't have their constraints met will be run when the relevant
- * {@link ConstraintObserver} is triggered.
- *
- * Similarly, this does not need to schedule retries with no delay, as this doesn't provide any
- * persistence, and other mechanisms will take care of that.
- */
-class InAppScheduler implements Scheduler {
-
- private static final String TAG = InAppScheduler.class.getSimpleName();
-
- private final JobManager jobManager;
- private final Handler handler;
-
- InAppScheduler(@NonNull JobManager jobManager) {
- HandlerThread handlerThread = new HandlerThread("InAppScheduler");
- handlerThread.start();
-
- this.jobManager = jobManager;
- this.handler = new Handler(handlerThread.getLooper());
- }
-
- @Override
- public void schedule(long delay, @NonNull List constraints) {
- if (delay > 0 && Stream.of(constraints).allMatch(Constraint::isMet)) {
- Log.i(TAG, "Scheduling a retry in " + delay + " ms.");
- handler.postDelayed(() -> {
- Log.i(TAG, "Triggering a job retry.");
- jobManager.wakeUp();
- }, delay);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java
deleted file mode 100644
index 990207779d..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java
+++ /dev/null
@@ -1,286 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.content.Context;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsignal.utilities.Log;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A durable unit of work.
- *
- * Jobs have {@link Parameters} that describe the conditions upon when you'd like them to run, how
- * often they should be retried, and how long they should be retried for.
- *
- * Never rely on a specific instance of this class being run. It can be created and destroyed as the
- * job is retried. State that you want to save is persisted to a {@link Data} object in
- * {@link #serialize()}. Your job is then recreated using a {@link Factory} that you register in
- * {@link JobManager.Configuration.Builder#setJobFactories(Map)}, which is given the saved
- * {@link Data} bundle.
- *
- * @deprecated
- * use WorkManager
- * API instead.
- */
-public abstract class Job {
-
- private static final String TAG = Log.tag(Job.class);
-
- private final Parameters parameters;
-
- private String id;
- private int runAttempt;
- private long nextRunAttemptTime;
-
- protected Context context;
-
- public Job(@NonNull Parameters parameters) {
- this.parameters = parameters;
- }
-
- public final String getId() {
- return id;
- }
-
- public final @NonNull Parameters getParameters() {
- return parameters;
- }
-
- public final int getRunAttempt() {
- return runAttempt;
- }
-
- public final long getNextRunAttemptTime() {
- return nextRunAttemptTime;
- }
-
- /**
- * This is already called by {@link JobController} during job submission, but if you ever run a
- * job without submitting it to the {@link JobManager}, then you'll need to invoke this yourself.
- */
- public final void setContext(@NonNull Context context) {
- this.context = context;
- }
-
- /** Should only be invoked by {@link JobController} */
- final void setId(@NonNull String id) {
- this.id = id;
- }
-
- /** Should only be invoked by {@link JobController} */
- final void setRunAttempt(int runAttempt) {
- this.runAttempt = runAttempt;
- }
-
- /** Should only be invoked by {@link JobController} */
- final void setNextRunAttemptTime(long nextRunAttemptTime) {
- this.nextRunAttemptTime = nextRunAttemptTime;
- }
-
- @WorkerThread
- final void onSubmit() {
- Log.i(TAG, JobLogger.format(this, "onSubmit()"));
- onAdded();
- }
-
- /**
- * Called when the job is first submitted to the {@link JobManager}.
- */
- @WorkerThread
- public void onAdded() {
- }
-
- /**
- * Called after a job has run and its determined that a retry is required.
- */
- @WorkerThread
- public void onRetry() {
- }
-
- /**
- * Serialize your job state so that it can be recreated in the future.
- */
- public abstract @NonNull Data serialize();
-
- /**
- * Returns the key that can be used to find the relevant factory needed to create your job.
- */
- public abstract @NonNull String getFactoryKey();
-
- /**
- * Called to do your actual work.
- */
- @WorkerThread
- public abstract @NonNull Result run();
-
- /**
- * Called when your job has completely failed.
- */
- @WorkerThread
- public abstract void onCanceled();
-
- public interface Factory {
- @NonNull T create(@NonNull Parameters parameters, @NonNull Data data);
- }
-
- public enum Result {
- SUCCESS, FAILURE, RETRY
- }
-
- public static final class Parameters {
-
- public static final int IMMORTAL = -1;
- public static final int UNLIMITED = -1;
-
- private final long createTime;
- private final long lifespan;
- private final int maxAttempts;
- private final long maxBackoff;
- private final int maxInstances;
- private final String queue;
- private final List constraintKeys;
-
- private Parameters(long createTime,
- long lifespan,
- int maxAttempts,
- long maxBackoff,
- int maxInstances,
- @Nullable String queue,
- @NonNull List constraintKeys)
- {
- this.createTime = createTime;
- this.lifespan = lifespan;
- this.maxAttempts = maxAttempts;
- this.maxBackoff = maxBackoff;
- this.maxInstances = maxInstances;
- this.queue = queue;
- this.constraintKeys = constraintKeys;
- }
-
- public long getCreateTime() {
- return createTime;
- }
-
- public long getLifespan() {
- return lifespan;
- }
-
- public int getMaxAttempts() {
- return maxAttempts;
- }
-
- public long getMaxBackoff() {
- return maxBackoff;
- }
-
- public int getMaxInstances() {
- return maxInstances;
- }
-
- public @Nullable String getQueue() {
- return queue;
- }
-
- public List getConstraintKeys() {
- return constraintKeys;
- }
-
-
- public static final class Builder {
-
- private long createTime = System.currentTimeMillis();
- private long maxBackoff = TimeUnit.SECONDS.toMillis(30);
- private long lifespan = IMMORTAL;
- private int maxAttempts = 1;
- private int maxInstances = UNLIMITED;
- private String queue = null;
- private List constraintKeys = new LinkedList<>();
-
- /** Should only be invoked by {@link JobController} */
- Builder setCreateTime(long createTime) {
- this.createTime = createTime;
- return this;
- }
-
- /**
- * Specify the amount of time this job is allowed to be retried. Defaults to {@link #IMMORTAL}.
- */
- public @NonNull Builder setLifespan(long lifespan) {
- this.lifespan = lifespan;
- return this;
- }
-
- /**
- * Specify the maximum number of times you want to attempt this job. Defaults to 1.
- */
- public @NonNull Builder setMaxAttempts(int maxAttempts) {
- this.maxAttempts = maxAttempts;
- return this;
- }
-
- /**
- * Specify the longest amount of time to wait between retries. No guarantees that this will
- * be respected on API >= 26.
- */
- public @NonNull Builder setMaxBackoff(long maxBackoff) {
- this.maxBackoff = maxBackoff;
- return this;
- }
-
- /**
- * Specify the maximum number of instances you'd want of this job at any given time. If
- * enqueueing this job would put it over that limit, it will be ignored.
- *
- * Duplicates are determined by two jobs having the same {@link Job#getFactoryKey()}.
- *
- * This property is ignored if the job is submitted as part of a {@link JobManager.Chain}.
- *
- * Defaults to {@link #UNLIMITED}.
- */
- public @NonNull Builder setMaxInstances(int maxInstances) {
- this.maxInstances = maxInstances;
- return this;
- }
-
- /**
- * Specify a string representing a queue. All jobs within the same queue are run in a
- * serialized fashion -- one after the other, in order of insertion. Failure of a job earlier
- * in the queue has no impact on the execution of jobs later in the queue.
- */
- public @NonNull Builder setQueue(@Nullable String queue) {
- this.queue = queue;
- return this;
- }
-
- /**
- * Add a constraint via the key that was used to register its factory in
- * {@link JobManager.Configuration)};
- */
- public @NonNull Builder addConstraint(@NonNull String constraintKey) {
- constraintKeys.add(constraintKey);
- return this;
- }
-
- /**
- * Set constraints via the key that was used to register its factory in
- * {@link JobManager.Configuration)};
- */
- public @NonNull Builder setConstraints(@NonNull List constraintKeys) {
- this.constraintKeys.clear();
- this.constraintKeys.addAll(constraintKeys);
- return this;
- }
-
- public @NonNull Parameters build() {
- return new Parameters(createTime, lifespan, maxAttempts, maxBackoff, maxInstances, queue, constraintKeys);
- }
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java
deleted file mode 100644
index 33345a03e1..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java
+++ /dev/null
@@ -1,354 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.app.Application;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-
-import com.annimon.stream.Stream;
-
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsession.utilities.Debouncer;
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Manages the queue of jobs. This is the only class that should write to {@link JobStorage} to
- * ensure consistency.
- */
-class JobController {
-
- private static final String TAG = JobController.class.getSimpleName();
-
- private final Application application;
- private final JobStorage jobStorage;
- private final JobInstantiator jobInstantiator;
- private final ConstraintInstantiator constraintInstantiator;
- private final Data.Serializer dataSerializer;
- private final Scheduler scheduler;
- private final Debouncer debouncer;
- private final Callback callback;
- private final Set runningJobs;
-
- JobController(@NonNull Application application,
- @NonNull JobStorage jobStorage,
- @NonNull JobInstantiator jobInstantiator,
- @NonNull ConstraintInstantiator constraintInstantiator,
- @NonNull Data.Serializer dataSerializer,
- @NonNull Scheduler scheduler,
- @NonNull Debouncer debouncer,
- @NonNull Callback callback)
- {
- this.application = application;
- this.jobStorage = jobStorage;
- this.jobInstantiator = jobInstantiator;
- this.constraintInstantiator = constraintInstantiator;
- this.dataSerializer = dataSerializer;
- this.scheduler = scheduler;
- this.debouncer = debouncer;
- this.callback = callback;
- this.runningJobs = new HashSet<>();
- }
-
- @WorkerThread
- synchronized void init() {
- jobStorage.init();
- jobStorage.updateAllJobsToBePending();
- notifyAll();
- }
-
- synchronized void wakeUp() {
- notifyAll();
- }
-
- @WorkerThread
- synchronized void submitNewJobChain(@NonNull List
> chain) {
- chain = Stream.of(chain).filterNot(List::isEmpty).toList();
-
- if (chain.isEmpty()) {
- Log.w(TAG, "Tried to submit an empty job chain. Skipping.");
- return;
- }
-
- if (chainExceedsMaximumInstances(chain)) {
- Job solo = chain.get(0).get(0);
- Log.w(TAG, JobLogger.format(solo, "Already at the max instance count of " + solo.getParameters().getMaxInstances() + ". Skipping."));
- return;
- }
-
- insertJobChain(chain);
- scheduleJobs(chain.get(0));
- triggerOnSubmit(chain);
- notifyAll();
- }
-
- @WorkerThread
- synchronized void onRetry(@NonNull Job job) {
- int nextRunAttempt = job.getRunAttempt() + 1;
- long nextRunAttemptTime = calculateNextRunAttemptTime(System.currentTimeMillis(), nextRunAttempt, job.getParameters().getMaxBackoff());
-
- jobStorage.updateJobAfterRetry(job.getId(), false, nextRunAttempt, nextRunAttemptTime);
-
- List constraints = Stream.of(jobStorage.getConstraintSpecs(job.getId()))
- .map(ConstraintSpec::getFactoryKey)
- .map(constraintInstantiator::instantiate)
- .toList();
-
-
- long delay = Math.max(0, nextRunAttemptTime - System.currentTimeMillis());
-
- Log.i(TAG, JobLogger.format(job, "Scheduling a retry in " + delay + " ms."));
- scheduler.schedule(delay, constraints);
-
- notifyAll();
- }
-
- synchronized void onJobFinished(@NonNull Job job) {
- runningJobs.remove(job.getId());
- }
-
- @WorkerThread
- synchronized void onSuccess(@NonNull Job job) {
- jobStorage.deleteJob(job.getId());
- notifyAll();
- }
-
- /**
- * @return The list of all dependent jobs that should also be failed.
- */
- @WorkerThread
- synchronized @NonNull List onFailure(@NonNull Job job) {
- List dependents = Stream.of(jobStorage.getDependencySpecsThatDependOnJob(job.getId()))
- .map(DependencySpec::getJobId)
- .map(jobStorage::getJobSpec)
- .withoutNulls()
- .map(jobSpec -> {
- List constraintSpecs = jobStorage.getConstraintSpecs(jobSpec.getId());
- return createJob(jobSpec, constraintSpecs);
- })
- .toList();
-
- List all = new ArrayList<>(dependents.size() + 1);
- all.add(job);
- all.addAll(dependents);
-
- jobStorage.deleteJobs(Stream.of(all).map(Job::getId).toList());
-
- return dependents;
- }
-
- /**
- * Retrieves the next job that is eligible for execution. To be 'eligible' means that the job:
- * - Has no dependencies
- * - Has no unmet constraints
- *
- * This method will block until a job is available.
- * When the job returned from this method has been run, you must call {@link #onJobFinished(Job)}.
- */
- @WorkerThread
- synchronized @NonNull Job pullNextEligibleJobForExecution() {
- try {
- Job job;
-
- while ((job = getNextEligibleJobForExecution()) == null) {
- if (runningJobs.isEmpty()) {
- debouncer.publish(callback::onEmpty);
- }
-
- wait();
- }
-
- jobStorage.updateJobRunningState(job.getId(), true);
- runningJobs.add(job.getId());
-
- return job;
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted.");
- throw new AssertionError(e);
- }
- }
-
- /**
- * Retrieves a string representing the state of the job queue. Intended for debugging.
- */
- @WorkerThread
- synchronized @NonNull String getDebugInfo() {
- List jobs = jobStorage.getAllJobSpecs();
- List constraints = jobStorage.getAllConstraintSpecs();
- List dependencies = jobStorage.getAllDependencySpecs();
-
- StringBuilder info = new StringBuilder();
-
- info.append("-- Jobs\n");
- if (!jobs.isEmpty()) {
- Stream.of(jobs).forEach(j -> info.append(j.toString()).append('\n'));
- } else {
- info.append("None\n");
- }
-
- info.append("\n-- Constraints\n");
- if (!constraints.isEmpty()) {
- Stream.of(constraints).forEach(c -> info.append(c.toString()).append('\n'));
- } else {
- info.append("None\n");
- }
-
- info.append("\n-- Dependencies\n");
- if (!dependencies.isEmpty()) {
- Stream.of(dependencies).forEach(d -> info.append(d.toString()).append('\n'));
- } else {
- info.append("None\n");
- }
-
- return info.toString();
- }
-
- @WorkerThread
- private boolean chainExceedsMaximumInstances(@NonNull List> chain) {
- if (chain.size() == 1 && chain.get(0).size() == 1) {
- Job solo = chain.get(0).get(0);
-
- if (solo.getParameters().getMaxInstances() != Job.Parameters.UNLIMITED &&
- jobStorage.getJobInstanceCount(solo.getFactoryKey()) >= solo.getParameters().getMaxInstances())
- {
- return true;
- }
- }
- return false;
- }
-
- @WorkerThread
- private void triggerOnSubmit(@NonNull List> chain) {
- Stream.of(chain)
- .forEach(list -> Stream.of(list).forEach(job -> {
- job.setContext(application);
- job.onSubmit();
- }));
- }
-
- @WorkerThread
- private void insertJobChain(@NonNull List> chain) {
- List fullSpecs = new LinkedList<>();
- List dependsOn = Collections.emptyList();
-
- for (List jobList : chain) {
- for (Job job : jobList) {
- fullSpecs.add(buildFullSpec(job, dependsOn));
- }
- dependsOn = jobList;
- }
-
- jobStorage.insertJobs(fullSpecs);
- }
-
- @WorkerThread
- private @NonNull FullSpec buildFullSpec(@NonNull Job job, @NonNull List dependsOn) {
- String id = UUID.randomUUID().toString();
-
- job.setId(id);
- job.setRunAttempt(0);
-
- JobSpec jobSpec = new JobSpec(job.getId(),
- job.getFactoryKey(),
- job.getParameters().getQueue(),
- job.getParameters().getCreateTime(),
- job.getNextRunAttemptTime(),
- job.getRunAttempt(),
- job.getParameters().getMaxAttempts(),
- job.getParameters().getMaxBackoff(),
- job.getParameters().getLifespan(),
- job.getParameters().getMaxInstances(),
- dataSerializer.serialize(job.serialize()),
- false);
-
- List constraintSpecs = Stream.of(job.getParameters().getConstraintKeys())
- .map(key -> new ConstraintSpec(jobSpec.getId(), key))
- .toList();
-
- List dependencySpecs = Stream.of(dependsOn)
- .map(depends -> new DependencySpec(job.getId(), depends.getId()))
- .toList();
-
- return new FullSpec(jobSpec, constraintSpecs, dependencySpecs);
- }
-
- @WorkerThread
- private void scheduleJobs(@NonNull List jobs) {
- for (Job job : jobs) {
- List constraints = Stream.of(job.getParameters().getConstraintKeys())
- .map(key -> new ConstraintSpec(job.getId(), key))
- .map(ConstraintSpec::getFactoryKey)
- .map(constraintInstantiator::instantiate)
- .toList();
-
- scheduler.schedule(0, constraints);
- }
- }
-
- @WorkerThread
- private @Nullable Job getNextEligibleJobForExecution() {
- List jobSpecs = jobStorage.getPendingJobsWithNoDependenciesInCreatedOrder(System.currentTimeMillis());
-
- for (JobSpec jobSpec : jobSpecs) {
- List constraintSpecs = jobStorage.getConstraintSpecs(jobSpec.getId());
- List constraints = Stream.of(constraintSpecs)
- .map(ConstraintSpec::getFactoryKey)
- .map(constraintInstantiator::instantiate)
- .toList();
-
- if (Stream.of(constraints).allMatch(Constraint::isMet)) {
- return createJob(jobSpec, constraintSpecs);
- }
- }
-
- return null;
- }
-
- private @NonNull Job createJob(@NonNull JobSpec jobSpec, @NonNull List constraintSpecs) {
- Job.Parameters parameters = buildJobParameters(jobSpec, constraintSpecs);
- Data data = dataSerializer.deserialize(jobSpec.getSerializedData());
- Job job = jobInstantiator.instantiate(jobSpec.getFactoryKey(), parameters, data);
-
- job.setId(jobSpec.getId());
- job.setRunAttempt(jobSpec.getRunAttempt());
- job.setNextRunAttemptTime(jobSpec.getNextRunAttemptTime());
- job.setContext(application);
-
- return job;
- }
-
- private @NonNull Job.Parameters buildJobParameters(@NonNull JobSpec jobSpec, @NonNull List constraintSpecs) {
- return new Job.Parameters.Builder()
- .setCreateTime(jobSpec.getCreateTime())
- .setLifespan(jobSpec.getLifespan())
- .setMaxAttempts(jobSpec.getMaxAttempts())
- .setQueue(jobSpec.getQueueKey())
- .setConstraints(Stream.of(constraintSpecs).map(ConstraintSpec::getFactoryKey).toList())
- .build();
- }
-
- private long calculateNextRunAttemptTime(long currentTime, int nextAttempt, long maxBackoff) {
- int boundedAttempt = Math.min(nextAttempt, 30);
- long exponentialBackoff = (long) Math.pow(2, boundedAttempt) * 1000;
- long actualBackoff = Math.min(exponentialBackoff, maxBackoff);
-
- return currentTime + actualBackoff;
- }
-
- interface Callback {
- void onEmpty();
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
index 6d1527d131..81e378288d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobmanager;
import androidx.annotation.NonNull;
+import org.session.libsession.messaging.jobs.Job;
import org.session.libsession.messaging.utilities.Data;
import java.util.HashMap;
@@ -15,9 +16,9 @@ class JobInstantiator {
this.jobFactories = new HashMap<>(jobFactories);
}
- public @NonNull Job instantiate(@NonNull String jobFactoryKey, @NonNull Job.Parameters parameters, @NonNull Data data) {
+ public @NonNull Job instantiate(@NonNull String jobFactoryKey, @NonNull Data data) {
if (jobFactories.containsKey(jobFactoryKey)) {
- return jobFactories.get(jobFactoryKey).create(parameters, data);
+ return jobFactories.get(jobFactoryKey).create(data);
} else {
throw new IllegalStateException("Tried to instantiate a job with key '" + jobFactoryKey + "', but no matching factory was found.");
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java
deleted file mode 100644
index c35f6dc1ac..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-import android.text.TextUtils;
-
-public class JobLogger {
-
- public static String format(@NonNull Job job, @NonNull String event) {
- return format(job, "", event);
- }
-
- public static String format(@NonNull Job job, @NonNull String extraTag, @NonNull String event) {
- String id = job.getId();
- String tag = TextUtils.isEmpty(extraTag) ? "" : "[" + extraTag + "]";
- long timeSinceSubmission = System.currentTimeMillis() - job.getParameters().getCreateTime();
- int runAttempt = job.getRunAttempt() + 1;
- String maxAttempts = job.getParameters().getMaxAttempts() == Job.Parameters.UNLIMITED ? "Unlimited"
- : String.valueOf(job.getParameters().getMaxAttempts());
- String lifespan = job.getParameters().getLifespan() == Job.Parameters.IMMORTAL ? "Immortal"
- : String.valueOf(job.getParameters().getLifespan()) + " ms";
- return String.format("[%s][%s]%s %s (Time Since Submission: %d ms, Lifespan: %s, Run Attempt: %d/%s)",
- id, job.getClass().getSimpleName(), tag, event, timeSinceSubmission, lifespan, runAttempt, maxAttempts);
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
index abb15d9f75..7bbd7679f7 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
@@ -6,24 +6,14 @@ import android.os.Build;
import androidx.annotation.NonNull;
-import org.session.libsession.messaging.utilities.Data;
-import org.session.libsession.utilities.Debouncer;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory;
-import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
/**
* Allows the scheduling of durable jobs that will be run as early as possible.
@@ -33,32 +23,13 @@ public class JobManager implements ConstraintObserver.Notifier {
private static final String TAG = JobManager.class.getSimpleName();
private final ExecutorService executor;
- private final JobController jobController;
- private final JobRunner[] jobRunners;
private final Set emptyQueueListeners = new CopyOnWriteArraySet<>();
public JobManager(@NonNull Application application, @NonNull Configuration configuration) {
this.executor = configuration.getExecutorFactory().newSingleThreadExecutor("JobManager");
- this.jobRunners = new JobRunner[configuration.getJobThreadCount()];
- this.jobController = new JobController(application,
- configuration.getJobStorage(),
- configuration.getJobInstantiator(),
- configuration.getConstraintFactories(),
- configuration.getDataSerializer(),
- Build.VERSION.SDK_INT < 26 ? new AlarmManagerScheduler(application)
- : new CompositeScheduler(new InAppScheduler(this), new JobSchedulerScheduler(application)),
- new Debouncer(500),
- this::onEmptyQueue);
executor.execute(() -> {
- jobController.init();
-
- for (int i = 0; i < jobRunners.length; i++) {
- jobRunners[i] = new JobRunner(application, i + 1, jobController);
- jobRunners[i].start();
- }
-
for (ConstraintObserver constraintObserver : configuration.getConstraintObservers()) {
constraintObserver.register(this);
}
@@ -71,13 +42,6 @@ public class JobManager implements ConstraintObserver.Notifier {
});
}
- /**
- * Enqueues a single job to be run.
- */
- public void add(@NonNull Job job) {
- new Chain(this, Collections.singletonList(job)).enqueue();
- }
-
/**
* Adds a listener to that will be notified when the job queue has been drained.
*/
@@ -105,166 +69,45 @@ public class JobManager implements ConstraintObserver.Notifier {
/**
* Pokes the system to take another pass at the job queue.
*/
- void wakeUp() {
- executor.execute(jobController::wakeUp);
- }
-
- private void enqueueChain(@NonNull Chain chain) {
- executor.execute(() -> {
- jobController.submitNewJobChain(chain.getJobListChain());
- wakeUp();
- });
- }
-
- private void onEmptyQueue() {
- executor.execute(() -> {
- for (EmptyQueueListener listener : emptyQueueListeners) {
- listener.onQueueEmpty();
- }
- });
- }
+ void wakeUp() {}
public interface EmptyQueueListener {
void onQueueEmpty();
}
- /**
- * Allows enqueuing work that depends on each other. Jobs that appear later in the chain will
- * only run after all jobs earlier in the chain have been completed. If a job fails, all jobs
- * that occur later in the chain will also be failed.
- */
- public static class Chain {
-
- private final JobManager jobManager;
- private final List> jobs;
-
- private Chain(@NonNull JobManager jobManager, @NonNull List extends Job> jobs) {
- this.jobManager = jobManager;
- this.jobs = new LinkedList<>();
-
- this.jobs.add(new ArrayList<>(jobs));
- }
-
- public Chain then(@NonNull Job job) {
- return then(Collections.singletonList(job));
- }
-
- public Chain then(@NonNull List jobs) {
- if (!jobs.isEmpty()) {
- this.jobs.add(new ArrayList<>(jobs));
- }
- return this;
- }
-
- public void enqueue() {
- jobManager.enqueueChain(this);
- }
-
- private List> getJobListChain() {
- return jobs;
- }
- }
-
public static class Configuration {
private final ExecutorFactory executorFactory;
- private final int jobThreadCount;
- private final JobInstantiator jobInstantiator;
- private final ConstraintInstantiator constraintInstantiator;
private final List constraintObservers;
- private final Data.Serializer dataSerializer;
- private final JobStorage jobStorage;
- private Configuration(int jobThreadCount,
- @NonNull ExecutorFactory executorFactory,
- @NonNull JobInstantiator jobInstantiator,
- @NonNull ConstraintInstantiator constraintInstantiator,
- @NonNull List constraintObservers,
- @NonNull Data.Serializer dataSerializer,
- @NonNull JobStorage jobStorage)
+ private Configuration(@NonNull ExecutorFactory executorFactory,
+ @NonNull List constraintObservers)
{
this.executorFactory = executorFactory;
- this.jobThreadCount = jobThreadCount;
- this.jobInstantiator = jobInstantiator;
- this.constraintInstantiator = constraintInstantiator;
this.constraintObservers = constraintObservers;
- this.dataSerializer = dataSerializer;
- this.jobStorage = jobStorage;
- }
-
- int getJobThreadCount() {
- return jobThreadCount;
}
@NonNull ExecutorFactory getExecutorFactory() {
return executorFactory;
}
- @NonNull JobInstantiator getJobInstantiator() {
- return jobInstantiator;
- }
-
- @NonNull
- ConstraintInstantiator getConstraintFactories() {
- return constraintInstantiator;
- }
-
@NonNull List getConstraintObservers() {
return constraintObservers;
}
- @NonNull Data.Serializer getDataSerializer() {
- return dataSerializer;
- }
-
- @NonNull JobStorage getJobStorage() {
- return jobStorage;
- }
-
-
public static class Builder {
private ExecutorFactory executorFactory = new DefaultExecutorFactory();
- private int jobThreadCount = 1;
- private Map jobFactories = new HashMap<>();
- private Map constraintFactories = new HashMap<>();
private List constraintObservers = new ArrayList<>();
- private Data.Serializer dataSerializer = new JsonDataSerializer();
- private JobStorage jobStorage = null;
-
- public @NonNull Builder setJobFactories(@NonNull Map jobFactories) {
- this.jobFactories = jobFactories;
- return this;
- }
-
- public @NonNull Builder setConstraintFactories(@NonNull Map constraintFactories) {
- this.constraintFactories = constraintFactories;
- return this;
- }
public @NonNull Builder setConstraintObservers(@NonNull List constraintObservers) {
this.constraintObservers = constraintObservers;
return this;
}
- public @NonNull Builder setDataSerializer(@NonNull Data.Serializer dataSerializer) {
- this.dataSerializer = dataSerializer;
- return this;
- }
-
- public @NonNull Builder setJobStorage(@NonNull JobStorage jobStorage) {
- this.jobStorage = jobStorage;
- return this;
- }
-
public @NonNull Configuration build() {
- return new Configuration(jobThreadCount,
- executorFactory,
- new JobInstantiator(jobFactories),
- new ConstraintInstantiator(constraintFactories),
- new ArrayList<>(constraintObservers),
- dataSerializer,
- jobStorage);
+ return new Configuration(executorFactory,
+ new ArrayList<>(constraintObservers));
}
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java
deleted file mode 100644
index 6eadf0fd5d..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.app.Application;
-import android.os.PowerManager;
-import androidx.annotation.NonNull;
-
-import com.annimon.stream.Stream;
-
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.util.WakeLockUtil;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-class JobRunner extends Thread {
-
- private static final String TAG = JobRunner.class.getSimpleName();
-
- private static long WAKE_LOCK_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
-
- private final Application application;
- private final int id;
- private final JobController jobController;
-
- JobRunner(@NonNull Application application, int id, @NonNull JobController jobController) {
- super("JobRunner-" + id);
-
- this.application = application;
- this.id = id;
- this.jobController = jobController;
- }
-
- @Override
- public synchronized void run() {
- while (true) {
- Job job = jobController.pullNextEligibleJobForExecution();
- Job.Result result = run(job);
-
- jobController.onJobFinished(job);
-
- switch (result) {
- case SUCCESS:
- jobController.onSuccess(job);
- break;
- case RETRY:
- jobController.onRetry(job);
- job.onRetry();
- break;
- case FAILURE:
- List dependents = jobController.onFailure(job);
- job.onCanceled();
- Stream.of(dependents).forEach(Job::onCanceled);
- break;
- }
- }
- }
-
- private Job.Result run(@NonNull Job job) {
- Log.i(TAG, JobLogger.format(job, String.valueOf(id), "Running job."));
-
- if (isJobExpired(job)) {
- Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its lifespan."));
- return Job.Result.FAILURE;
- }
-
- Job.Result result = null;
- PowerManager.WakeLock wakeLock = null;
-
- try {
- wakeLock = WakeLockUtil.acquire(application, PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TIMEOUT, job.getId());
- result = job.run();
- } catch (Exception e) {
- Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing due to an unexpected exception."), e);
- return Job.Result.FAILURE;
- } finally {
- if (wakeLock != null) {
- WakeLockUtil.release(wakeLock, job.getId());
- }
- }
-
- printResult(job, result);
-
- if (result == Job.Result.RETRY && job.getRunAttempt() + 1 >= job.getParameters().getMaxAttempts() &&
- job.getParameters().getMaxAttempts() != Job.Parameters.UNLIMITED)
- {
- Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its max number of attempts."));
- return Job.Result.FAILURE;
- }
-
- return result;
- }
-
- private boolean isJobExpired(@NonNull Job job) {
- long expirationTime = job.getParameters().getCreateTime() + job.getParameters().getLifespan();
-
- if (expirationTime < 0) {
- expirationTime = Long.MAX_VALUE;
- }
-
- return job.getParameters().getLifespan() != Job.Parameters.IMMORTAL && expirationTime <= System.currentTimeMillis();
- }
-
- private void printResult(@NonNull Job job, @NonNull Job.Result result) {
- if (result == Job.Result.FAILURE) {
- Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Job failed."));
- } else {
- Log.i(TAG, JobLogger.format(job, String.valueOf(id), "Job finished with result: " + result));
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java
deleted file mode 100644
index 40acbf520b..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.app.Application;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-import org.thoughtcrime.securesms.ApplicationContext;
-import org.session.libsignal.utilities.Log;
-
-import java.util.List;
-
-@RequiresApi(26)
-public class JobSchedulerScheduler implements Scheduler {
-
- private static final String TAG = JobSchedulerScheduler.class.getSimpleName();
-
- private static final String PREF_NAME = "JobSchedulerScheduler_prefs";
- private static final String PREF_NEXT_ID = "pref_next_id";
-
- private static final int MAX_ID = 75;
-
- private final Application application;
-
- JobSchedulerScheduler(@NonNull Application application) {
- this.application = application;
- }
-
- @RequiresApi(26)
- @Override
- public void schedule(long delay, @NonNull List constraints) {
- JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(getNextId(), new ComponentName(application, SystemService.class))
- .setMinimumLatency(delay)
- .setPersisted(true);
-
- for (Constraint constraint : constraints) {
- constraint.applyToJobInfo(jobInfoBuilder);
- }
-
- Log.i(TAG, "Scheduling a run in " + delay + " ms.");
- JobScheduler jobScheduler = application.getSystemService(JobScheduler.class);
- jobScheduler.schedule(jobInfoBuilder.build());
- }
-
- private int getNextId() {
- SharedPreferences prefs = application.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- int returnedId = prefs.getInt(PREF_NEXT_ID, 0);
- int nextId = returnedId + 1 > MAX_ID ? 0 : returnedId + 1;
-
- prefs.edit().putInt(PREF_NEXT_ID, nextId).apply();
-
- return returnedId;
- }
-
- @RequiresApi(api = 26)
- public static class SystemService extends JobService {
-
- @Override
- public boolean onStartJob(JobParameters params) {
- Log.d(TAG, "onStartJob()");
-
- JobManager jobManager = ApplicationContext.getInstance(getApplicationContext()).getJobManager();
-
- jobManager.addOnEmptyQueueListener(new JobManager.EmptyQueueListener() {
- @Override
- public void onQueueEmpty() {
- jobManager.removeOnEmptyQueueListener(this);
- jobFinished(params, false);
- Log.d(TAG, "jobFinished()");
- }
- });
-
- jobManager.wakeUp();
-
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters params) {
- Log.d(TAG, "onStopJob()");
- return false;
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java
deleted file mode 100644
index 194acd39b2..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-
-import java.util.List;
-
-public interface Scheduler {
- void schedule(long delay, @NonNull List constraints);
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java
deleted file mode 100644
index 0c11cc552b..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.JobLogger;
-import org.session.libsignal.utilities.Log;
-
-/**
- * @deprecated
- * use WorkManager
- * API instead.
- */
-public abstract class BaseJob extends Job {
-
- private static final String TAG = BaseJob.class.getSimpleName();
-
- public BaseJob(@NonNull Parameters parameters) {
- super(parameters);
- }
-
- @Override
- public @NonNull Result run() {
- try {
- onRun();
- return Result.SUCCESS;
- } catch (Exception e) {
- if (onShouldRetry(e)) {
- Log.i(TAG, JobLogger.format(this, "Encountered a retryable exception."), e);
- return Result.RETRY;
- } else {
- Log.w(TAG, JobLogger.format(this, "Encountered a failing exception."), e);
- return Result.FAILURE;
- }
- }
- }
-
- protected abstract void onRun() throws Exception;
-
- protected abstract boolean onShouldRetry(@NonNull Exception e);
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java
deleted file mode 100644
index 3b50dc2733..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.annimon.stream.Stream;
-
-import org.thoughtcrime.securesms.database.JobDatabase;
-import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
-
-import org.session.libsession.utilities.Util;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-public class FastJobStorage implements JobStorage {
-
- private final JobDatabase jobDatabase;
-
- private final List jobs;
- private final Map> constraintsByJobId;
- private final Map> dependenciesByJobId;
-
- public FastJobStorage(@NonNull JobDatabase jobDatabase) {
- this.jobDatabase = jobDatabase;
- this.jobs = new ArrayList<>();
- this.constraintsByJobId = new HashMap<>();
- this.dependenciesByJobId = new HashMap<>();
- }
-
- @Override
- public synchronized void init() {
- List jobSpecs = jobDatabase.getAllJobSpecs();
- List constraintSpecs = jobDatabase.getAllConstraintSpecs();
- List dependencySpecs = jobDatabase.getAllDependencySpecs();
-
- jobs.addAll(jobSpecs);
-
- for (ConstraintSpec constraintSpec: constraintSpecs) {
- List jobConstraints = Util.getOrDefault(constraintsByJobId, constraintSpec.getJobSpecId(), new LinkedList<>());
- jobConstraints.add(constraintSpec);
- constraintsByJobId.put(constraintSpec.getJobSpecId(), jobConstraints);
- }
-
- for (DependencySpec dependencySpec : dependencySpecs) {
- List jobDependencies = Util.getOrDefault(dependenciesByJobId, dependencySpec.getJobId(), new LinkedList<>());
- jobDependencies.add(dependencySpec);
- dependenciesByJobId.put(dependencySpec.getJobId(), jobDependencies);
- }
- }
-
- @Override
- public synchronized void insertJobs(@NonNull List fullSpecs) {
- jobDatabase.insertJobs(fullSpecs);
-
- for (FullSpec fullSpec : fullSpecs) {
- jobs.add(fullSpec.getJobSpec());
- constraintsByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getConstraintSpecs());
- dependenciesByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getDependencySpecs());
- }
- }
-
- @Override
- public synchronized @Nullable JobSpec getJobSpec(@NonNull String id) {
- for (JobSpec jobSpec : jobs) {
- if (jobSpec.getId().equals(id)) {
- return jobSpec;
- }
- }
- return null;
- }
-
- @Override
- public synchronized @NonNull List getAllJobSpecs() {
- return new ArrayList<>(jobs);
- }
-
- @Override
- public synchronized @NonNull List getPendingJobsWithNoDependenciesInCreatedOrder(long currentTime) {
- return Stream.of(jobs)
- .filter(j -> JobManagerFactories.hasFactoryForKey(j.getFactoryKey()))
- .filterNot(JobSpec::isRunning)
- .filter(this::firstInQueue)
- .filter(j -> !dependenciesByJobId.containsKey(j.getId()) || dependenciesByJobId.get(j.getId()).isEmpty())
- .filter(j -> j.getNextRunAttemptTime() <= currentTime)
- .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime()))
- .toList();
- }
-
- private boolean firstInQueue(@NonNull JobSpec job) {
- if (job.getQueueKey() == null) {
- return true;
- }
-
- return Stream.of(jobs)
- .filter(j -> Util.equals(j.getQueueKey(), job.getQueueKey()))
- .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime()))
- .toList()
- .get(0)
- .equals(job);
- }
-
- @Override
- public synchronized int getJobInstanceCount(@NonNull String factoryKey) {
- return (int) Stream.of(jobs)
- .filter(j -> j.getFactoryKey().equals(factoryKey))
- .count();
- }
-
- @Override
- public synchronized void updateJobRunningState(@NonNull String id, boolean isRunning) {
- jobDatabase.updateJobRunningState(id, isRunning);
-
- ListIterator iter = jobs.listIterator();
-
- while (iter.hasNext()) {
- JobSpec existing = iter.next();
- if (existing.getId().equals(id)) {
- JobSpec updated = new JobSpec(existing.getId(),
- existing.getFactoryKey(),
- existing.getQueueKey(),
- existing.getCreateTime(),
- existing.getNextRunAttemptTime(),
- existing.getRunAttempt(),
- existing.getMaxAttempts(),
- existing.getMaxBackoff(),
- existing.getLifespan(),
- existing.getMaxInstances(),
- existing.getSerializedData(),
- isRunning);
- iter.set(updated);
- }
- }
- }
-
- @Override
- public synchronized void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime) {
- jobDatabase.updateJobAfterRetry(id, isRunning, runAttempt, nextRunAttemptTime);
-
- ListIterator iter = jobs.listIterator();
-
- while (iter.hasNext()) {
- JobSpec existing = iter.next();
- if (existing.getId().equals(id)) {
- JobSpec updated = new JobSpec(existing.getId(),
- existing.getFactoryKey(),
- existing.getQueueKey(),
- existing.getCreateTime(),
- nextRunAttemptTime,
- runAttempt,
- existing.getMaxAttempts(),
- existing.getMaxBackoff(),
- existing.getLifespan(),
- existing.getMaxInstances(),
- existing.getSerializedData(),
- isRunning);
- iter.set(updated);
- }
- }
- }
-
- @Override
- public synchronized void updateAllJobsToBePending() {
- jobDatabase.updateAllJobsToBePending();
-
- ListIterator iter = jobs.listIterator();
-
- while (iter.hasNext()) {
- JobSpec existing = iter.next();
- JobSpec updated = new JobSpec(existing.getId(),
- existing.getFactoryKey(),
- existing.getQueueKey(),
- existing.getCreateTime(),
- existing.getNextRunAttemptTime(),
- existing.getRunAttempt(),
- existing.getMaxAttempts(),
- existing.getMaxBackoff(),
- existing.getLifespan(),
- existing.getMaxInstances(),
- existing.getSerializedData(),
- false);
- iter.set(updated);
- }
- }
-
- @Override
- public synchronized void deleteJob(@NonNull String jobId) {
- deleteJobs(Collections.singletonList(jobId));
- }
-
- @Override
- public synchronized void deleteJobs(@NonNull List jobIds) {
- jobDatabase.deleteJobs(jobIds);
-
- Set deleteIds = new HashSet<>(jobIds);
-
- Iterator jobIter = jobs.iterator();
- while (jobIter.hasNext()) {
- if (deleteIds.contains(jobIter.next().getId())) {
- jobIter.remove();
- }
- }
-
- for (String jobId : jobIds) {
- constraintsByJobId.remove(jobId);
- dependenciesByJobId.remove(jobId);
-
- for (Map.Entry> entry : dependenciesByJobId.entrySet()) {
- Iterator depedencyIter = entry.getValue().iterator();
-
- while (depedencyIter.hasNext()) {
- if (depedencyIter.next().getDependsOnJobId().equals(jobId)) {
- depedencyIter.remove();
- }
- }
- }
- }
- }
-
- @Override
- public synchronized @NonNull List getConstraintSpecs(@NonNull String jobId) {
- return Util.getOrDefault(constraintsByJobId, jobId, new LinkedList<>());
- }
-
- @Override
- public synchronized @NonNull List getAllConstraintSpecs() {
- return Stream.of(constraintsByJobId)
- .map(Map.Entry::getValue)
- .flatMap(Stream::of)
- .toList();
- }
-
- @Override
- public synchronized @NonNull List getDependencySpecsThatDependOnJob(@NonNull String jobSpecId) {
- return Stream.of(dependenciesByJobId.entrySet())
- .map(Map.Entry::getValue)
- .flatMap(Stream::of)
- .filter(j -> j.getDependsOnJobId().equals(jobSpecId))
- .toList();
- }
-
- @Override
- public @NonNull List getAllDependencySpecs() {
- return Stream.of(dependenciesByJobId)
- .map(Map.Entry::getValue)
- .flatMap(Stream::of)
- .toList();
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
index 910a9c09be..d892c0f439 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
@@ -26,7 +26,7 @@ public final class JobManagerFactories {
private static Collection factoryKeys = new ArrayList<>();
- public static Map getJobFactories(@NonNull Application application) {
+ public static Map getJobFactories() {
HashMap factoryHashMap = new HashMap() {{
put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
put(RetrieveProfileAvatarJob.Companion.getKEY(), new RetrieveProfileAvatarJob.Factory());
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java
index 0b1b3f8423..9cf88f4094 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.service;
import android.content.Context;
import android.content.Intent;
+import org.session.libsession.messaging.jobs.JobQueue;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.LocalBackupJob;
import org.session.libsession.utilities.TextSecurePreferences;
@@ -21,7 +22,9 @@ public class LocalBackupListener extends PersistentAlarmManagerListener {
@Override
protected long onAlarm(Context context, long scheduledTime) {
if (TextSecurePreferences.isBackupEnabled(context)) {
- ApplicationContext.getInstance(context).getJobManager().add(new LocalBackupJob());
+ LocalBackupJob job = new LocalBackupJob();
+ job.context = context;
+ JobQueue.getShared().add(job);
}
long nextTime = System.currentTimeMillis() + INTERVAL;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
index ef27916ac9..01ade94214 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
@@ -31,9 +31,9 @@ public class UpdateApkRefreshListener extends PersistentAlarmManagerListener {
if (scheduledTime != 0 && BuildConfig.PLAY_STORE_DISABLED) {
Log.i(TAG, "Queueing APK update job...");
- ApplicationContext.getInstance(context)
- .getJobManager()
- .add(new UpdateApkJob());
+ UpdateApkJob job = new UpdateApkJob();
+ job.context = context;
+ JobQueue.getShared().add(job);
}
long newTime = System.currentTimeMillis() + INTERVAL;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
index 2615eff588..3b6db9a76f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
@@ -41,9 +41,9 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
}
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
- val job = RetrieveProfileAvatarJob(recipient, profilePictureURL)
- val jobManager = ApplicationContext.getInstance(context).jobManager
- jobManager.add(job)
+ val job = RetrieveProfileAvatarJob(profilePictureURL, recipient.address)
+ job.context = context
+ JobQueue.shared.add(job)
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
diff --git a/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java b/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
deleted file mode 100644
index a6624189d1..0000000000
--- a/app/src/test/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
+++ /dev/null
@@ -1,350 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Application;
-
-import androidx.annotation.NonNull;
-
-import com.annimon.stream.Stream;
-
-import org.junit.Test;
-import org.session.libsession.messaging.utilities.Data;
-import org.thoughtcrime.securesms.database.JobDatabase;
-import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
-import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
-import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-public class FastJobStorageTest {
-
- private static final JsonDataSerializer serializer = new JsonDataSerializer();
- private static final String EMPTY_DATA = serializer.serialize(Data.EMPTY);
-
- @Test
- public void init_allStoredDataAvailable() {
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
-
- subject.init();
-
- DataSet1.assertJobsMatch(subject.getAllJobSpecs());
- DataSet1.assertConstraintsMatch(subject.getAllConstraintSpecs());
- DataSet1.assertDependenciesMatch(subject.getAllDependencySpecs());
- }
-
- @Test
- public void insertJobs_writesToDatabase() {
- JobDatabase database = noopDatabase();
- FastJobStorage subject = new FastJobStorage(database);
-
- subject.insertJobs(DataSet1.FULL_SPECS);
-
- verify(database).insertJobs(DataSet1.FULL_SPECS);
- }
-
- @Test
- public void insertJobs_dataCanBeFound() {
- FastJobStorage subject = new FastJobStorage(noopDatabase());
-
- subject.insertJobs(DataSet1.FULL_SPECS);
-
- DataSet1.assertJobsMatch(subject.getAllJobSpecs());
- DataSet1.assertConstraintsMatch(subject.getAllConstraintSpecs());
- DataSet1.assertDependenciesMatch(subject.getAllDependencySpecs());
- }
-
- @Test
- public void insertJobs_individualJobCanBeFound() {
- FastJobStorage subject = new FastJobStorage(noopDatabase());
-
- subject.insertJobs(DataSet1.FULL_SPECS);
-
- assertEquals(DataSet1.JOB_1, subject.getJobSpec(DataSet1.JOB_1.getId()));
- assertEquals(DataSet1.JOB_2, subject.getJobSpec(DataSet1.JOB_2.getId()));
- }
-
- @Test
- public void updateAllJobsToBePending_allArePending() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 1, 1, 1, 1, 1, 1, 1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", AvatarDownloadJob.KEY, null, 1, 1, 1, 1, 1, 1, 1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
-
- subject.init();
- subject.updateAllJobsToBePending();
-
- assertFalse(subject.getJobSpec("1").isRunning());
- assertFalse(subject.getJobSpec("2").isRunning());
- }
-
- @Test
- public void updateJobRunningState_writesToDatabase() {
- JobDatabase database = noopDatabase();
- FastJobStorage subject = new FastJobStorage(database);
-
- subject.updateJobRunningState("1", true);
-
- verify(database).updateJobRunningState("1", true);
- }
-
- @Test
- public void updateJobRunningState_stateUpdated() {
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
- subject.init();
-
- subject.updateJobRunningState(DataSet1.JOB_1.getId(), true);
- assertTrue(subject.getJobSpec(DataSet1.JOB_1.getId()).isRunning());
-
- subject.updateJobRunningState(DataSet1.JOB_1.getId(), false);
- assertFalse(subject.getJobSpec(DataSet1.JOB_1.getId()).isRunning());
- }
-
- @Test
- public void updateJobAfterRetry_writesToDatabase() {
- JobDatabase database = noopDatabase();
- FastJobStorage subject = new FastJobStorage(database);
-
- subject.updateJobAfterRetry("1", true, 1, 10);
-
- verify(database).updateJobAfterRetry("1", true, 1, 10);
- }
-
- @Test
- public void updateJobAfterRetry_stateUpdated() {
- FullSpec fullSpec = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 0, 0, 0, 3, 30000, -1, -1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
-
- subject.init();
- subject.updateJobAfterRetry("1", false, 1, 10);
-
- JobSpec job = subject.getJobSpec("1");
-
- assertNotNull(job);
- assertFalse(job.isRunning());
- assertEquals(1, job.getRunAttempt());
- assertEquals(10, job.getNextRunAttemptTime());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenEarlierItemInQueueInRunning() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", AvatarDownloadJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
- subject.init();
-
- assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(1).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenAllJobsAreRunning() {
- FullSpec fullSpec = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
- subject.init();
-
- assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenNextRunTimeIsAfterCurrentTime() {
- FullSpec fullSpec = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, "q", 0, 10, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
- subject.init();
-
- assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(0).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenDependentOnAnotherJob() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.singletonList(new DependencySpec("2", "1")));
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
- subject.init();
-
- assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(0).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_singleEligibleJob() {
- FullSpec fullSpec = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
- subject.init();
-
- assertEquals(1, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_multipleEligibleJobs() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
- subject.init();
-
- assertEquals(2, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_singleEligibleJobInMixedList() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", AvatarDownloadJob.KEY, null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
- subject.init();
-
- List jobs = subject.getPendingJobsWithNoDependenciesInCreatedOrder(10);
-
- assertEquals(1, jobs.size());
- assertEquals("2", jobs.get(0).getId());
- }
-
- @Test
- public void getPendingJobsWithNoDependenciesInCreatedOrder_firstItemInQueue() {
- FullSpec fullSpec1 = new FullSpec(new JobSpec("1", RetrieveProfileAvatarJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
- FullSpec fullSpec2 = new FullSpec(new JobSpec("2", RetrieveProfileAvatarJob.KEY, "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
- Collections.emptyList(),
- Collections.emptyList());
-
- JobManagerFactories.getJobFactories(mock(Application.class));
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
- subject.init();
-
- List jobs = subject.getPendingJobsWithNoDependenciesInCreatedOrder(10);
-
- assertEquals(1, jobs.size());
- assertEquals("1", jobs.get(0).getId());
- }
-
- @Test
- public void deleteJobs_writesToDatabase() {
- JobDatabase database = noopDatabase();
- FastJobStorage subject = new FastJobStorage(database);
- List ids = Arrays.asList("1", "2");
-
- subject.deleteJobs(ids);
-
- verify(database).deleteJobs(ids);
- }
-
- @Test
- public void deleteJobs_deletesAllRelevantPieces() {
- FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
-
- subject.init();
- subject.deleteJobs(Collections.singletonList("id1"));
-
- List jobs = subject.getAllJobSpecs();
- List constraints = subject.getAllConstraintSpecs();
- List dependencies = subject.getAllDependencySpecs();
-
- assertEquals(1, jobs.size());
- assertEquals(DataSet1.JOB_2, jobs.get(0));
- assertEquals(1, constraints.size());
- assertEquals(DataSet1.CONSTRAINT_2, constraints.get(0));
- assertEquals(0, dependencies.size());
- }
-
-
- private JobDatabase noopDatabase() {
- JobDatabase database = mock(JobDatabase.class);
-
- when(database.getAllJobSpecs()).thenReturn(Collections.emptyList());
- when(database.getAllConstraintSpecs()).thenReturn(Collections.emptyList());
- when(database.getAllDependencySpecs()).thenReturn(Collections.emptyList());
-
- return database;
- }
-
- private JobDatabase fixedDataDatabase(List fullSpecs) {
- JobDatabase database = mock(JobDatabase.class);
-
- when(database.getAllJobSpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getJobSpec).toList());
- when(database.getAllConstraintSpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getConstraintSpecs).flatMap(Stream::of).toList());
- when(database.getAllDependencySpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getDependencySpecs).flatMap(Stream::of).toList());
-
- return database;
- }
-
- private static final class DataSet1 {
- static final JobSpec JOB_1 = new JobSpec("id1", "f1", "q1", 1, 2, 3, 4, 5, 6, 7, EMPTY_DATA, false);
- static final JobSpec JOB_2 = new JobSpec("id2", "f2", "q2", 1, 2, 3, 4, 5, 6, 7, EMPTY_DATA, false);
- static final ConstraintSpec CONSTRAINT_1 = new ConstraintSpec("id1", "f1");
- static final ConstraintSpec CONSTRAINT_2 = new ConstraintSpec("id2", "f2");
- static final DependencySpec DEPENDENCY_2 = new DependencySpec("id2", "id1");
- static final FullSpec FULL_SPEC_1 = new FullSpec(JOB_1, Collections.singletonList(CONSTRAINT_1), Collections.emptyList());
- static final FullSpec FULL_SPEC_2 = new FullSpec(JOB_2, Collections.singletonList(CONSTRAINT_2), Collections.singletonList(DEPENDENCY_2));
- static final List FULL_SPECS = Arrays.asList(FULL_SPEC_1, FULL_SPEC_2);
-
- static void assertJobsMatch(@NonNull List jobs) {
- assertEquals(jobs.size(), 2);
- assertTrue(jobs.contains(DataSet1.JOB_1));
- assertTrue(jobs.contains(DataSet1.JOB_1));
- }
-
- static void assertConstraintsMatch(@NonNull List constraints) {
- assertEquals(constraints.size(), 2);
- assertTrue(constraints.contains(DataSet1.CONSTRAINT_1));
- assertTrue(constraints.contains(DataSet1.CONSTRAINT_2));
- }
-
- static void assertDependenciesMatch(@NonNull List dependencies) {
- assertEquals(dependencies.size(), 1);
- assertTrue(dependencies.contains(DataSet1.DEPENDENCY_2));
- }
- }
-}
From f0715f16e0e49df0161302c79a33fc46d5b546ca Mon Sep 17 00:00:00 2001
From: andrew
Date: Mon, 8 May 2023 14:07:36 +0930
Subject: [PATCH 27/83] Fix scroll to bottom button always visible if last item
is taller than RecyclerView
---
.../securesms/conversation/v2/ConversationActivityV2.kt | 5 +----
.../java/org/session/libsession/utilities/ViewUtils.kt | 9 ++++++++-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index cabb583085..107627b2c1 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -212,10 +212,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
var searchViewItem: MenuItem? = null
private val isScrolledToBottom: Boolean
- get() {
- val position = layoutManager?.findFirstCompletelyVisibleItemPosition() ?: 0
- return position == 0
- }
+ get() = binding?.conversationRecyclerView?.isScrolledToBottom ?: true
private val layoutManager: LinearLayoutManager?
get() { return binding?.conversationRecyclerView?.layoutManager as LinearLayoutManager? }
diff --git a/libsession/src/main/java/org/session/libsession/utilities/ViewUtils.kt b/libsession/src/main/java/org/session/libsession/utilities/ViewUtils.kt
index 5781ea3e2c..f67abe8ec4 100644
--- a/libsession/src/main/java/org/session/libsession/utilities/ViewUtils.kt
+++ b/libsession/src/main/java/org/session/libsession/utilities/ViewUtils.kt
@@ -4,6 +4,7 @@ import android.content.Context
import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
+import androidx.recyclerview.widget.RecyclerView
@ColorInt
fun Context.getColorFromAttr(
@@ -13,4 +14,10 @@ fun Context.getColorFromAttr(
): Int {
theme.resolveAttribute(attrColor, typedValue, resolveRefs)
return typedValue.data
-}
\ No newline at end of file
+}
+
+val RecyclerView.isScrolledToBottom: Boolean
+ get() {
+ val contentHeight = height - (paddingTop + paddingBottom)
+ return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight
+ }
From b6667b83ce116e3f494a34af991e485c4182c126 Mon Sep 17 00:00:00 2001
From: andrew
Date: Mon, 8 May 2023 14:43:08 +0930
Subject: [PATCH 28/83] Fix scroll to bottom button position when input not
visible
---
app/src/main/res/layout/activity_conversation_v2.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/src/main/res/layout/activity_conversation_v2.xml b/app/src/main/res/layout/activity_conversation_v2.xml
index d2696a45ec..099f9b9909 100644
--- a/app/src/main/res/layout/activity_conversation_v2.xml
+++ b/app/src/main/res/layout/activity_conversation_v2.xml
@@ -137,6 +137,7 @@
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_above="@+id/messageRequestBar"
+ android:layout_alignWithParentIfMissing="true"
android:layout_marginEnd="12dp"
android:layout_marginBottom="32dp">
From b494088c3db0e09a3dc3b8df35e8d969f2b31f83 Mon Sep 17 00:00:00 2001
From: Ryan Zhao
Date: Mon, 8 May 2023 17:12:20 +1000
Subject: [PATCH 29/83] WIP: further refactor on old jobs
---
.../securesms/ApplicationContext.java | 14 ---
.../securesms/database/Storage.kt | 3 +-
.../jobmanager/ConstraintObserver.java | 12 --
.../securesms/jobmanager/JobInstantiator.java | 26 ----
.../securesms/jobmanager/JobManager.java | 114 ------------------
.../impl/CellServiceConstraint.java | 48 --------
.../impl/CellServiceConstraintObserver.java | 38 ------
.../impl/NetworkConstraintObserver.java | 36 ------
.../impl/NetworkOrCellServiceConstraint.java | 48 --------
.../impl/SqlCipherMigrationConstraint.java | 48 --------
.../SqlCipherMigrationConstraintObserver.java | 32 -----
.../securesms/jobs/JobManagerFactories.java | 57 ---------
.../sskenvironment/ProfileManager.kt | 3 +-
.../libsession/database/StorageProtocol.kt | 1 +
.../jobs/RetrieveProfileAvatarJob.kt | 14 +--
15 files changed, 9 insertions(+), 485 deletions(-)
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
rename {app/src/main/java/org/thoughtcrime/securesms => libsession/src/main/java/org/session/libsession/messaging}/jobs/RetrieveProfileAvatarJob.kt (90%)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
index 0d5e57352e..df1bed7b3b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
@@ -65,9 +65,7 @@ import org.thoughtcrime.securesms.dependencies.DatabaseModule;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.home.HomeActivity;
-import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-import org.thoughtcrime.securesms.jobs.JobManagerFactories;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
@@ -130,7 +128,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private ExpiringMessageManager expiringMessageManager;
private TypingStatusRepository typingStatusRepository;
private TypingStatusSender typingStatusSender;
- private JobManager jobManager;
private ReadReceiptManager readReceiptManager;
private ProfileManager profileManager;
public MessageNotifier messageNotifier = null;
@@ -227,7 +224,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
initializeProfileManager();
initializePeriodicTasks();
SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager());
- initializeJobManager();
initializeWebRtc();
initializeBlobProvider();
resubmitProfilePictureIfNeeded();
@@ -284,10 +280,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
LocaleParser.Companion.configure(new LocaleParseHelper());
}
- public JobManager getJobManager() {
- return jobManager;
- }
-
public ExpiringMessageManager getExpiringMessageManager() {
return expiringMessageManager;
}
@@ -350,12 +342,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler));
}
- private void initializeJobManager() {
- this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
- .setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
- .build());
- }
-
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 891df6be87..3e21f63c09 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -42,13 +42,12 @@ import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.guava.Optional
-import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.groups.OpenGroupManager
-import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
+import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.security.MessageDigest
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java
deleted file mode 100644
index fd7f4fd43c..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-
-public interface ConstraintObserver {
-
- void register(@NonNull Notifier notifier);
-
- interface Notifier {
- void onConstraintMet(@NonNull String reason);
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
deleted file mode 100644
index 81e378288d..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsession.messaging.jobs.Job;
-import org.session.libsession.messaging.utilities.Data;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class JobInstantiator {
-
- private final Map jobFactories;
-
- JobInstantiator(@NonNull Map jobFactories) {
- this.jobFactories = new HashMap<>(jobFactories);
- }
-
- public @NonNull Job instantiate(@NonNull String jobFactoryKey, @NonNull Data data) {
- if (jobFactories.containsKey(jobFactoryKey)) {
- return jobFactories.get(jobFactoryKey).create(data);
- } else {
- throw new IllegalStateException("Tried to instantiate a job with key '" + jobFactoryKey + "', but no matching factory was found.");
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
deleted file mode 100644
index 7bbd7679f7..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager;
-
-import android.app.Application;
-import android.content.Intent;
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsignal.utilities.Log;
-import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.ExecutorService;
-
-/**
- * Allows the scheduling of durable jobs that will be run as early as possible.
- */
-public class JobManager implements ConstraintObserver.Notifier {
-
- private static final String TAG = JobManager.class.getSimpleName();
-
- private final ExecutorService executor;
-
- private final Set emptyQueueListeners = new CopyOnWriteArraySet<>();
-
- public JobManager(@NonNull Application application, @NonNull Configuration configuration) {
- this.executor = configuration.getExecutorFactory().newSingleThreadExecutor("JobManager");
-
- executor.execute(() -> {
- for (ConstraintObserver constraintObserver : configuration.getConstraintObservers()) {
- constraintObserver.register(this);
- }
-
- if (Build.VERSION.SDK_INT < 26) {
- application.startService(new Intent(application, KeepAliveService.class));
- }
-
- wakeUp();
- });
- }
-
- /**
- * Adds a listener to that will be notified when the job queue has been drained.
- */
- void addOnEmptyQueueListener(@NonNull EmptyQueueListener listener) {
- executor.execute(() -> {
- emptyQueueListeners.add(listener);
- });
- }
-
- /**
- * Removes a listener that was added via {@link #addOnEmptyQueueListener(EmptyQueueListener)}.
- */
- void removeOnEmptyQueueListener(@NonNull EmptyQueueListener listener) {
- executor.execute(() -> {
- emptyQueueListeners.remove(listener);
- });
- }
-
- @Override
- public void onConstraintMet(@NonNull String reason) {
- Log.i(TAG, "onConstraintMet(" + reason + ")");
- wakeUp();
- }
-
- /**
- * Pokes the system to take another pass at the job queue.
- */
- void wakeUp() {}
-
- public interface EmptyQueueListener {
- void onQueueEmpty();
- }
-
- public static class Configuration {
-
- private final ExecutorFactory executorFactory;
- private final List constraintObservers;
-
- private Configuration(@NonNull ExecutorFactory executorFactory,
- @NonNull List constraintObservers)
- {
- this.executorFactory = executorFactory;
- this.constraintObservers = constraintObservers;
- }
-
- @NonNull ExecutorFactory getExecutorFactory() {
- return executorFactory;
- }
-
- @NonNull List getConstraintObservers() {
- return constraintObservers;
- }
-
- public static class Builder {
-
- private ExecutorFactory executorFactory = new DefaultExecutorFactory();
- private List constraintObservers = new ArrayList<>();
-
- public @NonNull Builder setConstraintObservers(@NonNull List constraintObservers) {
- this.constraintObservers = constraintObservers;
- return this;
- }
-
- public @NonNull Configuration build() {
- return new Configuration(executorFactory,
- new ArrayList<>(constraintObservers));
- }
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java
deleted file mode 100644
index 6d6fc0499f..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import android.app.Application;
-import android.app.job.JobInfo;
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Constraint;
-import org.thoughtcrime.securesms.sms.TelephonyServiceState;
-
-public class CellServiceConstraint implements Constraint {
-
- public static final String KEY = "CellServiceConstraint";
-
- private final Application application;
-
- public CellServiceConstraint(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public boolean isMet() {
- TelephonyServiceState telephonyServiceState = new TelephonyServiceState();
- return telephonyServiceState.isConnected(application);
- }
-
- @Override
- public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
- }
-
- public static final class Factory implements Constraint.Factory {
-
- private final Application application;
-
- public Factory(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public CellServiceConstraint create() {
- return new CellServiceConstraint(application);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java
deleted file mode 100644
index fd0971dc57..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import android.app.Application;
-import android.content.Context;
-import androidx.annotation.NonNull;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
-
-import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
-
-public class CellServiceConstraintObserver implements ConstraintObserver {
-
- private static final String REASON = CellServiceConstraintObserver.class.getSimpleName();
-
- private Notifier notifier;
-
- public CellServiceConstraintObserver(@NonNull Application application) {
- TelephonyManager telephonyManager = (TelephonyManager) application.getSystemService(Context.TELEPHONY_SERVICE);
- ServiceStateListener serviceStateListener = new ServiceStateListener();
-
- telephonyManager.listen(serviceStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
- }
-
- @Override
- public void register(@NonNull Notifier notifier) {
- this.notifier = notifier;
- }
-
- private class ServiceStateListener extends PhoneStateListener {
- @Override
- public void onServiceStateChanged(ServiceState serviceState) {
- if (serviceState.getState() == ServiceState.STATE_IN_SERVICE && notifier != null) {
- notifier.onConstraintMet(REASON);
- }
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java
deleted file mode 100644
index ef4a61c7c5..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import android.app.Application;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
-
-public class NetworkConstraintObserver implements ConstraintObserver {
-
- private static final String REASON = NetworkConstraintObserver.class.getSimpleName();
-
- private final Application application;
-
- public NetworkConstraintObserver(Application application) {
- this.application = application;
- }
-
- @Override
- public void register(@NonNull Notifier notifier) {
- application.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- NetworkConstraint constraint = new NetworkConstraint.Factory(application).create();
-
- if (constraint.isMet()) {
- notifier.onConstraintMet(REASON);
- }
- }
- }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java
deleted file mode 100644
index c17931f977..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import android.app.Application;
-import android.app.job.JobInfo;
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Constraint;
-
-public class NetworkOrCellServiceConstraint implements Constraint {
-
- public static final String KEY = "NetworkOrCellServiceConstraint";
-
- private final NetworkConstraint networkConstraint;
- private final CellServiceConstraint serviceConstraint;
-
- public NetworkOrCellServiceConstraint(@NonNull Application application) {
- networkConstraint = new NetworkConstraint.Factory(application).create();
- serviceConstraint = new CellServiceConstraint.Factory(application).create();
- }
-
- @Override
- public @NonNull String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public boolean isMet() {
- return networkConstraint.isMet() || serviceConstraint.isMet();
- }
-
- @Override
- public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
- }
-
- public static class Factory implements Constraint.Factory {
-
- private final Application application;
-
- public Factory(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public NetworkOrCellServiceConstraint create() {
- return new NetworkOrCellServiceConstraint(application);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java
deleted file mode 100644
index 32fa84b6f5..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import android.app.Application;
-import android.app.job.JobInfo;
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Constraint;
-import org.session.libsession.utilities.TextSecurePreferences;
-
-public class SqlCipherMigrationConstraint implements Constraint {
-
- public static final String KEY = "SqlCipherMigrationConstraint";
-
- private final Application application;
-
- private SqlCipherMigrationConstraint(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public boolean isMet() {
- return !TextSecurePreferences.getNeedsSqlCipherMigration(application);
- }
-
- @NonNull
- @Override
- public String getFactoryKey() {
- return KEY;
- }
-
- @Override
- public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
- }
-
- public static final class Factory implements Constraint.Factory {
-
- private final Application application;
-
- public Factory(@NonNull Application application) {
- this.application = application;
- }
-
- @Override
- public SqlCipherMigrationConstraint create() {
- return new SqlCipherMigrationConstraint(application);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java
deleted file mode 100644
index 0c9225434d..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.impl;
-
-import androidx.annotation.NonNull;
-
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
-
-public class SqlCipherMigrationConstraintObserver implements ConstraintObserver {
-
- private static final String REASON = SqlCipherMigrationConstraintObserver.class.getSimpleName();
-
- private Notifier notifier;
-
- public SqlCipherMigrationConstraintObserver() {
- EventBus.getDefault().register(this);
- }
-
- @Override
- public void register(@NonNull Notifier notifier) {
- this.notifier = notifier;
- }
-
- @Subscribe(threadMode = ThreadMode.MAIN)
- public void onEvent(SqlCipherNeedsMigrationEvent event) {
- if (notifier != null) notifier.onConstraintMet(REASON);
- }
-
- public static class SqlCipherNeedsMigrationEvent {
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
deleted file mode 100644
index d892c0f439..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.app.Application;
-
-import androidx.annotation.NonNull;
-
-import org.session.libsession.messaging.jobs.Job;
-import org.thoughtcrime.securesms.jobmanager.Constraint;
-import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
-import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
-import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
-import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
-import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
-import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public final class JobManagerFactories {
-
- private static Collection factoryKeys = new ArrayList<>();
-
- public static Map getJobFactories() {
- HashMap factoryHashMap = new HashMap() {{
- put(LocalBackupJob.Companion.getKEY(), new LocalBackupJob.Factory());
- put(RetrieveProfileAvatarJob.Companion.getKEY(), new RetrieveProfileAvatarJob.Factory());
- put(UpdateApkJob.Companion.getKEY(), new UpdateApkJob.Factory());
- }};
- factoryKeys.addAll(factoryHashMap.keySet());
- return factoryHashMap;
- }
-
- public static Map getConstraintFactories(@NonNull Application application) {
- return new HashMap() {{
- put(CellServiceConstraint.KEY, new CellServiceConstraint.Factory(application));
- put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application));
- put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application));
- put(SqlCipherMigrationConstraint.KEY, new SqlCipherMigrationConstraint.Factory(application));
- }};
- }
-
- public static List getConstraintObservers(@NonNull Application application) {
- return Arrays.asList(new CellServiceConstraintObserver(application),
- new NetworkConstraintObserver(application),
- new SqlCipherMigrationConstraintObserver());
- }
-
- public static boolean hasFactoryForKey(String factoryKey) {
- return factoryKeys.contains(factoryKey);
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
index 3b6db9a76f..08ca6090bf 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
@@ -5,9 +5,8 @@ import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.recipients.Recipient
-import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
-import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
+import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
index d75e209d11..8ae9442748 100644
--- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
+++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
@@ -38,6 +38,7 @@ interface StorageProtocol {
fun getUserX25519KeyPair(): ECKeyPair
fun getUserProfile(): Profile
fun setUserProfilePictureURL(newProfilePicture: String)
+ fun
// Signal
fun getOrGenerateRegistrationID(): Int
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
similarity index 90%
rename from app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt
rename to libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
index a5b0fce2df..f00ba49a5f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
@@ -1,10 +1,9 @@
-package org.thoughtcrime.securesms.jobs
+package org.session.libsession.messaging.jobs
import android.content.Context
import android.text.TextUtils
import org.session.libsession.avatars.AvatarHelper
-import org.session.libsession.messaging.jobs.Job
-import org.session.libsession.messaging.jobs.JobDelegate
+import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.utilities.DownloadUtilities.downloadFile
import org.session.libsession.utilities.TextSecurePreferences.Companion.setProfileAvatarId
@@ -27,8 +26,6 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
override var failureCount: Int = 0
override val maxFailureCount: Int = 0
- lateinit var context: Context
-
companion object {
val TAG = RetrieveProfileAvatarJob::class.simpleName
val KEY: String = "RetrieveProfileAvatarJob"
@@ -39,8 +36,9 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
}
override fun execute(dispatcherName: String) {
+ val context = MessagingModuleConfiguration.shared.context
+ val storage = MessagingModuleConfiguration.shared.storage
val recipient = Recipient.from(context, recipientAddress, true)
- val database = get(context).recipientDatabase()
val profileKey = recipient.resolve().profileKey
if (profileKey == null || (profileKey.size != 32 && profileKey.size != 16)) {
@@ -56,7 +54,7 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
if (TextUtils.isEmpty(profileAvatar)) {
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
AvatarHelper.delete(context, recipient.address)
- database.setProfileAvatar(recipient, profileAvatar)
+ storage.setProfileAvatar(recipient, profileAvatar)
return
}
@@ -75,7 +73,7 @@ class RetrieveProfileAvatarJob(val profileAvatar: String, val recipientAddress:
if (recipient.isLocalNumber) {
setProfileAvatarId(context, SecureRandom().nextInt())
}
- database.setProfileAvatar(recipient, profileAvatar)
+ storage.setProfileAvatar(recipient, profileAvatar)
}
override fun serialize(): Data {
From 8d38d1c0fbbd7f3685ec7d8a53b138a5634ab482 Mon Sep 17 00:00:00 2001
From: andrew
Date: Tue, 9 May 2023 13:25:32 +0930
Subject: [PATCH 30/83] Fix links not working when message is partially
offscreen
---
.../securesms/conversation/v2/utilities/TextUtilities.kt | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
index 800ace54c3..7a47b92756 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
@@ -38,13 +38,12 @@ object TextUtilities {
fun TextView.getIntersectedModalSpans(hitRect: Rect): List {
val textLayout = layout ?: return emptyList()
val lineRect = Rect()
- val bodyTextRect = Rect()
- getGlobalVisibleRect(bodyTextRect)
+ val offset = intArrayOf(0, 0).also { getLocationOnScreen(it) }
val textSpannable = text.toSpannable()
return (0 until textLayout.lineCount).flatMap { line ->
textLayout.getLineBounds(line, lineRect)
- lineRect.offset(bodyTextRect.left + totalPaddingLeft, bodyTextRect.top + totalPaddingTop)
- if ((Rect(lineRect)).contains(hitRect)) {
+ lineRect.offset(offset[0] + totalPaddingLeft, offset[1] + totalPaddingTop)
+ if (lineRect.contains(hitRect)) {
// calculate the url span intersected with (if any)
val off = textLayout.getOffsetForHorizontal(line, hitRect.left.toFloat()) // left and right will be the same
textSpannable.getSpans(off, off).toList()
From fa71ea1850e0d3444eac4176df2ac82002b53f96 Mon Sep 17 00:00:00 2001
From: ryanzhao
Date: Tue, 9 May 2023 14:14:49 +1000
Subject: [PATCH 31/83] make RetrieveProfileAvatarJob work
---
.../main/java/org/thoughtcrime/securesms/database/Storage.kt | 5 +++++
.../thoughtcrime/securesms/sskenvironment/ProfileManager.kt | 1 -
.../java/org/session/libsession/database/StorageProtocol.kt | 2 +-
.../java/org/session/libsession/messaging/jobs/JobQueue.kt | 2 ++
.../libsession/messaging/jobs/RetrieveProfileAvatarJob.kt | 2 --
5 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 3e21f63c09..54d36af896 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -77,6 +77,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
JobQueue.shared.add(RetrieveProfileAvatarJob(newValue, ourRecipient.address))
}
+ override fun setProfileAvatar(recipient: Recipient, profileAvatar: String) {
+ val database = DatabaseComponent.get(context).recipientDatabase()
+ database.setProfileAvatar(recipient, profileAvatar)
+ }
+
override fun getOrGenerateRegistrationID(): Int {
var registrationID = TextSecurePreferences.getLocalRegistrationId(context)
if (registrationID == 0) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
index 08ca6090bf..f9f5524efa 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt
@@ -41,7 +41,6 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
val job = RetrieveProfileAvatarJob(profilePictureURL, recipient.address)
- job.context = context
JobQueue.shared.add(job)
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
index 8ae9442748..0727d1ab56 100644
--- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
+++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
@@ -38,7 +38,7 @@ interface StorageProtocol {
fun getUserX25519KeyPair(): ECKeyPair
fun getUserProfile(): Profile
fun setUserProfilePictureURL(newProfilePicture: String)
- fun
+ fun setProfileAvatar(recipient: Recipient, profileAvatar: String)
// Signal
fun getOrGenerateRegistrationID(): Int
diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/JobQueue.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/JobQueue.kt
index b78590c729..03b9546c4c 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/jobs/JobQueue.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/JobQueue.kt
@@ -125,6 +125,7 @@ class JobQueue : JobDelegate {
is NotifyPNServerJob, is AttachmentUploadJob, is MessageSendJob -> {
txQueue.send(job)
}
+ is RetrieveProfileAvatarJob,
is AttachmentDownloadJob -> {
mediaQueue.send(job)
}
@@ -224,6 +225,7 @@ class JobQueue : JobDelegate {
GroupAvatarDownloadJob.KEY,
BackgroundGroupAddJob.KEY,
OpenGroupDeleteJob.KEY,
+ RetrieveProfileAvatarJob.KEY,
)
allJobTypes.forEach { type ->
resumePendingJobs(type)
diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
index f00ba49a5f..8ce397a3a9 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt
@@ -1,6 +1,5 @@
package org.session.libsession.messaging.jobs
-import android.content.Context
import android.text.TextUtils
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.MessagingModuleConfiguration
@@ -13,7 +12,6 @@ import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.streams.ProfileCipherInputStream
import org.session.libsignal.utilities.Log
-import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
From c8fa2d8d6e2806c5c1de493552281c9887498311 Mon Sep 17 00:00:00 2001
From: andrew
Date: Tue, 9 May 2023 14:51:28 +0930
Subject: [PATCH 32/83] Remove reply from context menu when you can't write
---
.../securesms/conversation/v2/ConversationReactionOverlay.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
index 1d81325e03..b311327a4b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java
@@ -660,7 +660,8 @@ public final class ConversationReactionOverlay extends FrameLayout {
items.add(new ActionItem(R.attr.menu_select_icon, getContext().getResources().getString(R.string.conversation_context__menu_select), () -> handleActionItemClicked(Action.SELECT),
getContext().getResources().getString(R.string.AccessibilityId_select)));
// Reply
- if (!message.isPending() && !message.isFailed()) {
+ boolean canWrite = openGroup == null || openGroup.getCanWrite();
+ if (canWrite && !message.isPending() && !message.isFailed()) {
items.add(
new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_reply), () -> handleActionItemClicked(Action.REPLY),
getContext().getResources().getString(R.string.AccessibilityId_reply_message))
From 4469d9754a11978e8d5f1b2d8f03f1ef9e9c982a Mon Sep 17 00:00:00 2001
From: andrew
Date: Tue, 9 May 2023 15:10:03 +0930
Subject: [PATCH 33/83] Fix bubble entrance coordinates
---
.../securesms/conversation/v2/ConversationActivityV2.kt | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index cabb583085..97cf699db4 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -1109,12 +1109,11 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
})
- val contentBounds = Rect()
- visibleMessageView.messageContentView.getGlobalVisibleRect(contentBounds)
+ val topLeft = intArrayOf(0, 0).also { visibleMessageView.messageContentView.getLocationInWindow(it) }
val selectedConversationModel = SelectedConversationModel(
messageContentBitmap,
- contentBounds.left.toFloat(),
- contentBounds.top.toFloat(),
+ topLeft[0].toFloat(),
+ topLeft[1].toFloat(),
visibleMessageView.messageContentView.width,
message.isOutgoing,
visibleMessageView.messageContentView
From d20c27d6d3ef11bfe07511393ee3afe5023217fd Mon Sep 17 00:00:00 2001
From: andrew
Date: Tue, 9 May 2023 22:26:36 +0930
Subject: [PATCH 34/83] Remove laid out check before drawToBitmap
---
.../securesms/conversation/v2/ConversationActivityV2.kt | 1 -
.../java/org/thoughtcrime/securesms/util/ViewUtilities.kt | 8 ++++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index cabb583085..b2ec6d1233 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -21,7 +21,6 @@ import android.widget.Toast
import androidx.activity.viewModels
import androidx.annotation.DimenRes
import androidx.appcompat.app.AlertDialog
-import androidx.core.view.drawToBitmap
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
index 7b7f3a04f3..ffe5e9094f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
@@ -5,6 +5,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.content.Context
+import android.graphics.Bitmap
import android.graphics.PointF
import android.graphics.Rect
import android.view.View
@@ -13,6 +14,7 @@ import androidx.annotation.DimenRes
import network.loki.messenger.R
import org.session.libsession.utilities.getColorFromAttr
import android.view.inputmethod.InputMethodManager
+import androidx.core.graphics.applyCanvas
fun View.contains(point: PointF): Boolean {
return hitRect.contains(point.x.toInt(), point.y.toInt())
@@ -65,3 +67,9 @@ fun View.hideKeyboard() {
val imm = this.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(this.windowToken, 0)
}
+
+fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap =
+ Bitmap.createBitmap(width, height, config).applyCanvas {
+ translate(-scrollX.toFloat(), -scrollY.toFloat())
+ draw(this)
+ }
From 89545f0406176069402f5014e33a4a87de0b76a0 Mon Sep 17 00:00:00 2001
From: ryanzhao
Date: Wed, 10 May 2023 15:36:10 +1000
Subject: [PATCH 35/83] further clean up
---
app/src/main/AndroidManifest.xml | 6 -
.../securesms/ApplicationContext.java | 7 -
.../securesms/backup/BackupEvent.kt | 14 -
.../securesms/backup/BackupPassphrase.java | 47 -
.../securesms/backup/BackupPreferences.kt | 101 -
.../securesms/backup/BackupProtos.java | 6778 -----------------
.../securesms/backup/FullBackupExporter.kt | 447 --
.../securesms/backup/FullBackupImporter.kt | 352 -
.../securesms/database/JobDatabase.java | 178 -
.../dependencies/DatabaseComponent.kt | 1 -
.../securesms/dependencies/DatabaseModule.kt | 4 -
.../securesms/jobmanager/ExecutorFactory.java | 9 -
.../impl/DefaultExecutorFactory.java | 15 -
.../persistence/ConstraintSpec.java | 43 -
.../persistence/DependencySpec.java | 43 -
.../jobmanager/persistence/FullSpec.java | 50 -
.../jobmanager/persistence/JobSpec.java | 129 -
.../jobmanager/persistence/JobStorage.java | 55 -
.../securesms/jobs/LocalBackupJob.kt | 61 -
.../securesms/jobs/UpdateApkJob.kt | 200 -
.../service/LocalBackupListener.java | 41 -
.../service/UpdateApkRefreshListener.java | 49 -
.../thoughtcrime/securesms/util/BackupUtil.kt | 313 -
23 files changed, 8943 deletions(-)
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/ExecutorFactory.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/DefaultExecutorFactory.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/ConstraintSpec.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/DependencySpec.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/FullSpec.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobSpec.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobStorage.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.kt
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index da3be785c3..2d2b2123dd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -407,12 +407,6 @@
-
-
-
-
-
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
index df1bed7b3b..5a9999a7bc 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
@@ -55,7 +55,6 @@ import org.signal.aesgcmprovider.AesGcmProvider;
import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.KeyPairUtilities;
import org.thoughtcrime.securesms.database.EmojiSearchDatabase;
-import org.thoughtcrime.securesms.database.JobDatabase;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.database.Storage;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
@@ -78,7 +77,6 @@ import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.service.KeyCachingService;
-import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
import org.thoughtcrime.securesms.sskenvironment.ProfileManager;
import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager;
import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository;
@@ -142,7 +140,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject LokiAPIDatabase lokiAPIDatabase;
@Inject Storage storage;
@Inject MessageDataProvider messageDataProvider;
- @Inject JobDatabase jobDatabase;
@Inject TextSecurePreferences textSecurePreferences;
CallMessageProcessor callMessageProcessor;
MessagingModuleConfiguration messagingModuleConfiguration;
@@ -364,10 +361,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private void initializePeriodicTasks() {
BackgroundPollWorker.schedulePeriodic(this);
-
- if (BuildConfig.PLAY_STORE_DISABLED) {
- UpdateApkRefreshListener.schedule(this);
- }
}
private void initializeWebRtc() {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt
deleted file mode 100644
index 614dc30bba..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.thoughtcrime.securesms.backup
-
-data class BackupEvent constructor(val type: Type, val count: Int, val exception: Exception?) {
-
- enum class Type {
- PROGRESS, FINISHED
- }
-
- companion object {
- @JvmStatic fun createProgress(count: Int) = BackupEvent(Type.PROGRESS, count, null)
- @JvmStatic fun createFinished() = BackupEvent(Type.FINISHED, 0, null)
- @JvmStatic fun createFinished(e: Exception?) = BackupEvent(Type.FINISHED, 0, e)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java
deleted file mode 100644
index eec2a2e588..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.thoughtcrime.securesms.backup;
-
-import android.content.Context;
-import android.os.Build;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.thoughtcrime.securesms.crypto.KeyStoreHelper;
-import org.session.libsignal.utilities.Log;
-import org.session.libsession.utilities.TextSecurePreferences;
-
-/**
- * Allows the getting and setting of the backup passphrase, which is stored encrypted on API >= 23.
- */
-public class BackupPassphrase {
-
- private static final String TAG = BackupPassphrase.class.getSimpleName();
-
- public static @Nullable String get(@NonNull Context context) {
- String passphrase = TextSecurePreferences.getBackupPassphrase(context);
- String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
-
- if (Build.VERSION.SDK_INT < 23 || (passphrase == null && encryptedPassphrase == null)) {
- return passphrase;
- }
-
- if (encryptedPassphrase == null) {
- Log.i(TAG, "Migrating to encrypted passphrase.");
- set(context, passphrase);
- encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
- }
-
- KeyStoreHelper.SealedData data = KeyStoreHelper.SealedData.fromString(encryptedPassphrase);
- return new String(KeyStoreHelper.unseal(data));
- }
-
- public static void set(@NonNull Context context, @Nullable String passphrase) {
- if (passphrase == null || Build.VERSION.SDK_INT < 23) {
- TextSecurePreferences.setBackupPassphrase(context, passphrase);
- TextSecurePreferences.setEncryptedBackupPassphrase(context, null);
- } else {
- KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes());
- TextSecurePreferences.setEncryptedBackupPassphrase(context, encryptedPassphrase.serialize());
- TextSecurePreferences.setBackupPassphrase(context, null);
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt
deleted file mode 100644
index 8ddfc23a8b..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.thoughtcrime.securesms.backup
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.os.Build
-import android.preference.PreferenceManager
-import android.preference.PreferenceManager.getDefaultSharedPreferencesName
-import org.session.libsession.utilities.TextSecurePreferences
-import org.session.libsignal.utilities.Log
-import org.thoughtcrime.securesms.backup.FullBackupImporter.PREF_PREFIX_TYPE_BOOLEAN
-import org.thoughtcrime.securesms.backup.FullBackupImporter.PREF_PREFIX_TYPE_INT
-import java.util.*
-
-object BackupPreferences {
- // region Backup related
- fun getBackupRecords(context: Context): List {
- val preferences = PreferenceManager.getDefaultSharedPreferences(context)
- val prefsFileName: String
- prefsFileName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- getDefaultSharedPreferencesName(context)
- } else {
- context.packageName + "_preferences"
- }
- val prefList: LinkedList = LinkedList()
- addBackupEntryInt(prefList, preferences, prefsFileName, TextSecurePreferences.LOCAL_REGISTRATION_ID_PREF)
- addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.LOCAL_NUMBER_PREF)
- addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_NAME_PREF)
- addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_AVATAR_URL_PREF)
- addBackupEntryInt(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_AVATAR_ID_PREF)
- addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_KEY_PREF)
- addBackupEntryBoolean(prefList, preferences, prefsFileName, TextSecurePreferences.IS_USING_FCM)
- return prefList
- }
-
- private fun addBackupEntryString(
- outPrefList: MutableList,
- prefs: SharedPreferences,
- prefFileName: String,
- prefKey: String,
- ) {
- val value = prefs.getString(prefKey, null)
- if (value == null) {
- logBackupEntry(prefKey, false)
- return
- }
- outPrefList.add(BackupProtos.SharedPreference.newBuilder()
- .setFile(prefFileName)
- .setKey(prefKey)
- .setValue(value)
- .build())
- logBackupEntry(prefKey, true)
- }
-
- private fun addBackupEntryInt(
- outPrefList: MutableList,
- prefs: SharedPreferences,
- prefFileName: String,
- prefKey: String,
- ) {
- val value = prefs.getInt(prefKey, -1)
- if (value == -1) {
- logBackupEntry(prefKey, false)
- return
- }
- outPrefList.add(BackupProtos.SharedPreference.newBuilder()
- .setFile(prefFileName)
- .setKey(PREF_PREFIX_TYPE_INT + prefKey) // The prefix denotes the type of the preference.
- .setValue(value.toString())
- .build())
- logBackupEntry(prefKey, true)
- }
-
- private fun addBackupEntryBoolean(
- outPrefList: MutableList,
- prefs: SharedPreferences,
- prefFileName: String,
- prefKey: String,
- ) {
- if (!prefs.contains(prefKey)) {
- logBackupEntry(prefKey, false)
- return
- }
- outPrefList.add(BackupProtos.SharedPreference.newBuilder()
- .setFile(prefFileName)
- .setKey(PREF_PREFIX_TYPE_BOOLEAN + prefKey) // The prefix denotes the type of the preference.
- .setValue(prefs.getBoolean(prefKey, false).toString())
- .build())
- logBackupEntry(prefKey, true)
- }
-
- private fun logBackupEntry(prefName: String, wasIncluded: Boolean) {
- val sb = StringBuilder()
- sb.append("Backup preference ")
- sb.append(if (wasIncluded) "+ " else "- ")
- sb.append('\"').append(prefName).append("\" ")
- if (!wasIncluded) {
- sb.append("(is empty and not included)")
- }
- Log.d("Loki", sb.toString())
- } // endregion
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java
deleted file mode 100644
index f3b78606f4..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java
+++ /dev/null
@@ -1,6778 +0,0 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: Backups.proto
-
-package org.thoughtcrime.securesms.backup;
-
-public final class BackupProtos {
- private BackupProtos() {}
- public static void registerAllExtensions(
- com.google.protobuf.ExtensionRegistry registry) {
- }
- public interface SqlStatementOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional string statement = 1;
- /**
- * optional string statement = 1;
- */
- boolean hasStatement();
- /**
- * optional string statement = 1;
- */
- java.lang.String getStatement();
- /**
- * optional string statement = 1;
- */
- com.google.protobuf.ByteString
- getStatementBytes();
-
- // repeated .signal.SqlStatement.SqlParameter parameters = 2;
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- java.util.List
- getParametersList();
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index);
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- int getParametersCount();
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- java.util.List extends org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>
- getParametersOrBuilderList();
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder(
- int index);
- }
- /**
- * Protobuf type {@code signal.SqlStatement}
- */
- public static final class SqlStatement extends
- com.google.protobuf.GeneratedMessage
- implements SqlStatementOrBuilder {
- // Use SqlStatement.newBuilder() to construct.
- private SqlStatement(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private SqlStatement(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final SqlStatement defaultInstance;
- public static SqlStatement getDefaultInstance() {
- return defaultInstance;
- }
-
- public SqlStatement getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private SqlStatement(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 10: {
- bitField0_ |= 0x00000001;
- statement_ = input.readBytes();
- break;
- }
- case 18: {
- if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
- parameters_ = new java.util.ArrayList();
- mutable_bitField0_ |= 0x00000002;
- }
- parameters_.add(input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.PARSER, extensionRegistry));
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
- parameters_ = java.util.Collections.unmodifiableList(parameters_);
- }
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public SqlStatement parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new SqlStatement(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- public interface SqlParameterOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional string stringParamter = 1;
- /**
- * optional string stringParamter = 1;
- */
- boolean hasStringParamter();
- /**
- * optional string stringParamter = 1;
- */
- java.lang.String getStringParamter();
- /**
- * optional string stringParamter = 1;
- */
- com.google.protobuf.ByteString
- getStringParamterBytes();
-
- // optional uint64 integerParameter = 2;
- /**
- * optional uint64 integerParameter = 2;
- */
- boolean hasIntegerParameter();
- /**
- * optional uint64 integerParameter = 2;
- */
- long getIntegerParameter();
-
- // optional double doubleParameter = 3;
- /**
- * optional double doubleParameter = 3;
- */
- boolean hasDoubleParameter();
- /**
- * optional double doubleParameter = 3;
- */
- double getDoubleParameter();
-
- // optional bytes blobParameter = 4;
- /**
- * optional bytes blobParameter = 4;
- */
- boolean hasBlobParameter();
- /**
- * optional bytes blobParameter = 4;
- */
- com.google.protobuf.ByteString getBlobParameter();
-
- // optional bool nullparameter = 5;
- /**
- * optional bool nullparameter = 5;
- */
- boolean hasNullparameter();
- /**
- * optional bool nullparameter = 5;
- */
- boolean getNullparameter();
- }
- /**
- * Protobuf type {@code signal.SqlStatement.SqlParameter}
- */
- public static final class SqlParameter extends
- com.google.protobuf.GeneratedMessage
- implements SqlParameterOrBuilder {
- // Use SqlParameter.newBuilder() to construct.
- private SqlParameter(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private SqlParameter(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final SqlParameter defaultInstance;
- public static SqlParameter getDefaultInstance() {
- return defaultInstance;
- }
-
- public SqlParameter getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private SqlParameter(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 10: {
- bitField0_ |= 0x00000001;
- stringParamter_ = input.readBytes();
- break;
- }
- case 16: {
- bitField0_ |= 0x00000002;
- integerParameter_ = input.readUInt64();
- break;
- }
- case 25: {
- bitField0_ |= 0x00000004;
- doubleParameter_ = input.readDouble();
- break;
- }
- case 34: {
- bitField0_ |= 0x00000008;
- blobParameter_ = input.readBytes();
- break;
- }
- case 40: {
- bitField0_ |= 0x00000010;
- nullparameter_ = input.readBool();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public SqlParameter parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new SqlParameter(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional string stringParamter = 1;
- public static final int STRINGPARAMTER_FIELD_NUMBER = 1;
- private java.lang.Object stringParamter_;
- /**
- * optional string stringParamter = 1;
- */
- public boolean hasStringParamter() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string stringParamter = 1;
- */
- public java.lang.String getStringParamter() {
- java.lang.Object ref = stringParamter_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- stringParamter_ = s;
- }
- return s;
- }
- }
- /**
- * optional string stringParamter = 1;
- */
- public com.google.protobuf.ByteString
- getStringParamterBytes() {
- java.lang.Object ref = stringParamter_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- stringParamter_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- // optional uint64 integerParameter = 2;
- public static final int INTEGERPARAMETER_FIELD_NUMBER = 2;
- private long integerParameter_;
- /**
- * optional uint64 integerParameter = 2;
- */
- public boolean hasIntegerParameter() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint64 integerParameter = 2;
- */
- public long getIntegerParameter() {
- return integerParameter_;
- }
-
- // optional double doubleParameter = 3;
- public static final int DOUBLEPARAMETER_FIELD_NUMBER = 3;
- private double doubleParameter_;
- /**
- * optional double doubleParameter = 3;
- */
- public boolean hasDoubleParameter() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional double doubleParameter = 3;
- */
- public double getDoubleParameter() {
- return doubleParameter_;
- }
-
- // optional bytes blobParameter = 4;
- public static final int BLOBPARAMETER_FIELD_NUMBER = 4;
- private com.google.protobuf.ByteString blobParameter_;
- /**
- * optional bytes blobParameter = 4;
- */
- public boolean hasBlobParameter() {
- return ((bitField0_ & 0x00000008) == 0x00000008);
- }
- /**
- * optional bytes blobParameter = 4;
- */
- public com.google.protobuf.ByteString getBlobParameter() {
- return blobParameter_;
- }
-
- // optional bool nullparameter = 5;
- public static final int NULLPARAMETER_FIELD_NUMBER = 5;
- private boolean nullparameter_;
- /**
- * optional bool nullparameter = 5;
- */
- public boolean hasNullparameter() {
- return ((bitField0_ & 0x00000010) == 0x00000010);
- }
- /**
- * optional bool nullparameter = 5;
- */
- public boolean getNullparameter() {
- return nullparameter_;
- }
-
- private void initFields() {
- stringParamter_ = "";
- integerParameter_ = 0L;
- doubleParameter_ = 0D;
- blobParameter_ = com.google.protobuf.ByteString.EMPTY;
- nullparameter_ = false;
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeBytes(1, getStringParamterBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- output.writeUInt64(2, integerParameter_);
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- output.writeDouble(3, doubleParameter_);
- }
- if (((bitField0_ & 0x00000008) == 0x00000008)) {
- output.writeBytes(4, blobParameter_);
- }
- if (((bitField0_ & 0x00000010) == 0x00000010)) {
- output.writeBool(5, nullparameter_);
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(1, getStringParamterBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt64Size(2, integerParameter_);
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- size += com.google.protobuf.CodedOutputStream
- .computeDoubleSize(3, doubleParameter_);
- }
- if (((bitField0_ & 0x00000008) == 0x00000008)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(4, blobParameter_);
- }
- if (((bitField0_ & 0x00000010) == 0x00000010)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBoolSize(5, nullparameter_);
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.SqlStatement.SqlParameter}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- stringParamter_ = "";
- bitField0_ = (bitField0_ & ~0x00000001);
- integerParameter_ = 0L;
- bitField0_ = (bitField0_ & ~0x00000002);
- doubleParameter_ = 0D;
- bitField0_ = (bitField0_ & ~0x00000004);
- blobParameter_ = com.google.protobuf.ByteString.EMPTY;
- bitField0_ = (bitField0_ & ~0x00000008);
- nullparameter_ = false;
- bitField0_ = (bitField0_ & ~0x00000010);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter build() {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter result = new org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.stringParamter_ = stringParamter_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
- result.integerParameter_ = integerParameter_;
- if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
- to_bitField0_ |= 0x00000004;
- }
- result.doubleParameter_ = doubleParameter_;
- if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
- to_bitField0_ |= 0x00000008;
- }
- result.blobParameter_ = blobParameter_;
- if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
- to_bitField0_ |= 0x00000010;
- }
- result.nullparameter_ = nullparameter_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance()) return this;
- if (other.hasStringParamter()) {
- bitField0_ |= 0x00000001;
- stringParamter_ = other.stringParamter_;
- onChanged();
- }
- if (other.hasIntegerParameter()) {
- setIntegerParameter(other.getIntegerParameter());
- }
- if (other.hasDoubleParameter()) {
- setDoubleParameter(other.getDoubleParameter());
- }
- if (other.hasBlobParameter()) {
- setBlobParameter(other.getBlobParameter());
- }
- if (other.hasNullparameter()) {
- setNullparameter(other.getNullparameter());
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional string stringParamter = 1;
- private java.lang.Object stringParamter_ = "";
- /**
- * optional string stringParamter = 1;
- */
- public boolean hasStringParamter() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string stringParamter = 1;
- */
- public java.lang.String getStringParamter() {
- java.lang.Object ref = stringParamter_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- stringParamter_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string stringParamter = 1;
- */
- public com.google.protobuf.ByteString
- getStringParamterBytes() {
- java.lang.Object ref = stringParamter_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- stringParamter_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string stringParamter = 1;
- */
- public Builder setStringParamter(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- stringParamter_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string stringParamter = 1;
- */
- public Builder clearStringParamter() {
- bitField0_ = (bitField0_ & ~0x00000001);
- stringParamter_ = getDefaultInstance().getStringParamter();
- onChanged();
- return this;
- }
- /**
- * optional string stringParamter = 1;
- */
- public Builder setStringParamterBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- stringParamter_ = value;
- onChanged();
- return this;
- }
-
- // optional uint64 integerParameter = 2;
- private long integerParameter_ ;
- /**
- * optional uint64 integerParameter = 2;
- */
- public boolean hasIntegerParameter() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint64 integerParameter = 2;
- */
- public long getIntegerParameter() {
- return integerParameter_;
- }
- /**
- * optional uint64 integerParameter = 2;
- */
- public Builder setIntegerParameter(long value) {
- bitField0_ |= 0x00000002;
- integerParameter_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint64 integerParameter = 2;
- */
- public Builder clearIntegerParameter() {
- bitField0_ = (bitField0_ & ~0x00000002);
- integerParameter_ = 0L;
- onChanged();
- return this;
- }
-
- // optional double doubleParameter = 3;
- private double doubleParameter_ ;
- /**
- * optional double doubleParameter = 3;
- */
- public boolean hasDoubleParameter() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional double doubleParameter = 3;
- */
- public double getDoubleParameter() {
- return doubleParameter_;
- }
- /**
- * optional double doubleParameter = 3;
- */
- public Builder setDoubleParameter(double value) {
- bitField0_ |= 0x00000004;
- doubleParameter_ = value;
- onChanged();
- return this;
- }
- /**
- * optional double doubleParameter = 3;
- */
- public Builder clearDoubleParameter() {
- bitField0_ = (bitField0_ & ~0x00000004);
- doubleParameter_ = 0D;
- onChanged();
- return this;
- }
-
- // optional bytes blobParameter = 4;
- private com.google.protobuf.ByteString blobParameter_ = com.google.protobuf.ByteString.EMPTY;
- /**
- * optional bytes blobParameter = 4;
- */
- public boolean hasBlobParameter() {
- return ((bitField0_ & 0x00000008) == 0x00000008);
- }
- /**
- * optional bytes blobParameter = 4;
- */
- public com.google.protobuf.ByteString getBlobParameter() {
- return blobParameter_;
- }
- /**
- * optional bytes blobParameter = 4;
- */
- public Builder setBlobParameter(com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000008;
- blobParameter_ = value;
- onChanged();
- return this;
- }
- /**
- * optional bytes blobParameter = 4;
- */
- public Builder clearBlobParameter() {
- bitField0_ = (bitField0_ & ~0x00000008);
- blobParameter_ = getDefaultInstance().getBlobParameter();
- onChanged();
- return this;
- }
-
- // optional bool nullparameter = 5;
- private boolean nullparameter_ ;
- /**
- * optional bool nullparameter = 5;
- */
- public boolean hasNullparameter() {
- return ((bitField0_ & 0x00000010) == 0x00000010);
- }
- /**
- * optional bool nullparameter = 5;
- */
- public boolean getNullparameter() {
- return nullparameter_;
- }
- /**
- * optional bool nullparameter = 5;
- */
- public Builder setNullparameter(boolean value) {
- bitField0_ |= 0x00000010;
- nullparameter_ = value;
- onChanged();
- return this;
- }
- /**
- * optional bool nullparameter = 5;
- */
- public Builder clearNullparameter() {
- bitField0_ = (bitField0_ & ~0x00000010);
- nullparameter_ = false;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.SqlStatement.SqlParameter)
- }
-
- static {
- defaultInstance = new SqlParameter(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.SqlStatement.SqlParameter)
- }
-
- private int bitField0_;
- // optional string statement = 1;
- public static final int STATEMENT_FIELD_NUMBER = 1;
- private java.lang.Object statement_;
- /**
- * optional string statement = 1;
- */
- public boolean hasStatement() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string statement = 1;
- */
- public java.lang.String getStatement() {
- java.lang.Object ref = statement_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- statement_ = s;
- }
- return s;
- }
- }
- /**
- * optional string statement = 1;
- */
- public com.google.protobuf.ByteString
- getStatementBytes() {
- java.lang.Object ref = statement_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- statement_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- // repeated .signal.SqlStatement.SqlParameter parameters = 2;
- public static final int PARAMETERS_FIELD_NUMBER = 2;
- private java.util.List parameters_;
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public java.util.List getParametersList() {
- return parameters_;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public java.util.List extends org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>
- getParametersOrBuilderList() {
- return parameters_;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public int getParametersCount() {
- return parameters_.size();
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index) {
- return parameters_.get(index);
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder(
- int index) {
- return parameters_.get(index);
- }
-
- private void initFields() {
- statement_ = "";
- parameters_ = java.util.Collections.emptyList();
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeBytes(1, getStatementBytes());
- }
- for (int i = 0; i < parameters_.size(); i++) {
- output.writeMessage(2, parameters_.get(i));
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(1, getStatementBytes());
- }
- for (int i = 0; i < parameters_.size(); i++) {
- size += com.google.protobuf.CodedOutputStream
- .computeMessageSize(2, parameters_.get(i));
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.SqlStatement}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- getParametersFieldBuilder();
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- statement_ = "";
- bitField0_ = (bitField0_ & ~0x00000001);
- if (parametersBuilder_ == null) {
- parameters_ = java.util.Collections.emptyList();
- bitField0_ = (bitField0_ & ~0x00000002);
- } else {
- parametersBuilder_.clear();
- }
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement build() {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = new org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.statement_ = statement_;
- if (parametersBuilder_ == null) {
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- parameters_ = java.util.Collections.unmodifiableList(parameters_);
- bitField0_ = (bitField0_ & ~0x00000002);
- }
- result.parameters_ = parameters_;
- } else {
- result.parameters_ = parametersBuilder_.build();
- }
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance()) return this;
- if (other.hasStatement()) {
- bitField0_ |= 0x00000001;
- statement_ = other.statement_;
- onChanged();
- }
- if (parametersBuilder_ == null) {
- if (!other.parameters_.isEmpty()) {
- if (parameters_.isEmpty()) {
- parameters_ = other.parameters_;
- bitField0_ = (bitField0_ & ~0x00000002);
- } else {
- ensureParametersIsMutable();
- parameters_.addAll(other.parameters_);
- }
- onChanged();
- }
- } else {
- if (!other.parameters_.isEmpty()) {
- if (parametersBuilder_.isEmpty()) {
- parametersBuilder_.dispose();
- parametersBuilder_ = null;
- parameters_ = other.parameters_;
- bitField0_ = (bitField0_ & ~0x00000002);
- parametersBuilder_ =
- com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
- getParametersFieldBuilder() : null;
- } else {
- parametersBuilder_.addAllMessages(other.parameters_);
- }
- }
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional string statement = 1;
- private java.lang.Object statement_ = "";
- /**
- * optional string statement = 1;
- */
- public boolean hasStatement() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string statement = 1;
- */
- public java.lang.String getStatement() {
- java.lang.Object ref = statement_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- statement_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string statement = 1;
- */
- public com.google.protobuf.ByteString
- getStatementBytes() {
- java.lang.Object ref = statement_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- statement_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string statement = 1;
- */
- public Builder setStatement(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- statement_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string statement = 1;
- */
- public Builder clearStatement() {
- bitField0_ = (bitField0_ & ~0x00000001);
- statement_ = getDefaultInstance().getStatement();
- onChanged();
- return this;
- }
- /**
- * optional string statement = 1;
- */
- public Builder setStatementBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- statement_ = value;
- onChanged();
- return this;
- }
-
- // repeated .signal.SqlStatement.SqlParameter parameters = 2;
- private java.util.List parameters_ =
- java.util.Collections.emptyList();
- private void ensureParametersIsMutable() {
- if (!((bitField0_ & 0x00000002) == 0x00000002)) {
- parameters_ = new java.util.ArrayList(parameters_);
- bitField0_ |= 0x00000002;
- }
- }
-
- private com.google.protobuf.RepeatedFieldBuilder<
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder> parametersBuilder_;
-
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public java.util.List getParametersList() {
- if (parametersBuilder_ == null) {
- return java.util.Collections.unmodifiableList(parameters_);
- } else {
- return parametersBuilder_.getMessageList();
- }
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public int getParametersCount() {
- if (parametersBuilder_ == null) {
- return parameters_.size();
- } else {
- return parametersBuilder_.getCount();
- }
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index) {
- if (parametersBuilder_ == null) {
- return parameters_.get(index);
- } else {
- return parametersBuilder_.getMessage(index);
- }
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder setParameters(
- int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) {
- if (parametersBuilder_ == null) {
- if (value == null) {
- throw new NullPointerException();
- }
- ensureParametersIsMutable();
- parameters_.set(index, value);
- onChanged();
- } else {
- parametersBuilder_.setMessage(index, value);
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder setParameters(
- int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) {
- if (parametersBuilder_ == null) {
- ensureParametersIsMutable();
- parameters_.set(index, builderForValue.build());
- onChanged();
- } else {
- parametersBuilder_.setMessage(index, builderForValue.build());
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder addParameters(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) {
- if (parametersBuilder_ == null) {
- if (value == null) {
- throw new NullPointerException();
- }
- ensureParametersIsMutable();
- parameters_.add(value);
- onChanged();
- } else {
- parametersBuilder_.addMessage(value);
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder addParameters(
- int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) {
- if (parametersBuilder_ == null) {
- if (value == null) {
- throw new NullPointerException();
- }
- ensureParametersIsMutable();
- parameters_.add(index, value);
- onChanged();
- } else {
- parametersBuilder_.addMessage(index, value);
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder addParameters(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) {
- if (parametersBuilder_ == null) {
- ensureParametersIsMutable();
- parameters_.add(builderForValue.build());
- onChanged();
- } else {
- parametersBuilder_.addMessage(builderForValue.build());
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder addParameters(
- int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) {
- if (parametersBuilder_ == null) {
- ensureParametersIsMutable();
- parameters_.add(index, builderForValue.build());
- onChanged();
- } else {
- parametersBuilder_.addMessage(index, builderForValue.build());
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder addAllParameters(
- java.lang.Iterable extends org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter> values) {
- if (parametersBuilder_ == null) {
- ensureParametersIsMutable();
- super.addAll(values, parameters_);
- onChanged();
- } else {
- parametersBuilder_.addAllMessages(values);
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder clearParameters() {
- if (parametersBuilder_ == null) {
- parameters_ = java.util.Collections.emptyList();
- bitField0_ = (bitField0_ & ~0x00000002);
- onChanged();
- } else {
- parametersBuilder_.clear();
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public Builder removeParameters(int index) {
- if (parametersBuilder_ == null) {
- ensureParametersIsMutable();
- parameters_.remove(index);
- onChanged();
- } else {
- parametersBuilder_.remove(index);
- }
- return this;
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder getParametersBuilder(
- int index) {
- return getParametersFieldBuilder().getBuilder(index);
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder(
- int index) {
- if (parametersBuilder_ == null) {
- return parameters_.get(index); } else {
- return parametersBuilder_.getMessageOrBuilder(index);
- }
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public java.util.List extends org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>
- getParametersOrBuilderList() {
- if (parametersBuilder_ != null) {
- return parametersBuilder_.getMessageOrBuilderList();
- } else {
- return java.util.Collections.unmodifiableList(parameters_);
- }
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder addParametersBuilder() {
- return getParametersFieldBuilder().addBuilder(
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance());
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder addParametersBuilder(
- int index) {
- return getParametersFieldBuilder().addBuilder(
- index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance());
- }
- /**
- * repeated .signal.SqlStatement.SqlParameter parameters = 2;
- */
- public java.util.List
- getParametersBuilderList() {
- return getParametersFieldBuilder().getBuilderList();
- }
- private com.google.protobuf.RepeatedFieldBuilder<
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>
- getParametersFieldBuilder() {
- if (parametersBuilder_ == null) {
- parametersBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
- org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>(
- parameters_,
- ((bitField0_ & 0x00000002) == 0x00000002),
- getParentForChildren(),
- isClean());
- parameters_ = null;
- }
- return parametersBuilder_;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.SqlStatement)
- }
-
- static {
- defaultInstance = new SqlStatement(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.SqlStatement)
- }
-
- public interface SharedPreferenceOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional string file = 1;
- /**
- * optional string file = 1;
- */
- boolean hasFile();
- /**
- * optional string file = 1;
- */
- java.lang.String getFile();
- /**
- * optional string file = 1;
- */
- com.google.protobuf.ByteString
- getFileBytes();
-
- // optional string key = 2;
- /**
- * optional string key = 2;
- */
- boolean hasKey();
- /**
- * optional string key = 2;
- */
- java.lang.String getKey();
- /**
- * optional string key = 2;
- */
- com.google.protobuf.ByteString
- getKeyBytes();
-
- // optional string value = 3;
- /**
- * optional string value = 3;
- */
- boolean hasValue();
- /**
- * optional string value = 3;
- */
- java.lang.String getValue();
- /**
- * optional string value = 3;
- */
- com.google.protobuf.ByteString
- getValueBytes();
- }
- /**
- * Protobuf type {@code signal.SharedPreference}
- */
- public static final class SharedPreference extends
- com.google.protobuf.GeneratedMessage
- implements SharedPreferenceOrBuilder {
- // Use SharedPreference.newBuilder() to construct.
- private SharedPreference(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private SharedPreference(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final SharedPreference defaultInstance;
- public static SharedPreference getDefaultInstance() {
- return defaultInstance;
- }
-
- public SharedPreference getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private SharedPreference(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 10: {
- bitField0_ |= 0x00000001;
- file_ = input.readBytes();
- break;
- }
- case 18: {
- bitField0_ |= 0x00000002;
- key_ = input.readBytes();
- break;
- }
- case 26: {
- bitField0_ |= 0x00000004;
- value_ = input.readBytes();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public SharedPreference parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new SharedPreference(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional string file = 1;
- public static final int FILE_FIELD_NUMBER = 1;
- private java.lang.Object file_;
- /**
- * optional string file = 1;
- */
- public boolean hasFile() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string file = 1;
- */
- public java.lang.String getFile() {
- java.lang.Object ref = file_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- file_ = s;
- }
- return s;
- }
- }
- /**
- * optional string file = 1;
- */
- public com.google.protobuf.ByteString
- getFileBytes() {
- java.lang.Object ref = file_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- file_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- // optional string key = 2;
- public static final int KEY_FIELD_NUMBER = 2;
- private java.lang.Object key_;
- /**
- * optional string key = 2;
- */
- public boolean hasKey() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional string key = 2;
- */
- public java.lang.String getKey() {
- java.lang.Object ref = key_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- key_ = s;
- }
- return s;
- }
- }
- /**
- * optional string key = 2;
- */
- public com.google.protobuf.ByteString
- getKeyBytes() {
- java.lang.Object ref = key_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- key_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- // optional string value = 3;
- public static final int VALUE_FIELD_NUMBER = 3;
- private java.lang.Object value_;
- /**
- * optional string value = 3;
- */
- public boolean hasValue() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional string value = 3;
- */
- public java.lang.String getValue() {
- java.lang.Object ref = value_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- value_ = s;
- }
- return s;
- }
- }
- /**
- * optional string value = 3;
- */
- public com.google.protobuf.ByteString
- getValueBytes() {
- java.lang.Object ref = value_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- value_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- private void initFields() {
- file_ = "";
- key_ = "";
- value_ = "";
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeBytes(1, getFileBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- output.writeBytes(2, getKeyBytes());
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- output.writeBytes(3, getValueBytes());
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(1, getFileBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(2, getKeyBytes());
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(3, getValueBytes());
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.SharedPreference}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- file_ = "";
- bitField0_ = (bitField0_ & ~0x00000001);
- key_ = "";
- bitField0_ = (bitField0_ & ~0x00000002);
- value_ = "";
- bitField0_ = (bitField0_ & ~0x00000004);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference build() {
- org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = new org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.file_ = file_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
- result.key_ = key_;
- if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
- to_bitField0_ |= 0x00000004;
- }
- result.value_ = value_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance()) return this;
- if (other.hasFile()) {
- bitField0_ |= 0x00000001;
- file_ = other.file_;
- onChanged();
- }
- if (other.hasKey()) {
- bitField0_ |= 0x00000002;
- key_ = other.key_;
- onChanged();
- }
- if (other.hasValue()) {
- bitField0_ |= 0x00000004;
- value_ = other.value_;
- onChanged();
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional string file = 1;
- private java.lang.Object file_ = "";
- /**
- * optional string file = 1;
- */
- public boolean hasFile() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string file = 1;
- */
- public java.lang.String getFile() {
- java.lang.Object ref = file_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- file_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string file = 1;
- */
- public com.google.protobuf.ByteString
- getFileBytes() {
- java.lang.Object ref = file_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- file_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string file = 1;
- */
- public Builder setFile(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- file_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string file = 1;
- */
- public Builder clearFile() {
- bitField0_ = (bitField0_ & ~0x00000001);
- file_ = getDefaultInstance().getFile();
- onChanged();
- return this;
- }
- /**
- * optional string file = 1;
- */
- public Builder setFileBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- file_ = value;
- onChanged();
- return this;
- }
-
- // optional string key = 2;
- private java.lang.Object key_ = "";
- /**
- * optional string key = 2;
- */
- public boolean hasKey() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional string key = 2;
- */
- public java.lang.String getKey() {
- java.lang.Object ref = key_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- key_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string key = 2;
- */
- public com.google.protobuf.ByteString
- getKeyBytes() {
- java.lang.Object ref = key_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- key_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string key = 2;
- */
- public Builder setKey(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000002;
- key_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string key = 2;
- */
- public Builder clearKey() {
- bitField0_ = (bitField0_ & ~0x00000002);
- key_ = getDefaultInstance().getKey();
- onChanged();
- return this;
- }
- /**
- * optional string key = 2;
- */
- public Builder setKeyBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000002;
- key_ = value;
- onChanged();
- return this;
- }
-
- // optional string value = 3;
- private java.lang.Object value_ = "";
- /**
- * optional string value = 3;
- */
- public boolean hasValue() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional string value = 3;
- */
- public java.lang.String getValue() {
- java.lang.Object ref = value_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- value_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string value = 3;
- */
- public com.google.protobuf.ByteString
- getValueBytes() {
- java.lang.Object ref = value_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- value_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string value = 3;
- */
- public Builder setValue(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000004;
- value_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string value = 3;
- */
- public Builder clearValue() {
- bitField0_ = (bitField0_ & ~0x00000004);
- value_ = getDefaultInstance().getValue();
- onChanged();
- return this;
- }
- /**
- * optional string value = 3;
- */
- public Builder setValueBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000004;
- value_ = value;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.SharedPreference)
- }
-
- static {
- defaultInstance = new SharedPreference(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.SharedPreference)
- }
-
- public interface AttachmentOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional uint64 rowId = 1;
- /**
- * optional uint64 rowId = 1;
- */
- boolean hasRowId();
- /**
- * optional uint64 rowId = 1;
- */
- long getRowId();
-
- // optional uint64 attachmentId = 2;
- /**
- * optional uint64 attachmentId = 2;
- */
- boolean hasAttachmentId();
- /**
- * optional uint64 attachmentId = 2;
- */
- long getAttachmentId();
-
- // optional uint32 length = 3;
- /**
- * optional uint32 length = 3;
- */
- boolean hasLength();
- /**
- * optional uint32 length = 3;
- */
- int getLength();
- }
- /**
- * Protobuf type {@code signal.Attachment}
- */
- public static final class Attachment extends
- com.google.protobuf.GeneratedMessage
- implements AttachmentOrBuilder {
- // Use Attachment.newBuilder() to construct.
- private Attachment(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private Attachment(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final Attachment defaultInstance;
- public static Attachment getDefaultInstance() {
- return defaultInstance;
- }
-
- public Attachment getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private Attachment(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 8: {
- bitField0_ |= 0x00000001;
- rowId_ = input.readUInt64();
- break;
- }
- case 16: {
- bitField0_ |= 0x00000002;
- attachmentId_ = input.readUInt64();
- break;
- }
- case 24: {
- bitField0_ |= 0x00000004;
- length_ = input.readUInt32();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public Attachment parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new Attachment(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional uint64 rowId = 1;
- public static final int ROWID_FIELD_NUMBER = 1;
- private long rowId_;
- /**
- * optional uint64 rowId = 1;
- */
- public boolean hasRowId() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint64 rowId = 1;
- */
- public long getRowId() {
- return rowId_;
- }
-
- // optional uint64 attachmentId = 2;
- public static final int ATTACHMENTID_FIELD_NUMBER = 2;
- private long attachmentId_;
- /**
- * optional uint64 attachmentId = 2;
- */
- public boolean hasAttachmentId() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint64 attachmentId = 2;
- */
- public long getAttachmentId() {
- return attachmentId_;
- }
-
- // optional uint32 length = 3;
- public static final int LENGTH_FIELD_NUMBER = 3;
- private int length_;
- /**
- * optional uint32 length = 3;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional uint32 length = 3;
- */
- public int getLength() {
- return length_;
- }
-
- private void initFields() {
- rowId_ = 0L;
- attachmentId_ = 0L;
- length_ = 0;
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeUInt64(1, rowId_);
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- output.writeUInt64(2, attachmentId_);
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- output.writeUInt32(3, length_);
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt64Size(1, rowId_);
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt64Size(2, attachmentId_);
- }
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt32Size(3, length_);
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Attachment prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.Attachment}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Attachment.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- rowId_ = 0L;
- bitField0_ = (bitField0_ & ~0x00000001);
- attachmentId_ = 0L;
- bitField0_ = (bitField0_ & ~0x00000002);
- length_ = 0;
- bitField0_ = (bitField0_ & ~0x00000004);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Attachment build() {
- org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Attachment buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = new org.thoughtcrime.securesms.backup.BackupProtos.Attachment(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.rowId_ = rowId_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
- result.attachmentId_ = attachmentId_;
- if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
- to_bitField0_ |= 0x00000004;
- }
- result.length_ = length_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Attachment) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Attachment)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Attachment other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance()) return this;
- if (other.hasRowId()) {
- setRowId(other.getRowId());
- }
- if (other.hasAttachmentId()) {
- setAttachmentId(other.getAttachmentId());
- }
- if (other.hasLength()) {
- setLength(other.getLength());
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.Attachment parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Attachment) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional uint64 rowId = 1;
- private long rowId_ ;
- /**
- * optional uint64 rowId = 1;
- */
- public boolean hasRowId() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint64 rowId = 1;
- */
- public long getRowId() {
- return rowId_;
- }
- /**
- * optional uint64 rowId = 1;
- */
- public Builder setRowId(long value) {
- bitField0_ |= 0x00000001;
- rowId_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint64 rowId = 1;
- */
- public Builder clearRowId() {
- bitField0_ = (bitField0_ & ~0x00000001);
- rowId_ = 0L;
- onChanged();
- return this;
- }
-
- // optional uint64 attachmentId = 2;
- private long attachmentId_ ;
- /**
- * optional uint64 attachmentId = 2;
- */
- public boolean hasAttachmentId() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint64 attachmentId = 2;
- */
- public long getAttachmentId() {
- return attachmentId_;
- }
- /**
- * optional uint64 attachmentId = 2;
- */
- public Builder setAttachmentId(long value) {
- bitField0_ |= 0x00000002;
- attachmentId_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint64 attachmentId = 2;
- */
- public Builder clearAttachmentId() {
- bitField0_ = (bitField0_ & ~0x00000002);
- attachmentId_ = 0L;
- onChanged();
- return this;
- }
-
- // optional uint32 length = 3;
- private int length_ ;
- /**
- * optional uint32 length = 3;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
- }
- /**
- * optional uint32 length = 3;
- */
- public int getLength() {
- return length_;
- }
- /**
- * optional uint32 length = 3;
- */
- public Builder setLength(int value) {
- bitField0_ |= 0x00000004;
- length_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint32 length = 3;
- */
- public Builder clearLength() {
- bitField0_ = (bitField0_ & ~0x00000004);
- length_ = 0;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.Attachment)
- }
-
- static {
- defaultInstance = new Attachment(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.Attachment)
- }
-
- public interface StickerOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional uint64 rowId = 1;
- /**
- * optional uint64 rowId = 1;
- */
- boolean hasRowId();
- /**
- * optional uint64 rowId = 1;
- */
- long getRowId();
-
- // optional uint32 length = 2;
- /**
- * optional uint32 length = 2;
- */
- boolean hasLength();
- /**
- * optional uint32 length = 2;
- */
- int getLength();
- }
- /**
- * Protobuf type {@code signal.Sticker}
- */
- public static final class Sticker extends
- com.google.protobuf.GeneratedMessage
- implements StickerOrBuilder {
- // Use Sticker.newBuilder() to construct.
- private Sticker(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private Sticker(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final Sticker defaultInstance;
- public static Sticker getDefaultInstance() {
- return defaultInstance;
- }
-
- public Sticker getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private Sticker(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 8: {
- bitField0_ |= 0x00000001;
- rowId_ = input.readUInt64();
- break;
- }
- case 16: {
- bitField0_ |= 0x00000002;
- length_ = input.readUInt32();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Sticker.class, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public Sticker parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new Sticker(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional uint64 rowId = 1;
- public static final int ROWID_FIELD_NUMBER = 1;
- private long rowId_;
- /**
- * optional uint64 rowId = 1;
- */
- public boolean hasRowId() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint64 rowId = 1;
- */
- public long getRowId() {
- return rowId_;
- }
-
- // optional uint32 length = 2;
- public static final int LENGTH_FIELD_NUMBER = 2;
- private int length_;
- /**
- * optional uint32 length = 2;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint32 length = 2;
- */
- public int getLength() {
- return length_;
- }
-
- private void initFields() {
- rowId_ = 0L;
- length_ = 0;
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeUInt64(1, rowId_);
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- output.writeUInt32(2, length_);
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt64Size(1, rowId_);
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt32Size(2, length_);
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Sticker prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.Sticker}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Sticker.class, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Sticker.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- rowId_ = 0L;
- bitField0_ = (bitField0_ & ~0x00000001);
- length_ = 0;
- bitField0_ = (bitField0_ & ~0x00000002);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Sticker getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Sticker build() {
- org.thoughtcrime.securesms.backup.BackupProtos.Sticker result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Sticker buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.Sticker result = new org.thoughtcrime.securesms.backup.BackupProtos.Sticker(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.rowId_ = rowId_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
- result.length_ = length_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Sticker) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Sticker)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Sticker other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance()) return this;
- if (other.hasRowId()) {
- setRowId(other.getRowId());
- }
- if (other.hasLength()) {
- setLength(other.getLength());
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.Sticker parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Sticker) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional uint64 rowId = 1;
- private long rowId_ ;
- /**
- * optional uint64 rowId = 1;
- */
- public boolean hasRowId() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint64 rowId = 1;
- */
- public long getRowId() {
- return rowId_;
- }
- /**
- * optional uint64 rowId = 1;
- */
- public Builder setRowId(long value) {
- bitField0_ |= 0x00000001;
- rowId_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint64 rowId = 1;
- */
- public Builder clearRowId() {
- bitField0_ = (bitField0_ & ~0x00000001);
- rowId_ = 0L;
- onChanged();
- return this;
- }
-
- // optional uint32 length = 2;
- private int length_ ;
- /**
- * optional uint32 length = 2;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint32 length = 2;
- */
- public int getLength() {
- return length_;
- }
- /**
- * optional uint32 length = 2;
- */
- public Builder setLength(int value) {
- bitField0_ |= 0x00000002;
- length_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint32 length = 2;
- */
- public Builder clearLength() {
- bitField0_ = (bitField0_ & ~0x00000002);
- length_ = 0;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.Sticker)
- }
-
- static {
- defaultInstance = new Sticker(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.Sticker)
- }
-
- public interface AvatarOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional string name = 1;
- /**
- * optional string name = 1;
- */
- boolean hasName();
- /**
- * optional string name = 1;
- */
- java.lang.String getName();
- /**
- * optional string name = 1;
- */
- com.google.protobuf.ByteString
- getNameBytes();
-
- // optional uint32 length = 2;
- /**
- * optional uint32 length = 2;
- */
- boolean hasLength();
- /**
- * optional uint32 length = 2;
- */
- int getLength();
- }
- /**
- * Protobuf type {@code signal.Avatar}
- */
- public static final class Avatar extends
- com.google.protobuf.GeneratedMessage
- implements AvatarOrBuilder {
- // Use Avatar.newBuilder() to construct.
- private Avatar(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private Avatar(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final Avatar defaultInstance;
- public static Avatar getDefaultInstance() {
- return defaultInstance;
- }
-
- public Avatar getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private Avatar(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 10: {
- bitField0_ |= 0x00000001;
- name_ = input.readBytes();
- break;
- }
- case 16: {
- bitField0_ |= 0x00000002;
- length_ = input.readUInt32();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Avatar.class, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public Avatar parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new Avatar(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional string name = 1;
- public static final int NAME_FIELD_NUMBER = 1;
- private java.lang.Object name_;
- /**
- * optional string name = 1;
- */
- public boolean hasName() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string name = 1;
- */
- public java.lang.String getName() {
- java.lang.Object ref = name_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- name_ = s;
- }
- return s;
- }
- }
- /**
- * optional string name = 1;
- */
- public com.google.protobuf.ByteString
- getNameBytes() {
- java.lang.Object ref = name_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- name_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- // optional uint32 length = 2;
- public static final int LENGTH_FIELD_NUMBER = 2;
- private int length_;
- /**
- * optional uint32 length = 2;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint32 length = 2;
- */
- public int getLength() {
- return length_;
- }
-
- private void initFields() {
- name_ = "";
- length_ = 0;
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeBytes(1, getNameBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- output.writeUInt32(2, length_);
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(1, getNameBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt32Size(2, length_);
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Avatar prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.Avatar}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Avatar.class, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Avatar.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- name_ = "";
- bitField0_ = (bitField0_ & ~0x00000001);
- length_ = 0;
- bitField0_ = (bitField0_ & ~0x00000002);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Avatar getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Avatar build() {
- org.thoughtcrime.securesms.backup.BackupProtos.Avatar result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.Avatar buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.Avatar result = new org.thoughtcrime.securesms.backup.BackupProtos.Avatar(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.name_ = name_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
- result.length_ = length_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Avatar) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Avatar)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Avatar other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance()) return this;
- if (other.hasName()) {
- bitField0_ |= 0x00000001;
- name_ = other.name_;
- onChanged();
- }
- if (other.hasLength()) {
- setLength(other.getLength());
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.Avatar parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Avatar) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional string name = 1;
- private java.lang.Object name_ = "";
- /**
- * optional string name = 1;
- */
- public boolean hasName() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional string name = 1;
- */
- public java.lang.String getName() {
- java.lang.Object ref = name_;
- if (!(ref instanceof java.lang.String)) {
- java.lang.String s = ((com.google.protobuf.ByteString) ref)
- .toStringUtf8();
- name_ = s;
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * optional string name = 1;
- */
- public com.google.protobuf.ByteString
- getNameBytes() {
- java.lang.Object ref = name_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- name_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * optional string name = 1;
- */
- public Builder setName(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- name_ = value;
- onChanged();
- return this;
- }
- /**
- * optional string name = 1;
- */
- public Builder clearName() {
- bitField0_ = (bitField0_ & ~0x00000001);
- name_ = getDefaultInstance().getName();
- onChanged();
- return this;
- }
- /**
- * optional string name = 1;
- */
- public Builder setNameBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- name_ = value;
- onChanged();
- return this;
- }
-
- // optional uint32 length = 2;
- private int length_ ;
- /**
- * optional uint32 length = 2;
- */
- public boolean hasLength() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
- }
- /**
- * optional uint32 length = 2;
- */
- public int getLength() {
- return length_;
- }
- /**
- * optional uint32 length = 2;
- */
- public Builder setLength(int value) {
- bitField0_ |= 0x00000002;
- length_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint32 length = 2;
- */
- public Builder clearLength() {
- bitField0_ = (bitField0_ & ~0x00000002);
- length_ = 0;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.Avatar)
- }
-
- static {
- defaultInstance = new Avatar(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.Avatar)
- }
-
- public interface DatabaseVersionOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional uint32 version = 1;
- /**
- * optional uint32 version = 1;
- */
- boolean hasVersion();
- /**
- * optional uint32 version = 1;
- */
- int getVersion();
- }
- /**
- * Protobuf type {@code signal.DatabaseVersion}
- */
- public static final class DatabaseVersion extends
- com.google.protobuf.GeneratedMessage
- implements DatabaseVersionOrBuilder {
- // Use DatabaseVersion.newBuilder() to construct.
- private DatabaseVersion(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private DatabaseVersion(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final DatabaseVersion defaultInstance;
- public static DatabaseVersion getDefaultInstance() {
- return defaultInstance;
- }
-
- public DatabaseVersion getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private DatabaseVersion(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 8: {
- bitField0_ |= 0x00000001;
- version_ = input.readUInt32();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public DatabaseVersion parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new DatabaseVersion(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional uint32 version = 1;
- public static final int VERSION_FIELD_NUMBER = 1;
- private int version_;
- /**
- * optional uint32 version = 1;
- */
- public boolean hasVersion() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint32 version = 1;
- */
- public int getVersion() {
- return version_;
- }
-
- private void initFields() {
- version_ = 0;
- }
- private byte memoizedIsInitialized = -1;
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized != -1) return isInitialized == 1;
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- getSerializedSize();
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeUInt32(1, version_);
- }
- getUnknownFields().writeTo(output);
- }
-
- private int memoizedSerializedSize = -1;
- public int getSerializedSize() {
- int size = memoizedSerializedSize;
- if (size != -1) return size;
-
- size = 0;
- if (((bitField0_ & 0x00000001) == 0x00000001)) {
- size += com.google.protobuf.CodedOutputStream
- .computeUInt32Size(1, version_);
- }
- size += getUnknownFields().getSerializedSize();
- memoizedSerializedSize = size;
- return size;
- }
-
- private static final long serialVersionUID = 0L;
- @java.lang.Override
- protected java.lang.Object writeReplace()
- throws java.io.ObjectStreamException {
- return super.writeReplace();
- }
-
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseDelimitedFrom(input, extensionRegistry);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return PARSER.parseFrom(input);
- }
- public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return PARSER.parseFrom(input, extensionRegistry);
- }
-
- public static Builder newBuilder() { return Builder.create(); }
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion prototype) {
- return newBuilder().mergeFrom(prototype);
- }
- public Builder toBuilder() { return newBuilder(this); }
-
- @java.lang.Override
- protected Builder newBuilderForType(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code signal.DatabaseVersion}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessage.Builder
- implements org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class);
- }
-
- // Construct using org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- com.google.protobuf.GeneratedMessage.BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
- }
- }
- private static Builder create() {
- return new Builder();
- }
-
- public Builder clear() {
- super.clear();
- version_ = 0;
- bitField0_ = (bitField0_ & ~0x00000001);
- return this;
- }
-
- public Builder clone() {
- return create().mergeFrom(buildPartial());
- }
-
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getDefaultInstanceForType() {
- return org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance();
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion build() {
- org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion buildPartial() {
- org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = new org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion(this);
- int from_bitField0_ = bitField0_;
- int to_bitField0_ = 0;
- if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
- to_bitField0_ |= 0x00000001;
- }
- result.version_ = version_;
- result.bitField0_ = to_bitField0_;
- onBuilt();
- return result;
- }
-
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) {
- return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion other) {
- if (other == org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance()) return this;
- if (other.hasVersion()) {
- setVersion(other.getVersion());
- }
- this.mergeUnknownFields(other.getUnknownFields());
- return this;
- }
-
- public final boolean isInitialized() {
- return true;
- }
-
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- // optional uint32 version = 1;
- private int version_ ;
- /**
- * optional uint32 version = 1;
- */
- public boolean hasVersion() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- /**
- * optional uint32 version = 1;
- */
- public int getVersion() {
- return version_;
- }
- /**
- * optional uint32 version = 1;
- */
- public Builder setVersion(int value) {
- bitField0_ |= 0x00000001;
- version_ = value;
- onChanged();
- return this;
- }
- /**
- * optional uint32 version = 1;
- */
- public Builder clearVersion() {
- bitField0_ = (bitField0_ & ~0x00000001);
- version_ = 0;
- onChanged();
- return this;
- }
-
- // @@protoc_insertion_point(builder_scope:signal.DatabaseVersion)
- }
-
- static {
- defaultInstance = new DatabaseVersion(true);
- defaultInstance.initFields();
- }
-
- // @@protoc_insertion_point(class_scope:signal.DatabaseVersion)
- }
-
- public interface HeaderOrBuilder
- extends com.google.protobuf.MessageOrBuilder {
-
- // optional bytes iv = 1;
- /**
- * optional bytes iv = 1;
- */
- boolean hasIv();
- /**
- * optional bytes iv = 1;
- */
- com.google.protobuf.ByteString getIv();
-
- // optional bytes salt = 2;
- /**
- * optional bytes salt = 2;
- */
- boolean hasSalt();
- /**
- * optional bytes salt = 2;
- */
- com.google.protobuf.ByteString getSalt();
- }
- /**
- * Protobuf type {@code signal.Header}
- */
- public static final class Header extends
- com.google.protobuf.GeneratedMessage
- implements HeaderOrBuilder {
- // Use Header.newBuilder() to construct.
- private Header(com.google.protobuf.GeneratedMessage.Builder> builder) {
- super(builder);
- this.unknownFields = builder.getUnknownFields();
- }
- private Header(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
- private static final Header defaultInstance;
- public static Header getDefaultInstance() {
- return defaultInstance;
- }
-
- public Header getDefaultInstanceForType() {
- return defaultInstance;
- }
-
- private final com.google.protobuf.UnknownFieldSet unknownFields;
- @java.lang.Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private Header(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- initFields();
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- default: {
- if (!parseUnknownField(input, unknownFields,
- extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- case 10: {
- bitField0_ |= 0x00000001;
- iv_ = input.readBytes();
- break;
- }
- case 18: {
- bitField0_ |= 0x00000002;
- salt_ = input.readBytes();
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e.getMessage()).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor;
- }
-
- protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internalGetFieldAccessorTable() {
- return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- org.thoughtcrime.securesms.backup.BackupProtos.Header.class, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder.class);
- }
-
- public static com.google.protobuf.Parser PARSER =
- new com.google.protobuf.AbstractParser() {
- public Header parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new Header(input, extensionRegistry);
- }
- };
-
- @java.lang.Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- private int bitField0_;
- // optional bytes iv = 1;
- public static final int IV_FIELD_NUMBER = 1;
- private com.google.protobuf.ByteString iv_;
- /**
- *