diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml
index fef27a8305..bb58816d13 100644
--- a/res/layout/conversation_item_received.xml
+++ b/res/layout/conversation_item_received.xml
@@ -113,6 +113,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingTop="2dp"
+ android:paddingRight="4dp"
+ android:paddingEnd="4dp"
android:src="?menu_lock_icon_small"
android:contentDescription="@string/conversation_item__secure_message_description"
android:visibility="gone"
@@ -126,6 +128,19 @@
android:visibility="gone"/>
+
+
+ android:linksClickable="false"
+ android:visibility="gone"
+ tools:visibility="visible"
+ tools:text="from SIM1"/>
diff --git a/res/layout/conversation_item_sent.xml b/res/layout/conversation_item_sent.xml
index 9c8097a7dc..5cb9cf0065 100644
--- a/res/layout/conversation_item_sent.xml
+++ b/res/layout/conversation_item_sent.xml
@@ -125,6 +125,25 @@
android:paddingBottom="2dp"
tools:text="30 mins" />
+
+
+
-
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a43d874bd9..7c43d814fb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -100,6 +100,8 @@
Fallback to unencrypted MMS?
This message will not be encrypted because the recipient is no longer a Signal user.\n\nSend unsecured message?
Can\'t find an app able to open this media.
+ from %s
+ to %s
Reset secure session?
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index bfdb3a65be..1f473a117c 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -535,7 +535,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
final Context context = getApplicationContext();
OutgoingEndSessionMessage endSessionMessage =
- new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE"));
+ new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE", -1));
new AsyncTask() {
@Override
@@ -823,22 +823,43 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void onSecurityUpdated() {
- updateInviteReminder();
+ updateRecipientPreferences();
}
- protected void updateInviteReminder() {
- if (TextSecurePreferences.isPushRegistered(this) &&
- !isSecureText &&
- recipients.isSingleRecipient() &&
- recipients.getPrimaryRecipient() != null &&
+ private void updateRecipientPreferences() {
+ if (recipients.getPrimaryRecipient() != null &&
recipients.getPrimaryRecipient().getContactUri() != null)
{
- new ShowInviteReminderTask().execute(recipients);
+ new RecipientPreferencesTask().execute(recipients);
+ }
+ }
+
+ protected void updateInviteReminder(boolean seenInvite) {
+ Log.w(TAG, "updateInviteReminder(" + seenInvite+")");
+ if (TextSecurePreferences.isPushRegistered(this) &&
+ !isSecureText &&
+ !seenInvite &&
+ recipients.isSingleRecipient())
+ {
+ InviteReminder reminder = new InviteReminder(this, recipients);
+ reminder.setOkListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ handleInviteLink();
+ reminderView.requestDismiss();
+ }
+ });
+ reminderView.showReminder(reminder);
} else {
reminderView.hide();
}
}
+ private void updateDefaultSubscriptionId(Optional defaultSubscriptionId) {
+ Log.w(TAG, "updateDefaultSubscriptionId(" + defaultSubscriptionId.orNull() + ")");
+ sendButton.setDefaultSubscriptionId(defaultSubscriptionId);
+ }
+
private void initializeMmsEnabledCheck() {
new AsyncTask() {
@Override
@@ -896,11 +917,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
sendButton.setEnabled(true);
sendButton.addOnTransportChangedListener(new OnTransportChangedListener() {
@Override
- public void onChange(TransportOption newTransport) {
+ public void onChange(TransportOption newTransport, boolean manuallySelected) {
calculateCharactersRemaining();
composeText.setTransport(newTransport);
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), Mode.MULTIPLY);
buttonToggle.getBackground().invalidateSelf();
+ if (manuallySelected) recordSubscriptionIdPreference(newTransport.getSimSubscriptionId());
}
});
@@ -968,7 +990,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
titleView.setTitle(recipients);
setBlockedUserState(recipients);
setActionBarColor(recipients.getColor());
- updateInviteReminder();
+ updateRecipientPreferences();
}
});
}
@@ -1242,8 +1264,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void sendMessage() {
try {
- Recipients recipients = getRecipients();
- boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
+ Recipients recipients = getRecipients();
+ boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
+ int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
Log.w(TAG, "isManual Selection: " + sendButton.isManualSelection());
Log.w(TAG, "forceSms: " + forceSms);
@@ -1255,9 +1278,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
handleManualMmsRequired();
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
- sendMediaMessage(forceSms);
+ sendMediaMessage(forceSms, subscriptionId);
} else {
- sendTextMessage(forceSms);
+ sendTextMessage(forceSms, subscriptionId);
}
} catch (RecipientFormattingException ex) {
Toast.makeText(ConversationActivity.this,
@@ -1271,13 +1294,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
- private void sendMediaMessage(final boolean forceSms)
+ private void sendMediaMessage(final boolean forceSms, final int subscriptionId)
throws InvalidMessageException
{
- sendMediaMessage(forceSms, getMessage(), attachmentManager.buildSlideDeck());
+ sendMediaMessage(forceSms, getMessage(), attachmentManager.buildSlideDeck(), subscriptionId);
}
- private ListenableFuture sendMediaMessage(final boolean forceSms, String body, SlideDeck slideDeck)
+ private ListenableFuture sendMediaMessage(final boolean forceSms, String body, SlideDeck slideDeck, final int subscriptionId)
throws InvalidMessageException
{
final SettableFuture future = new SettableFuture<>();
@@ -1286,6 +1309,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
slideDeck,
body,
System.currentTimeMillis(),
+ subscriptionId,
distributionType);
if (isSecureText && !forceSms) {
@@ -1311,7 +1335,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return future;
}
- private void sendTextMessage(final boolean forceSms)
+ private void sendTextMessage(final boolean forceSms, final int subscriptionId)
throws InvalidMessageException
{
final Context context = getApplicationContext();
@@ -1320,7 +1344,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (isSecureText && !forceSms) {
message = new OutgoingEncryptedMessage(recipients, getMessage());
} else {
- message = new OutgoingTextMessage(recipients, getMessage());
+ message = new OutgoingTextMessage(recipients, getMessage(), subscriptionId);
}
this.composeText.setText("");
@@ -1348,6 +1372,17 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
+ private void recordSubscriptionIdPreference(final Optional subscriptionId) {
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
+ .setDefaultSubscriptionId(recipients, subscriptionId.or(-1));
+ return null;
+ }
+ }.execute();
+ }
+
@Override
public void onAttachmentDrawerStateChanged(DrawerState drawerState) {
if (drawerState == DrawerState.FULL_EXPANDED) {
@@ -1398,12 +1433,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onSuccess(final @NonNull Pair result) {
try {
- boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
- AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, ContentType.AUDIO_AAC);
- SlideDeck slideDeck = new SlideDeck();
+ boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
+ int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
+ AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, ContentType.AUDIO_AAC);
+ SlideDeck slideDeck = new SlideDeck();
slideDeck.addSlide(audioSlide);
- sendMediaMessage(forceSms, "", slideDeck).addListener(new AssertedSuccessListener() {
+ sendMediaMessage(forceSms, "", slideDeck, subscriptionId).addListener(new AssertedSuccessListener() {
@Override
public void onSuccess(Void nothing) {
new AsyncTask() {
@@ -1568,30 +1604,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
updateToggleButtonState();
}
- private class ShowInviteReminderTask extends AsyncTask> {
+ private class RecipientPreferencesTask extends AsyncTask> {
@Override
- protected Pair doInBackground(Recipients... recipients) {
- if (recipients.length != 1 || recipients[0] == null) throw new AssertionError("task needs exactly one Recipients object");
+ protected Pair doInBackground(Recipients... recipients) {
+ if (recipients.length != 1 || recipients[0] == null) {
+ throw new AssertionError("task needs exactly one Recipients object");
+ }
Optional prefs = DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
.getRecipientsPreferences(recipients[0].getIds());
- return new Pair<>(recipients[0], prefs.isPresent() && prefs.get().hasSeenInviteReminder());
+ return new Pair<>(recipients[0], prefs.orNull());
}
@Override
- protected void onPostExecute(Pair result) {
- if (!result.second && result.first == recipients) {
- InviteReminder reminder = new InviteReminder(ConversationActivity.this, result.first);
- reminder.setOkListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleInviteLink();
- reminderView.requestDismiss();
- }
- });
- reminderView.showReminder(reminder);
- } else {
- reminderView.hide();
+ protected void onPostExecute(@NonNull Pair result) {
+ if (result.first == recipients) {
+ updateInviteReminder(result.second != null && result.second.hasSeenInviteReminder());
+ updateDefaultSubscriptionId(result.second != null ? result.second.getDefaultSubscriptionId() : Optional.absent());
}
}
}
diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java
index 08debe8c95..5186263b9c 100644
--- a/src/org/thoughtcrime/securesms/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationItem.java
@@ -65,6 +65,9 @@ import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
+import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
+import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.HashSet;
import java.util.List;
@@ -93,6 +96,7 @@ public class ConversationItem extends LinearLayout
private View bodyBubble;
private TextView bodyText;
private TextView dateText;
+ private TextView simInfoText;
private TextView indicatorText;
private TextView groupStatusText;
private ImageView secureImage;
@@ -135,6 +139,7 @@ public class ConversationItem extends LinearLayout
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
+ this.simInfoText = (TextView) findViewById(R.id.sim_info);
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
@@ -188,6 +193,7 @@ public class ConversationItem extends LinearLayout
setGroupMessageStatus(messageRecord, recipient);
setMinimumWidth();
setMediaAttributes(messageRecord);
+ setSimInfo(messageRecord);
}
private void initializeAttributes() {
@@ -327,6 +333,25 @@ public class ConversationItem extends LinearLayout
}
}
+ private void setSimInfo(MessageRecord messageRecord) {
+ if (messageRecord.getSubscriptionId() == -1) {
+ simInfoText.setVisibility(View.GONE);
+ } else {
+ SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
+ Optional subscriptionInfo = subscriptionManager.getActiveSubscriptionInfo(messageRecord.getSubscriptionId());
+
+ if (subscriptionInfo.isPresent() && messageRecord.isOutgoing()) {
+ simInfoText.setText(getContext().getString(R.string.ConversationItem_from_s, subscriptionInfo.get().getDisplayName()));
+ simInfoText.setVisibility(View.VISIBLE);
+ } else if (subscriptionInfo.isPresent()) {
+ simInfoText.setText(getContext().getString(R.string.ConversationItem_to_s, subscriptionInfo.get().getDisplayName()));
+ simInfoText.setVisibility(View.VISIBLE);
+ } else {
+ simInfoText.setVisibility(View.GONE);
+ }
+ }
+ }
+
private void setFailedStatusIcons() {
alertView.setFailed();
deliveryStatusIndicator.setNone();
diff --git a/src/org/thoughtcrime/securesms/ConversationPopupActivity.java b/src/org/thoughtcrime/securesms/ConversationPopupActivity.java
index 3c34b85f7a..e0ba797db6 100644
--- a/src/org/thoughtcrime/securesms/ConversationPopupActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationPopupActivity.java
@@ -121,7 +121,7 @@ public class ConversationPopupActivity extends ConversationActivity {
}
@Override
- protected void updateInviteReminder() {
+ protected void updateInviteReminder(boolean seenInvite) {
reminderView.setVisibility(View.GONE);
}
}
diff --git a/src/org/thoughtcrime/securesms/InviteActivity.java b/src/org/thoughtcrime/securesms/InviteActivity.java
index bf3b79754a..b16c73c749 100644
--- a/src/org/thoughtcrime/securesms/InviteActivity.java
+++ b/src/org/thoughtcrime/securesms/InviteActivity.java
@@ -28,13 +28,15 @@ import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
-import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture.Listener;
+import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.concurrent.ExecutionException;
@@ -227,9 +229,14 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
if (context == null) return null;
for (String number : numbers) {
- final Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
- if (recipients != null && recipients.getPrimaryRecipient() != null) {
- MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message), -1L, true);
+ Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
+
+ if (recipients.getPrimaryRecipient() != null) {
+ Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipients.getIds());
+ int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
+
+ MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message, subscriptionId), -1L, true);
+
if (recipients.getPrimaryRecipient().getContactUri() != null) {
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipients, true);
}
diff --git a/src/org/thoughtcrime/securesms/TransportOption.java b/src/org/thoughtcrime/securesms/TransportOption.java
index 875f1114ad..7d91d1c04a 100644
--- a/src/org/thoughtcrime/securesms/TransportOption.java
+++ b/src/org/thoughtcrime/securesms/TransportOption.java
@@ -1,9 +1,11 @@
package org.thoughtcrime.securesms;
import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.util.CharacterCalculator;
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
+import org.whispersystems.libaxolotl.util.guava.Optional;
public class TransportOption {
@@ -12,19 +14,34 @@ public class TransportOption {
TEXTSECURE
}
- private int drawable;
- private int backgroundColor;
- private String text;
- private Type type;
- private String composeHint;
- private CharacterCalculator characterCalculator;
+ private final int drawable;
+ private final int backgroundColor;
+ private final @NonNull String text;
+ private final @NonNull Type type;
+ private final @NonNull String composeHint;
+ private final @NonNull CharacterCalculator characterCalculator;
+ private final @NonNull Optional simName;
+ private final @NonNull Optional simSubscriptionId;
- public TransportOption(Type type,
+ public TransportOption(@NonNull Type type,
@DrawableRes int drawable,
int backgroundColor,
- String text,
- String composeHint,
- CharacterCalculator characterCalculator)
+ @NonNull String text,
+ @NonNull String composeHint,
+ @NonNull CharacterCalculator characterCalculator)
+ {
+ this(type, drawable, backgroundColor, text, composeHint, characterCalculator,
+ Optional.absent(), Optional.absent());
+ }
+
+ public TransportOption(@NonNull Type type,
+ @DrawableRes int drawable,
+ int backgroundColor,
+ @NonNull String text,
+ @NonNull String composeHint,
+ @NonNull CharacterCalculator characterCalculator,
+ @NonNull Optional simName,
+ @NonNull Optional simSubscriptionId)
{
this.type = type;
this.drawable = drawable;
@@ -32,9 +49,12 @@ public class TransportOption {
this.text = text;
this.composeHint = composeHint;
this.characterCalculator = characterCalculator;
+ this.simName = simName;
+ this.simSubscriptionId = simSubscriptionId;
}
- public Type getType() {
+
+ public @NonNull Type getType() {
return type;
}
@@ -58,11 +78,22 @@ public class TransportOption {
return backgroundColor;
}
- public String getComposeHint() {
+ public @NonNull String getComposeHint() {
return composeHint;
}
- public String getDescription() {
+ public @NonNull String getDescription() {
return text;
}
+
+ @NonNull
+ public Optional getSimName() {
+ return simName;
+ }
+
+ @NonNull
+ public Optional getSimSubscriptionId() {
+ return simSubscriptionId;
+ }
+
}
diff --git a/src/org/thoughtcrime/securesms/TransportOptions.java b/src/org/thoughtcrime/securesms/TransportOptions.java
index c78d3986e7..ccbc66143c 100644
--- a/src/org/thoughtcrime/securesms/TransportOptions.java
+++ b/src/org/thoughtcrime/securesms/TransportOptions.java
@@ -1,10 +1,15 @@
package org.thoughtcrime.securesms;
import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import org.thoughtcrime.securesms.util.CharacterCalculator;
import org.thoughtcrime.securesms.util.MmsCharacterCalculator;
import org.thoughtcrime.securesms.util.PushCharacterCalculator;
import org.thoughtcrime.securesms.util.SmsCharacterCalculator;
+import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
+import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.LinkedList;
@@ -20,49 +25,76 @@ public class TransportOptions {
private final Context context;
private final List enabledTransports;
- private Type selectedType;
- private boolean manuallySelected;
+ private Type defaultTransportType = Type.SMS;
+ private Optional defaultSubscriptionId = Optional.absent();
+ private Optional selectedOption = Optional.absent();
public TransportOptions(Context context, boolean media) {
this.context = context;
this.enabledTransports = initializeAvailableTransports(media);
-
- setDefaultTransport(Type.SMS);
}
public void reset(boolean media) {
List transportOptions = initializeAvailableTransports(media);
+
this.enabledTransports.clear();
this.enabledTransports.addAll(transportOptions);
- if (!find(selectedType).isPresent()) {
- this.manuallySelected = false;
- setTransport(Type.SMS);
+ if (selectedOption.isPresent() && !isEnabled(selectedOption.get())) {
+ setSelectedTransport(null);
} else {
+ this.defaultTransportType = Type.SMS;
+ this.defaultSubscriptionId = Optional.absent();
+
notifyTransportChangeListeners();
}
}
public void setDefaultTransport(Type type) {
- if (!this.manuallySelected) {
- setTransport(type);
+ this.defaultTransportType = type;
+
+ if (!selectedOption.isPresent()) {
+ notifyTransportChangeListeners();
}
}
- public void setSelectedTransport(Type type) {
- this.manuallySelected= true;
- setTransport(type);
+ public void setDefaultSubscriptionId(Optional subscriptionId) {
+ this.defaultSubscriptionId = subscriptionId;
+
+ if (!selectedOption.isPresent()) {
+ notifyTransportChangeListeners();
+ }
+ }
+
+ public void setSelectedTransport(@Nullable TransportOption transportOption) {
+ this.selectedOption = Optional.fromNullable(transportOption);
+ notifyTransportChangeListeners();
}
public boolean isManualSelection() {
- return manuallySelected;
+ return this.selectedOption.isPresent();
}
- public TransportOption getSelectedTransport() {
- Optional option = find(selectedType);
+ public @NonNull TransportOption getSelectedTransport() {
+ if (selectedOption.isPresent()) return selectedOption.get();
- if (option.isPresent()) return option.get();
- else throw new AssertionError("Selected type isn't present!");
+ if (defaultSubscriptionId.isPresent()) {
+ for (TransportOption transportOption : enabledTransports) {
+ if (transportOption.getType() == defaultTransportType &&
+ (int)defaultSubscriptionId.get() == transportOption.getSimSubscriptionId().or(-1))
+ {
+ return transportOption;
+ }
+ }
+ }
+
+ for (TransportOption transportOption : enabledTransports) {
+ if (transportOption.getType() == defaultTransportType) {
+ return transportOption;
+ }
+ }
+
+ throw new AssertionError("No options of default type!");
}
public void disableTransport(Type type) {
@@ -71,8 +103,8 @@ public class TransportOptions {
if (option.isPresent()) {
enabledTransports.remove(option.get());
- if (manuallySelected && type == selectedType) {
- manuallySelected = false;
+ if (selectedOption.isPresent() && selectedOption.get().getType() == type) {
+ setSelectedTransport(null);
}
}
}
@@ -89,17 +121,13 @@ public class TransportOptions {
List results = new LinkedList<>();
if (isMediaMessage) {
- results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
- context.getResources().getColor(R.color.grey_600),
- context.getString(R.string.ConversationActivity_transport_insecure_mms),
- context.getString(R.string.conversation_activity__type_message_mms_insecure),
- new MmsCharacterCalculator()));
+ results.addAll(getTransportOptionsForSimCards(context.getString(R.string.ConversationActivity_transport_insecure_mms),
+ context.getString(R.string.conversation_activity__type_message_mms_insecure),
+ new MmsCharacterCalculator()));
} else {
- results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
- context.getResources().getColor(R.color.grey_600),
- context.getString(R.string.ConversationActivity_transport_insecure_sms),
- context.getString(R.string.conversation_activity__type_message_sms_insecure),
- new SmsCharacterCalculator()));
+ results.addAll(getTransportOptionsForSimCards(context.getString(R.string.ConversationActivity_transport_insecure_sms),
+ context.getString(R.string.conversation_activity__type_message_sms_insecure),
+ new SmsCharacterCalculator()));
}
results.add(new TransportOption(Type.TEXTSECURE, R.drawable.ic_send_push_white_24dp,
@@ -111,16 +139,34 @@ public class TransportOptions {
return results;
}
+ private @NonNull List getTransportOptionsForSimCards(@NonNull String text,
+ @NonNull String composeHint,
+ @NonNull CharacterCalculator characterCalculator)
+ {
+ List results = new LinkedList<>();
+ SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
+ List subscriptions = subscriptionManager.getActiveSubscriptionInfoList();
- private void setTransport(Type type) {
- this.selectedType = type;
+ if (subscriptions.size() < 2) {
+ results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
+ context.getResources().getColor(R.color.grey_600),
+ text, composeHint, characterCalculator));
+ } else {
+ for (SubscriptionInfoCompat subscriptionInfo : subscriptions) {
+ results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
+ context.getResources().getColor(R.color.grey_600),
+ text, composeHint, characterCalculator,
+ Optional.of(subscriptionInfo.getDisplayName()),
+ Optional.of(subscriptionInfo.getSubscriptionId())));
+ }
+ }
- notifyTransportChangeListeners();
+ return results;
}
private void notifyTransportChangeListeners() {
for (OnTransportChangedListener listener : listeners) {
- listener.onChange(getSelectedTransport());
+ listener.onChange(getSelectedTransport(), selectedOption.isPresent());
}
}
@@ -134,7 +180,15 @@ public class TransportOptions {
return Optional.absent();
}
+ private boolean isEnabled(TransportOption transportOption) {
+ for (TransportOption option : enabledTransports) {
+ if (option.equals(transportOption)) return true;
+ }
+
+ return false;
+ }
+
public interface OnTransportChangedListener {
- public void onChange(TransportOption newTransport);
+ public void onChange(TransportOption newTransport, boolean manuallySelected);
}
}
diff --git a/src/org/thoughtcrime/securesms/TransportOptionsAdapter.java b/src/org/thoughtcrime/securesms/TransportOptionsAdapter.java
index 72d10a1f28..e301eb804f 100644
--- a/src/org/thoughtcrime/securesms/TransportOptionsAdapter.java
+++ b/src/org/thoughtcrime/securesms/TransportOptionsAdapter.java
@@ -10,6 +10,8 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+import org.thoughtcrime.securesms.util.ViewUtil;
+
import java.util.List;
public class TransportOptionsAdapter extends BaseAdapter {
@@ -51,14 +53,22 @@ public class TransportOptionsAdapter extends BaseAdapter {
convertView = inflater.inflate(R.layout.transport_selection_list_item, parent, false);
}
- TransportOption transport = (TransportOption) getItem(position);
- ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
- TextView textView = (TextView) convertView.findViewById(R.id.text);
+ TransportOption transport = (TransportOption) getItem(position);
+ ImageView imageView = ViewUtil.findById(convertView, R.id.icon);
+ TextView textView = ViewUtil.findById(convertView, R.id.text);
+ TextView subtextView = ViewUtil.findById(convertView, R.id.subtext);
imageView.getBackground().setColorFilter(transport.getBackgroundColor(), Mode.MULTIPLY);
imageView.setImageResource(transport.getDrawable());
textView.setText(transport.getDescription());
+ if (transport.getSimName().isPresent()) {
+ subtextView.setText(transport.getSimName().get());
+ subtextView.setVisibility(View.VISIBLE);
+ } else {
+ subtextView.setVisibility(View.GONE);
+ }
+
return convertView;
}
}
diff --git a/src/org/thoughtcrime/securesms/components/ComposeText.java b/src/org/thoughtcrime/securesms/components/ComposeText.java
index ae9b85d175..4ae48d64d9 100644
--- a/src/org/thoughtcrime/securesms/components/ComposeText.java
+++ b/src/org/thoughtcrime/securesms/components/ComposeText.java
@@ -3,9 +3,11 @@ package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.res.Configuration;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.text.InputType;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.text.style.RelativeSizeSpan;
@@ -17,7 +19,9 @@ import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class ComposeText extends EmojiEditText {
+
private SpannableString hint;
+ private SpannableString subHint;
public ComposeText(Context context) {
super(context);
@@ -31,10 +35,18 @@ public class ComposeText extends EmojiEditText {
super(context, attrs, defStyleAttr);
}
- @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+
if (!TextUtils.isEmpty(hint)) {
- setHint(ellipsizeToWidth(hint));
+ if (!TextUtils.isEmpty(subHint)) {
+ setHint(new SpannableStringBuilder().append(ellipsizeToWidth(hint))
+ .append("\n")
+ .append(ellipsizeToWidth(subHint)));
+ } else {
+ setHint(ellipsizeToWidth(hint));
+ }
}
}
@@ -45,10 +57,24 @@ public class ComposeText extends EmojiEditText {
TruncateAt.END);
}
- public void setHint(@NonNull String hint) {
+ public void setHint(@NonNull String hint, @Nullable CharSequence subHint) {
this.hint = new SpannableString(hint);
this.hint.setSpan(new RelativeSizeSpan(0.8f), 0, hint.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- super.setHint(ellipsizeToWidth(this.hint));
+
+ if (subHint != null) {
+ this.subHint = new SpannableString(subHint);
+ this.subHint.setSpan(new RelativeSizeSpan(0.8f), 0, subHint.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ } else {
+ this.subHint = null;
+ }
+
+ if (this.subHint != null) {
+ super.setHint(new SpannableStringBuilder().append(ellipsizeToWidth(this.hint))
+ .append("\n")
+ .append(ellipsizeToWidth(this.subHint)));
+ } else {
+ super.setHint(ellipsizeToWidth(this.hint));
+ }
}
public void appendInvite(String invite) {
@@ -88,6 +114,6 @@ public class ComposeText extends EmojiEditText {
setInputType(inputType);
setImeOptions(imeOptions);
- setHint(transport.getComposeHint());
+ setHint(transport.getComposeHint(), transport.getSimName().isPresent() ? "From " + transport.getSimName().get() : null);
}
}
diff --git a/src/org/thoughtcrime/securesms/components/SendButton.java b/src/org/thoughtcrime/securesms/components/SendButton.java
index e139ec18ae..f0e6d4e72e 100644
--- a/src/org/thoughtcrime/securesms/components/SendButton.java
+++ b/src/org/thoughtcrime/securesms/components/SendButton.java
@@ -83,14 +83,18 @@ public class SendButton extends ImageButton
transportOptions.setDefaultTransport(type);
}
+ public void setDefaultSubscriptionId(Optional subscriptionId) {
+ transportOptions.setDefaultSubscriptionId(subscriptionId);
+ }
+
@Override
public void onSelected(TransportOption option) {
- transportOptions.setSelectedTransport(option.getType());
+ transportOptions.setSelectedTransport(option);
getTransportOptionsPopup().dismiss();
}
@Override
- public void onChange(TransportOption newTransport) {
+ public void onChange(TransportOption newTransport, boolean isManualSelection) {
setImageResource(newTransport.getDrawable());
setContentDescription(newTransport.getDescription());
}
diff --git a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
index d3ac714a47..8329150e4e 100644
--- a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
+++ b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java
@@ -71,7 +71,8 @@ public class DatabaseFactory {
private static final int INTRODUCED_ARCHIVE_VERSION = 24;
private static final int INTRODUCED_CONVERSATION_LIST_STATUS_VERSION = 25;
private static final int MIGRATED_CONVERSATION_LIST_STATUS_VERSION = 26;
- private static final int DATABASE_VERSION = 26;
+ private static final int INTRODUCED_SUBSCRIPTION_ID_VERSION = 27;
+ private static final int DATABASE_VERSION = 27;
private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object();
@@ -813,6 +814,12 @@ public class DatabaseFactory {
}
}
+ if (oldVersion < INTRODUCED_SUBSCRIPTION_ID_VERSION) {
+ db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN default_subscription_id INTEGER DEFAULT -1");
+ db.execSQL("ALTER TABLE sms ADD COLUMN subscription_id INTEGER DEFAULT -1");
+ db.execSQL("ALTER TABLE mms ADD COLUMN subscription_id INTEGER DEFAULT -1");
+ }
+
db.setTransactionSuccessful();
db.endTransaction();
}
diff --git a/src/org/thoughtcrime/securesms/database/EncryptingSmsDatabase.java b/src/org/thoughtcrime/securesms/database/EncryptingSmsDatabase.java
index 0d8acec5c2..9109db04fa 100644
--- a/src/org/thoughtcrime/securesms/database/EncryptingSmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/EncryptingSmsDatabase.java
@@ -20,27 +20,24 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
+import org.thoughtcrime.securesms.crypto.MasterCipher;
+import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
-import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.model.DisplayRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.LRUCache;
import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.thoughtcrime.securesms.crypto.MasterCipher;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import java.lang.ref.SoftReference;
import java.util.Collections;
-import java.util.List;
import java.util.Map;
public class EncryptingSmsDatabase extends SmsDatabase {
diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
index 6b4a983fea..fd97a8f504 100644
--- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
@@ -24,7 +24,6 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -110,7 +109,8 @@ public class MmsDatabase extends MessagingDatabase {
"retr_txt" + " TEXT, " + "retr_txt_cs" + " INTEGER, " + "read_status" + " INTEGER, " +
"ct_cls" + " INTEGER, " + "resp_txt" + " TEXT, " + "d_tm" + " INTEGER, " +
RECEIPT_COUNT + " INTEGER DEFAULT 0, " + MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " +
- NETWORK_FAILURE + " TEXT DEFAULT NULL," + "d_rpt" + " INTEGER);";
+ NETWORK_FAILURE + " TEXT DEFAULT NULL," + "d_rpt" + " INTEGER, " +
+ SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
public static final String[] CREATE_INDEXS = {
"CREATE INDEX IF NOT EXISTS mms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
@@ -129,7 +129,7 @@ public class MmsDatabase extends MessagingDatabase {
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
BODY, PART_COUNT, ADDRESS, ADDRESS_DEVICE_ID,
- RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE,
+ RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE, SUBSCRIPTION_ID,
AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ATTACHMENT_ID_ALIAS,
AttachmentDatabase.UNIQUE_ID,
AttachmentDatabase.MMS_ID,
@@ -478,7 +478,7 @@ public class MmsDatabase extends MessagingDatabase {
return new Pair<>(messageId, threadId);
}
- public Optional getNotification(long messageId) {
+ public Optional> getNotification(long messageId) {
Cursor cursor = null;
try {
@@ -493,7 +493,8 @@ public class MmsDatabase extends MessagingDatabase {
builder.addLong(MESSAGE_SIZE, PduHeaders.MESSAGE_SIZE);
builder.addText(TRANSACTION_ID, PduHeaders.TRANSACTION_ID);
- return Optional.of(new NotificationInd(headers));
+ return Optional.of(new Pair<>(new NotificationInd(headers),
+ cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))));
} else {
return Optional.absent();
}
@@ -514,13 +515,14 @@ public class MmsDatabase extends MessagingDatabase {
cursor = rawQuery(RAW_ID_WHERE, new String[] {String.valueOf(messageId)});
if (cursor != null && cursor.moveToNext()) {
- long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
- String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
- long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
- List attachments = new LinkedList(attachmentDatabase.getAttachmentsForMessage(messageId));
- MmsAddresses addresses = addr.getAddressesForId(messageId);
- List destinations = new LinkedList<>();
- String body = getDecryptedBody(masterSecret, messageText, outboxType);
+ long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
+ String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
+ long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
+ List attachments = new LinkedList(attachmentDatabase.getAttachmentsForMessage(messageId));
+ MmsAddresses addresses = addr.getAddressesForId(messageId);
+ List destinations = new LinkedList<>();
+ String body = getDecryptedBody(masterSecret, messageText, outboxType);
destinations.addAll(addresses.getBcc());
destinations.addAll(addresses.getCc());
@@ -532,7 +534,7 @@ public class MmsDatabase extends MessagingDatabase {
return new OutgoingGroupMediaMessage(recipients, body, attachments, timestamp);
}
- OutgoingMediaMessage message = new OutgoingMediaMessage(recipients, body, attachments, timestamp,
+ OutgoingMediaMessage message = new OutgoingMediaMessage(recipients, body, attachments, timestamp, subscriptionId,
!addresses.getBcc().isEmpty() ? ThreadDatabase.DistributionTypes.BROADCAST :
ThreadDatabase.DistributionTypes.DEFAULT);
if (Types.isSecureType(outboxType)) {
@@ -615,6 +617,7 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
contentValues.put(PART_COUNT, retrieved.getAttachments().size());
+ contentValues.put(SUBSCRIPTION_ID, retrieved.getSubscriptionId());
contentValues.put(READ, 0);
if (!contentValues.containsKey(DATE_SENT)) {
@@ -673,7 +676,7 @@ public class MmsDatabase extends MessagingDatabase {
return insertMessageInbox(masterSecret, retrieved, "", threadId, type);
}
- public Pair insertMessageInbox(@NonNull NotificationInd notification) {
+ public Pair insertMessageInbox(@NonNull NotificationInd notification, int subscriptionId) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
long threadId = getThreadIdFor(notification);
@@ -702,6 +705,7 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
contentValues.put(READ, Util.isDefaultSmsProvider(context) ? 0 : 1);
+ contentValues.put(SUBSCRIPTION_ID, subscriptionId);
if (!contentValues.containsKey(DATE_SENT))
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
@@ -761,6 +765,7 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(THREAD_ID, threadId);
contentValues.put(READ, 1);
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
+ contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
if (message.getRecipients().isSingleRecipient()) {
try {
@@ -1021,6 +1026,7 @@ public class MmsDatabase extends MessagingDatabase {
long expiry = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRY));
int status = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.STATUS));
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.RECEIPT_COUNT));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
byte[]contentLocationBytes = null;
byte[]transactionIdBytes = null;
@@ -1035,7 +1041,7 @@ public class MmsDatabase extends MessagingDatabase {
return new NotificationMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
addressDeviceId, dateSent, dateReceived, receiptCount, threadId,
contentLocationBytes, messageSize, expiry, status,
- transactionIdBytes, mailbox);
+ transactionIdBytes, mailbox, subscriptionId);
}
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
@@ -1051,6 +1057,7 @@ public class MmsDatabase extends MessagingDatabase {
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
Recipients recipients = getRecipientsFor(address);
List mismatches = getMismatchedIdentities(mismatchDocument);
@@ -1059,7 +1066,8 @@ public class MmsDatabase extends MessagingDatabase {
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
addressDeviceId, dateSent, dateReceived, receiptCount,
- threadId, body, slideDeck, partCount, box, mismatches, networkFailures);
+ threadId, body, slideDeck, partCount, box, mismatches,
+ networkFailures, subscriptionId);
}
private Recipients getRecipientsFor(String address) {
diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
index cdeb24947c..0044948a93 100644
--- a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
+++ b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
@@ -14,6 +14,7 @@ public interface MmsSmsColumns {
public static final String RECEIPT_COUNT = "delivery_receipt_count";
public static final String MISMATCHED_IDENTITIES = "mismatched_identities";
public static final String UNIQUE_ROW_ID = "unique_row_id";
+ public static final String SUBSCRIPTION_ID = "subscription_id";
public static class Types {
protected static final long TOTAL_MASK = 0xFFFFFFFF;
diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java
index ca6d9e2389..2358e7a178 100644
--- a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java
@@ -52,7 +52,8 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
MmsDatabase.STATUS, MmsSmsColumns.RECEIPT_COUNT,
MmsSmsColumns.MISMATCHED_IDENTITIES,
- MmsDatabase.NETWORK_FAILURE, TRANSPORT,
+ MmsDatabase.NETWORK_FAILURE,
+ MmsSmsColumns.SUBSCRIPTION_ID, TRANSPORT,
AttachmentDatabase.ATTACHMENT_ID_ALIAS,
AttachmentDatabase.UNIQUE_ID,
AttachmentDatabase.MMS_ID,
@@ -132,7 +133,7 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
- MmsDatabase.NETWORK_FAILURE, TRANSPORT,
+ MmsSmsColumns.SUBSCRIPTION_ID, MmsDatabase.NETWORK_FAILURE, TRANSPORT,
AttachmentDatabase.UNIQUE_ID,
AttachmentDatabase.MMS_ID,
AttachmentDatabase.SIZE,
@@ -156,6 +157,7 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
+ MmsSmsColumns.SUBSCRIPTION_ID,
MmsDatabase.NETWORK_FAILURE, TRANSPORT,
AttachmentDatabase.UNIQUE_ID,
AttachmentDatabase.MMS_ID,
@@ -192,6 +194,7 @@ public class MmsSmsDatabase extends Database {
mmsColumnsPresent.add(MmsSmsColumns.ADDRESS_DEVICE_ID);
mmsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
mmsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
+ mmsColumnsPresent.add(MmsSmsColumns.SUBSCRIPTION_ID);
mmsColumnsPresent.add(MmsDatabase.MESSAGE_TYPE);
mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX);
mmsColumnsPresent.add(MmsDatabase.DATE_SENT);
@@ -222,6 +225,7 @@ public class MmsSmsDatabase extends Database {
smsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
smsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
smsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
+ smsColumnsPresent.add(MmsSmsColumns.SUBSCRIPTION_ID);
smsColumnsPresent.add(SmsDatabase.TYPE);
smsColumnsPresent.add(SmsDatabase.SUBJECT);
smsColumnsPresent.add(SmsDatabase.DATE_SENT);
diff --git a/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java b/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
index 02f21f0f37..7d1271acb6 100644
--- a/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
@@ -23,15 +23,16 @@ public class RecipientPreferenceDatabase extends Database {
private static final String TAG = RecipientPreferenceDatabase.class.getSimpleName();
private static final String RECIPIENT_PREFERENCES_URI = "content://textsecure/recipients/";
- private static final String TABLE_NAME = "recipient_preferences";
- private static final String ID = "_id";
- private static final String RECIPIENT_IDS = "recipient_ids";
- private static final String BLOCK = "block";
- private static final String NOTIFICATION = "notification";
- private static final String VIBRATE = "vibrate";
- private static final String MUTE_UNTIL = "mute_until";
- private static final String COLOR = "color";
- private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
+ private static final String TABLE_NAME = "recipient_preferences";
+ private static final String ID = "_id";
+ private static final String RECIPIENT_IDS = "recipient_ids";
+ private static final String BLOCK = "block";
+ private static final String NOTIFICATION = "notification";
+ private static final String VIBRATE = "vibrate";
+ private static final String MUTE_UNTIL = "mute_until";
+ private static final String COLOR = "color";
+ private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
+ private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id";
public enum VibrateState {
DEFAULT(0), ENABLED(1), DISABLED(2);
@@ -60,7 +61,8 @@ public class RecipientPreferenceDatabase extends Database {
VIBRATE + " INTEGER DEFAULT " + VibrateState.DEFAULT.getId() + ", " +
MUTE_UNTIL + " INTEGER DEFAULT 0, " +
COLOR + " TEXT DEFAULT NULL, " +
- SEEN_INVITE_REMINDER + " INTEGER DEFAULT 0);";
+ SEEN_INVITE_REMINDER + " INTEGER DEFAULT 0, " +
+ DEFAULT_SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
public RecipientPreferenceDatabase(Context context, SQLiteOpenHelper databaseHelper) {
super(context, databaseHelper);
@@ -88,13 +90,14 @@ public class RecipientPreferenceDatabase extends Database {
null, null, null);
if (cursor != null && cursor.moveToNext()) {
- boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
- String notification = cursor.getString(cursor.getColumnIndexOrThrow(NOTIFICATION));
- int vibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(VIBRATE));
- long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL));
- String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR));
- Uri notificationUri = notification == null ? null : Uri.parse(notification);
- boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
+ boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
+ String notification = cursor.getString(cursor.getColumnIndexOrThrow(NOTIFICATION));
+ int vibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(VIBRATE));
+ long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL));
+ String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR));
+ Uri notificationUri = notification == null ? null : Uri.parse(notification);
+ boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
+ int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID));
MaterialColor color;
@@ -109,7 +112,8 @@ public class RecipientPreferenceDatabase extends Database {
return Optional.of(new RecipientsPreferences(blocked, muteUntil,
VibrateState.fromId(vibrateState),
- notificationUri, color, seenInviteReminder));
+ notificationUri, color, seenInviteReminder,
+ defaultSubscriptionId));
}
return Optional.absent();
@@ -124,6 +128,13 @@ public class RecipientPreferenceDatabase extends Database {
updateOrInsert(recipients, values);
}
+ public void setDefaultSubscriptionId(@NonNull Recipients recipients, int defaultSubscriptionId) {
+ ContentValues values = new ContentValues();
+ values.put(DEFAULT_SUBSCRIPTION_ID, defaultSubscriptionId);
+ updateOrInsert(recipients, values);
+ }
+
+
public void setBlocked(Recipients recipients, boolean blocked) {
ContentValues values = new ContentValues();
values.put(BLOCK, blocked ? 1 : 0);
@@ -181,19 +192,22 @@ public class RecipientPreferenceDatabase extends Database {
private final Uri notification;
private final MaterialColor color;
private final boolean seenInviteReminder;
+ private final int defaultSubscriptionId;
public RecipientsPreferences(boolean blocked, long muteUntil,
@NonNull VibrateState vibrateState,
@Nullable Uri notification,
@Nullable MaterialColor color,
- boolean seenInviteReminder)
+ boolean seenInviteReminder,
+ int defaultSubscriptionId)
{
- this.blocked = blocked;
- this.muteUntil = muteUntil;
- this.vibrateState = vibrateState;
- this.notification = notification;
- this.color = color;
- this.seenInviteReminder = seenInviteReminder;
+ this.blocked = blocked;
+ this.muteUntil = muteUntil;
+ this.vibrateState = vibrateState;
+ this.notification = notification;
+ this.color = color;
+ this.seenInviteReminder = seenInviteReminder;
+ this.defaultSubscriptionId = defaultSubscriptionId;
}
public @Nullable MaterialColor getColor() {
@@ -219,5 +233,9 @@ public class RecipientPreferenceDatabase extends Database {
public boolean hasSeenInviteReminder() {
return seenInviteReminder;
}
+
+ public Optional getDefaultSubscriptionId() {
+ return defaultSubscriptionId != -1 ? Optional.of(defaultSubscriptionId) : Optional.absent();
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
index 8a6f8c9fd8..771ca39620 100644
--- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
@@ -41,7 +41,6 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.JsonUtils;
-import org.thoughtcrime.securesms.util.LRUCache;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
@@ -78,7 +77,7 @@ public class SmsDatabase extends MessagingDatabase {
DATE_RECEIVED + " INTEGER, " + DATE_SENT + " INTEGER, " + PROTOCOL + " INTEGER, " + READ + " INTEGER DEFAULT 0, " +
STATUS + " INTEGER DEFAULT -1," + TYPE + " INTEGER, " + REPLY_PATH_PRESENT + " INTEGER, " +
RECEIPT_COUNT + " INTEGER DEFAULT 0," + SUBJECT + " TEXT, " + BODY + " TEXT, " +
- MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " + SERVICE_CENTER + " TEXT);";
+ MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " + SERVICE_CENTER + " TEXT, " + SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
public static final String[] CREATE_INDEXS = {
"CREATE INDEX IF NOT EXISTS sms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
@@ -95,7 +94,7 @@ public class SmsDatabase extends MessagingDatabase {
DATE_SENT + " AS " + NORMALIZED_DATE_SENT,
PROTOCOL, READ, STATUS, TYPE,
REPLY_PATH_PRESENT, SUBJECT, BODY, SERVICE_CENTER, RECEIPT_COUNT,
- MISMATCHED_IDENTITIES
+ MISMATCHED_IDENTITIES, SUBSCRIPTION_ID
};
private static final EarlyReceiptCache earlyReceiptCache = new EarlyReceiptCache();
@@ -451,6 +450,7 @@ public class SmsDatabase extends MessagingDatabase {
values.put(DATE_SENT, message.getSentTimestampMillis());
values.put(PROTOCOL, message.getProtocol());
values.put(READ, unread ? 0 : 1);
+ values.put(SUBSCRIPTION_ID, message.getSubscriptionId());
if (!TextUtils.isEmpty(message.getPseudoSubject()))
values.put(SUBJECT, message.getPseudoSubject());
@@ -497,6 +497,7 @@ public class SmsDatabase extends MessagingDatabase {
contentValues.put(DATE_SENT, date);
contentValues.put(READ, 1);
contentValues.put(TYPE, type);
+ contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
try {
contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(date, canonicalizeNumber(context, address)));
@@ -663,6 +664,7 @@ public class SmsDatabase extends MessagingDatabase {
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.RECEIPT_COUNT));
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID));
List mismatches = getMismatches(mismatchDocument);
Recipients recipients = getRecipientsFor(address);
@@ -672,7 +674,7 @@ public class SmsDatabase extends MessagingDatabase {
recipients.getPrimaryRecipient(),
addressDeviceId,
dateSent, dateReceived, receiptCount, type,
- threadId, status, mismatches);
+ threadId, status, mismatches, subscriptionId);
}
private Recipients getRecipientsFor(String address) {
diff --git a/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java
index deb32c37b7..7615e7a021 100644
--- a/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java
@@ -21,8 +21,8 @@ import android.support.annotation.NonNull;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.MmsDatabase;
+import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.mms.SlideDeck;
@@ -53,10 +53,10 @@ public class MediaMmsMessageRecord extends MessageRecord {
@NonNull SlideDeck slideDeck,
int partCount, long mailbox,
List mismatches,
- List failures)
+ List failures, int subscriptionId)
{
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent,
- dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures);
+ dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures, subscriptionId);
this.context = context.getApplicationContext();
this.partCount = partCount;
diff --git a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
index dcba1fefbd..608e14304e 100644
--- a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
@@ -50,13 +50,15 @@ public abstract class MessageRecord extends DisplayRecord {
private final long id;
private final List mismatches;
private final List networkFailures;
+ private final int subscriptionId;
MessageRecord(Context context, long id, Body body, Recipients recipients,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, long threadId,
int deliveryStatus, int receiptCount, long type,
List mismatches,
- List networkFailures)
+ List networkFailures,
+ int subscriptionId)
{
super(context, body, recipients, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
type);
@@ -65,6 +67,7 @@ public abstract class MessageRecord extends DisplayRecord {
this.recipientDeviceId = recipientDeviceId;
this.mismatches = mismatches;
this.networkFailures = networkFailures;
+ this.subscriptionId = subscriptionId;
}
public abstract boolean isMms();
@@ -195,4 +198,7 @@ public abstract class MessageRecord extends DisplayRecord {
return (int)getId();
}
+ public int getSubscriptionId() {
+ return subscriptionId;
+ }
}
diff --git a/src/org/thoughtcrime/securesms/database/model/NotificationMmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/NotificationMmsMessageRecord.java
index 2dfa01547a..8da31f5308 100644
--- a/src/org/thoughtcrime/securesms/database/model/NotificationMmsMessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/NotificationMmsMessageRecord.java
@@ -49,11 +49,12 @@ public class NotificationMmsMessageRecord extends MessageRecord {
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, int receiptCount,
long threadId, byte[] contentLocation, long messageSize,
- long expiry, int status, byte[] transactionId, long mailbox)
+ long expiry, int status, byte[] transactionId, long mailbox,
+ int subscriptionId)
{
super(context, id, new Body("", true), recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox,
- new LinkedList(), new LinkedList());
+ new LinkedList(), new LinkedList(), subscriptionId);
this.contentLocation = contentLocation;
this.messageSize = messageSize;
diff --git a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
index cdbd38d894..6000aea9db 100644
--- a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
@@ -47,11 +47,12 @@ public class SmsMessageRecord extends MessageRecord {
long dateSent, long dateReceived,
int receiptCount,
long type, long threadId,
- int status, List mismatches)
+ int status, List mismatches,
+ int subscriptionId)
{
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, status, receiptCount, type,
- mismatches, new LinkedList());
+ mismatches, new LinkedList(), subscriptionId);
}
public long getType() {
diff --git a/src/org/thoughtcrime/securesms/groups/GroupManager.java b/src/org/thoughtcrime/securesms/groups/GroupManager.java
index c98c6c18b4..adc2f4da57 100644
--- a/src/org/thoughtcrime/securesms/groups/GroupManager.java
+++ b/src/org/thoughtcrime/securesms/groups/GroupManager.java
@@ -107,8 +107,8 @@ public class GroupManager {
avatarAttachment = new UriAttachment(avatarUri, ContentType.IMAGE_JPEG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length);
}
- OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis());
- long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false);
+ OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis());
+ long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false);
return new GroupActionResult(groupRecipient, threadId);
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
index 0c4765a9aa..260277d17d 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
@@ -9,9 +9,9 @@ import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
+import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
@@ -35,7 +35,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import ws.com.google.android.mms.pdu.NotificationInd;
@@ -75,8 +74,8 @@ public class MmsDownloadJob extends MasterSecretJob {
@Override
public void onRun(MasterSecret masterSecret) {
- MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
- Optional notification = database.getNotification(messageId);
+ MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
+ Optional> notification = database.getNotification(messageId);
if (!notification.isPresent()) {
Log.w(TAG, "No notification for ID: " + messageId);
@@ -84,22 +83,24 @@ public class MmsDownloadJob extends MasterSecretJob {
}
try {
- if (notification.get().getContentLocation() == null) {
+ if (notification.get().first.getContentLocation() == null) {
throw new MmsException("Notification content location was null.");
}
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
- String contentLocation = new String(notification.get().getContentLocation());
- byte[] transactionId = notification.get().getTransactionId();
+ String contentLocation = new String(notification.get().first.getContentLocation());
+ byte[] transactionId = notification.get().first.getTransactionId();
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
- RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId);
+ RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().second);
+
if (retrieveConf == null) {
throw new MmsException("RetrieveConf was null");
}
- storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf);
+
+ storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().second);
} catch (ApnUnavailableException e) {
Log.w(TAG, e);
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
@@ -146,7 +147,8 @@ public class MmsDownloadJob extends MasterSecretJob {
}
private void storeRetrievedMms(MasterSecret masterSecret, String contentLocation,
- long messageId, long threadId, RetrieveConf retrieved)
+ long messageId, long threadId, RetrieveConf retrieved,
+ int subscriptionId)
throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
LegacyMessageException
{
@@ -192,7 +194,7 @@ public class MmsDownloadJob extends MasterSecretJob {
- IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments);
+ IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId);
Pair messageAndThreadId = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
message, contentLocation, threadId);
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
index 6ae212cb99..7bb413f6e2 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
@@ -19,16 +19,20 @@ import ws.com.google.android.mms.pdu.PduParser;
public class MmsReceiveJob extends ContextJob {
+ private static final long serialVersionUID = 1L;
+
private static final String TAG = MmsReceiveJob.class.getSimpleName();
private final byte[] data;
+ private final int subscriptionId;
- public MmsReceiveJob(Context context, byte[] data) {
+ public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
super(context, JobParameters.newBuilder()
.withWakeLock(true)
.withPersistence().create());
- this.data = data;
+ this.data = data;
+ this.subscriptionId = subscriptionId;
}
@Override
@@ -54,7 +58,7 @@ public class MmsReceiveJob extends ContextJob {
if (isNotification(pdu) && !isBlocked(pdu)) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
- Pair messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu);
+ Pair messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu, subscriptionId);
Log.w(TAG, "Inserted received MMS notification...");
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
index 4d3d71c9b9..796b953f8f 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
@@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
@@ -25,12 +24,9 @@ import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.NumberUtil;
import org.thoughtcrime.securesms.util.SmilUtil;
import org.thoughtcrime.securesms.util.TelephonyUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
-import org.whispersystems.textsecure.api.util.InvalidNumberException;
-import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
import java.io.IOException;
import java.util.Arrays;
@@ -83,7 +79,7 @@ public class MmsSendJob extends SendJob {
validateDestinations(message, pdu);
final byte[] pduBytes = getPduBytes(pdu);
- final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes);
+ final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes, message.getSubscriptionId());
final MmsSendResult result = getSendResult(sendConf, pdu);
database.markAsSent(messageId);
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 33c3c5012f..bbbc9a46bb 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -261,7 +261,7 @@ public class PushDecryptJob extends ContextJob {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String localNumber = TextSecurePreferences.getLocalNumber(context);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
- localNumber, message.getTimestamp(),
+ localNumber, message.getTimestamp(), -1,
Optional.fromNullable(envelope.getRelay()),
message.getBody(),
message.getGroupInfo(),
@@ -293,7 +293,7 @@ public class PushDecryptJob extends ContextJob {
Recipients recipients = getSyncMessageDestination(message);
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
- message.getTimestamp(), ThreadDatabase.DistributionTypes.DEFAULT);
+ message.getTimestamp(), -1, ThreadDatabase.DistributionTypes.DEFAULT);
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
@@ -350,7 +350,7 @@ public class PushDecryptJob extends ContextJob {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
Recipients recipients = getSyncMessageDestination(message);
String body = message.getMessage().getBody().or("");
- OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body);
+ OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body, -1);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp());
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
index 23c3f874db..a829c56eed 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
@@ -23,17 +23,21 @@ import java.util.List;
public class SmsReceiveJob extends ContextJob {
+ private static final long serialVersionUID = 1L;
+
private static final String TAG = SmsReceiveJob.class.getSimpleName();
private final Object[] pdus;
+ private final int subscriptionId;
- public SmsReceiveJob(Context context, Object[] pdus) {
+ public SmsReceiveJob(Context context, Object[] pdus, int subscriptionId) {
super(context, JobParameters.newBuilder()
.withPersistence()
.withWakeLock(true)
.create());
- this.pdus = pdus;
+ this.pdus = pdus;
+ this.subscriptionId = subscriptionId;
}
@Override
@@ -41,7 +45,7 @@ public class SmsReceiveJob extends ContextJob {
@Override
public void onRun() {
- Optional message = assembleMessageFragments(pdus);
+ Optional message = assembleMessageFragments(pdus, subscriptionId);
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
MasterSecretUnion masterSecretUnion;
@@ -95,11 +99,11 @@ public class SmsReceiveJob extends ContextJob {
return messageAndThreadId;
}
- private Optional assembleMessageFragments(Object[] pdus) {
+ private Optional assembleMessageFragments(Object[] pdus, int subscriptionId) {
List messages = new LinkedList<>();
for (Object pdu : pdus) {
- messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu)));
+ messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
}
if (messages.isEmpty()) {
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
index f93c42b266..e6b916f015 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
@@ -4,6 +4,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.util.Log;
@@ -105,7 +106,7 @@ public class SmsSendJob extends SendJob {
// catching it and marking the message as a failure. That way at least it doesn't
// repeatedly crash every time you start the app.
try {
- SmsManager.getDefault().sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
+ getSmsManagerFor(message.getSubscriptionId()).sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
} catch (NullPointerException npe) {
Log.w(TAG, npe);
Log.w(TAG, "Recipient: " + recipient);
@@ -113,9 +114,9 @@ public class SmsSendJob extends SendJob {
try {
for (int i=0;i= 22 && subscriptionId != -1) {
+ return SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
+ } else {
+ return SmsManager.getDefault();
+ }
+ }
+
private static JobParameters constructParameters(Context context, String name) {
JobParameters.Builder builder = JobParameters.newBuilder()
.withPersistence()
diff --git a/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java b/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
index c93415f751..b80ba0241d 100644
--- a/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
+import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
@@ -26,38 +27,46 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
@Nullable
@Override
- public SendConf send(@NonNull byte[] pduBytes)
+ public SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
throws UndeliverableMessageException
{
- try {
+ if (subscriptionId == -1 || VERSION.SDK_INT < 22) {
Log.w(TAG, "Sending via legacy connection");
- return new OutgoingLegacyMmsConnection(context).send(pduBytes);
- } catch (UndeliverableMessageException | ApnUnavailableException e) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- Log.w(TAG, "Falling back to try sending via Lollipop API");
- return new OutgoingLollipopMmsConnection(context).send(pduBytes);
- } else {
- throw new UndeliverableMessageException(e);
+ try {
+ return new OutgoingLegacyMmsConnection(context).send(pduBytes, subscriptionId);
+ } catch (UndeliverableMessageException | ApnUnavailableException e) {
+ Log.w(TAG, e);
}
}
+
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
+ } else {
+ throw new UndeliverableMessageException("Lollipop API not available to try...");
+ }
}
@Nullable
@Override
public RetrieveConf retrieve(@NonNull String contentLocation,
- byte[] transactionId)
+ byte[] transactionId,
+ int subscriptionId)
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
{
- try {
+ if (VERSION.SDK_INT < 22 || subscriptionId == -1) {
Log.w(TAG, "Receiving via legacy connection");
- return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId);
- } catch (MmsRadioException | IOException | ApnUnavailableException e) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- Log.w(TAG, "Falling back to try receiving via Lollipop API");
- return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId);
- } else {
- throw e;
+ try {
+ return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
+ } catch (MmsRadioException | ApnUnavailableException | IOException e) {
+ Log.w(TAG, e);
}
}
+
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ Log.w(TAG, "Falling back to try receiving via Lollipop API");
+ return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
+ } else {
+ throw new IOException("Not able to use Lollipop APIs, giving up...");
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java b/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java
index 547a711cd8..e4ccdb86f9 100644
--- a/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/IncomingLegacyMmsConnection.java
@@ -60,7 +60,7 @@ public class IncomingLegacyMmsConnection extends LegacyMmsConnection implements
@Override
public @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
- byte[] transactionId)
+ byte[] transactionId, int subscriptionId)
throws MmsRadioException, ApnUnavailableException, IOException
{
MmsRadio radio = MmsRadio.getInstance(context);
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java b/src/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java
index 7305120e4b..984c0b2f35 100644
--- a/src/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java
@@ -39,6 +39,7 @@ import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
public class IncomingLollipopMmsConnection extends LollipopMmsConnection implements IncomingMmsConnection {
+
public static final String ACTION = IncomingLollipopMmsConnection.class.getCanonicalName() + "MMS_DOWNLOADED_ACTION";
private static final String TAG = IncomingLollipopMmsConnection.class.getSimpleName();
@@ -58,7 +59,8 @@ public class IncomingLollipopMmsConnection extends LollipopMmsConnection impleme
@Override
@TargetApi(VERSION_CODES.LOLLIPOP)
public synchronized @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
- byte[] transactionId) throws MmsException
+ byte[] transactionId,
+ int subscriptionId) throws MmsException
{
beginTransaction();
@@ -66,11 +68,20 @@ public class IncomingLollipopMmsConnection extends LollipopMmsConnection impleme
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
Log.w(TAG, "downloading multimedia from " + contentLocation + " to " + pointer.getUri());
- SmsManager.getDefault().downloadMultimediaMessage(getContext(),
- contentLocation,
- pointer.getUri(),
- null,
- getPendingIntent());
+
+ SmsManager smsManager;
+
+ if (VERSION.SDK_INT >= 22 && subscriptionId != -1) {
+ smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
+ } else {
+ smsManager = SmsManager.getDefault();
+ }
+
+ smsManager.downloadMultimediaMessage(getContext(),
+ contentLocation,
+ pointer.getUri(),
+ null,
+ getPendingIntent());
waitForResult();
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
index b9b384d109..b47c796e1d 100644
--- a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
+++ b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
@@ -19,6 +19,7 @@ public class IncomingMediaMessage {
private final String groupId;
private final boolean push;
private final long sentTimeMillis;
+ private final int subscriptionId;
private final List to = new LinkedList<>();
private final List cc = new LinkedList<>();
@@ -26,13 +27,14 @@ public class IncomingMediaMessage {
public IncomingMediaMessage(String from, List to, List cc,
String body, long sentTimeMillis,
- List attachments)
+ List attachments, int subscriptionId)
{
this.from = from;
this.sentTimeMillis = sentTimeMillis;
this.body = body;
this.groupId = null;
this.push = false;
+ this.subscriptionId = subscriptionId;
this.to.addAll(to);
this.cc.addAll(cc);
@@ -43,6 +45,7 @@ public class IncomingMediaMessage {
String from,
String to,
long sentTimeMillis,
+ int subscriptionId,
Optional relay,
Optional body,
Optional group,
@@ -52,6 +55,7 @@ public class IncomingMediaMessage {
this.from = from;
this.sentTimeMillis = sentTimeMillis;
this.body = body.orNull();
+ this.subscriptionId = subscriptionId;
if (group.isPresent()) this.groupId = GroupUtil.getEncodedId(group.get().getGroupId());
else this.groupId = null;
@@ -60,6 +64,10 @@ public class IncomingMediaMessage {
this.attachments.addAll(PointerAttachment.forPointers(masterSecret, attachments));
}
+ public int getSubscriptionId() {
+ return subscriptionId;
+ }
+
public String getBody() {
return body;
}
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java b/src/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java
index 0b42fcac18..d29724511b 100644
--- a/src/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java
@@ -9,5 +9,5 @@ import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.RetrieveConf;
public interface IncomingMmsConnection {
- @Nullable RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
+ @Nullable RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
}
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java b/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java
index eda1836235..2ac7c241ab 100644
--- a/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/OutgoingLegacyMmsConnection.java
@@ -72,7 +72,7 @@ public class OutgoingLegacyMmsConnection extends LegacyMmsConnection implements
}
@Override
- public @Nullable SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException {
+ public @Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException {
try {
MmsRadio radio = MmsRadio.getInstance(context);
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java b/src/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java
index 20323247e0..d6c2e0740f 100644
--- a/src/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java
@@ -59,17 +59,27 @@ public class OutgoingLollipopMmsConnection extends LollipopMmsConnection impleme
@Override
@TargetApi(VERSION_CODES.LOLLIPOP)
- public @Nullable synchronized SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException {
+ public @Nullable synchronized SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
+ throws UndeliverableMessageException
+ {
beginTransaction();
try {
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
Util.copy(new ByteArrayInputStream(pduBytes), pointer.getOutputStream());
- SmsManager.getDefault().sendMultimediaMessage(getContext(),
- pointer.getUri(),
- null,
- null,
- getPendingIntent());
+ SmsManager smsManager;
+
+ if (VERSION.SDK_INT >= 22 && subscriptionId != -1) {
+ smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
+ } else {
+ smsManager = SmsManager.getDefault();
+ }
+
+ smsManager.sendMultimediaMessage(getContext(),
+ pointer.getUri(),
+ null,
+ null,
+ getPendingIntent());
waitForResult();
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java b/src/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java
index c47ef5663e..93f5c23a47 100644
--- a/src/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java
+++ b/src/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java
@@ -14,9 +14,11 @@ public class OutgoingMediaMessage {
protected final List attachments;
private final long sentTimeMillis;
private final int distributionType;
+ private final int subscriptionId;
public OutgoingMediaMessage(Recipients recipients, String message,
List attachments, long sentTimeMillis,
+ int subscriptionId,
int distributionType)
{
this.recipients = recipients;
@@ -24,14 +26,15 @@ public class OutgoingMediaMessage {
this.sentTimeMillis = sentTimeMillis;
this.distributionType = distributionType;
this.attachments = attachments;
+ this.subscriptionId = subscriptionId;
}
- public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int distributionType)
+ public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int subscriptionId, int distributionType)
{
this(recipients,
buildMessage(slideDeck, message),
slideDeck.asAttachments(),
- sentTimeMillis,
+ sentTimeMillis, subscriptionId,
distributionType);
}
@@ -41,6 +44,7 @@ public class OutgoingMediaMessage {
this.distributionType = that.distributionType;
this.attachments = that.attachments;
this.sentTimeMillis = that.sentTimeMillis;
+ this.subscriptionId = that.subscriptionId;
}
public Recipients getRecipients() {
@@ -71,6 +75,10 @@ public class OutgoingMediaMessage {
return sentTimeMillis;
}
+ public int getSubscriptionId() {
+ return subscriptionId;
+ }
+
private static String buildMessage(SlideDeck slideDeck, String message) {
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
return slideDeck.getBody() + "\n\n" + message;
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java b/src/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java
index 5fc669456e..64a3c58a99 100644
--- a/src/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java
@@ -8,5 +8,5 @@ import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import ws.com.google.android.mms.pdu.SendConf;
public interface OutgoingMmsConnection {
- @Nullable SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException;
+ @Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException;
}
diff --git a/src/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java b/src/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java
index 084579db62..ae20107388 100644
--- a/src/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java
+++ b/src/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java
@@ -16,7 +16,7 @@ public class OutgoingSecureMediaMessage extends OutgoingMediaMessage {
long sentTimeMillis,
int distributionType)
{
- super(recipients, body, attachments, sentTimeMillis, distributionType);
+ super(recipients, body, attachments, sentTimeMillis, -1, distributionType);
}
public OutgoingSecureMediaMessage(OutgoingMediaMessage base) {
diff --git a/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java b/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java
index 5ca13526d4..a352dd70dc 100644
--- a/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java
+++ b/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java
@@ -27,16 +27,16 @@ import android.support.v4.app.RemoteInput;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.LinkedList;
-import ws.com.google.android.mms.pdu.PduBody;
-
/**
* Get the response text from the Wearable Device and sends an message as a reply
*/
@@ -66,11 +66,14 @@ public class WearReplyReceiver extends MasterSecretBroadcastReceiver {
protected Void doInBackground(Void... params) {
long threadId;
+ Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipientIds);
+ int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
+
if (recipients.isGroupRecipient()) {
- OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList(), System.currentTimeMillis(), 0);
+ OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList(), System.currentTimeMillis(), subscriptionId, 0);
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
} else {
- OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString());
+ OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), subscriptionId);
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
}
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
index d2543bdca7..8c91ba8539 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
@@ -66,7 +66,7 @@ public class RecipientFactory {
return provider.getRecipients(context, recipientIds, asynchronous);
}
- public static Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
+ public static @NonNull Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
List ids = new LinkedList<>();
@@ -81,7 +81,7 @@ public class RecipientFactory {
return getRecipientsForIds(context, ids, asynchronous);
}
- public static Recipients getRecipientsFromStrings(@NonNull Context context, @NonNull List numbers, boolean asynchronous) {
+ public static @NonNull Recipients getRecipientsFromStrings(@NonNull Context context, @NonNull List numbers, boolean asynchronous) {
List ids = new LinkedList<>();
for (String number : numbers) {
@@ -95,7 +95,7 @@ public class RecipientFactory {
return getRecipientsForIds(context, ids, asynchronous);
}
- private static Recipients getRecipientsForIds(Context context, List idStrings, boolean asynchronous) {
+ private static @NonNull Recipients getRecipientsForIds(Context context, List idStrings, boolean asynchronous) {
long[] ids = new long[idStrings.size()];
int i = 0;
diff --git a/src/org/thoughtcrime/securesms/service/MmsListener.java b/src/org/thoughtcrime/securesms/service/MmsListener.java
index 02d0d27d20..3d8417d809 100644
--- a/src/org/thoughtcrime/securesms/service/MmsListener.java
+++ b/src/org/thoughtcrime/securesms/service/MmsListener.java
@@ -63,9 +63,11 @@ public class MmsListener extends BroadcastReceiver {
isRelevant(context, intent)))
{
Log.w(TAG, "Relevant!");
+ int subscriptionId = intent.getExtras().getInt("subscription", -1);
+
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MmsReceiveJob(context, intent.getByteArrayExtra("data")));
+ .add(new MmsReceiveJob(context, intent.getByteArrayExtra("data"), subscriptionId));
abortBroadcast();
}
diff --git a/src/org/thoughtcrime/securesms/service/QuickResponseService.java b/src/org/thoughtcrime/securesms/service/QuickResponseService.java
index 77e544ccac..467f4d0e98 100644
--- a/src/org/thoughtcrime/securesms/service/QuickResponseService.java
+++ b/src/org/thoughtcrime/securesms/service/QuickResponseService.java
@@ -9,6 +9,8 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.SlideDeck;
@@ -17,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.Rfc5724Uri;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.net.URISyntaxException;
import java.net.URLDecoder;
@@ -49,14 +52,17 @@ public class QuickResponseService extends MasterSecretIntentService {
if(numbers.contains("%")){
numbers = URLDecoder.decode(numbers);
}
- Recipients recipients = RecipientFactory.getRecipientsFromString(this, numbers, false);
+
+ Recipients recipients = RecipientFactory.getRecipientsFromString(this, numbers, false);
+ Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(this).getRecipientsPreferences(recipients.getIds());
+ int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
if (!TextUtils.isEmpty(content)) {
if (recipients.isSingleRecipient()) {
- MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipients, content), -1, false);
+ MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipients, content, subscriptionId), -1, false);
} else {
MessageSender.send(this, masterSecret, new OutgoingMediaMessage(recipients, new SlideDeck(), content, System.currentTimeMillis(),
- ThreadDatabase.DistributionTypes.DEFAULT), -1, false);
+ subscriptionId, ThreadDatabase.DistributionTypes.DEFAULT), -1, false);
}
}
} catch (URISyntaxException e) {
diff --git a/src/org/thoughtcrime/securesms/service/SmsListener.java b/src/org/thoughtcrime/securesms/service/SmsListener.java
index 8a58d90a04..82395bbd65 100644
--- a/src/org/thoughtcrime/securesms/service/SmsListener.java
+++ b/src/org/thoughtcrime/securesms/service/SmsListener.java
@@ -84,16 +84,6 @@ public class SmsListener extends BroadcastReceiver {
return bodyBuilder.toString();
}
-// private ArrayList getAsTextMessages(Intent intent) {
-// Object[] pdus = (Object[])intent.getExtras().get("pdus");
-// ArrayList messages = new ArrayList(pdus.length);
-//
-// for (int i=0;i fragments) {
@@ -112,6 +117,7 @@ public class IncomingTextMessage implements Parcelable {
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
this.groupId = fragments.get(0).getGroupId();
this.push = fragments.get(0).isPush();
+ this.subscriptionId = fragments.get(0).getSubscriptionId();
}
protected IncomingTextMessage(String sender, String groupId)
@@ -126,6 +132,11 @@ public class IncomingTextMessage implements Parcelable {
this.sentTimestampMillis = System.currentTimeMillis();
this.groupId = groupId;
this.push = true;
+ this.subscriptionId = -1;
+ }
+
+ public int getSubscriptionId() {
+ return subscriptionId;
}
public long getSentTimestampMillis() {
@@ -209,5 +220,6 @@ public class IncomingTextMessage implements Parcelable {
out.writeLong(sentTimestampMillis);
out.writeString(groupId);
out.writeInt(push ? 1 : 0);
+ out.writeInt(subscriptionId);
}
}
diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java
index 8e94d583c1..28f59b0fe8 100644
--- a/src/org/thoughtcrime/securesms/sms/MessageSender.java
+++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java
@@ -74,7 +74,8 @@ public class MessageSender {
allocatedThreadId = threadId;
}
- long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), allocatedThreadId, message, forceSms, System.currentTimeMillis());
+ long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), allocatedThreadId,
+ message, forceSms, System.currentTimeMillis());
sendTextMessage(context, recipients, forceSms, keyExchange, messageId);
diff --git a/src/org/thoughtcrime/securesms/sms/OutgoingEncryptedMessage.java b/src/org/thoughtcrime/securesms/sms/OutgoingEncryptedMessage.java
index 4025157a85..dfc0c66002 100644
--- a/src/org/thoughtcrime/securesms/sms/OutgoingEncryptedMessage.java
+++ b/src/org/thoughtcrime/securesms/sms/OutgoingEncryptedMessage.java
@@ -6,7 +6,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
public OutgoingEncryptedMessage(Recipients recipients, String body) {
- super(recipients, body);
+ super(recipients, body, -1);
}
private OutgoingEncryptedMessage(OutgoingEncryptedMessage base, String body) {
diff --git a/src/org/thoughtcrime/securesms/sms/OutgoingKeyExchangeMessage.java b/src/org/thoughtcrime/securesms/sms/OutgoingKeyExchangeMessage.java
index a517ebf87e..5a39e155b2 100644
--- a/src/org/thoughtcrime/securesms/sms/OutgoingKeyExchangeMessage.java
+++ b/src/org/thoughtcrime/securesms/sms/OutgoingKeyExchangeMessage.java
@@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
public class OutgoingKeyExchangeMessage extends OutgoingTextMessage {
public OutgoingKeyExchangeMessage(Recipients recipients, String message) {
- super(recipients, message);
+ super(recipients, message, -1);
}
private OutgoingKeyExchangeMessage(OutgoingKeyExchangeMessage base, String body) {
diff --git a/src/org/thoughtcrime/securesms/sms/OutgoingTextMessage.java b/src/org/thoughtcrime/securesms/sms/OutgoingTextMessage.java
index c01ad36b0b..cb24306e4e 100644
--- a/src/org/thoughtcrime/securesms/sms/OutgoingTextMessage.java
+++ b/src/org/thoughtcrime/securesms/sms/OutgoingTextMessage.java
@@ -7,15 +7,22 @@ public class OutgoingTextMessage {
private final Recipients recipients;
private final String message;
+ private final int subscriptionId;
- public OutgoingTextMessage(Recipients recipients, String message) {
- this.recipients = recipients;
- this.message = message;
+ public OutgoingTextMessage(Recipients recipients, String message, int subscriptionId) {
+ this.recipients = recipients;
+ this.message = message;
+ this.subscriptionId = subscriptionId;
}
protected OutgoingTextMessage(OutgoingTextMessage base, String body) {
- this.recipients = base.getRecipients();
- this.message = body;
+ this.recipients = base.getRecipients();
+ this.subscriptionId = base.getSubscriptionId();
+ this.message = body;
+ }
+
+ public int getSubscriptionId() {
+ return subscriptionId;
}
public String getMessageBody() {
@@ -48,9 +55,9 @@ public class OutgoingTextMessage {
} else if (record.isKeyExchange()) {
return new OutgoingKeyExchangeMessage(record.getRecipients(), record.getBody().getBody());
} else if (record.isEndSession()) {
- return new OutgoingEndSessionMessage(new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody()));
+ return new OutgoingEndSessionMessage(new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody(), -1));
} else {
- return new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody());
+ return new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody(), record.getSubscriptionId());
}
}
diff --git a/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionInfoCompat.java b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionInfoCompat.java
new file mode 100644
index 0000000000..59ba5e399a
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionInfoCompat.java
@@ -0,0 +1,23 @@
+package org.thoughtcrime.securesms.util.dualsim;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+public class SubscriptionInfoCompat {
+
+ private final int subscriptionId;
+ private final @Nullable CharSequence displayName;
+
+ public SubscriptionInfoCompat(int subscriptionId, @Nullable CharSequence displayName) {
+ this.subscriptionId = subscriptionId;
+ this.displayName = displayName;
+ }
+
+ public @NonNull CharSequence getDisplayName() {
+ return displayName != null ? displayName : "";
+ }
+
+ public int getSubscriptionId() {
+ return subscriptionId;
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java
new file mode 100644
index 0000000000..0a29d68d86
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java
@@ -0,0 +1,57 @@
+package org.thoughtcrime.securesms.util.dualsim;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class SubscriptionManagerCompat {
+
+ private final Context context;
+
+ public SubscriptionManagerCompat(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+ public Optional getActiveSubscriptionInfo(int subscriptionId) {
+ if (Build.VERSION.SDK_INT < 22) {
+ return Optional.absent();
+ }
+
+ SubscriptionInfo subscriptionInfo = SubscriptionManager.from(context).getActiveSubscriptionInfo(subscriptionId);
+
+ if (subscriptionInfo != null) {
+ return Optional.of(new SubscriptionInfoCompat(subscriptionId, subscriptionInfo.getDisplayName()));
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ public @NonNull List getActiveSubscriptionInfoList() {
+ if (Build.VERSION.SDK_INT < 22) {
+ return new LinkedList<>();
+ }
+
+ List subscriptionInfos = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
+
+ if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
+ return new LinkedList<>();
+ }
+
+ List compatList = new LinkedList<>();
+
+ for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
+ compatList.add(new SubscriptionInfoCompat(subscriptionInfo.getSubscriptionId(),
+ subscriptionInfo.getDisplayName()));
+ }
+
+ return compatList;
+ }
+
+}