diff --git a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java index 1ff0e0403..f7715fd6f 100644 --- a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java +++ b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.services; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Intent; import android.content.SharedPreferences; @@ -87,14 +88,32 @@ public class UnifiedPushBroker { if (transport.account.isEnabled()) { renewUnifiedEndpoint(transportOptional.get(), pushTargetMessenger); } else { + if (pushTargetMessenger.messenger != null) { + sendRegistrationDelayed(pushTargetMessenger.messenger,"account is disabled"); + } Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled"); } } else { + if (pushTargetMessenger.messenger != null) { + sendRegistrationDelayed(pushTargetMessenger.messenger,"no transport selected"); + } Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. No transport selected"); } return transportOptional; } + private void sendRegistrationDelayed(final Messenger messenger, final String error) { + final Intent intent = new Intent(UnifiedPushDistributor.ACTION_REGISTRATION_DELAYED); + intent.putExtra(UnifiedPushDistributor.EXTRA_MESSAGE, error); + final var message = new Message(); + message.obj = intent; + try { + messenger.send(message); + } catch (final RemoteException e) { + Log.d(Config.LOGTAG,"unable to tell messenger of delayed registration",e); + } + } + private void renewUnifiedEndpoint(final Transport transport, final PushTargetMessenger pushTargetMessenger) { final Account account = transport.account; final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service); @@ -346,11 +365,17 @@ public class UnifiedPushBroker { service.sendBroadcast(updateIntent); } - private static Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) { + private Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) { final Intent intent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT); intent.setPackage(endpoint.application); intent.putExtra("token", instance); intent.putExtra("endpoint", endpoint.endpoint); + final var distributorVerificationIntent = new Intent(); + distributorVerificationIntent.setPackage(service.getPackageName()); + final var pendingIntent = + PendingIntent.getBroadcast( + service, 0, distributorVerificationIntent, PendingIntent.FLAG_IMMUTABLE); + intent.putExtra("distributor", pendingIntent); return intent; } @@ -378,7 +403,7 @@ public class UnifiedPushBroker { public static class PushTargetMessenger { private final UnifiedPushDatabase.PushTarget pushTarget; - private final Messenger messenger; + public final Messenger messenger; public PushTargetMessenger(UnifiedPushDatabase.PushTarget pushTarget, Messenger messenger) { this.pushTarget = pushTarget; diff --git a/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java b/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java index a1b4c3e3c..4616cc622 100644 --- a/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java +++ b/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java @@ -6,8 +6,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Message; import android.os.Messenger; import android.os.Parcelable; +import android.os.RemoteException; import android.util.Log; import com.google.common.base.Charsets; @@ -33,10 +35,17 @@ public class UnifiedPushDistributor extends BroadcastReceiver { "org.unifiedpush.android.distributor.feature.BYTES_MESSAGE"; public static final String ACTION_REGISTRATION_FAILED = "org.unifiedpush.android.connector.REGISTRATION_FAILED"; + + // this action is only used in 'messenger' communication to tell the app that a registration is + // probably fine but can not be processed right now; for example due to spotty internet + public static final String ACTION_REGISTRATION_DELAYED = + "org.unifiedpush.android.connector.REGISTRATION_DELAYED"; public static final String ACTION_MESSAGE = "org.unifiedpush.android.connector.MESSAGE"; public static final String ACTION_NEW_ENDPOINT = "org.unifiedpush.android.connector.NEW_ENDPOINT"; + public static final String EXTRA_MESSAGE = "message"; + public static final String PREFERENCE_ACCOUNT = "up_push_account"; public static final String PREFERENCE_PUSH_SERVER = "up_push_server"; @@ -50,9 +59,8 @@ public class UnifiedPushDistributor extends BroadcastReceiver { } final String action = intent.getAction(); final String application; - final Parcelable appByPendingIntent = intent.getParcelableExtra("app"); - if (appByPendingIntent instanceof PendingIntent) { - final PendingIntent pendingIntent = (PendingIntent) appByPendingIntent; + final Parcelable appVerification = intent.getParcelableExtra("app"); + if (appVerification instanceof PendingIntent pendingIntent) { application = pendingIntent.getIntentSender().getCreatorPackage(); Log.d(Config.LOGTAG,"received application name via pending intent "+ application); } else { @@ -62,18 +70,12 @@ public class UnifiedPushDistributor extends BroadcastReceiver { final String instance = intent.getStringExtra("token"); final List features = intent.getStringArrayListExtra("features"); switch (Strings.nullToEmpty(action)) { - case ACTION_REGISTER: - register(context, application, instance, features, messenger); - break; - case ACTION_UNREGISTER: - unregister(context, instance); - break; - case Intent.ACTION_PACKAGE_FULLY_REMOVED: - unregisterApplication(context, intent.getData()); - break; - default: - Log.d(Config.LOGTAG, "UnifiedPushDistributor received unknown action " + action); - break; + case ACTION_REGISTER -> register(context, application, instance, features, messenger); + case ACTION_UNREGISTER -> unregister(context, instance); + case Intent.ACTION_PACKAGE_FULLY_REMOVED -> + unregisterApplication(context, intent.getData()); + default -> + Log.d(Config.LOGTAG, "UnifiedPushDistributor received unknown action " + action); } } @@ -114,11 +116,25 @@ public class UnifiedPushDistributor extends BroadcastReceiver { } else { Log.d(Config.LOGTAG, "not successful. sending error message back to application"); final Intent registrationFailed = new Intent(ACTION_REGISTRATION_FAILED); + registrationFailed.putExtra(EXTRA_MESSAGE, "instance already exits"); registrationFailed.setPackage(application); registrationFailed.putExtra("token", instance); - context.sendBroadcast(registrationFailed); + if (messenger instanceof Messenger m) { + final var message = new Message(); + message.obj = registrationFailed; + try { + m.send(message); + } catch (final RemoteException e) { + context.sendBroadcast(registrationFailed); + } + } else { + context.sendBroadcast(registrationFailed); + } } } else { + if (messenger instanceof Messenger m) { + sendRegistrationFailed(m,"Your application is not registered to receive messages"); + } Log.d( Config.LOGTAG, "ignoring invalid UnifiedPush registration. Unknown application " @@ -126,6 +142,18 @@ public class UnifiedPushDistributor extends BroadcastReceiver { } } + private void sendRegistrationFailed(final Messenger messenger, final String error) { + final Intent intent = new Intent(ACTION_REGISTRATION_FAILED); + intent.putExtra(EXTRA_MESSAGE, error); + final var message = new Message(); + message.obj = intent; + try { + messenger.send(message); + } catch (final RemoteException e) { + Log.d(Config.LOGTAG,"unable to tell messenger of failed registration",e); + } + } + private List getBroadcastReceivers(final Context context, final String application) { final Intent messageIntent = new Intent(ACTION_MESSAGE); messageIntent.setPackage(application);