pull/1696/merge
Ceoslugpk 2 months ago committed by GitHub
commit 3f448f5e90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -3,17 +3,8 @@ apply plugin: 'com.google.protobuf'
apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'com.mikepenz.aboutlibraries.plugin'
def getCmdOutput = { cmd -> def getGitHash = { -> return "unknown" }
def stdout = new ByteArrayOutputStream() def getGitBranch = { -> return "unknown" }
exec {
commandLine cmd
standardOutput = stdout
}
return stdout.toString().trim()
}
def getGitHash = { -> return getCmdOutput(["git", "rev-parse", "--short", "HEAD"]) }
def getGitBranch = { -> return getCmdOutput(["git", "rev-parse", "--abbrev-ref", "HEAD"]) }
def packageName = "com.beemdevelopment.aegis" def packageName = "com.beemdevelopment.aegis"
def fileProviderAuthority = "${packageName}.fileprovider" def fileProviderAuthority = "${packageName}.fileprovider"
@ -26,7 +17,7 @@ android {
defaultConfig { defaultConfig {
applicationId "${packageName}" applicationId "${packageName}"
minSdkVersion 23 minSdkVersion 16
targetSdkVersion 35 targetSdkVersion 35
versionCode 80 versionCode 80
versionName "3.4.1" versionName "3.4.1"
@ -98,7 +89,7 @@ android {
cruncherEnabled = false cruncherEnabled = false
} }
defaultConfig { defaultConfig {
vectorDrawables.generatedDensities = [] vectorDrawables.useSupportLibrary = true
} }
packagingOptions { packagingOptions {
@ -112,8 +103,8 @@ android {
} }
compileOptions { compileOptions {
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_1_8
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled true
} }
lint { lint {
@ -191,7 +182,7 @@ dependencies {
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}" implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}" implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
implementation "com.google.guava:guava:${guavaVersion}-android" implementation "com.google.guava:guava:${guavaVersion}-android"
implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.material:material:1.4.0'
implementation 'com.google.protobuf:protobuf-javalite:4.31.0' implementation 'com.google.protobuf:protobuf-javalite:4.31.0'
implementation 'com.google.zxing:core:3.5.3' implementation 'com.google.zxing:core:3.5.3'
implementation('com.mikepenz:aboutlibraries:11.2.3') { implementation('com.mikepenz:aboutlibraries:11.2.3') {

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-sdk tools:overrideLibrary="androidx.camera.video, androidx.camera.camera2, androidx.camera.lifecycle, androidx.camera.view, androidx.camera.core, com.mikepenz.aboutlibraries" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
@ -20,17 +22,13 @@
<application <application
android:name=".AegisApplication" android:name=".AegisApplication"
android:allowBackup="true" android:allowBackup="true"
android:fullBackupOnly="true"
android:fullBackupContent="@xml/backup_rules_old" android:fullBackupContent="@xml/backup_rules_old"
android:dataExtractionRules="@xml/backup_rules"
android:backupAgent=".AegisBackupAgent" android:backupAgent=".AegisBackupAgent"
android:enableOnBackInvokedCallback="true"
android:icon="@mipmap/${iconName}" android:icon="@mipmap/${iconName}"
android:label="Aegis" android:label="Aegis"
android:supportsRtl="true" android:supportsRtl="true"
android:largeHeap="true" android:largeHeap="true"
android:theme="@style/Theme.Aegis.Launch" android:theme="@style/Theme.Aegis.Launch">
tools:targetApi="tiramisu">
<activity android:name=".ui.TransferEntriesActivity" <activity android:name=".ui.TransferEntriesActivity"
android:label="@string/title_activity_transfer" /> android:label="@string/title_activity_transfer" />
<activity <activity
@ -109,7 +107,8 @@
android:label="@string/tile_open_vault" android:label="@string/tile_open_vault"
android:icon="@drawable/ic_aegis_quicksettings" android:icon="@drawable/ic_aegis_quicksettings"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true"> android:exported="true"
tools:targetApi="n">
<intent-filter> <intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" /> <action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter> </intent-filter>
@ -122,7 +121,8 @@
android:label="@string/tile_open_scanner" android:label="@string/tile_open_scanner"
android:icon="@drawable/ic_aegis_quicksettings" android:icon="@drawable/ic_aegis_quicksettings"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true"> android:exported="true"
tools:targetApi="n">
<intent-filter> <intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" /> <action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter> </intent-filter>

@ -28,13 +28,17 @@ public class BiometricSlotInitializer extends BiometricPrompt.AuthenticationCall
public BiometricSlotInitializer(Fragment fragment, Listener listener) { public BiometricSlotInitializer(Fragment fragment, Listener listener) {
_listener = listener; _listener = listener;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
_prompt = new BiometricPrompt(fragment, new UiThreadExecutor(), this); _prompt = new BiometricPrompt(fragment, new UiThreadExecutor(), this);
} }
}
public BiometricSlotInitializer(FragmentActivity activity, Listener listener) { public BiometricSlotInitializer(FragmentActivity activity, Listener listener) {
_listener = listener; _listener = listener;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
_prompt = new BiometricPrompt(activity, new UiThreadExecutor(), this); _prompt = new BiometricPrompt(activity, new UiThreadExecutor(), this);
} }
}
/** /**
* Generates a new key in the Android KeyStore for the new BiometricSlot, * Generates a new key in the Android KeyStore for the new BiometricSlot,
@ -43,6 +47,11 @@ public class BiometricSlotInitializer extends BiometricPrompt.AuthenticationCall
* initialized and delivered back through the listener. * initialized and delivered back through the listener.
*/ */
public void authenticate(BiometricPrompt.PromptInfo info) { public void authenticate(BiometricPrompt.PromptInfo info) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
fail(0, "Biometric authentication is not supported on this device.");
return;
}
if (_slot != null) { if (_slot != null) {
throw new IllegalStateException("Biometric authentication already in progress"); throw new IllegalStateException("Biometric authentication already in progress");
} }
@ -114,20 +123,26 @@ public class BiometricSlotInitializer extends BiometricPrompt.AuthenticationCall
@Override @Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationError(errorCode, errString); super.onAuthenticationError(errorCode, errString);
fail(errorCode, errString.toString()); fail(errorCode, errString.toString());
} }
}
@Override @Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationSucceeded(result); super.onAuthenticationSucceeded(result);
_listener.onInitializeSlot(_slot, Objects.requireNonNull(result.getCryptoObject()).getCipher()); _listener.onInitializeSlot(_slot, Objects.requireNonNull(result.getCryptoObject()).getCipher());
} }
}
@Override @Override
public void onAuthenticationFailed() { public void onAuthenticationFailed() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationFailed(); super.onAuthenticationFailed();
} }
}
public interface Listener { public interface Listener {
void onInitializeSlot(BiometricSlot slot, Cipher cipher); void onInitializeSlot(BiometricSlot slot, Cipher cipher);

@ -11,10 +11,20 @@ public class BiometricsHelper {
} }
public static BiometricManager getManager(Context context) { public static BiometricManager getManager(Context context) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
return null;
}
BiometricManager manager = BiometricManager.from(context); BiometricManager manager = BiometricManager.from(context);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
if (manager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS) { if (manager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS) {
return manager; return manager;
} }
} else {
if (manager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
return manager;
}
}
return null; return null;
} }

