From e37c06c563c895208e8ec51bdc67ddfbe88e7f51 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Wed, 15 Nov 2017 16:29:00 -0800 Subject: [PATCH] Show dialog if another device registered with same number --- build.gradle | 10 ++--- .../securesms/ConversationActivity.java | 40 ++++++++++++------- .../securesms/ConversationFragment.java | 4 +- .../securesms/ConversationListFragment.java | 31 ++++++++++---- .../securesms/ConversationPopupActivity.java | 2 +- .../securesms/RegistrationActivity.java | 1 + .../reminder/ExpiredBuildReminder.java | 15 +++---- .../reminder/UnauthorizedReminder.java | 27 +++++++++++++ .../SignalCommunicationModule.java | 35 +++++++++++++++- .../securesms/events/ReminderUpdateEvent.java | 5 +++ .../securesms/util/TextSecurePreferences.java | 9 +++++ 11 files changed, 139 insertions(+), 40 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/components/reminder/UnauthorizedReminder.java create mode 100644 src/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java diff --git a/build.gradle b/build.gradle index b5c519b698..961165232f 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ dependencies { compile 'org.whispersystems:jobmanager:1.0.2' compile 'org.whispersystems:libpastelog:1.0.7' - compile 'org.whispersystems:signal-service-android:2.6.11' + compile 'org.whispersystems:signal-service-android:2.6.12' compile 'org.whispersystems:webrtc-android:M63' compile "me.leolin:ShortcutBadger:1.1.16" @@ -160,7 +160,7 @@ dependencyVerification { 'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718', 'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181', 'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88', - 'org.whispersystems:signal-service-android:89f8630cc1737c3d52178dc46926f0755d75fed3ac9b94d067c0a42e4e3169c9', + 'org.whispersystems:signal-service-android:6d29df68961b7fabb119b50afec3c599b66d2cb85cc6e92b40eb27861bb7e4b9', 'org.whispersystems:webrtc-android:3f5c39b710797fbda9fe6015cb6a8667ab2fc14ef2c1eb9be832a53b368aa110', 'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774', 'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb', @@ -199,7 +199,7 @@ dependencyVerification { 'com.github.bumptech.glide:gifdecoder:fe793861d4d4619b5041d3bd68186000b6151581292053e88c96a5d0b60e5337', 'com.android.support:support-annotations:99d6199ad5a09a0e5e8a49a4cc08f818483ddcfd7eedea2f9923412daf982309', 'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1', - 'org.whispersystems:signal-service-java:ef89da56b915490bb907d848eae79efdf1218e985763e7dd2e8047c7ccb03c0c', + 'org.whispersystems:signal-service-java:80d4b0410c1effd40847e12d9e9de074c6a6395b8d43396ae2e5a4a22077de18', 'com.github.bumptech.glide:disklrucache:b5cf8f76b423a6c86edbe82380958adbe6a2f1d5afbd6add23a9c8ad141eb406', 'com.github.bumptech.glide:annotations:10a910f62ee27de5f0e44a72acb7fe31ed1e45b3ffac82fb3a8ebada150765f1', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', @@ -210,9 +210,9 @@ dependencyVerification { 'org.whispersystems:curve25519-android:82595394422b957d4a5b5f1b27b75ba25cf6dc4db4d312418ca38cd6fff279ca', 'org.whispersystems:signal-protocol-java:5152c2b01a25147967d6bf82e540f947901bdfa79260be3eb3e96b03f787d6b5', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', - 'com.googlecode.libphonenumber:libphonenumber:be23ec6195df9f328364a3122ddd111e30f42d18a841dd06f84d2685c7fabb9f', + 'com.googlecode.libphonenumber:libphonenumber:c0a4c5df3a5388debd6b63e768c5b3ae1f4f635eb2ec49e20b06d662e5979598', 'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d', - 'com.squareup.okhttp3:okhttp:c1d57f913f74f61d424d4250a92723ba9a61affc12a0ab194d84cc179b472841', + 'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4', 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', 'android.arch.lifecycle:common:86bf301a20ad0cd0a391e22a52e6fbf90575c096ff83233fa9fd0d52b3219121', 'android.arch.core:common:5192934cd73df32e2c15722ed7fc488dde90baaec9ae030010dd1a80fb4e74e1', diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index b1b2be7c2a..e871269426 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -90,8 +90,10 @@ import org.thoughtcrime.securesms.components.identity.UntrustedSendDialog; import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView; import org.thoughtcrime.securesms.components.identity.UnverifiedSendDialog; import org.thoughtcrime.securesms.components.location.SignalPlace; +import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder; import org.thoughtcrime.securesms.components.reminder.InviteReminder; import org.thoughtcrime.securesms.components.reminder.ReminderView; +import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; @@ -113,6 +115,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.identity.IdentityRecordList; +import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; import org.thoughtcrime.securesms.mms.AttachmentManager; @@ -567,6 +570,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity inputPanel.onKeyboardShown(); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(ReminderUpdateEvent event) { + updateReminders(recipient.hasSeenInviteReminder()); + } + //////// Event Handlers private void handleReturnToConversationList() { @@ -1079,25 +1087,27 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void onSecurityUpdated() { Log.w(TAG, "onSecurityUpdated()"); - updateInviteReminder(recipient.hasSeenInviteReminder()); + updateReminders(recipient.hasSeenInviteReminder()); updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId()); } - protected void updateInviteReminder(boolean seenInvite) { - Log.w(TAG, "updateInviteReminder(" + seenInvite+")"); - if (TextSecurePreferences.isPushRegistered(this) && - TextSecurePreferences.isShowInviteReminders(this) && - !isSecureText && - !seenInvite && - !recipient.isGroupRecipient()) + protected void updateReminders(boolean seenInvite) { + Log.w(TAG, "updateReminders(" + seenInvite+")"); + + if (UnauthorizedReminder.isEligible(this)) { + reminderView.get().showReminder(new UnauthorizedReminder(this)); + } else if (ExpiredBuildReminder.isEligible()) { + reminderView.get().showReminder(new ExpiredBuildReminder(this)); + } else if (TextSecurePreferences.isPushRegistered(this) && + TextSecurePreferences.isShowInviteReminders(this) && + !isSecureText && + !seenInvite && + !recipient.isGroupRecipient()) { InviteReminder reminder = new InviteReminder(this, recipient); - reminder.setOkListener(new OnClickListener() { - @Override - public void onClick(View v) { - handleInviteLink(); - reminderView.get().requestDismiss(); - } + reminder.setOkListener(v -> { + handleInviteLink(); + reminderView.get().requestDismiss(); }); reminderView.get().showReminder(reminder); } else if (reminderView.resolved()) { @@ -1302,7 +1312,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity setBlockedUserState(recipient, isSecureText, isDefaultSms); setActionBarColor(recipient.getColor()); setGroupShareProfileReminder(recipient); - updateInviteReminder(recipient.hasSeenInviteReminder()); + updateReminders(recipient.hasSeenInviteReminder()); updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId()); initializeSecurity(isSecureText, isDefaultSms); invalidateOptionsMenu(); diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index fa617634da..24b04bd7b7 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -16,6 +16,7 @@ */ package org.thoughtcrime.securesms; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; @@ -42,7 +43,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.Window; import android.view.animation.Animation; @@ -53,7 +53,6 @@ import android.widget.Toast; import org.thoughtcrime.securesms.ConversationAdapter.HeaderViewHolder; import org.thoughtcrime.securesms.ConversationAdapter.ItemClickListener; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase; @@ -80,6 +79,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +@SuppressLint("StaticFieldLeak") public class ConversationFragment extends Fragment implements LoaderManager.LoaderCallbacks { diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java index c8aa943acc..faae789368 100644 --- a/src/org/thoughtcrime/securesms/ConversationListFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java @@ -52,6 +52,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener; import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator; import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton; @@ -64,10 +67,12 @@ import org.thoughtcrime.securesms.components.reminder.Reminder; import org.thoughtcrime.securesms.components.reminder.ReminderView; import org.thoughtcrime.securesms.components.reminder.ShareReminder; import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder; +import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; import org.thoughtcrime.securesms.database.loaders.ConversationListLoader; +import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.notifications.MarkReadReceiver; import org.thoughtcrime.securesms.notifications.MessageNotifier; @@ -121,7 +126,7 @@ public class ConversationListFragment extends Fragment if (archive) fab.setVisibility(View.GONE); else fab.setVisibility(View.VISIBLE); - reminderView.setOnDismissListener(this::updateReminders); + reminderView.setOnDismissListener(() -> updateReminders(true)); list.setHasFixedSize(true); list.setLayoutManager(new LinearLayoutManager(getActivity())); @@ -146,8 +151,9 @@ public class ConversationListFragment extends Fragment public void onResume() { super.onResume(); - updateReminders(); + updateReminders(true); list.getAdapter().notifyDataSetChanged(); + EventBus.getDefault().register(this); } @Override @@ -155,6 +161,7 @@ public class ConversationListFragment extends Fragment super.onPause(); fab.stopPulse(); + EventBus.getDefault().unregister(this); } public ConversationListAdapter getListAdapter() { @@ -173,12 +180,14 @@ public class ConversationListFragment extends Fragment } @SuppressLint("StaticFieldLeak") - private void updateReminders() { - reminderView.hide(); + private void updateReminders(boolean hide) { new AsyncTask>() { - @Override protected Optional doInBackground(Context... params) { + @Override + protected Optional doInBackground(Context... params) { final Context context = params[0]; - if (ExpiredBuildReminder.isEligible()) { + if (UnauthorizedReminder.isEligible(context)) { + return Optional.of(new UnauthorizedReminder(context)); + } else if (ExpiredBuildReminder.isEligible()) { return Optional.of(new ExpiredBuildReminder(context)); } else if (OutdatedBuildReminder.isEligible()) { return Optional.of(new OutdatedBuildReminder(context)); @@ -197,9 +206,12 @@ public class ConversationListFragment extends Fragment } } - @Override protected void onPostExecute(Optional reminder) { + @Override + protected void onPostExecute(Optional reminder) { if (reminder.isPresent() && getActivity() != null && !isRemoving()) { reminderView.showReminder(reminder.get()); + } else if (!reminder.isPresent()) { + reminderView.hide(); } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); @@ -436,6 +448,11 @@ public class ConversationListFragment extends Fragment actionMode = null; } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(ReminderUpdateEvent event) { + updateReminders(false); + } + private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback { ArchiveListenerCallback() { diff --git a/src/org/thoughtcrime/securesms/ConversationPopupActivity.java b/src/org/thoughtcrime/securesms/ConversationPopupActivity.java index 56cf4b2a3f..38217ff687 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(boolean seenInvite) { + protected void updateReminders(boolean seenInvite) { if (reminderView.resolved()) { reminderView.get().setVisibility(View.GONE); } diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index a1fbab50da..f02220bd8e 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -373,6 +373,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif TextSecurePreferences.setSignalingKey(RegistrationActivity.this, signalingKey); TextSecurePreferences.setSignedPreKeyRegistered(RegistrationActivity.this, true); TextSecurePreferences.setPromptedPushRegistration(RegistrationActivity.this, true); + TextSecurePreferences.setUnauthorizedReceived(RegistrationActivity.this, false); return true; } catch (IOException e) { diff --git a/src/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java b/src/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java index b74a93c76f..08f69da6c2 100644 --- a/src/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java +++ b/src/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java @@ -3,25 +3,22 @@ package org.thoughtcrime.securesms.components.reminder; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.view.View; -import android.view.View.OnClickListener; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.util.Util; public class ExpiredBuildReminder extends Reminder { + @SuppressWarnings("unused") private static final String TAG = ExpiredBuildReminder.class.getSimpleName(); public ExpiredBuildReminder(final Context context) { super(context.getString(R.string.reminder_header_expired_build), context.getString(R.string.reminder_header_expired_build_details)); - setOkListener(new OnClickListener() { - @Override public void onClick(View v) { - try { - context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName()))); - } catch (android.content.ActivityNotFoundException anfe) { - context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName()))); - } + setOkListener(v -> { + try { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName()))); + } catch (android.content.ActivityNotFoundException anfe) { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName()))); } }); } diff --git a/src/org/thoughtcrime/securesms/components/reminder/UnauthorizedReminder.java b/src/org/thoughtcrime/securesms/components/reminder/UnauthorizedReminder.java new file mode 100644 index 0000000000..3077930e5f --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/reminder/UnauthorizedReminder.java @@ -0,0 +1,27 @@ +package org.thoughtcrime.securesms.components.reminder; + + +import android.content.Context; +import android.content.Intent; + +import org.thoughtcrime.securesms.RegistrationActivity; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +public class UnauthorizedReminder extends Reminder { + + public UnauthorizedReminder(final Context context) { + super("Device no longer registered", + "This is likely because you registered your phone number with Signal on a different device. Tap to re-register."); + + setOkListener(v -> context.startActivity(new Intent(context, RegistrationActivity.class))); + } + + @Override + public boolean isDismissable() { + return false; + } + + public static boolean isEligible(Context context) { + return TextSecurePreferences.isUnauthorizedRecieved(context); + } +} diff --git a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index efeed01f02..cc4d71d4f6 100644 --- a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -1,11 +1,14 @@ package org.thoughtcrime.securesms.dependencies; import android.content.Context; +import android.util.Log; +import org.greenrobot.eventbus.EventBus; import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.CreateProfileActivity; import org.thoughtcrime.securesms.DeviceListFragment; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; +import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; @@ -40,6 +43,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.util.CredentialsProvider; +import org.whispersystems.signalservice.api.websocket.ConnectivityListener; import dagger.Module; import dagger.Provides; @@ -74,6 +78,8 @@ import dagger.Provides; MultiDeviceReadReceiptUpdateJob.class}) public class SignalCommunicationModule { + private static final String TAG = SignalCommunicationModule.class.getSimpleName(); + private final Context context; private final SignalServiceNetworkAccess networkAccess; @@ -118,7 +124,8 @@ public class SignalCommunicationModule { if (this.messageReceiver == null) { this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context), new DynamicCredentialsProvider(context), - BuildConfig.USER_AGENT); + BuildConfig.USER_AGENT, + new PipeConnectivityListener()); } return this.messageReceiver; @@ -148,4 +155,30 @@ public class SignalCommunicationModule { } } + private class PipeConnectivityListener implements ConnectivityListener { + + @Override + public void onConnected() { + Log.w(TAG, "onConnected()"); + } + + @Override + public void onConnecting() { + Log.w(TAG, "onConnecting()"); + } + + @Override + public void onDisconnected() { + Log.w(TAG, "onDisconnected()"); + } + + @Override + public void onAuthenticationFailure() { + Log.w(TAG, "onAuthenticationFailure()"); + TextSecurePreferences.setUnauthorizedReceived(context, true); + EventBus.getDefault().post(new ReminderUpdateEvent()); + } + + } + } diff --git a/src/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java b/src/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java new file mode 100644 index 0000000000..582143a1c9 --- /dev/null +++ b/src/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java @@ -0,0 +1,5 @@ +package org.thoughtcrime.securesms.events; + + +public class ReminderUpdateEvent { +} diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 2791094568..e7fc6307ef 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -115,6 +115,15 @@ public class TextSecurePreferences { private static final String PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id"; public static final String READ_RECEIPTS_PREF = "pref_read_receipts"; public static final String INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard"; + private static final String UNAUTHORIZED_RECEIVED = "pref_unauthorized_received"; + + public static void setUnauthorizedReceived(Context context, boolean value) { + setBooleanPreference(context, UNAUTHORIZED_RECEIVED, value); + } + + public static boolean isUnauthorizedRecieved(Context context) { + return getBooleanPreference(context, UNAUTHORIZED_RECEIVED, false); + } public static boolean isIncognitoKeyboardEnabled(Context context) { return getBooleanPreference(context, INCOGNITO_KEYBORAD_PREF, false);