Commit 89d78c8e authored by Bastien Le Querrec's avatar Bastien Le Querrec

improve multi-SIM support

* Each SIM card is now bound to a unique key pair.
* Display number or slot index if display name is the same for multiple
  cards.
* Use subcription ID of last received message as default SIM, but do not
  change it if user is in conversation.
* Update app subscription IDs on new phone
* Start secure session only for SIM which received message, allow user to
  select SIM when starting a secure session

Fixes #467
Fixes #497
parent 2a833862
......@@ -55,6 +55,11 @@
android:resource="@xml/badge_widget_provider"/>
</receiver>
<receiver android:name="org.smssecure.smssecure.util.dualsim.SimChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.SIM_STATE_CHANGED"/>
</intent-filter>
</receiver>
<meta-data android:name="org.smssecure.smssecure.mms.SilenceGlideModule"
android:value="GlideModule" />
......
......@@ -10,14 +10,13 @@
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="monospace"
android:id="@+id/identity_fingerprint"
android:text=""
android:padding="7dip" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="monospace"
android:id="@+id/identity_fingerprint"
android:text=""
android:padding="7dip" />
</LinearLayout>
</ScrollView>
......@@ -8,6 +8,10 @@
<item android:title="@string/conversation_insecure__menu_start_secure_session"
android:id="@+id/menu_start_secure_session" />
<item android:title="@string/conversation_insecure__menu_start_secure_session"
android:id="@+id/menu_start_secure_session_dual_sim">
<menu></menu>
</item>
</menu>
</item>
</menu>
......@@ -6,7 +6,12 @@
app:showAsAction="ifRoom">
<menu>
<item android:title="@string/conversation_secure_verified__menu_verify_identity"
android:id="@+id/menu_verify_identity"/>
android:id="@+id/menu_verify_identity" />
<item android:title="@string/conversation_secure_verified__menu_verify_identity"
android:id="@+id/menu_verify_identity_dual_sim">
<menu></menu>
</item>
</menu>
</item>
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/conversation_secure_verified__menu_abort_secure_session"
android:id="@+id/menu_abort_session"/>
</menu>
\ No newline at end of file
android:id="@+id/menu_abort_session" />
<item android:title="@string/conversation_secure_verified__menu_abort_secure_session"
android:id="@+id/menu_abort_session_dual_sim">
<menu></menu>
</item>
<item android:title="@string/conversation_insecure__menu_start_secure_session"
android:id="@+id/menu_start_secure_session" />
<item android:title="@string/conversation_insecure__menu_start_secure_session"
android:id="@+id/menu_start_secure_session_dual_sim">
<menu></menu>
</item>
</menu>
......@@ -26,6 +26,12 @@
android:id="@+id/menu_my_identity"
android:icon="@android:drawable/ic_menu_view" />
<item android:title="@string/arrays__your_identity_key"
android:id="@+id/menu_my_identity_dual_sim"
android:icon="@android:drawable/ic_menu_view">
<menu></menu>
</item>
<item android:title="@string/text_secure_normal__menu_settings"
android:id="@+id/menu_settings"
android:icon="@android:drawable/ic_menu_preferences" />
......
......@@ -454,6 +454,11 @@
<string name="SingleRecipientNotificationBuilder_silence" translatable="false">Silence</string>
<string name="SingleRecipientNotificationBuilder_new_message">New message</string>
<!-- SubscriptionInfoCompat -->
<string name="SubscriptionInfoCompat_slot">Slot %1$s</string>
<string name="SubscriptionInfoCompat_display_name">%1$s (slot %2$s)</string>
<!-- change_passphrase_activity -->
<string name="change_passphrase_activity__old_passphrase">Old passphrase</string>
<string name="change_passphrase_activity__new_passphrase">New passphrase</string>
......
......@@ -20,6 +20,7 @@ import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.util.Log;
import android.support.v4.app.NotificationManagerCompat;
......@@ -31,6 +32,7 @@ import org.smssecure.smssecure.jobs.requirements.MediaNetworkRequirementProvider
import org.smssecure.smssecure.jobs.requirements.ServiceRequirementProvider;
import org.smssecure.smssecure.notifications.NotificationChannels;
import org.smssecure.smssecure.util.SilencePreferences;
import org.smssecure.smssecure.util.dualsim.SimChangedReceiver;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.jobqueue.dependencies.DependencyInjector;
import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider;
......@@ -50,6 +52,7 @@ import dagger.ObjectGraph;
* @author Moxie Marlinspike
*/
public class ApplicationContext extends Application implements DependencyInjector {
private static final String TAG = ApplicationContext.class.getSimpleName();
private JobManager jobManager;
private ObjectGraph objectGraph;
......@@ -66,6 +69,7 @@ public class ApplicationContext extends Application implements DependencyInjecto
initializeRandomNumberFix();
initializeLogging();
initializeJobManager();
checkSimState();
NotificationChannels.create(this);
}
......@@ -105,4 +109,8 @@ public class ApplicationContext extends Application implements DependencyInjecto
mediaNetworkRequirementProvider.notifyMediaControlEvent();
}
private void checkSimState() {
SimChangedReceiver.checkSimState(this);
}
}
......@@ -402,7 +402,7 @@ public class ConversationItem extends LinearLayout
}
private void setSimInfo(MessageRecord messageRecord) {
SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
SubscriptionManagerCompat subscriptionManager = SubscriptionManagerCompat.from(context);
if (messageRecord.getSubscriptionId() == -1 || subscriptionManager.getActiveSubscriptionInfoList().size() < 2) {
simInfoText.setVisibility(View.GONE);
......@@ -518,7 +518,7 @@ public class ConversationItem extends LinearLayout
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
KeyExchangeInitiator.initiate(context, masterSecret, recipients, true, subscriptionId);
KeyExchangeInitiator.initiate(context, masterSecret, recipients, true);
}
});
builder.show();
......
......@@ -19,16 +19,18 @@ package org.smssecure.smssecure;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.database.DatabaseFactory;
......@@ -36,10 +38,14 @@ import org.smssecure.smssecure.notifications.MessageNotifier;
import org.smssecure.smssecure.recipients.RecipientFactory;
import org.smssecure.smssecure.recipients.Recipients;
import org.smssecure.smssecure.service.KeyCachingService;
import org.smssecure.smssecure.util.dualsim.SubscriptionInfoCompat;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.DynamicLanguage;
import org.smssecure.smssecure.util.DynamicTheme;
import org.smssecure.smssecure.util.SilencePreferences;
import java.util.List;
public class ConversationListActivity extends PassphraseRequiredActionBarActivity
implements ConversationListFragment.ConversationSelectedListener
{
......@@ -52,6 +58,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
private ContentObserver observer;
private MasterSecret masterSecret;
private List<SubscriptionInfoCompat> activeSubscriptions;
@Override
protected void onPreCreate() {
dynamicTheme.onCreate(this);
......@@ -61,6 +69,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
this.activeSubscriptions = SubscriptionManagerCompat.from(this).getActiveSubscriptionInfoList();
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
getSupportActionBar().setTitle(R.string.app_name);
......@@ -91,6 +100,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
menu.findItem(R.id.menu_clear_passphrase).setVisible(!SilencePreferences.isPasswordDisabled(this));
inflateViewIdentities(menu);
inflater.inflate(R.menu.conversation_list, menu);
MenuItem menuItem = menu.findItem(R.id.menu_search);
initializeSearch(menuItem);
......@@ -99,6 +110,27 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
return true;
}
private void inflateViewIdentities(Menu menu) {
if (Build.VERSION.SDK_INT >= 22 && activeSubscriptions.size() > 1) {
menu.findItem(R.id.menu_my_identity).setVisible(false);
MenuItem menuItem = menu.findItem(R.id.menu_my_identity_dual_sim);
SubMenu identitiesMenu = menuItem.getSubMenu();
for (SubscriptionInfoCompat subscriptionInfo : activeSubscriptions) {
final int subscriptionId = subscriptionInfo.getSubscriptionId();
identitiesMenu.add(Menu.NONE, Menu.NONE, Menu.NONE, subscriptionInfo.getDisplayName())
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
handleMyIdentity(subscriptionId);
return true;
}
});
}
} else {
menu.findItem(R.id.menu_my_identity_dual_sim).setVisible(false);
}
}
private void initializeSearch(MenuItem searchViewItem) {
SearchView searchView = (SearchView)MenuItemCompat.getActionView(searchViewItem);
searchView.setQueryHint(getString(R.string.ConversationListActivity_search));
......@@ -197,7 +229,16 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
}
private void handleMyIdentity() {
startActivity(new Intent(this, ViewLocalIdentityActivity.class));
if (Build.VERSION.SDK_INT < 22 || activeSubscriptions.size() < 2) {
int subscriptionId = Build.VERSION.SDK_INT < 22 ? -1 : activeSubscriptions.get(0).getSubscriptionId();
handleMyIdentity(subscriptionId);
}
}
private void handleMyIdentity(int subscriptionId) {
Intent intent = new Intent(this, ViewIdentityActivity.class);
intent.putExtra("subscription_id", subscriptionId);
startActivity(intent);
}
private void handleMarkAllRead() {
......
......@@ -78,6 +78,7 @@ import org.smssecure.smssecure.recipients.Recipients;
import org.smssecure.smssecure.sms.MessageSender;
import org.smssecure.smssecure.sms.OutgoingEncryptedMessage;
import org.smssecure.smssecure.sms.OutgoingTextMessage;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.Util;
import org.smssecure.smssecure.util.ViewUtil;
import org.smssecure.smssecure.util.task.SnackbarAsyncTask;
......@@ -348,8 +349,9 @@ public class ConversationListFragment extends Fragment
recipients = getListAdapter().getRecipientsFromThreadId(threadId);
if (recipients != null) {
int subscriptionId = SubscriptionManagerCompat.getDefaultMessagingSubscriptionId().or(-1);
isSingleConversation = recipients.isSingleRecipient() && !recipients.isGroupRecipient();
isSecureDestination = isSingleConversation && SessionUtil.hasSession(context, masterSecret, recipients.getPrimaryRecipient());
isSecureDestination = isSingleConversation && SessionUtil.hasSession(context, masterSecret, recipients.getPrimaryRecipient().getNumber(), subscriptionId);
Log.w(TAG, "Number of drafts: " + drafts.size());
if (drafts.size() > 1 && !drafts.get(1).getType().equals(DraftDatabase.Draft.TEXT)) {
......
......@@ -21,22 +21,19 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import org.smssecure.smssecure.crypto.IdentityKeyUtil;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.database.DatabaseFactory;
import org.smssecure.smssecure.database.MmsDatabase;
import org.smssecure.smssecure.database.MmsDatabase.Reader;
import org.smssecure.smssecure.database.EncryptingSmsDatabase;
import org.smssecure.smssecure.database.model.MessageRecord;
import org.smssecure.smssecure.database.SmsDatabase;
import org.smssecure.smssecure.database.model.SmsMessageRecord;
import org.smssecure.smssecure.jobs.SmsDecryptJob;
import org.smssecure.smssecure.notifications.MessageNotifier;
import org.smssecure.smssecure.util.dualsim.DualSimUpgradeUtil;
import org.smssecure.smssecure.util.dualsim.SubscriptionInfoCompat;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.ParcelUtil;
import org.smssecure.smssecure.util.SilencePreferences;
......@@ -44,7 +41,6 @@ import org.smssecure.smssecure.util.Util;
import org.smssecure.smssecure.util.VersionTracker;
import org.whispersystems.jobqueue.EncryptionKeys;
import java.io.File;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
......@@ -52,25 +48,12 @@ import java.util.TreeSet;
public class DatabaseUpgradeActivity extends BaseActivity {
private static final String TAG = DatabaseUpgradeActivity.class.getSimpleName();
public static final int NO_MORE_KEY_EXCHANGE_PREFIX_VERSION = 46;
public static final int MMS_BODY_VERSION = 46;
public static final int TOFU_IDENTITIES_VERSION = 50;
public static final int CURVE25519_VERSION = 63;
public static final int ASYMMETRIC_MASTER_SECRET_FIX_VERSION = 73;
public static final int NO_V1_VERSION = 83;
public static final int SIGNED_PREKEY_VERSION = 83;
public static final int NO_DECRYPT_QUEUE_VERSION = 84;
public static final int ASK_FOR_SIM_CARD_VERSION = 143;
public static final int ASK_FOR_SIM_CARD_VERSION = 143;
public static final int MULTI_SIM_MULTI_KEYS_VERSION = 129;
private static final SortedSet<Integer> UPGRADE_VERSIONS = new TreeSet<Integer>() {{
add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION);
add(TOFU_IDENTITIES_VERSION);
add(CURVE25519_VERSION);
add(ASYMMETRIC_MASTER_SECRET_FIX_VERSION);
add(NO_V1_VERSION);
add(SIGNED_PREKEY_VERSION);
add(NO_DECRYPT_QUEUE_VERSION);
add(ASK_FOR_SIM_CARD_VERSION);
add(MULTI_SIM_MULTI_KEYS_VERSION);
}};
private MasterSecret masterSecret;
......@@ -81,7 +64,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
this.masterSecret = getIntent().getParcelableExtra("master_secret");
if (needsUpgradeTask()) {
Log.w("DatabaseUpgradeActivity", "Upgrading...");
Log.w(TAG, "Upgrading...");
setContentView(R.layout.database_upgrade_activity);
ProgressBar indeterminateProgress = (ProgressBar)findViewById(R.id.indeterminate_progress);
......@@ -105,13 +88,13 @@ public class DatabaseUpgradeActivity extends BaseActivity {
int currentVersionCode = Util.getCurrentApkReleaseVersion(this);
int lastSeenVersion = VersionTracker.getLastSeenVersion(this);
Log.w("DatabaseUpgradeActivity", "LastSeenVersion: " + lastSeenVersion);
Log.w(TAG, "LastSeenVersion: " + lastSeenVersion);
if (lastSeenVersion >= currentVersionCode)
return false;
for (int version : UPGRADE_VERSIONS) {
Log.w("DatabaseUpgradeActivity", "Comparing: " + version);
Log.w(TAG, "Comparing: " + version);
if (lastSeenVersion < version)
return true;
}
......@@ -160,58 +143,39 @@ public class DatabaseUpgradeActivity extends BaseActivity {
protected Void doInBackground(Integer... params) {
Context context = DatabaseUpgradeActivity.this.getApplicationContext();
Log.w("DatabaseUpgradeActivity", "Running background upgrade..");
Log.w(TAG, "Running background upgrade..");
DatabaseFactory.getInstance(DatabaseUpgradeActivity.this)
.onApplicationLevelUpgrade(context, masterSecret, params[0], this);
if (params[0] < CURVE25519_VERSION) {
if (!IdentityKeyUtil.hasCurve25519IdentityKeys(context)) {
IdentityKeyUtil.generateCurve25519IdentityKeys(context, masterSecret);
if (params[0] < ASK_FOR_SIM_CARD_VERSION) {
if (!SilencePreferences.isFirstRun(context) &&
SubscriptionManagerCompat.from(context).getActiveSubscriptionInfoList().size() > 1)
{
SilencePreferences.setSimCardAsked(context, false);
}
}
if (params[0] < NO_V1_VERSION) {
File v1sessions = new File(context.getFilesDir(), "sessions");
if (v1sessions.exists() && v1sessions.isDirectory()) {
File[] contents = v1sessions.listFiles();
if (params[0] < MULTI_SIM_MULTI_KEYS_VERSION) {
if (Build.VERSION.SDK_INT >= 22) {
SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
List<SubscriptionInfo> activeSubscriptions = subscriptionManager.getActiveSubscriptionInfoList();
if (contents != null) {
for (File session : contents) {
session.delete();
}
for (SubscriptionInfo subscriptionInfo : activeSubscriptions) {
int subscriptionId = subscriptionInfo.getSubscriptionId();
SilencePreferences.setAppSubscriptionId(context, subscriptionId, subscriptionId);
}
v1sessions.delete();
}
}
if (params[0] < NO_DECRYPT_QUEUE_VERSION) {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(getApplicationContext());
SmsDatabase.Reader smsReader = null;
/*
* getDefaultSubscriptionId() is available for API 24+ only, so we
* move keys and sessions to SIM card in slot 1, not to the default one.
*/
int defaultSubscriptionId = activeSubscriptions.get(0).getSubscriptionId();
SmsMessageRecord record;
List<SubscriptionInfoCompat> activeSubscriptionsCompat = SubscriptionManagerCompat.from(context).getActiveSubscriptionInfoList();
try {
smsReader = smsDatabase.getDecryptInProgressMessages(masterSecret);
while ((record = smsReader.getNext()) != null) {
ApplicationContext.getInstance(getApplicationContext())
.getJobManager()
.add(new SmsDecryptJob(getApplicationContext(), record.getId()));
}
} finally {
if (smsReader != null)
smsReader.close();
}
}
if (params[0] < ASK_FOR_SIM_CARD_VERSION) {
if (!SilencePreferences.isFirstRun(context) &&
new SubscriptionManagerCompat(context).getActiveSubscriptionInfoList().size() > 1)
{
SilencePreferences.setSimCardAsked(context, false);
DualSimUpgradeUtil.moveIdentityKeysAndSessionsToSubscriptionId(context, -1, defaultSubscriptionId);
DualSimUpgradeUtil.generateKeysIfDoNotExist(context, masterSecret, activeSubscriptionsCompat);
DualSimUpgradeUtil.bindSubscriptionId(context, activeSubscriptionsCompat);
}
}
......
......@@ -17,15 +17,21 @@
package org.smssecure.smssecure;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import org.smssecure.smssecure.crypto.IdentityKeyUtil;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.crypto.MasterSecretUtil;
import org.smssecure.smssecure.util.dualsim.DualSimUpgradeUtil;
import org.smssecure.smssecure.util.dualsim.SubscriptionInfoCompat;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.SilencePreferences;
import org.smssecure.smssecure.util.VersionTracker;
import java.util.List;
/**
* Activity for creating a user's local encryption passphrase.
*
......@@ -66,7 +72,14 @@ public class PassphraseCreateActivity extends PassphraseActivity {
passphrase);
MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret);
IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this, masterSecret);
if (Build.VERSION.SDK_INT >= 22) {
List<SubscriptionInfoCompat> activeSubscriptions = SubscriptionManagerCompat.from(PassphraseCreateActivity.this).getActiveSubscriptionInfoList();
DualSimUpgradeUtil.generateKeysIfDoNotExist(PassphraseCreateActivity.this, masterSecret, activeSubscriptions);
DualSimUpgradeUtil.bindSubscriptionId(PassphraseCreateActivity.this, activeSubscriptions);
} else {
IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this, masterSecret, -1);
}
VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this);
SilencePreferences.setPasswordDisabled(PassphraseCreateActivity.this, true);
......
......@@ -77,7 +77,7 @@ public class ReceiveKeyDialog extends AlertDialog {
final IncomingKeyExchangeMessage message = getMessage(messageRecord);
final IdentityKey identityKey = getIdentityKey(message);
if (isTrusted(masterSecret, identityKey, messageRecord.getIndividualRecipient())){
if (isTrusted(masterSecret, identityKey, messageRecord.getIndividualRecipient(), messageRecord.getSubscriptionId())){
setMessage(context.getString(R.string.ReceiveKeyActivity_the_signature_on_this_key_exchange_is_trusted_but));
} else {
setUntrustedText(messageRecord, identityKey);
......@@ -121,8 +121,8 @@ public class ReceiveKeyDialog extends AlertDialog {
setMessage(spannableString);
}
private boolean isTrusted(MasterSecret masterSecret, IdentityKey identityKey, Recipient recipient) {
IdentityKeyStore identityKeyStore = new SilenceIdentityKeyStore(getContext(), masterSecret);
private boolean isTrusted(MasterSecret masterSecret, IdentityKey identityKey, Recipient recipient, int subscriptionId) {
IdentityKeyStore identityKeyStore = new SilenceIdentityKeyStore(getContext(), masterSecret, subscriptionId);
return identityKeyStore.isTrustedIdentity(new SignalProtocolAddress(recipient.getNumber(), 1), identityKey, IdentityKeyStore.Direction.RECEIVING);
}
......@@ -134,7 +134,8 @@ public class ReceiveKeyDialog extends AlertDialog {
IncomingTextMessage message = new IncomingTextMessage(messageRecord.getIndividualRecipient().getNumber(),
messageRecord.getRecipientDeviceId(),
System.currentTimeMillis(),
messageRecord.getBody().getBody());
messageRecord.getBody().getBody(),
messageRecord.getSubscriptionId());
if (messageRecord.isBundleKeyExchange()) {
return new IncomingPreKeyBundleMessage(message, message.getMessageBody());
......
......@@ -113,6 +113,17 @@ public class TransportOptions {
}
}
public void disableTransport(Type type, int subscriptionId) {
List<TransportOption> options = find(type);
for (TransportOption option : options) {
if (option.getSimSubscriptionId().or(-1) == subscriptionId) enabledTransports.remove(option);
if (selectedOption.isPresent() && selectedOption.get().getType() == type && selectedOption.get().getSimSubscriptionId().or(-1) == subscriptionId) {
setSelectedTransport(null);
}
}
}
public List<TransportOption> getEnabledTransports() {
return enabledTransports;
}
......@@ -159,7 +170,7 @@ public class TransportOptions {
@NonNull CharacterCalculator characterCalculator)
{
List<TransportOption> results = new LinkedList<>();
SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
SubscriptionManagerCompat subscriptionManager = SubscriptionManagerCompat.from(context);
List<SubscriptionInfoCompat> subscriptions;
if (Permissions.hasAll(context, Manifest.permission.READ_PHONE_STATE)) {
......
......@@ -30,6 +30,7 @@ import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.crypto.storage.SilenceSessionStore;
import org.smssecure.smssecure.recipients.Recipient;
import org.smssecure.smssecure.recipients.RecipientFactory;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.Hex;
import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.IdentityKey;
......@@ -72,12 +73,14 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
}
private void initializeFingerprints() {
if (!IdentityKeyUtil.hasIdentityKey(this)) {
int subscriptionId = getIntent().getIntExtra("subscription_id", SubscriptionManagerCompat.getDefaultMessagingSubscriptionId().or(-1));
if (!IdentityKeyUtil.hasIdentityKey(this, subscriptionId)) {
localIdentityFingerprint.setText(R.string.VerifyIdentityActivity_you_do_not_have_an_identity_key);
return;
}
localIdentityFingerprint.setText(Hex.toString(IdentityKeyUtil.getIdentityKey(this).serialize()));
localIdentityFingerprint.setText(Hex.toString(IdentityKeyUtil.getIdentityKey(this, subscriptionId).serialize()));
IdentityKey identityKey = getRemoteIdentityKey(masterSecret, recipient);
......@@ -90,7 +93,9 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
@Override
protected void initiateDisplay() {
if (!IdentityKeyUtil.hasIdentityKey(this)) {
int subscriptionId = SubscriptionManagerCompat.getDefaultMessagingSubscriptionId().or(-1);
if (!IdentityKeyUtil.hasIdentityKey(this, subscriptionId)) {
Toast.makeText(this,
R.string.VerifyIdentityActivity_you_do_not_have_an_identity_key,
Toast.LENGTH_LONG).show();
......@@ -129,7 +134,9 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
@Override
protected IdentityKey getIdentityKeyToDisplay() {
return IdentityKeyUtil.getIdentityKey(this);
int subscriptionId = SubscriptionManagerCompat.getDefaultMessagingSubscriptionId().or(-1);
return IdentityKeyUtil.getIdentityKey(this, subscriptionId);
}
@Override
......@@ -153,13 +160,14 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
}
private @Nullable IdentityKey getRemoteIdentityKey(MasterSecret masterSecret, Recipient recipient) {
int subscriptionId = SubscriptionManagerCompat.getDefaultMessagingSubscriptionId().or(-1);
IdentityKeyParcelable identityKeyParcelable = getIntent().getParcelableExtra("remote_identity");
if (identityKeyParcelable != null) {
return identityKeyParcelable.get();
}
SessionStore sessionStore = new SilenceSessionStore(this, masterSecret);
SessionStore sessionStore = new SilenceSessionStore(this, masterSecret, subscriptionId);
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(recipient.getNumber(), 1);
SessionRecord record = sessionStore.loadSession(axolotlAddress);
......
......@@ -19,11 +19,17 @@ package org.smssecure.smssecure;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.widget.TextView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import org.smssecure.smssecure.crypto.IdentityKeyParcelable;
import org.smssecure.smssecure.crypto.IdentityKeyUtil;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.smssecure.smssecure.util.Hex;
import org.whispersystems.libsignal.IdentityKey;
import org.smssecure.smssecure.crypto.IdentityKeyParcelable;
/**
* Activity for displaying an identity key.
......@@ -39,13 +45,41 @@ public class ViewIdentityActivity extends KeyScanningActivity {
private IdentityKey identityKey;
@Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
int subscriptionId = getIntent().getIntExtra("subscription_id", SubscriptionManagerCompat.<