@ -37,6 +37,13 @@ public class AboutActivity extends AegisActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (android.os.Build.VERSION.SDK_INT < 21) {
Toast.makeText(this, "About screen is not supported on this device.", Toast.LENGTH_LONG).show();
finish();
return;
}
if (abortIfOrphan(savedInstanceState)) { if (abortIfOrphan(savedInstanceState)) {
return; return;
} }

@ -129,6 +129,7 @@ public class AuthActivity extends AegisActivity {
// only show the biometric prompt if the api version is new enough, permission is granted, a scanner is found and a biometric slot is found // only show the biometric prompt if the api version is new enough, permission is granted, a scanner is found and a biometric slot is found
_slots = _vaultFile.getHeader().getSlots(); _slots = _vaultFile.getHeader().getSlots();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (_slots.has(BiometricSlot.class) && BiometricsHelper.isAvailable(this)) { if (_slots.has(BiometricSlot.class) && BiometricsHelper.isAvailable(this)) {
boolean invalidated = false; boolean invalidated = false;
@ -163,6 +164,7 @@ public class AuthActivity extends AegisActivity {
biometricsButton.setVisibility(View.GONE); biometricsButton.setVisibility(View.GONE);
} }
} }
}
_decryptButton.setOnClickListener(v -> { _decryptButton.setOnClickListener(v -> {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
@ -177,12 +179,13 @@ public class AuthActivity extends AegisActivity {
_decryptButton.setEnabled(false); _decryptButton.setEnabled(false);
}); });
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
biometricsButton.setOnClickListener(v -> { biometricsButton.setOnClickListener(v -> {
if (_prefs.isPasswordReminderNeeded()) { if (_prefs.isPasswordReminderNeeded()) {
Dialogs.showSecureDialog(new MaterialAlertDialogBuilder(this, R.style.ThemeOverlay_Aegis_AlertDialog_Warning) Dialogs.showSecureDialog(new MaterialAlertDialogBuilder(this, R.style.ThemeOverlay_Aegis_AlertDialog_Warning)
.setTitle(getString(R.string.password_reminder_dialog_title)) .setTitle(getString(R.string.password_reminder_dialog_title))
.setMessage(getString(R.string.password_reminder_dialog_message)) .setMessage(getString(R.string.password_reminder_dialog_message))
.setCancelable(false) .setCancelable(false))
.setIconAttribute(android.R.attr.alertDialogIcon) .setIconAttribute(android.R.attr.alertDialogIcon)
.setPositiveButton(android.R.string.ok, (dialog1, which) -> { .setPositiveButton(android.R.string.ok, (dialog1, which) -> {
showBiometricPrompt(); showBiometricPrompt();
@ -193,6 +196,7 @@ public class AuthActivity extends AegisActivity {
} }
}); });
} }
}
@Override @Override
protected void onSaveInstanceState(@NonNull Bundle outState) { protected void onSaveInstanceState(@NonNull Bundle outState) {
@ -216,29 +220,35 @@ public class AuthActivity extends AegisActivity {
focusPasswordField(); focusPasswordField();
} }
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (_bioKey != null && _bioPrompt == null && !_inhibitBioPrompt && !remindPassword) { if (_bioKey != null && _bioPrompt == null && !_inhibitBioPrompt && !remindPassword) {
_bioPrompt = showBiometricPrompt(); _bioPrompt = showBiometricPrompt();
} }
}
_inhibitBioPrompt = false; _inhibitBioPrompt = false;
} }
@Override @Override
public void onPause() { public void onPause() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!isChangingConfigurations() && _bioPrompt != null) { if (!isChangingConfigurations() && _bioPrompt != null) {
_bioPrompt.cancelAuthentication(); _bioPrompt.cancelAuthentication();
_bioPrompt = null; _bioPrompt = null;
} }
}
super.onPause(); super.onPause();
} }
@Override @Override
public void onAttachedToWindow() { public void onAttachedToWindow() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (_bioKey != null && _prefs.isPasswordReminderNeeded()) { if (_bioKey != null && _prefs.isPasswordReminderNeeded()) {
showPasswordReminder(); showPasswordReminder();
} }
} }
}
private void focusPasswordField() { private void focusPasswordField() {
_textPassword.requestFocus(); _textPassword.requestFocus();
@ -268,6 +278,7 @@ public class AuthActivity extends AegisActivity {
} }
public BiometricPrompt showBiometricPrompt() { public BiometricPrompt showBiometricPrompt() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(_textPassword.getWindowToken(), 0); imm.hideSoftInputFromWindow(_textPassword.getWindowToken(), 0);
@ -291,6 +302,8 @@ public class AuthActivity extends AegisActivity {
prompt.authenticate(info, cryptoObj); prompt.authenticate(info, cryptoObj);
return prompt; return prompt;
} }
return null;
}
private void finish(MasterKey key, boolean isSlotRepaired) { private void finish(MasterKey key, boolean isSlotRepaired) {
VaultFileCredentials creds = new VaultFileCredentials(key, _slots); VaultFileCredentials creds = new VaultFileCredentials(key, _slots);
@ -366,6 +379,7 @@ public class AuthActivity extends AegisActivity {
private class BiometricPromptListener extends BiometricPrompt.AuthenticationCallback { private class BiometricPromptListener extends BiometricPrompt.AuthenticationCallback {
@Override @Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationError(errorCode, errString); super.onAuthenticationError(errorCode, errString);
_bioPrompt = null; _bioPrompt = null;
@ -374,9 +388,11 @@ public class AuthActivity extends AegisActivity {
Toast.makeText(AuthActivity.this, errString, Toast.LENGTH_LONG).show(); Toast.makeText(AuthActivity.this, errString, Toast.LENGTH_LONG).show();
} }
} }
}
@Override @Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationSucceeded(result); super.onAuthenticationSucceeded(result);
_bioPrompt = null; _bioPrompt = null;
@ -393,10 +409,13 @@ public class AuthActivity extends AegisActivity {
finish(key, false); finish(key, false);
} }
}
@Override @Override
public void onAuthenticationFailed() { public void onAuthenticationFailed() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
super.onAuthenticationFailed(); super.onAuthenticationFailed();
} }
} }
} }
}

