123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /*
- * ownCloud Android client application
- *
- * @author David A. Velasco
- * Copyright (C) 2015 ownCloud Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package com.owncloud.android.authentication
- import android.app.Activity
- import android.content.Context
- import android.content.Intent
- import android.os.PowerManager
- import android.view.WindowManager
- import com.nextcloud.client.core.Clock
- import com.nextcloud.client.preferences.AppPreferences
- import com.owncloud.android.MainApp
- import com.owncloud.android.ui.activity.PassCodeActivity
- import com.owncloud.android.ui.activity.RequestCredentialsActivity
- import com.owncloud.android.ui.activity.SettingsActivity
- import com.owncloud.android.utils.DeviceCredentialUtils
- import kotlin.math.abs
- @Suppress("TooManyFunctions")
- class PassCodeManager(private val preferences: AppPreferences, private val clock: Clock) {
- companion object {
- private val exemptOfPasscodeActivities = setOf(
- PassCodeActivity::class.java,
- RequestCredentialsActivity::class.java
- )
- const val PASSCODE_ACTIVITY = 9999
- /**
- * Keeping a "low" positive value is the easiest way to prevent
- * the pass code being requested on screen rotations.
- */
- private const val PASS_CODE_TIMEOUT = 5000
- }
- private var visibleActivitiesCounter = 0
- private fun isExemptActivity(activity: Activity): Boolean {
- return exemptOfPasscodeActivities.contains(activity.javaClass)
- }
- fun onActivityStarted(activity: Activity): Boolean {
- var askedForPin = false
- val timestamp = preferences.lockTimestamp
- setSecureFlag(activity)
- if (!isExemptActivity(activity)) {
- if (passCodeShouldBeRequested(timestamp)) {
- askedForPin = true
- preferences.lockTimestamp = 0
- requestPasscode(activity)
- }
- if (deviceCredentialsShouldBeRequested(timestamp, activity)) {
- askedForPin = true
- preferences.lockTimestamp = 0
- requestCredentials(activity)
- }
- }
- if (!askedForPin && preferences.lockTimestamp != 0L) {
- updateLockTimestamp()
- }
- if (!isExemptActivity(activity)) {
- visibleActivitiesCounter++ // keep it AFTER passCodeShouldBeRequested was checked
- }
- return askedForPin
- }
- private fun setSecureFlag(activity: Activity) {
- val window = activity.window
- if (window != null) {
- if (isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) {
- window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
- } else {
- window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
- }
- }
- }
- 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
- 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
- activity.startActivityForResult(i, PASSCODE_ACTIVITY)
- }
- fun onActivityStopped(activity: Activity) {
- if (visibleActivitiesCounter > 0 && !isExemptActivity(activity)) {
- visibleActivitiesCounter--
- }
- val powerMgr = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
- if ((isPassCodeEnabled() || deviceCredentialsAreEnabled(activity)) && !powerMgr?.isScreenOn) {
- activity.moveTaskToBack(true)
- }
- }
- fun updateLockTimestamp() {
- preferences.lockTimestamp = clock.millisSinceBoot
- }
- /**
- * `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 passCodeShouldBeRequested(timestamp: Long): Boolean {
- return shouldBeLocked(timestamp) && isPassCodeEnabled()
- }
- private fun isPassCodeEnabled(): Boolean = SettingsActivity.LOCK_PASSCODE == preferences.lockPreference
- private fun deviceCredentialsShouldBeRequested(timestamp: Long, activity: Activity): Boolean {
- return shouldBeLocked(timestamp) && deviceCredentialsAreEnabled(activity)
- }
- private fun deviceCredentialsAreEnabled(activity: Activity): Boolean {
- return SettingsActivity.LOCK_DEVICE_CREDENTIALS == preferences.lockPreference ||
- (preferences.isFingerprintUnlockEnabled && DeviceCredentialUtils.areCredentialsAvailable(activity))
- }
- }
|