Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions app/src/main/java/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@
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;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
Expand Down Expand Up @@ -295,6 +298,8 @@ public void onCreate() {
setAppTheme(preferences.getDarkThemeMode());
super.onCreate();

ProcessLifecycleOwner.get().getLifecycle().addObserver(lifecycleEventObserver);

insertConscrypt();

initSecurityKeyManager();
Expand Down Expand Up @@ -353,6 +358,15 @@ public void onCreate() {
registerGlobalPassCodeProtection();
}

private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> {
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");
}
});

private void registerGlobalPassCodeProtection() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down