@ -240,10 +240,15 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
dialog.dismiss(); dialog.dismiss();
startScanImageActivity(); startScanImageActivity();
}); });
view.findViewById(R.id.fab_scan).setOnClickListener(v3 -> { View fabScan = view.findViewById(R.id.fab_scan);
if (android.os.Build.VERSION.SDK_INT < 21) {
fabScan.setVisibility(View.GONE);
} else {
fabScan.setOnClickListener(v3 -> {
dialog.dismiss(); dialog.dismiss();
startScanActivity(); startScanActivity();
}); });
}
Dialogs.showSecureDialog(dialog); Dialogs.showSecureDialog(dialog);
}); });
@ -805,7 +810,9 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
switch (action) { switch (action) {
case "scan": case "scan":
if (android.os.Build.VERSION.SDK_INT >= 21) {
startScanActivity(); startScanActivity();
}
break; break;
} }
@ -974,6 +981,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
_menu = menu; _menu = menu;
getMenuInflater().inflate(R.menu.menu_main, menu); getMenuInflater().inflate(R.menu.menu_main, menu);
if (android.os.Build.VERSION.SDK_INT < 21) {
menu.findItem(R.id.action_about).setVisible(false);
}
updateLockIcon(); updateLockIcon();
updateSortCategoryMenu(); updateSortCategoryMenu();
@ -1050,8 +1061,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
if (itemId == R.id.action_settings) { if (itemId == R.id.action_settings) {
startPreferencesActivity(); startPreferencesActivity();
} else if (itemId == R.id.action_about) { } else if (itemId == R.id.action_about) {
if (android.os.Build.VERSION.SDK_INT >= 21) {
Intent intent = new Intent(this, AboutActivity.class); Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent); startActivity(intent);
}
} else if (itemId == R.id.action_lock) { } else if (itemId == R.id.action_lock) {
_vaultManager.lock(true); _vaultManager.lock(true);
} else { } else {

@ -33,6 +33,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@androidx.annotation.RequiresApi(21)
public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Listener { public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Listener {
private ProcessCameraProvider _cameraProvider; private ProcessCameraProvider _cameraProvider;
private ListenableFuture<ProcessCameraProvider> _cameraProviderFuture; private ListenableFuture<ProcessCameraProvider> _cameraProviderFuture;
@ -52,6 +53,13 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (android.os.Build.VERSION.SDK_INT < 21) {
Toast.makeText(this, R.string.camera_not_supported, Toast.LENGTH_LONG).show();
finish();
return;
}
if (abortIfOrphan(savedInstanceState)) { if (abortIfOrphan(savedInstanceState)) {
return; return;
} }

@ -109,6 +109,7 @@ public class SecurityPreferencesFragment extends PreferencesFragment {
_biometricsPreference = requirePreference("pref_biometrics"); _biometricsPreference = requirePreference("pref_biometrics");
_biometricsPreference.setOnPreferenceChangeListener((preference, newValue) -> { _biometricsPreference.setOnPreferenceChangeListener((preference, newValue) -> {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
VaultFileCredentials creds = _vaultManager.getVault().getCredentials(); VaultFileCredentials creds = _vaultManager.getVault().getCredentials();
SlotList slots = creds.getSlots(); SlotList slots = creds.getSlots();
@ -138,6 +139,7 @@ public class SecurityPreferencesFragment extends PreferencesFragment {
saveAndBackupVault(); saveAndBackupVault();
updateEncryptionPreferences(); updateEncryptionPreferences();
} }
}
return false; return false;
}); });
@ -271,12 +273,20 @@ public class SecurityPreferencesFragment extends PreferencesFragment {
SlotList slots = _vaultManager.getVault().getCredentials().getSlots(); SlotList slots = _vaultManager.getVault().getCredentials().getSlots();
boolean multiBackupPassword = slots.findBackupPasswordSlots().size() > 1; boolean multiBackupPassword = slots.findBackupPasswordSlots().size() > 1;
boolean multiPassword = slots.findRegularPasswordSlots().size() > 1; boolean multiPassword = slots.findRegularPasswordSlots().size() > 1;
_setPasswordPreference.setEnabled(!multiPassword);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
boolean multiBio = slots.findAll(BiometricSlot.class).size() > 1; boolean multiBio = slots.findAll(BiometricSlot.class).size() > 1;
boolean canUseBio = BiometricsHelper.isAvailable(requireContext()); boolean canUseBio = BiometricsHelper.isAvailable(requireContext());
_setPasswordPreference.setEnabled(!multiPassword);
_biometricsPreference.setEnabled(canUseBio && !multiBio); _biometricsPreference.setEnabled(canUseBio && !multiBio);
_biometricsPreference.setChecked(slots.has(BiometricSlot.class), true); _biometricsPreference.setChecked(slots.has(BiometricSlot.class), true);
_passwordReminderPreference.setVisible(slots.has(BiometricSlot.class)); _passwordReminderPreference.setVisible(slots.has(BiometricSlot.class));
} else {
_biometricsPreference.setEnabled(false);
_biometricsPreference.setChecked(false, true);
_passwordReminderPreference.setVisible(false);
}
_backupPasswordChangePreference.setEnabled(!multiBackupPassword); _backupPasswordChangePreference.setEnabled(!multiBackupPassword);
} else { } else {
_setPasswordPreference.setEnabled(false); _setPasswordPreference.setEnabled(false);
@ -399,6 +409,7 @@ public class SecurityPreferencesFragment extends PreferencesFragment {
private class RegisterBiometricsListener implements BiometricSlotInitializer.Listener { private class RegisterBiometricsListener implements BiometricSlotInitializer.Listener {
@Override @Override
public void onInitializeSlot(BiometricSlot slot, Cipher cipher) { public void onInitializeSlot(BiometricSlot slot, Cipher cipher) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
VaultFileCredentials creds = _vaultManager.getVault().getCredentials(); VaultFileCredentials creds = _vaultManager.getVault().getCredentials();
try { try {
slot.setKey(creds.getKey(), cipher); slot.setKey(creds.getKey(), cipher);
@ -413,14 +424,17 @@ public class SecurityPreferencesFragment extends PreferencesFragment {
saveAndBackupVault(); saveAndBackupVault();
updateEncryptionPreferences(); updateEncryptionPreferences();
} }
}
@Override @Override
public void onSlotInitializationFailed(int errorCode, @NonNull CharSequence errString) { public void onSlotInitializationFailed(int errorCode, @NonNull CharSequence errString) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!BiometricsHelper.isCanceled(errorCode)) { if (!BiometricsHelper.isCanceled(errorCode)) {
Dialogs.showErrorDialog(requireContext(), R.string.encryption_enable_biometrics_error, errString); Dialogs.showErrorDialog(requireContext(), R.string.encryption_enable_biometrics_error, errString);
} }
} }
} }
}
private class EnableEncryptionListener implements Dialogs.PasswordSlotListener { private class EnableEncryptionListener implements Dialogs.PasswordSlotListener {
@Override @Override

@ -98,6 +98,7 @@ public class SecuritySetupSlide extends SlideFragment {
} }
private void showBiometricPrompt() { private void showBiometricPrompt() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
BiometricSlotInitializer initializer = new BiometricSlotInitializer(this, new BiometricsListener()); BiometricSlotInitializer initializer = new BiometricSlotInitializer(this, new BiometricsListener());
BiometricPrompt.PromptInfo info = new BiometricPrompt.PromptInfo.Builder() BiometricPrompt.PromptInfo info = new BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.set_up_biometric)) .setTitle(getString(R.string.set_up_biometric))
@ -105,6 +106,7 @@ public class SecuritySetupSlide extends SlideFragment {
.build(); .build();
initializer.authenticate(info); initializer.authenticate(info);
} }
}
private void deriveKey() { private void deriveKey() {
PasswordSlot slot = new PasswordSlot(); PasswordSlot slot = new PasswordSlot();
@ -119,9 +121,11 @@ public class SecuritySetupSlide extends SlideFragment {
case CRYPT_TYPE_NONE: case CRYPT_TYPE_NONE:
return true; return true;
case CRYPT_TYPE_BIOMETRIC: case CRYPT_TYPE_BIOMETRIC:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!_creds.getSlots().has(BiometricSlot.class)) { if (!_creds.getSlots().has(BiometricSlot.class)) {
return false; return false;
} }
}
// intentional fallthrough // intentional fallthrough
case CRYPT_TYPE_PASS: case CRYPT_TYPE_PASS:
if (EditTextHelper.areEditTextsEqual(_textPassword, _textPasswordConfirm)) { if (EditTextHelper.areEditTextsEqual(_textPassword, _textPasswordConfirm)) {
@ -140,7 +144,7 @@ public class SecuritySetupSlide extends SlideFragment {
Toast.makeText(requireContext(), R.string.password_equality_error, Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), R.string.password_equality_error, Toast.LENGTH_SHORT).show();
} else if (_cryptType != SecurityPickerSlide.CRYPT_TYPE_BIOMETRIC) { } else if (_cryptType != SecurityPickerSlide.CRYPT_TYPE_BIOMETRIC) {
deriveKey(); deriveKey();
} else if (!_creds.getSlots().has(BiometricSlot.class)) { } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && !_creds.getSlots().has(BiometricSlot.class)) {
showBiometricPrompt(); showBiometricPrompt();
} }
} }
@ -170,6 +174,7 @@ public class SecuritySetupSlide extends SlideFragment {
private class BiometricsListener implements BiometricSlotInitializer.Listener { private class BiometricsListener implements BiometricSlotInitializer.Listener {
@Override @Override
public void onInitializeSlot(BiometricSlot slot, Cipher cipher) { public void onInitializeSlot(BiometricSlot slot, Cipher cipher) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
try { try {
slot.setKey(_creds.getKey(), cipher); slot.setKey(_creds.getKey(), cipher);
_creds.getSlots().add(slot); _creds.getSlots().add(slot);
@ -181,12 +186,15 @@ public class SecuritySetupSlide extends SlideFragment {
deriveKey(); deriveKey();
} }
}
@Override @Override
public void onSlotInitializationFailed(int errorCode, @NonNull CharSequence errString) { public void onSlotInitializationFailed(int errorCode, @NonNull CharSequence errString) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (!BiometricsHelper.isCanceled(errorCode)) { if (!BiometricsHelper.isCanceled(errorCode)) {
Dialogs.showErrorDialog(requireContext(), R.string.encryption_enable_biometrics_error, errString); Dialogs.showErrorDialog(requireContext(), R.string.encryption_enable_biometrics_error, errString);
} }
} }
} }
} }
}

