Skip to content

Commit 1d3ec9d

Browse files
Merge pull request #12819 from nextcloud/backport/12817/stable-3.28
[stable-3.28] Enhance Passcode
2 parents 5e3bde0 + 73fd2ea commit 1d3ec9d

File tree

2 files changed

+33
-52
lines changed

2 files changed

+33
-52
lines changed

app/src/main/java/com/owncloud/android/MainApp.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@
112112
import androidx.appcompat.app.AlertDialog;
113113
import androidx.appcompat.app.AppCompatDelegate;
114114
import androidx.core.util.Pair;
115+
import androidx.lifecycle.Lifecycle;
116+
import androidx.lifecycle.LifecycleEventObserver;
117+
import androidx.lifecycle.ProcessLifecycleOwner;
115118
import androidx.multidex.MultiDexApplication;
116119
import dagger.android.AndroidInjector;
117120
import dagger.android.DispatchingAndroidInjector;
@@ -295,6 +298,8 @@ public void onCreate() {
295298
setAppTheme(preferences.getDarkThemeMode());
296299
super.onCreate();
297300

301+
ProcessLifecycleOwner.get().getLifecycle().addObserver(lifecycleEventObserver);
302+
298303
insertConscrypt();
299304

300305
initSecurityKeyManager();
@@ -353,6 +358,15 @@ public void onCreate() {
353358
registerGlobalPassCodeProtection();
354359
}
355360

361+
private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> {
362+
if (event == Lifecycle.Event.ON_START) {
363+
Log_OC.d(TAG, "APP IN FOREGROUND");
364+
} else if (event == Lifecycle.Event.ON_STOP) {
365+
passCodeManager.setCanAskPin(true);
366+
Log_OC.d(TAG, "APP IN BACKGROUND");
367+
}
368+
});
369+
356370
private void registerGlobalPassCodeProtection() {
357371
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
358372

app/src/main/java/com/owncloud/android/authentication/PassCodeManager.kt

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock
4949
* the pass code being requested on screen rotations.
5050
*/
5151
private const val PASS_CODE_TIMEOUT = 5000
52-
53-
private const val TAG = "PassCodeManager"
5452
}
5553

56-
private var visibleActivitiesCounter = 0
57-
private var lastResumedActivity: Activity? = null
54+
var canAskPin = true
55+
private var askPinWhenDeviceLocked = false
5856

5957
private fun isExemptActivity(activity: Activity): Boolean {
6058
return exemptOfPasscodeActivities.contains(activity.javaClass)
@@ -69,7 +67,7 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock
6967
val passcodeRequested = passCodeShouldBeRequested(timestamp)
7068
val credentialsRequested = deviceCredentialsShouldBeRequested(timestamp, activity)
7169
val shouldHideView = passcodeRequested || credentialsRequested
72-
toggleActivityVisibility(shouldHideView, activity)
70+
getActivityRootView(activity)?.visibility = if (shouldHideView) View.GONE else View.VISIBLE
7371
askedForPin = shouldHideView
7472

7573
if (passcodeRequested) {
@@ -82,47 +80,16 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock
8280
}
8381
}
8482

85-
if (!askedForPin && preferences.lockTimestamp != 0L) {
83+
if (!askedForPin && preferences.lockTimestamp != 0L || askPinWhenDeviceLocked) {
8684
updateLockTimestamp()
87-
}
88-
89-
if (!isExemptActivity(activity)) {
90-
addVisibleActivity(activity) // keep it AFTER passCodeShouldBeRequested was checked
85+
askPinWhenDeviceLocked = false
9186
}
9287

9388
return askedForPin
9489
}
9590

96-
/**
97-
* Used to hide root view while transitioning to passcode activity
98-
*/
99-
private fun toggleActivityVisibility(
100-
hide: Boolean,
101-
activity: Activity
102-
) {
103-
if (hide) {
104-
getActivityRootView(activity)?.visibility = View.GONE
105-
} else {
106-
getActivityRootView(activity)?.visibility = View.VISIBLE
107-
}
108-
}
109-
110-
private fun addVisibleActivity(activity: Activity) {
111-
// don't count the same activity twice
112-
if (lastResumedActivity != activity) {
113-
visibleActivitiesCounter++
114-
lastResumedActivity = activity
115-
}
116-
}
117-
118-
private fun removeVisibleActivity() {
119-
visibleActivitiesCounter--
120-
lastResumedActivity = null
121-
}
122-
12391
private fun setSecureFlag(activity: Activity) {
124-
val window = activity.window
125-
if (window != null) {
92+
activity.window?.let { window ->
12693
if (isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) {
12794
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
12895
} else {
@@ -132,38 +99,38 @@ class PassCodeManager(private val preferences: AppPreferences, private val clock
13299
}
133100

134101
private fun requestPasscode(activity: Activity) {
135-
val i = Intent(MainApp.getAppContext(), PassCodeActivity::class.java)
136-
i.action = PassCodeActivity.ACTION_CHECK
137-
i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
102+
val i = Intent(MainApp.getAppContext(), PassCodeActivity::class.java).apply {
103+
action = PassCodeActivity.ACTION_CHECK
104+
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
105+
}
138106
activity.startActivityForResult(i, PASSCODE_ACTIVITY)
139107
}
140108

141109
private fun requestCredentials(activity: Activity) {
142-
val i = Intent(MainApp.getAppContext(), RequestCredentialsActivity::class.java)
143-
i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
110+
val i = Intent(MainApp.getAppContext(), RequestCredentialsActivity::class.java).apply {
111+
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
112+
}
144113
activity.startActivityForResult(i, PASSCODE_ACTIVITY)
145114
}
146115

147116
fun onActivityStopped(activity: Activity) {
148-
if (visibleActivitiesCounter > 0 && !isExemptActivity(activity)) {
149-
removeVisibleActivity()
150-
}
151117
val powerMgr = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
152-
if ((isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) && !powerMgr.isScreenOn) {
153-
activity.moveTaskToBack(true)
118+
if ((isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) && !powerMgr.isInteractive) {
119+
askPinWhenDeviceLocked = true
154120
}
155121
}
156122

157123
fun updateLockTimestamp() {
158124
preferences.lockTimestamp = clock.millisSinceBoot
125+
canAskPin = false
159126
}
160127

161128
/**
162129
* `true` if the time elapsed since last unlock is longer than [PASS_CODE_TIMEOUT] and no activities are visible
163130
*/
164-
private fun shouldBeLocked(timestamp: Long) =
165-
abs(clock.millisSinceBoot - timestamp) > PASS_CODE_TIMEOUT &&
166-
visibleActivitiesCounter <= 0
131+
private fun shouldBeLocked(timestamp: Long): Boolean {
132+
return (abs(clock.millisSinceBoot - timestamp) > PASS_CODE_TIMEOUT && canAskPin) || askPinWhenDeviceLocked
133+
}
167134

168135
@VisibleForTesting
169136
fun passCodeShouldBeRequested(timestamp: Long): Boolean {

0 commit comments

Comments
 (0)