Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Properly restart IncomingMessageObserver Foreground Service
Browse files Browse the repository at this point in the history
If needed : when switching notification method or when
UnifiedPush status changes.
Always use UnifiedPushRefreshJob to update UP related
component and to register to MollySocket.
  • Loading branch information
p1gp1g committed Nov 8, 2023
1 parent ded4b5e commit f8cb2a3
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -468,16 +468,19 @@ private void initializeNetworkSettings() {
}
}

// MOLLY: this initialize FCM, websocket and UnifiedPush
public void initializeFcmCheck() {
if (!SignalStore.account().isRegistered()) {
return;
}

PlayServicesUtil.PlayServicesStatus fcmStatus = PlayServicesUtil.getPlayServicesStatus(this);
boolean unifiedPushAvailable = UnifiedPushHelper.isUnifiedPushAvailable();
boolean forceWebSocket = SignalStore.internalValues().isWebsocketModeForced();

if (UnifiedPushHelper.isUnifiedPushAvailable()
if (unifiedPushAvailable || forceWebSocket
|| fcmStatus == PlayServicesUtil.PlayServicesStatus.DISABLED) {
if (!SignalStore.unifiedpush().getAirGaped()) {
if (unifiedPushAvailable && !SignalStore.unifiedpush().getAirGaped()) {
ApplicationDependencies.getJobManager().add(new UnifiedPushRefreshJob());
}
ApplicationDependencies.getJobManager().cancel(new FcmRefreshJob().getId());
Expand All @@ -495,12 +498,10 @@ public void initializeFcmCheck() {
SignalStore.account().getFcmTokenLastSetTime() < 0) {
Log.i(TAG, "Play Services are newly-available. Updating to use FCM.");
SignalStore.account().setFcmEnabled(true);
ApplicationDependencies.getJobManager().cancel(new UnifiedPushRefreshJob().getId());
ApplicationDependencies.getJobManager().startChain(new FcmRefreshJob())
.then(new RefreshAttributesJob())
.enqueue();
} else {
ApplicationDependencies.getJobManager().cancel(new UnifiedPushRefreshJob().getId());
long nextSetTime = SignalStore.account().getFcmTokenLastSetTime() + TimeUnit.HOURS.toMillis(6);

if (SignalStore.account().getFcmToken() == null || nextSetTime <= System.currentTimeMillis()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.os.Build
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import im.molly.unifiedpush.jobs.UnifiedPushRefreshJob

import im.molly.unifiedpush.util.UnifiedPushHelper
import org.signal.core.util.concurrent.SignalExecutors
Expand Down Expand Up @@ -111,23 +112,24 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer

fun setNotificationDeliveryMethod(method: NotificationDeliveryMethod) {
SignalStore.settings().notificationDeliveryMethod = method
SignalStore.unifiedpush().enabled = method == NotificationDeliveryMethod.UNIFIEDPUSH
SignalStore.internalValues().isWebsocketModeForced = method == NotificationDeliveryMethod.WEBSOCKET
val context = ApplicationContext.getInstance()
if (method == NotificationDeliveryMethod.UNIFIEDPUSH) {
SignalStore.unifiedpush().pending = true
UnifiedPush.getDistributors(context).getOrNull(0)?.let {
refresh()
EXECUTOR.enqueue {
UnifiedPush.saveDistributor(context, it)
UnifiedPush.registerApp(context)
UnifiedPushHelper.initializeMollySocketLinkedDevice(context)
ApplicationDependencies.getJobManager().add(UnifiedPushRefreshJob())
}
// Do not enable if there is no distributor
} ?: return
} else {
UnifiedPush.unregisterApp(context)
SignalStore.unifiedpush().airGaped = false
SignalStore.unifiedpush().mollySocketUrl = null
ApplicationDependencies.getJobManager().add(UnifiedPushRefreshJob())
}
refresh()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import im.molly.unifiedpush.events.UnifiedPushRegistrationEvent
import im.molly.unifiedpush.jobs.UnifiedPushRefreshJob
import im.molly.unifiedpush.model.UnifiedPushStatus
import im.molly.unifiedpush.model.saveStatus
import im.molly.unifiedpush.util.MollySocketRequest
import org.greenrobot.eventbus.Subscribe
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor
import org.thoughtcrime.securesms.util.livedata.Store
Expand All @@ -29,8 +30,10 @@ class UnifiedPushSettingsViewModel(private val application: Application) : ViewM
val state: LiveData<UnifiedPushSettingsState> = store.stateLiveData

@Subscribe
fun onNewEndpoint(e: UnifiedPushRegistrationEvent) {
processNewStatus()
fun onStatusRefreshed(e: UnifiedPushRegistrationEvent) {
Log.d(TAG, "Received event to refresh.")
status = SignalStore.unifiedpush().status
store.update { getState() }
}

private fun getState(): UnifiedPushSettingsState {
Expand Down Expand Up @@ -104,40 +107,21 @@ class UnifiedPushSettingsViewModel(private val application: Application) : ViewM
} else {
url
}
processNewStatus()
EXECUTOR.enqueue {
SignalStore.unifiedpush().mollySocketFound = try {
MollySocketRequest.discoverMollySocketServer()
} catch (e: Exception) {
SignalStore.unifiedpush().mollySocketInternalError = true
false
}
processNewStatus()
}
}

private fun processNewStatus() {
status = SignalStore.unifiedpush().status
if (SignalStore.unifiedpush().status in listOf(
UnifiedPushStatus.OK,
UnifiedPushStatus.FORBIDDEN_UUID,
UnifiedPushStatus.INTERNAL_ERROR,
UnifiedPushStatus.SERVER_NOT_FOUND_AT_URL,
)
) {
Log.d(TAG, "Trying to register to MollySocket")
status = UnifiedPushStatus.PENDING
EXECUTOR.enqueue {
try {
if (MollySocketRequest.discoverMollySocketServer()) {
SignalStore.unifiedpush().mollySocketFound = true
MollySocketRequest.registerToMollySocketServer().saveStatus()
status = SignalStore.unifiedpush().status
} else {
SignalStore.unifiedpush().mollySocketFound = false
status = SignalStore.unifiedpush().status
}
} catch (e: Exception) {
SignalStore.unifiedpush().mollySocketFound = false
status = UnifiedPushStatus.INTERNAL_ERROR
}
store.update { getState() }
}
} else {
status = SignalStore.unifiedpush().status
}
SignalStore.unifiedpush().pending = true
store.update { getState() }
ApplicationDependencies.getJobManager().add(UnifiedPushRefreshJob())
}

class Factory(private val application: Application) : ViewModelProvider.Factory {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@

package im.molly.unifiedpush.jobs

import im.molly.unifiedpush.events.UnifiedPushRegistrationEvent
import im.molly.unifiedpush.model.RegistrationStatus
import im.molly.unifiedpush.model.UnifiedPushStatus
import im.molly.unifiedpush.model.saveStatus
import im.molly.unifiedpush.util.MollySocketRequest
import im.molly.unifiedpush.util.UnifiedPushHelper
import im.molly.unifiedpush.util.UnifiedPushNotificationBuilder
import org.greenrobot.eventbus.EventBus
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.jobs.BaseJob
import org.thoughtcrime.securesms.keyvalue.SettingsValues
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException
import java.util.concurrent.TimeUnit

/*
This job is called when :
- The delivery Method is called
- Delivery method == UnifiedPush and :
- The app starts
- one component related to UnifiedPush is changed
*/

class UnifiedPushRefreshJob private constructor(parameters: Parameters) : BaseJob(parameters) {
constructor() : this(
Parameters.Builder()
Expand All @@ -35,20 +47,75 @@ class UnifiedPushRefreshJob private constructor(parameters: Parameters) : BaseJo
@Throws(Exception::class)
public override fun onRun() {
Log.d(TAG, "Running the refresh job")

// If this job is called while changing the notification method
val currentMethod = SignalStore.settings().notificationDeliveryMethod
if (currentMethod == SettingsValues.NotificationDeliveryMethod.FCM
|| currentMethod == SettingsValues.NotificationDeliveryMethod.WEBSOCKET) {
Log.d(TAG, "New method: $currentMethod, reinitializing notification services.")
reInitializeNotificationServices()
return
}

// Else : we try to use UnifiedPush
UnifiedPushHelper.checkDistributorPresence(context)
if (UnifiedPushHelper.isUnifiedPushAvailable() && !SignalStore.unifiedpush().airGaped) {
Log.i(TAG, "Reregistering to MollySocket...")
when (val status = MollySocketRequest.registerToMollySocketServer()) {
RegistrationStatus.INTERNAL_ERROR -> Log.d(TAG, "An error occurred while trying to re-register with MollySocket. It may be a bad connection: ignore it.")
RegistrationStatus.OK -> Log.d(TAG, "Successfully re-registered to MollySocket")
else -> {
Log.w(TAG, "The registration status has changed!")
status.saveStatus()
ApplicationContext.getInstance().initializeFcmCheck()
UnifiedPushNotificationBuilder(context).setNotificationMollySocketRegistrationChanged()
when (val status = SignalStore.unifiedpush().status) {
// Should not occur
UnifiedPushStatus.DISABLED,
UnifiedPushStatus.UNKNOWN -> Log.e(TAG, "UnifiedPush setup should not be in this state here : $status.")
// It will fallback on FCM/Websocket
UnifiedPushStatus.MISSING_ENDPOINT,
UnifiedPushStatus.NO_DISTRIBUTOR,
UnifiedPushStatus.LINK_DEVICE_ERROR,
UnifiedPushStatus.SERVER_NOT_FOUND_AT_URL-> {
Log.i(TAG, "UnifiedPush enabled, but this is currently unavailable. Status=$status.")
reInitializeNotificationServices()
}
// Considered as successful setup
UnifiedPushStatus.AIR_GAPED -> {
Log.i(TAG, "UnifiedPush available in AirGaped mode. No MollySocket to register to.")
reInitializeNotificationServices()
}
// We try to register to MollySocket server,
// Then re-init the services
UnifiedPushStatus.PENDING,
UnifiedPushStatus.FORBIDDEN_UUID,
UnifiedPushStatus.FORBIDDEN_ENDPOINT,
UnifiedPushStatus.INTERNAL_ERROR -> {
Log.i(TAG, "Registering to MollySocket...")
SignalStore.unifiedpush().pending = false
val msStatus = MollySocketRequest.registerToMollySocketServer()
msStatus.saveStatus()
when (msStatus) {
RegistrationStatus.INTERNAL_ERROR -> Log.d(TAG, "An error occurred while trying to re-register with MollySocket.")
RegistrationStatus.OK -> {
Log.d(TAG, "Successfully re-registered to MollySocket")
reInitializeNotificationServices()
}
else -> Log.d(TAG, "Still not able to register to MollySocket: $msStatus.")
}
}
UnifiedPushStatus.OK -> {
Log.i(TAG, "Registering again to MollySocket...")
when (val msStatus = MollySocketRequest.registerToMollySocketServer()) {
RegistrationStatus.INTERNAL_ERROR -> Log.d(TAG, "An error occurred while trying to re-register with MollySocket. It may be a bad connection: ignore it.")
RegistrationStatus.OK -> Log.d(TAG, "Successfully re-registered to MollySocket")
else -> {
Log.w(TAG, "The registration status has changed!")
msStatus.saveStatus()
reInitializeNotificationServices()
UnifiedPushNotificationBuilder(context).setNotificationMollySocketRegistrationChanged()
}
}
}
}
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
}

private fun reInitializeNotificationServices() {
ApplicationContext.getInstance().finalizeMessageRetrieval()
ApplicationContext.getInstance().initializeFcmCheck()
ApplicationContext.getInstance().initializeMessageRetrieval()
}

override fun onFailure() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ package im.molly.unifiedpush.receiver
import android.content.Context
import androidx.core.os.bundleOf
import com.google.firebase.messaging.RemoteMessage
import im.molly.unifiedpush.events.UnifiedPushRegistrationEvent
import im.molly.unifiedpush.model.UnifiedPushStatus
import im.molly.unifiedpush.model.saveStatus
import im.molly.unifiedpush.util.MollySocketRequest
import im.molly.unifiedpush.jobs.UnifiedPushRefreshJob
import im.molly.unifiedpush.util.UnifiedPushHelper
import im.molly.unifiedpush.util.UnifiedPushNotificationBuilder
import org.greenrobot.eventbus.EventBus
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.gcm.FcmReceiveService
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor
Expand All @@ -25,32 +22,7 @@ class UnifiedPushReceiver : MessagingReceiver() {
Log.d(TAG, "New endpoint: $endpoint")
if (SignalStore.unifiedpush().endpoint != endpoint) {
SignalStore.unifiedpush().endpoint = endpoint
when (SignalStore.unifiedpush().status) {
UnifiedPushStatus.AIR_GAPED -> {
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
UnifiedPushNotificationBuilder(context).setNotificationEndpointChangedAirGaped()
}
UnifiedPushStatus.OK -> {
EXECUTOR.enqueue {
MollySocketRequest.registerToMollySocketServer().saveStatus()
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
if (SignalStore.unifiedpush().status != UnifiedPushStatus.OK)
UnifiedPushNotificationBuilder(context).setNotificationEndpointChangedError()
}
}
in listOf(
UnifiedPushStatus.INTERNAL_ERROR,
UnifiedPushStatus.MISSING_ENDPOINT,
) -> {
EXECUTOR.enqueue {
MollySocketRequest.registerToMollySocketServer().saveStatus()
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
}
}
else -> {
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
}
}
ApplicationDependencies.getJobManager().add(UnifiedPushRefreshJob())
}
}

Expand All @@ -63,7 +35,7 @@ class UnifiedPushReceiver : MessagingReceiver() {
// called when this application is unregistered from receiving push messages
// isPushAvailable becomes false => The websocket starts
SignalStore.unifiedpush().endpoint = null
EventBus.getDefault().post(UnifiedPushRegistrationEvent)
ApplicationDependencies.getJobManager().add(UnifiedPushRefreshJob())
}

override fun onMessage(context: Context, message: ByteArray, instance: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal class UnifiedPushValues(store: KeyValueStore) : SignalStoreValues(store
private const val MOLLYSOCKET_INTERNAL_ERROR = "unifiedpush.mollysocket.internal_error"
private const val UNIFIEDPUSH_ENDPOINT = "unifiedpush.endpoint"
private const val UNIFIEDPUSH_ENABLED = "unifiedpush.enabled"
private const val UNIFIEDPUSH_PENDING = "unifiedpush.pending"
private const val UNIFIEDPUSH_AIR_GAPED = "unifiedpush.air_gaped"
}

Expand Down Expand Up @@ -45,7 +46,7 @@ internal class UnifiedPushValues(store: KeyValueStore) : SignalStoreValues(store

var endpoint: String? by stringValue(UNIFIEDPUSH_ENDPOINT, null)

var enabled: Boolean by booleanValue(UNIFIEDPUSH_ENABLED, false)
var pending: Boolean by booleanValue(UNIFIEDPUSH_PENDING, false)

var airGaped: Boolean by booleanValue(UNIFIEDPUSH_AIR_GAPED, false)

Expand All @@ -61,12 +62,14 @@ internal class UnifiedPushValues(store: KeyValueStore) : SignalStoreValues(store

val status: UnifiedPushStatus
get() = when {
!SignalStore.unifiedpush().enabled -> UnifiedPushStatus.DISABLED
SignalStore.settings().notificationDeliveryMethod != SettingsValues.NotificationDeliveryMethod.UNIFIEDPUSH -> UnifiedPushStatus.DISABLED
SignalStore.unifiedpush().pending -> UnifiedPushStatus.PENDING
SignalStore.unifiedpush().device == null -> UnifiedPushStatus.LINK_DEVICE_ERROR
SignalStore.unifiedpush().endpoint == null -> UnifiedPushStatus.MISSING_ENDPOINT
SignalStore.unifiedpush().airGaped -> UnifiedPushStatus.AIR_GAPED
SignalStore.unifiedpush().mollySocketUrl.isNullOrBlank() ||
!SignalStore.unifiedpush().mollySocketFound -> UnifiedPushStatus.SERVER_NOT_FOUND_AT_URL
SignalStore.unifiedpush().mollySocketInternalError -> UnifiedPushStatus.INTERNAL_ERROR
SignalStore.unifiedpush().forbiddenUuid -> UnifiedPushStatus.FORBIDDEN_UUID
SignalStore.unifiedpush().forbiddenEndpoint -> UnifiedPushStatus.FORBIDDEN_ENDPOINT
else -> UnifiedPushStatus.OK
Expand Down

0 comments on commit f8cb2a3

Please sign in to comment.