@ -16,7 +16,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:paddingHorizontal="48dp" android:paddingLeft="48dp"
android:paddingRight="48dp"
android:paddingTop="48dp" android:paddingTop="48dp"
android:orientation="vertical"> android:orientation="vertical">
@ -126,6 +127,7 @@
android:textAllCaps="true" android:textAllCaps="true"
android:textStyle="bold" android:textStyle="bold"
android:textColor="?attr/colorOnSurfaceDim" android:textColor="?attr/colorOnSurfaceDim"
android:paddingVertical="50dp" /> android:paddingTop="50dp"
android:paddingBottom="50dp" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

@ -240,7 +240,6 @@
</LinearLayout> </LinearLayout>
<RelativeLayout <RelativeLayout
android:foreground="?android:attr/selectableItemBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/accordian_header" android:id="@+id/accordian_header"
@ -275,7 +274,8 @@
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
android:alpha="0" android:alpha="0"
android:layout_marginHorizontal="10dp"> android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<LinearLayout <LinearLayout
android:id="@+id/layout_type_algo" android:id="@+id/layout_type_algo"
android:layout_width="match_parent" android:layout_width="match_parent"

@ -26,7 +26,7 @@
android:layout_width="15dp" android:layout_width="15dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="-11dp" android:layout_marginStart="-11dp"
android:backgroundTint="?attr/colorFavorite" app:backgroundTint="?attr/colorFavorite"
android:background="@drawable/favorite_indicator" /> android:background="@drawable/favorite_indicator" />
<RelativeLayout <RelativeLayout
@ -125,7 +125,6 @@
android:fontFamily="sans-serif-light" android:fontFamily="sans-serif-light"
tools:text="012 345" tools:text="012 345"
android:id="@+id/profile_code" android:id="@+id/profile_code"
android:layoutDirection="ltr"
android:textSize="34sp" android:textSize="34sp"
android:layout_below="@id/description" android:layout_below="@id/description"
android:textColor="?attr/colorCode" android:textColor="?attr/colorCode"

@ -619,4 +619,5 @@
<item quantity="one">%d item selected</item> <item quantity="one">%d item selected</item>
<item quantity="other">%d items selected</item> <item quantity="other">%d items selected</item>
</plurals> </plurals>
<string name="camera_not_supported">Camera is not supported on this device.</string>
</resources> </resources>

Loading…
Cancel
Save