From 1e3ceefeec61081ca18a6858f8f4a599e14edce8 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Wed, 14 Sep 2022 19:29:36 +0200 Subject: [PATCH] Request permission to show notifications This is needed since API 33, because we show a "Vault unlocked" notification if the user has enabled encryption and has unlocked the vault. --- .../com/beemdevelopment/aegis/AegisTest.java | 5 +++++ .../com/beemdevelopment/aegis/IntroTest.java | 8 +++++++ .../beemdevelopment/aegis/OverallTest.java | 1 + app/src/main/AndroidManifest.xml | 1 + .../aegis/ui/AuthActivity.java | 12 ++++++++++ .../aegis/ui/IntroActivity.java | 22 ++++++++++++++++++- .../aegis/vault/VaultManager.java | 6 ++++- 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/beemdevelopment/aegis/AegisTest.java b/app/src/androidTest/java/com/beemdevelopment/aegis/AegisTest.java index d3dfff30..806a724c 100644 --- a/app/src/androidTest/java/com/beemdevelopment/aegis/AegisTest.java +++ b/app/src/androidTest/java/com/beemdevelopment/aegis/AegisTest.java @@ -1,11 +1,13 @@ package com.beemdevelopment.aegis; +import android.Manifest; import android.view.View; import androidx.annotation.Nullable; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; import com.beemdevelopment.aegis.crypto.CryptoUtils; import com.beemdevelopment.aegis.crypto.SCryptParameters; @@ -42,6 +44,9 @@ public abstract class AegisTest { @Rule public HiltAndroidRule hiltRule = new HiltAndroidRule(this); + @Rule + public final GrantPermissionRule permRule = GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS); + @Inject protected VaultManager _vaultManager; diff --git a/app/src/androidTest/java/com/beemdevelopment/aegis/IntroTest.java b/app/src/androidTest/java/com/beemdevelopment/aegis/IntroTest.java index 7fe70971..062325db 100644 --- a/app/src/androidTest/java/com/beemdevelopment/aegis/IntroTest.java +++ b/app/src/androidTest/java/com/beemdevelopment/aegis/IntroTest.java @@ -82,6 +82,7 @@ public class IntroTest extends AegisTest { @Test public void doIntro_None() { + assertFalse(_prefs.isIntroDone()); ViewInteraction next = onView(withId(R.id.btnNext)); ViewInteraction prev = onView(withId(R.id.btnPrevious)); @@ -98,10 +99,12 @@ public class IntroTest extends AegisTest { VaultRepository vault = _vaultManager.getVault(); assertFalse(vault.isEncryptionEnabled()); assertNull(vault.getCredentials()); + assertTrue(_prefs.isIntroDone()); } @Test public void doIntro_Password() { + assertFalse(_prefs.isIntroDone()); ViewInteraction next = onView(withId(R.id.btnNext)); ViewInteraction prev = onView(withId(R.id.btnPrevious)); @@ -129,10 +132,12 @@ public class IntroTest extends AegisTest { assertTrue(vault.isEncryptionEnabled()); assertTrue(slots.has(PasswordSlot.class)); assertFalse(slots.has(BiometricSlot.class)); + assertTrue(_prefs.isIntroDone()); } @Test public void doIntro_Import_Plain() { + assertFalse(_prefs.isIntroDone()); Uri uri = getResourceUri("aegis_plain.json"); Intent resultData = new Intent(); resultData.setData(uri); @@ -147,10 +152,12 @@ public class IntroTest extends AegisTest { VaultRepository vault = _vaultManager.getVault(); assertFalse(vault.isEncryptionEnabled()); assertNull(vault.getCredentials()); + assertTrue(_prefs.isIntroDone()); } @Test public void doIntro_Import_Encrypted() { + assertFalse(_prefs.isIntroDone()); Uri uri = getResourceUri("aegis_encrypted.json"); Intent resultData = new Intent(); resultData.setData(uri); @@ -169,6 +176,7 @@ public class IntroTest extends AegisTest { assertTrue(vault.isEncryptionEnabled()); assertTrue(slots.has(PasswordSlot.class)); assertFalse(slots.has(BiometricSlot.class)); + assertTrue(_prefs.isIntroDone()); } private Uri getResourceUri(String resourceName) { diff --git a/app/src/androidTest/java/com/beemdevelopment/aegis/OverallTest.java b/app/src/androidTest/java/com/beemdevelopment/aegis/OverallTest.java index ca15b5cb..86e7bf65 100644 --- a/app/src/androidTest/java/com/beemdevelopment/aegis/OverallTest.java +++ b/app/src/androidTest/java/com/beemdevelopment/aegis/OverallTest.java @@ -75,6 +75,7 @@ public class OverallTest extends AegisTest { VaultRepository vault = _vaultManager.getVault(); assertTrue(vault.isEncryptionEnabled()); assertTrue(vault.getCredentials().getSlots().has(PasswordSlot.class)); + assertTrue(_prefs.isIntroDone()); List entries = Arrays.asList( generateEntry(TotpInfo.class, "Frank", "Google"), diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ef9e4fca..c5bcd524 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ + = 33) { + PermissionHelper.request(this, CODE_PERM_NOTIFICATIONS, Manifest.permission.POST_NOTIFICATIONS); + } } else { _inhibitBioPrompt = savedInstanceState.getBoolean("inhibitBioPrompt", false); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/IntroActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/IntroActivity.java index ae2eb99d..8c85d7fb 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/IntroActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/IntroActivity.java @@ -5,12 +5,18 @@ import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_NONE; import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_PASS; +import android.Manifest; +import android.os.Build; import android.os.Bundle; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.ThemeMap; +import com.beemdevelopment.aegis.helpers.PermissionHelper; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; import com.beemdevelopment.aegis.ui.intro.IntroBaseActivity; import com.beemdevelopment.aegis.ui.intro.SlideFragment; @@ -24,6 +30,9 @@ import com.beemdevelopment.aegis.vault.slots.BiometricSlot; import com.beemdevelopment.aegis.vault.slots.PasswordSlot; public class IntroActivity extends IntroBaseActivity { + // Permission request codes + private static final int CODE_PERM_NOTIFICATIONS = 0; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -40,7 +49,7 @@ public class IntroActivity extends IntroBaseActivity { } @Override - protected boolean onBeforeSlideChanged(Class oldSlide, Class newSlide) { + protected boolean onBeforeSlideChanged(Class oldSlide, @NonNull Class newSlide) { // hide the keyboard before every slide change InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(findViewById(android.R.id.content).getWindowToken(), 0); @@ -67,6 +76,17 @@ public class IntroActivity extends IntroBaseActivity { return false; } + @Override + protected void onAfterSlideChanged(@Nullable Class oldSlide, @NonNull Class newSlide) { + // If the user has enabled encryption, we need to request permission to show notifications + // in order to be able to show the "Vault unlocked" notification. + if (newSlide == DoneSlide.class && getState().getSerializable("creds") != null) { + if (Build.VERSION.SDK_INT >= 33) { + PermissionHelper.request(this, CODE_PERM_NOTIFICATIONS, Manifest.permission.POST_NOTIFICATIONS); + } + } + } + @Override protected void onDonePressed() { Bundle state = getState(); diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultManager.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultManager.java index df414587..c99b5687 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultManager.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultManager.java @@ -1,5 +1,6 @@ package com.beemdevelopment.aegis.vault; +import android.Manifest; import android.app.Activity; import android.app.backup.BackupManager; import android.content.ActivityNotFoundException; @@ -14,6 +15,7 @@ import com.beemdevelopment.aegis.Preferences; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.crypto.KeyStoreHandle; import com.beemdevelopment.aegis.crypto.KeyStoreHandleException; +import com.beemdevelopment.aegis.helpers.PermissionHelper; import com.beemdevelopment.aegis.services.NotificationService; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; @@ -350,7 +352,9 @@ public class VaultManager { } private void startNotificationService() { - _context.startService(getNotificationServiceIntent()); + if (PermissionHelper.granted(_context, Manifest.permission.POST_NOTIFICATIONS)) { + _context.startService(getNotificationServiceIntent()); + } } private void stopNotificationService() {