From 684d9806bec52b844a8f4f1844dadb41eef677ca Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 4 Apr 2024 09:35:37 +0200 Subject: [PATCH 1/2] Enhance passcode Signed-off-by: alperozturk --- .../java/com/owncloud/android/MainApp.java | 16 +++++ .../android/authentication/PassCodeManager.kt | 71 +++++-------------- 2 files changed, 35 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/MainApp.java b/app/src/main/java/com/owncloud/android/MainApp.java index a8b19e9eaeda..0bdf6669a7db 100644 --- a/app/src/main/java/com/owncloud/android/MainApp.java +++ b/app/src/main/java/com/owncloud/android/MainApp.java @@ -113,6 +113,8 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.util.Pair; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.ProcessLifecycleOwner; import androidx.multidex.MultiDexApplication; import dagger.android.AndroidInjector; import dagger.android.DispatchingAndroidInjector; @@ -297,6 +299,8 @@ public void onCreate() { setAppTheme(preferences.getDarkThemeMode()); super.onCreate(); + ProcessLifecycleOwner.get().getLifecycle().addObserver(lifecycleEventObserver); + insertConscrypt(); initSecurityKeyManager(); @@ -362,6 +366,18 @@ public void onCreate() { registerGlobalPassCodeProtection(); } + private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> { + switch (event) { + case ON_START -> { + Log_OC.d(TAG, "APP IN FOREGROUND"); + } + case ON_STOP -> { + passCodeManager.setCanAskPin(true); + Log_OC.d(TAG, "APP IN BACKGROUND"); + } + } + }); + private void registerGlobalPassCodeProtection() { registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { diff --git a/app/src/main/java/com/owncloud/android/authentication/PassCodeManager.kt b/app/src/main/java/com/owncloud/android/authentication/PassCodeManager.kt index fed4cf3f434e..062e6acb4f6c 100644 --- a/app/src/main/java/com/owncloud/android/authentication/PassCodeManager.kt +++ b/app/src/main/java/com/owncloud/android/authentication/PassCodeManager.kt @@ -49,12 +49,10 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock * the pass code being requested on screen rotations. */ private const val PASS_CODE_TIMEOUT = 5000 - - private const val TAG = "PassCodeManager" } - private var visibleActivitiesCounter = 0 - private var lastResumedActivity: Activity? = null + var canAskPin = true + private var askPinWhenDeviceLocked = false private fun isExemptActivity(activity: Activity): Boolean { return exemptOfPasscodeActivities.contains(activity.javaClass) @@ -69,7 +67,7 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock val passcodeRequested = passCodeShouldBeRequested(timestamp) val credentialsRequested = deviceCredentialsShouldBeRequested(timestamp, activity) val shouldHideView = passcodeRequested || credentialsRequested - toggleActivityVisibility(shouldHideView, activity) + getActivityRootView(activity)?.visibility = if (shouldHideView) View.GONE else View.VISIBLE askedForPin = shouldHideView if (passcodeRequested) { @@ -82,47 +80,16 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock } } - if (!askedForPin && preferences.lockTimestamp != 0L) { + if (!askedForPin && preferences.lockTimestamp != 0L || askPinWhenDeviceLocked) { updateLockTimestamp() - } - - if (!isExemptActivity(activity)) { - addVisibleActivity(activity) // keep it AFTER passCodeShouldBeRequested was checked + askPinWhenDeviceLocked = false } return askedForPin } - /** - * Used to hide root view while transitioning to passcode activity - */ - private fun toggleActivityVisibility( - hide: Boolean, - activity: Activity - ) { - if (hide) { - getActivityRootView(activity)?.visibility = View.GONE - } else { - getActivityRootView(activity)?.visibility = View.VISIBLE - } - } - - private fun addVisibleActivity(activity: Activity) { - // don't count the same activity twice - if (lastResumedActivity != activity) { - visibleActivitiesCounter++ - lastResumedActivity = activity - } - } - - private fun removeVisibleActivity() { - visibleActivitiesCounter-- - lastResumedActivity = null - } - private fun setSecureFlag(activity: Activity) { - val window = activity.window - if (window != null) { + activity.window?.let { window -> if (isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) { window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) } else { @@ -132,38 +99,38 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock } private fun requestPasscode(activity: Activity) { - val i = Intent(MainApp.getAppContext(), PassCodeActivity::class.java) - i.action = PassCodeActivity.ACTION_CHECK - i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP + val i = Intent(MainApp.getAppContext(), PassCodeActivity::class.java).apply { + action = PassCodeActivity.ACTION_CHECK + flags = Intent.FLAG_ACTIVITY_SINGLE_TOP + } activity.startActivityForResult(i, PASSCODE_ACTIVITY) } private fun requestCredentials(activity: Activity) { - val i = Intent(MainApp.getAppContext(), RequestCredentialsActivity::class.java) - i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP + val i = Intent(MainApp.getAppContext(), RequestCredentialsActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_SINGLE_TOP + } activity.startActivityForResult(i, PASSCODE_ACTIVITY) } fun onActivityStopped(activity: Activity) { - if (visibleActivitiesCounter > 0 && !isExemptActivity(activity)) { - removeVisibleActivity() - } val powerMgr = activity.getSystemService(Context.POWER_SERVICE) as PowerManager - if ((isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) && !powerMgr.isScreenOn) { - activity.moveTaskToBack(true) + if ((isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) && !powerMgr.isInteractive) { + askPinWhenDeviceLocked = true } } fun updateLockTimestamp() { preferences.lockTimestamp = clock.millisSinceBoot + canAskPin = false } /** * `true` if the time elapsed since last unlock is longer than [PASS_CODE_TIMEOUT] and no activities are visible */ - private fun shouldBeLocked(timestamp: Long) = - abs(clock.millisSinceBoot - timestamp) > PASS_CODE_TIMEOUT && - visibleActivitiesCounter <= 0 + private fun shouldBeLocked(timestamp: Long): Boolean { + return (abs(clock.millisSinceBoot - timestamp) > PASS_CODE_TIMEOUT && canAskPin) || askPinWhenDeviceLocked + } @VisibleForTesting fun passCodeShouldBeRequested(timestamp: Long): Boolean { From 0f17882e3c240db64426fc126d3493e5345a0a2c Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 4 Apr 2024 10:26:27 +0200 Subject: [PATCH 2/2] Fix dodgy bugs Signed-off-by: alperozturk --- .../main/java/com/owncloud/android/MainApp.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/MainApp.java b/app/src/main/java/com/owncloud/android/MainApp.java index 0bdf6669a7db..a735e11d1339 100644 --- a/app/src/main/java/com/owncloud/android/MainApp.java +++ b/app/src/main/java/com/owncloud/android/MainApp.java @@ -113,6 +113,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.util.Pair; +import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.ProcessLifecycleOwner; import androidx.multidex.MultiDexApplication; @@ -367,14 +368,11 @@ public void onCreate() { } private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> { - switch (event) { - case ON_START -> { - Log_OC.d(TAG, "APP IN FOREGROUND"); - } - case ON_STOP -> { - passCodeManager.setCanAskPin(true); - Log_OC.d(TAG, "APP IN BACKGROUND"); - } + if (event == Lifecycle.Event.ON_START) { + Log_OC.d(TAG, "APP IN FOREGROUND"); + } else if (event == Lifecycle.Event.ON_STOP) { + passCodeManager.setCanAskPin(true); + Log_OC.d(TAG, "APP IN BACKGROUND"); } });