mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Migrate to Android fingerprints and auth for Signal screen lock
This commit is contained in:
parent
3970a30e14
commit
d28dc670ea
@ -19,6 +19,7 @@
|
|||||||
<uses-feature android:name="android.hardware.portrait" android:required="false"/>
|
<uses-feature android:name="android.hardware.portrait" android:required="false"/>
|
||||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||||
<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"/>
|
<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"/>
|
||||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_PROFILE"/>
|
<uses-permission android:name="android.permission.WRITE_PROFILE"/>
|
||||||
@ -262,10 +263,8 @@
|
|||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||||
|
|
||||||
<activity android:name=".PassphrasePromptActivity"
|
<activity android:name=".PassphrasePromptActivity"
|
||||||
android:label="@string/AndroidManifest__enter_passphrase"
|
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/TextSecure.LightIntroTheme"
|
android:theme="@style/TextSecure.LightIntroTheme"
|
||||||
android:windowSoftInputMode="stateAlwaysVisible"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||||
|
|
||||||
<activity android:name=".NewConversationActivity"
|
<activity android:name=".NewConversationActivity"
|
||||||
|
BIN
res/drawable-hdpi/ic_fingerprint_white_48dp.png
Normal file
BIN
res/drawable-hdpi/ic_fingerprint_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
res/drawable-mdpi/ic_fingerprint_white_48dp.png
Normal file
BIN
res/drawable-mdpi/ic_fingerprint_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
res/drawable-xhdpi/ic_fingerprint_white_48dp.png
Normal file
BIN
res/drawable-xhdpi/ic_fingerprint_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
res/drawable-xxhdpi/ic_fingerprint_white_48dp.png
Normal file
BIN
res/drawable-xxhdpi/ic_fingerprint_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
res/drawable-xxxhdpi/ic_fingerprint_white_48dp.png
Normal file
BIN
res/drawable-xxxhdpi/ic_fingerprint_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
7
res/drawable/rounded_rectangle_dark.xml
Normal file
7
res/drawable/rounded_rectangle_dark.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
|
||||||
|
<solid android:color="@color/gray70"/>
|
||||||
|
<stroke android:width="1dp" android:color="@color/gray70"/>
|
||||||
|
<corners android:radius="10dp"/>
|
||||||
|
<padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp"/>
|
||||||
|
</shape>
|
7
res/drawable/rounded_rectangle_white.xml
Normal file
7
res/drawable/rounded_rectangle_white.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
|
||||||
|
<solid android:color="@color/white"/>
|
||||||
|
<stroke android:width="1dp" android:color="@color/white"/>
|
||||||
|
<corners android:radius="10dp"/>
|
||||||
|
<padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp"/>
|
||||||
|
</shape>
|
@ -1,28 +1,76 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/scroll_parent"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/prompt_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View android:id="@+id/shim"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fillViewport="true">
|
android:background="?login_top_background"
|
||||||
|
android:layout_above="@id/shim">
|
||||||
|
|
||||||
<RelativeLayout android:id="@+id/prompt_layout"
|
</FrameLayout>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView android:id="@+id/watermark"
|
<android.support.v7.widget.Toolbar
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/toolbar"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:layout_marginBottom="50dp"
|
android:layout_marginTop="20dp">
|
||||||
android:src="?lockscreen_watermark"
|
|
||||||
android:contentDescription="@string/PassphrasePromptActivity_watermark_content_description"
|
|
||||||
android:layout_marginTop="30dp"/>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/icon_transparent"
|
||||||
|
android:layout_gravity="center"/>
|
||||||
|
|
||||||
|
</android.support.v7.widget.Toolbar>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/watermark">
|
android:layout_marginLeft="30dp"
|
||||||
|
android:layout_marginRight="30dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="?login_floating_background"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:elevation="10dp">
|
||||||
|
|
||||||
|
<TextView android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="40dp"
|
||||||
|
android:text="@string/prompt_passphrase_activity__unlock_signal"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textSize="25sp"/>
|
||||||
|
|
||||||
|
<ImageView android:id="@+id/fingerprint_auth_container"
|
||||||
|
android:src="@drawable/ic_fingerprint_white_48dp"
|
||||||
|
android:background="@drawable/circle_tintable"
|
||||||
|
android:backgroundTint="@color/signal_primary"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginBottom="60dp"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<RelativeLayout android:id="@+id/password_auth_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="60dp"
|
||||||
|
tools:visibility="gone">
|
||||||
|
|
||||||
<EditText android:id="@+id/passphrase_edit"
|
<EditText android:id="@+id/passphrase_edit"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -83,6 +131,5 @@
|
|||||||
android:paddingBottom="5dp"/>
|
android:paddingBottom="5dp"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
</ScrollView>
|
|
@ -134,6 +134,9 @@
|
|||||||
|
|
||||||
<attr name="contact_list_divider" format="reference"/>
|
<attr name="contact_list_divider" format="reference"/>
|
||||||
|
|
||||||
|
<attr name="login_top_background" format="color"/>
|
||||||
|
<attr name="login_floating_background" format="reference"/>
|
||||||
|
|
||||||
<declare-styleable name="ColorPreference">
|
<declare-styleable name="ColorPreference">
|
||||||
<attr name="itemLayout" format="reference" />
|
<attr name="itemLayout" format="reference" />
|
||||||
<attr name="choices" format="reference" />
|
<attr name="choices" format="reference" />
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<string name="ApplicationPreferencesActivity_off">off</string>
|
<string name="ApplicationPreferencesActivity_off">off</string>
|
||||||
<string name="ApplicationPreferencesActivity_Off">Off</string>
|
<string name="ApplicationPreferencesActivity_Off">Off</string>
|
||||||
<string name="ApplicationPreferencesActivity_sms_mms_summary">SMS %1$s, MMS %2$s</string>
|
<string name="ApplicationPreferencesActivity_sms_mms_summary">SMS %1$s, MMS %2$s</string>
|
||||||
<string name="ApplicationPreferencesActivity_privacy_summary">Passphrase %1$s, Screen security %2$s</string>
|
<string name="ApplicationPreferencesActivity_privacy_summary">Screen lock %1$s, Screen security %2$s</string>
|
||||||
<string name="ApplicationPreferencesActivity_appearance_summary">Theme %1$s, Language %2$s</string>
|
<string name="ApplicationPreferencesActivity_appearance_summary">Theme %1$s, Language %2$s</string>
|
||||||
|
|
||||||
<!-- AppProtectionPreferenceFragment -->
|
<!-- AppProtectionPreferenceFragment -->
|
||||||
@ -1360,6 +1360,11 @@
|
|||||||
<string name="RegistrationActivity_wrong_number">Wrong number?</string>
|
<string name="RegistrationActivity_wrong_number">Wrong number?</string>
|
||||||
<string name="BackupUtil_never">Never</string>
|
<string name="BackupUtil_never">Never</string>
|
||||||
<string name="BackupUtil_unknown">Unknown</string>
|
<string name="BackupUtil_unknown">Unknown</string>
|
||||||
|
<string name="prompt_passphrase_activity__unlock_signal">Unlock Signal</string>
|
||||||
|
<string name="preferences_app_protection__screen_lock">Screen lock</string>
|
||||||
|
<string name="preferences_app_protection__lock_signal_access_with_android_screen_lock_or_fingerprint">Lock Signal access with Android screen lock or fingerprint</string>
|
||||||
|
<string name="preferences_app_protection__screen_lock_inactivity_timeout">Screen lock inactivity timeout</string>
|
||||||
|
<string name="AppProtectionPreferenceFragment_none">None</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- EOF -->
|
<!-- EOF -->
|
||||||
|
@ -58,23 +58,28 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="TextSecure.LightIntroTheme" parent="@style/Theme.AppCompat.Light">
|
<style name="TextSecure.LightIntroTheme" parent="@style/Theme.AppCompat.Light">
|
||||||
<!--<item name="colorPrimary">@android:color/transparent</item>-->
|
<item name="windowActionBar">false</item>
|
||||||
<item name="actionBarStyle">@style/TextSecure.IntroActionBar</item>
|
<item name="windowNoTitle">true</item>
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
<item name="windowActionModeOverlay">true</item>
|
||||||
<item name="colorAccent">@color/signal_primary</item>
|
<item name="colorAccent">@color/signal_primary</item>
|
||||||
|
|
||||||
<item name="android:textColorHint">#cc000000</item>
|
<item name="android:textColorHint">#cc000000</item>
|
||||||
<item name="centered_app_title_color">#55000000</item>
|
<item name="centered_app_title_color">#55000000</item>
|
||||||
<item name="ic_arrow_forward">@drawable/ic_arrow_forward_light</item>
|
<item name="ic_arrow_forward">@drawable/ic_arrow_forward_light</item>
|
||||||
<item name="lockscreen_watermark">@drawable/lockscreen_watermark_light</item>
|
<item name="lockscreen_watermark">@drawable/lockscreen_watermark_light</item>
|
||||||
<item name="android:windowBackground">@color/gray5</item>
|
<item name="android:windowBackground">@color/white</item>
|
||||||
<item name="ic_visibility">@drawable/ic_visibility_grey600_24dp</item>
|
<item name="ic_visibility">@drawable/ic_visibility_grey600_24dp</item>
|
||||||
<item name="ic_visibility_off">@drawable/ic_visibility_off_grey600_24dp</item>
|
<item name="ic_visibility_off">@drawable/ic_visibility_off_grey600_24dp</item>
|
||||||
|
|
||||||
|
<item name="login_top_background">@color/signal_primary</item>
|
||||||
|
<item name="login_floating_background">@drawable/rounded_rectangle_white</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="TextSecure.DarkIntroTheme" parent="@style/Theme.AppCompat">
|
<style name="TextSecure.DarkIntroTheme" parent="@style/Theme.AppCompat">
|
||||||
<item name="actionBarStyle">@style/TextSecure.IntroActionBar</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="windowActionModeOverlay">true</item>
|
||||||
<item name="colorAccent">@color/signal_primary_dark</item>
|
<item name="colorAccent">@color/signal_primary_dark</item>
|
||||||
|
|
||||||
<item name="android:textColorHint">@color/white</item>
|
<item name="android:textColorHint">@color/white</item>
|
||||||
@ -84,6 +89,9 @@
|
|||||||
<item name="android:windowBackground">@color/black</item>
|
<item name="android:windowBackground">@color/black</item>
|
||||||
<item name="ic_visibility">@drawable/ic_visibility_white_24dp</item>
|
<item name="ic_visibility">@drawable/ic_visibility_white_24dp</item>
|
||||||
<item name="ic_visibility_off">@drawable/ic_visibility_off_white_24dp</item>
|
<item name="ic_visibility_off">@drawable/ic_visibility_off_white_24dp</item>
|
||||||
|
|
||||||
|
<item name="login_top_background">@color/black</item>
|
||||||
|
<item name="login_floating_background">@drawable/rounded_rectangle_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="PopupAnimation" parent="@android:style/Animation">
|
<style name="PopupAnimation" parent="@android:style/Animation">
|
||||||
@ -352,4 +360,5 @@
|
|||||||
<style name="RationaleDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
|
<style name="RationaleDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
|
||||||
<item name="android:windowBackground">@drawable/permission_rationale_dialog_corners</item>
|
<item name="android:windowBackground">@drawable/permission_rationale_dialog_corners</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<PreferenceCategory android:title="@string/preferences_app_protection__app_access">
|
<PreferenceCategory android:title="@string/preferences_app_protection__app_access">
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||||
|
android:key="pref_android_screen_lock"
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:title="@string/preferences_app_protection__screen_lock"
|
||||||
|
android:summary="@string/preferences_app_protection__lock_signal_access_with_android_screen_lock_or_fingerprint"/>
|
||||||
|
|
||||||
|
<Preference android:title="@string/preferences_app_protection__screen_lock_inactivity_timeout"
|
||||||
|
android:key="pref_android_screen_lock_timeout"
|
||||||
|
android:dependency="pref_android_screen_lock"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||||
android:key="pref_enable_passphrase_temporary"
|
android:key="pref_enable_passphrase_temporary"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* Copyright (C) 2011 Whisper Systems
|
* Copyright (C) 2011 Whisper Systems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -16,32 +16,47 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.app.KeyguardManager;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
|
||||||
|
import android.support.v4.os.CancellationSignal;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.style.RelativeSizeSpan;
|
import android.text.style.RelativeSizeSpan;
|
||||||
import android.text.style.TypefaceSpan;
|
import android.text.style.TypefaceSpan;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.BounceInterpolator;
|
||||||
|
import android.view.animation.TranslateAnimation;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||||
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
||||||
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
|
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
|
||||||
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||||
import org.thoughtcrime.securesms.util.DynamicIntroTheme;
|
import org.thoughtcrime.securesms.util.DynamicIntroTheme;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity that prompts for a user's passphrase.
|
* Activity that prompts for a user's passphrase.
|
||||||
@ -50,18 +65,29 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||||||
*/
|
*/
|
||||||
public class PassphrasePromptActivity extends PassphraseActivity {
|
public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
|
|
||||||
|
private static final String TAG = PassphrasePromptActivity.class.getSimpleName();
|
||||||
|
|
||||||
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
||||||
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||||
|
|
||||||
|
private ImageView fingerprintPrompt;
|
||||||
|
|
||||||
private EditText passphraseText;
|
private EditText passphraseText;
|
||||||
private ImageButton showButton;
|
private ImageButton showButton;
|
||||||
private ImageButton hideButton;
|
private ImageButton hideButton;
|
||||||
private AnimatingToggle visibilityToggle;
|
private AnimatingToggle visibilityToggle;
|
||||||
|
|
||||||
|
private FingerprintManagerCompat fingerprintManager;
|
||||||
|
private CancellationSignal fingerprintCancellationSignal;
|
||||||
|
private FingerprintListener fingerprintListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.w(TAG, "onCreate()");
|
||||||
dynamicTheme.onCreate(this);
|
dynamicTheme.onCreate(this);
|
||||||
dynamicLanguage.onCreate(this);
|
dynamicLanguage.onCreate(this);
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.prompt_passphrase_activity);
|
setContentView(R.layout.prompt_passphrase_activity);
|
||||||
@ -73,6 +99,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
super.onResume();
|
super.onResume();
|
||||||
dynamicTheme.onResume(this);
|
dynamicTheme.onResume(this);
|
||||||
dynamicLanguage.onResume(this);
|
dynamicLanguage.onResume(this);
|
||||||
|
|
||||||
|
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
|
resumeScreenLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
|
pauseScreenLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,6 +140,17 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onActivityResult(int requestCode, int resultcode, Intent data) {
|
||||||
|
if (requestCode != 1) return;
|
||||||
|
|
||||||
|
if (resultcode == RESULT_OK) {
|
||||||
|
handleAuthenticated();
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Authentication failed");
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleLogSubmit() {
|
private void handleLogSubmit() {
|
||||||
Intent intent = new Intent(this, LogSubmitActivity.class);
|
Intent intent = new Intent(this, LogSubmitActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@ -120,6 +170,15 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleAuthenticated() {
|
||||||
|
try {
|
||||||
|
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||||
|
setMasterSecret(masterSecret);
|
||||||
|
} catch (InvalidPassphraseException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setPassphraseVisibility(boolean visibility) {
|
private void setPassphraseVisibility(boolean visibility) {
|
||||||
int cursorPosition = passphraseText.getSelectionStart();
|
int cursorPosition = passphraseText.getSelectionStart();
|
||||||
if (visibility) {
|
if (visibility) {
|
||||||
@ -133,15 +192,22 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
|
View passphraseAuthContainer = findViewById(R.id.password_auth_container);
|
||||||
getSupportActionBar().setCustomView(R.layout.centered_app_title);
|
ImageButton okButton = findViewById(R.id.ok_button);
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
|
||||||
ImageButton okButton = (ImageButton) findViewById(R.id.ok_button);
|
showButton = findViewById(R.id.passphrase_visibility);
|
||||||
|
hideButton = findViewById(R.id.passphrase_visibility_off);
|
||||||
|
visibilityToggle = findViewById(R.id.button_toggle);
|
||||||
|
passphraseText = findViewById(R.id.passphrase_edit);
|
||||||
|
fingerprintPrompt = findViewById(R.id.fingerprint_auth_container);
|
||||||
|
fingerprintManager = FingerprintManagerCompat.from(this);
|
||||||
|
fingerprintCancellationSignal = new CancellationSignal();
|
||||||
|
fingerprintListener = new FingerprintListener();
|
||||||
|
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
getSupportActionBar().setTitle("");
|
||||||
|
|
||||||
showButton = (ImageButton) findViewById(R.id.passphrase_visibility);
|
|
||||||
hideButton = (ImageButton) findViewById(R.id.passphrase_visibility_off);
|
|
||||||
visibilityToggle = (AnimatingToggle) findViewById(R.id.button_toggle);
|
|
||||||
passphraseText = (EditText) findViewById(R.id.passphrase_edit);
|
|
||||||
SpannableString hint = new SpannableString(" " + getString(R.string.PassphrasePromptActivity_enter_passphrase));
|
SpannableString hint = new SpannableString(" " + getString(R.string.PassphrasePromptActivity_enter_passphrase));
|
||||||
hint.setSpan(new RelativeSizeSpan(0.9f), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
hint.setSpan(new RelativeSizeSpan(0.9f), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
@ -153,6 +219,48 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
passphraseText.setOnEditorActionListener(new PassphraseActionListener());
|
passphraseText.setOnEditorActionListener(new PassphraseActionListener());
|
||||||
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock),
|
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock),
|
||||||
EditorInfo.IME_ACTION_DONE);
|
EditorInfo.IME_ACTION_DONE);
|
||||||
|
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||||
|
|
||||||
|
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
|
passphraseAuthContainer.setVisibility(View.GONE);
|
||||||
|
fingerprintPrompt.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
passphraseAuthContainer.setVisibility(View.VISIBLE);
|
||||||
|
fingerprintPrompt.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resumeScreenLock() {
|
||||||
|
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
|
||||||
|
|
||||||
|
assert keyguardManager != null;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && !keyguardManager.isKeyguardSecure()) {
|
||||||
|
Log.w(TAG ,"Keyguard not secure...");
|
||||||
|
handleAuthenticated();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 16 && fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
||||||
|
Log.w(TAG, "Listening for fingerprints...");
|
||||||
|
fingerprintCancellationSignal = new CancellationSignal();
|
||||||
|
fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= 21){
|
||||||
|
Log.w(TAG, "firing intent...");
|
||||||
|
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Signal", "");
|
||||||
|
startActivityForResult(intent, 1);
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Not compatible...");
|
||||||
|
handleAuthenticated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pauseScreenLock() {
|
||||||
|
if (Build.VERSION.SDK_INT >= 16 && fingerprintCancellationSignal != null) {
|
||||||
|
fingerprintCancellationSignal.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PassphraseActionListener implements TextView.OnEditorActionListener {
|
private class PassphraseActionListener implements TextView.OnEditorActionListener {
|
||||||
@ -202,4 +310,57 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
|||||||
this.passphraseText.setText("");
|
this.passphraseText.setText("");
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class FingerprintListener extends FingerprintManagerCompat.AuthenticationCallback {
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
||||||
|
Log.w(TAG, "Authentication error: " + errMsgId + " " + errString);
|
||||||
|
onAuthenticationFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
||||||
|
Log.w(TAG, "onAuthenticationSucceeded");
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||||
|
fingerprintPrompt.animate().setInterpolator(new BounceInterpolator()).scaleX(1.1f).scaleY(1.1f).setDuration(500).setListener(new AnimationCompleteListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
handleAuthenticated();
|
||||||
|
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationFailed() {
|
||||||
|
Log.w(TAG, "onAuthenticatoinFailed()");
|
||||||
|
FingerprintManagerCompat.AuthenticationCallback callback = this;
|
||||||
|
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN);
|
||||||
|
|
||||||
|
TranslateAnimation shake = new TranslateAnimation(0, 30, 0, 0);
|
||||||
|
shake.setDuration(50);
|
||||||
|
shake.setRepeatCount(7);
|
||||||
|
shake.setAnimationListener(new Animation.AnimationListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animation animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animation animation) {
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animation animation) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
fingerprintPrompt.startAnimation(shake);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.preferences;
|
package org.thoughtcrime.securesms.preferences;
|
||||||
|
|
||||||
|
import android.app.KeyguardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
@ -18,6 +20,7 @@ import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
|||||||
import org.thoughtcrime.securesms.BlockedContactsActivity;
|
import org.thoughtcrime.securesms.BlockedContactsActivity;
|
||||||
import org.thoughtcrime.securesms.PassphraseChangeActivity;
|
import org.thoughtcrime.securesms.PassphraseChangeActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||||
import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob;
|
import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
@ -37,16 +40,16 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||||||
|
|
||||||
disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary");
|
disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary");
|
||||||
|
|
||||||
this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF)
|
this.findPreference(TextSecurePreferences.SCREEN_LOCK).setOnPreferenceChangeListener(new ScreenLockListener());
|
||||||
.setOnPreferenceClickListener(new ChangePassphraseClickListener());
|
this.findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setOnPreferenceClickListener(new ScreenLockTimeoutListener());
|
||||||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF)
|
|
||||||
.setOnPreferenceClickListener(new PassphraseIntervalClickListener());
|
this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF).setOnPreferenceClickListener(new ChangePassphraseClickListener());
|
||||||
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF)
|
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF).setOnPreferenceClickListener(new PassphraseIntervalClickListener());
|
||||||
.setOnPreferenceChangeListener(new ReadReceiptToggleListener());
|
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF).setOnPreferenceChangeListener(new ReadReceiptToggleListener());
|
||||||
this.findPreference(PREFERENCE_CATEGORY_BLOCKED)
|
this.findPreference(PREFERENCE_CATEGORY_BLOCKED).setOnPreferenceClickListener(new BlockedContactsClickListener());
|
||||||
.setOnPreferenceClickListener(new BlockedContactsClickListener());
|
disablePassphrase.setOnPreferenceChangeListener(new DisablePassphraseClickListener());
|
||||||
disablePassphrase
|
|
||||||
.setOnPreferenceChangeListener(new DisablePassphraseClickListener());
|
initializeVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -59,17 +62,88 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||||||
super.onResume();
|
super.onResume();
|
||||||
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__privacy);
|
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__privacy);
|
||||||
|
|
||||||
initializeTimeoutSummary();
|
if (!TextSecurePreferences.isPasswordDisabled(getContext())) initializePassphraseTimeoutSummary();
|
||||||
|
else initializeScreenLockTimeoutSummary();
|
||||||
|
|
||||||
disablePassphrase.setChecked(!TextSecurePreferences.isPasswordDisabled(getActivity()));
|
disablePassphrase.setChecked(!TextSecurePreferences.isPasswordDisabled(getActivity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeTimeoutSummary() {
|
private void initializePassphraseTimeoutSummary() {
|
||||||
int timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(getActivity());
|
int timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(getActivity());
|
||||||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF)
|
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF)
|
||||||
.setSummary(getResources().getQuantityString(R.plurals.AppProtectionPreferenceFragment_minutes, timeoutMinutes, timeoutMinutes));
|
.setSummary(getResources().getQuantityString(R.plurals.AppProtectionPreferenceFragment_minutes, timeoutMinutes, timeoutMinutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeScreenLockTimeoutSummary() {
|
||||||
|
long timeoutSeconds = TextSecurePreferences.getScreenLockTimeout(getContext());
|
||||||
|
long hours = TimeUnit.SECONDS.toHours(timeoutSeconds);
|
||||||
|
long minutes = TimeUnit.SECONDS.toMinutes(timeoutSeconds) - (TimeUnit.SECONDS.toHours(timeoutSeconds) * 60 );
|
||||||
|
long seconds = TimeUnit.SECONDS.toSeconds(timeoutSeconds) - (TimeUnit.SECONDS.toMinutes(timeoutSeconds) * 60);
|
||||||
|
|
||||||
|
findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT)
|
||||||
|
.setSummary(timeoutSeconds <= 0 ? getString(R.string.AppProtectionPreferenceFragment_none) :
|
||||||
|
String.format("%02d:%02d:%02d", hours, minutes, seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeVisibility() {
|
||||||
|
if (TextSecurePreferences.isPasswordDisabled(getContext())) {
|
||||||
|
findPreference("pref_enable_passphrase_temporary").setVisible(false);
|
||||||
|
findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF).setVisible(false);
|
||||||
|
findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF).setVisible(false);
|
||||||
|
findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_PREF).setVisible(false);
|
||||||
|
|
||||||
|
KeyguardManager keyguardManager = (KeyguardManager)getContext().getSystemService(Context.KEYGUARD_SERVICE);
|
||||||
|
if (Build.VERSION.SDK_INT < 16 || !keyguardManager.isKeyguardSecure()) {
|
||||||
|
((SwitchPreferenceCompat)findPreference(TextSecurePreferences.SCREEN_LOCK)).setChecked(false);
|
||||||
|
findPreference(TextSecurePreferences.SCREEN_LOCK).setEnabled(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
findPreference(TextSecurePreferences.SCREEN_LOCK).setVisible(false);
|
||||||
|
findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScreenLockListener implements Preference.OnPreferenceChangeListener {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
TextSecurePreferences.setScreenLockEnabled(getContext(), (Boolean)newValue);
|
||||||
|
|
||||||
|
Intent intent = new Intent(getContext(), KeyCachingService.class);
|
||||||
|
intent.setAction(KeyCachingService.CLEAR_KEY_EVENT);
|
||||||
|
getContext().startService(intent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScreenLockTimeoutListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
int[] attributes = {R.attr.app_protect_timeout_picker_color};
|
||||||
|
TypedArray hmsStyle = getActivity().obtainStyledAttributes(attributes);
|
||||||
|
|
||||||
|
new HmsPickerBuilder().setFragmentManager(getFragmentManager())
|
||||||
|
.setStyleResId(hmsStyle.getResourceId(0, R.style.BetterPickersDialogFragment_Light))
|
||||||
|
.addHmsPickerDialogHandler(this)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
hmsStyle.recycle();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDialogHmsSet(int reference, int hours, int minutes, int seconds) {
|
||||||
|
long timeoutSeconds = Math.max(TimeUnit.HOURS.toSeconds(hours) +
|
||||||
|
TimeUnit.MINUTES.toSeconds(minutes) +
|
||||||
|
TimeUnit.SECONDS.toSeconds(seconds), 60);
|
||||||
|
|
||||||
|
TextSecurePreferences.setScreenLockTimeout(getContext(), timeoutSeconds);
|
||||||
|
initializeScreenLockTimeoutSummary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class BlockedContactsClickListener implements Preference.OnPreferenceClickListener {
|
private class BlockedContactsClickListener implements Preference.OnPreferenceClickListener {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
@ -118,7 +192,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||||||
(int)TimeUnit.SECONDS.toMinutes(seconds), 1);
|
(int)TimeUnit.SECONDS.toMinutes(seconds), 1);
|
||||||
|
|
||||||
TextSecurePreferences.setPassphraseTimeoutInterval(getActivity(), timeoutMinutes);
|
TextSecurePreferences.setPassphraseTimeoutInterval(getActivity(), timeoutMinutes);
|
||||||
initializeTimeoutSummary();
|
initializePassphraseTimeoutSummary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +216,8 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||||||
Intent intent = new Intent(getActivity(), KeyCachingService.class);
|
Intent intent = new Intent(getActivity(), KeyCachingService.class);
|
||||||
intent.setAction(KeyCachingService.DISABLE_ACTION);
|
intent.setAction(KeyCachingService.DISABLE_ACTION);
|
||||||
getActivity().startService(intent);
|
getActivity().startService(intent);
|
||||||
|
|
||||||
|
initializeVisibility();
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
builder.show();
|
builder.show();
|
||||||
@ -171,7 +247,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||||||
final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on);
|
final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on);
|
||||||
final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off);
|
final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off);
|
||||||
|
|
||||||
if (TextSecurePreferences.isPasswordDisabled(context)) {
|
if (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context)) {
|
||||||
if (TextSecurePreferences.isScreenSecurityEnabled(context)) {
|
if (TextSecurePreferences.isScreenSecurityEnabled(context)) {
|
||||||
return context.getString(privacySummaryResId, offRes, onRes);
|
return context.getString(privacySummaryResId, offRes, onRes);
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +83,7 @@ public class KeyCachingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized @Nullable MasterSecret getMasterSecret(Context context) {
|
public static synchronized @Nullable MasterSecret getMasterSecret(Context context) {
|
||||||
if (masterSecret == null && TextSecurePreferences.isPasswordDisabled(context)) {
|
if (masterSecret == null && (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context))) {
|
||||||
try {
|
try {
|
||||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(context, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(context, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||||
Intent intent = new Intent(context, KeyCachingService.class);
|
Intent intent = new Intent(context, KeyCachingService.class);
|
||||||
@ -146,7 +146,7 @@ public class KeyCachingService extends Service {
|
|||||||
this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null,
|
this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null,
|
||||||
this, KeyCachingService.class), 0);
|
this, KeyCachingService.class), 0);
|
||||||
|
|
||||||
if (TextSecurePreferences.isPasswordDisabled(this)) {
|
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
try {
|
try {
|
||||||
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
|
||||||
setMasterSecret(masterSecret);
|
setMasterSecret(masterSecret);
|
||||||
@ -210,8 +210,11 @@ public class KeyCachingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleDisableService() {
|
private void handleDisableService() {
|
||||||
if (TextSecurePreferences.isPasswordDisabled(this))
|
if (TextSecurePreferences.isPasswordDisabled(this) &&
|
||||||
|
!TextSecurePreferences.isScreenLockEnabled(this))
|
||||||
|
{
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLocaleChanged() {
|
private void handleLocaleChanged() {
|
||||||
@ -221,10 +224,19 @@ public class KeyCachingService extends Service {
|
|||||||
|
|
||||||
private void startTimeoutIfAppropriate() {
|
private void startTimeoutIfAppropriate() {
|
||||||
boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(this);
|
boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(this);
|
||||||
|
long screenTimeout = TextSecurePreferences.getScreenLockTimeout(this);
|
||||||
|
|
||||||
if ((activitiesRunning == 0) && (KeyCachingService.masterSecret != null) && timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) {
|
if ((activitiesRunning == 0) && (KeyCachingService.masterSecret != null) &&
|
||||||
long timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this);
|
(timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) ||
|
||||||
long timeoutMillis = TimeUnit.MINUTES.toMillis(timeoutMinutes);
|
(screenTimeout >= 60 && TextSecurePreferences.isScreenLockEnabled(this)))
|
||||||
|
{
|
||||||
|
long passphraseTimeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this);
|
||||||
|
long screenLockTimeoutSeconds = TextSecurePreferences.getScreenLockTimeout(this);
|
||||||
|
|
||||||
|
long timeoutMillis;
|
||||||
|
|
||||||
|
if (!TextSecurePreferences.isPasswordDisabled(this)) timeoutMillis = TimeUnit.MINUTES.toMillis(passphraseTimeoutMinutes);
|
||||||
|
else timeoutMillis = TimeUnit.SECONDS.toMillis(screenLockTimeoutSeconds);
|
||||||
|
|
||||||
Log.w("KeyCachingService", "Starting timeout: " + timeoutMillis);
|
Log.w("KeyCachingService", "Starting timeout: " + timeoutMillis);
|
||||||
|
|
||||||
@ -280,7 +292,7 @@ public class KeyCachingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void foregroundService() {
|
private void foregroundService() {
|
||||||
if (TextSecurePreferences.isPasswordDisabled(this)) {
|
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class TextSecurePreferences {
|
|||||||
public static final String ALL_MMS_PREF = "pref_all_mms";
|
public static final String ALL_MMS_PREF = "pref_all_mms";
|
||||||
public static final String ALL_SMS_PREF = "pref_all_sms";
|
public static final String ALL_SMS_PREF = "pref_all_sms";
|
||||||
public static final String PASSPHRASE_TIMEOUT_INTERVAL_PREF = "pref_timeout_interval";
|
public static final String PASSPHRASE_TIMEOUT_INTERVAL_PREF = "pref_timeout_interval";
|
||||||
private static final String PASSPHRASE_TIMEOUT_PREF = "pref_timeout_passphrase";
|
public static final String PASSPHRASE_TIMEOUT_PREF = "pref_timeout_passphrase";
|
||||||
public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
|
public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
|
||||||
private static final String ENTER_SENDS_PREF = "pref_enter_sends";
|
private static final String ENTER_SENDS_PREF = "pref_enter_sends";
|
||||||
private static final String ENTER_PRESENT_PREF = "pref_enter_key";
|
private static final String ENTER_PRESENT_PREF = "pref_enter_key";
|
||||||
@ -142,6 +142,25 @@ public class TextSecurePreferences {
|
|||||||
private static final String BACKUP_TIME = "pref_backup_next_time";
|
private static final String BACKUP_TIME = "pref_backup_next_time";
|
||||||
public static final String BACKUP_NOW = "pref_backup_create";
|
public static final String BACKUP_NOW = "pref_backup_create";
|
||||||
|
|
||||||
|
public static final String SCREEN_LOCK = "pref_android_screen_lock";
|
||||||
|
public static final String SCREEN_LOCK_TIMEOUT = "pref_android_screen_lock_timeout";
|
||||||
|
|
||||||
|
public static boolean isScreenLockEnabled(@NonNull Context context) {
|
||||||
|
return getBooleanPreference(context, SCREEN_LOCK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setScreenLockEnabled(@NonNull Context context, boolean value) {
|
||||||
|
setBooleanPreference(context, SCREEN_LOCK, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getScreenLockTimeout(@NonNull Context context) {
|
||||||
|
return getLongPreference(context, SCREEN_LOCK_TIMEOUT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setScreenLockTimeout(@NonNull Context context, long value) {
|
||||||
|
setLongPreference(context, SCREEN_LOCK_TIMEOUT, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setBackupPassphrase(@NonNull Context context, @Nullable String passphrase) {
|
public static void setBackupPassphrase(@NonNull Context context, @Nullable String passphrase) {
|
||||||
setStringPreference(context, BACKUP_PASSPHRASE, passphrase);
|
setStringPreference(context, BACKUP_PASSPHRASE, passphrase);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user