/* * 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 . * */ package com.owncloud.android.authentication; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.PowerManager; import android.view.Window; import android.view.WindowManager; import com.nextcloud.client.preferences.PreferenceManager; 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 java.util.HashSet; import java.util.Set; public final class PassCodeManager { private static final Set exemptOfPasscodeActivities; public static final int PASSCODE_ACTIVITY = 9999; static { exemptOfPasscodeActivities = new HashSet<>(); exemptOfPasscodeActivities.add(PassCodeActivity.class); exemptOfPasscodeActivities.add(RequestCredentialsActivity.class); // other activities may be exempted, if needed } private static final int PASS_CODE_TIMEOUT = 5000; // keeping a "low" positive value is the easiest way to prevent the pass code is requested on rotations private static PassCodeManager passCodeManagerInstance; private int visibleActivitiesCounter; public static PassCodeManager getPassCodeManager() { if (passCodeManagerInstance == null) { passCodeManagerInstance = new PassCodeManager(); } return passCodeManagerInstance; } private PassCodeManager() {} public void onActivityCreated(Activity activity) { Window window = activity.getWindow(); if (window != null) { if (passCodeIsEnabled() || deviceCredentialsAreEnabled(activity)) { window.addFlags(WindowManager.LayoutParams.FLAG_SECURE); } else { window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE); } } } public void onActivityStarted(Activity activity) { Long timestamp = PreferenceManager.getLockTimestamp(activity); if (!exemptOfPasscodeActivities.contains(activity.getClass()) && passCodeShouldBeRequested(timestamp)) { Intent i = new Intent(MainApp.getAppContext(), PassCodeActivity.class); i.setAction(PassCodeActivity.ACTION_CHECK); i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); activity.startActivityForResult(i, PASSCODE_ACTIVITY); } if (!exemptOfPasscodeActivities.contains(activity.getClass()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && deviceCredentialsShouldBeRequested(timestamp, activity)) { Intent i = new Intent(MainApp.getAppContext(), RequestCredentialsActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); activity.startActivityForResult(i, PASSCODE_ACTIVITY); } visibleActivitiesCounter++; // keep it AFTER passCodeShouldBeRequested was checked } public void onActivityStopped(Activity activity) { if (visibleActivitiesCounter > 0) { visibleActivitiesCounter--; } setUnlockTimestamp(activity); PowerManager powerMgr = (PowerManager) activity.getSystemService(Context.POWER_SERVICE); if ((passCodeIsEnabled() || deviceCredentialsAreEnabled(activity)) && powerMgr != null && !powerMgr.isScreenOn()) { activity.moveTaskToBack(true); } } private void setUnlockTimestamp(Activity activity) { PreferenceManager.setLockTimestamp(activity, System.currentTimeMillis()); } private boolean passCodeShouldBeRequested(Long timestamp) { return (System.currentTimeMillis() - timestamp) > PASS_CODE_TIMEOUT && visibleActivitiesCounter <= 0 && passCodeIsEnabled(); } private boolean passCodeIsEnabled() { return SettingsActivity.LOCK_PASSCODE.equals(PreferenceManager.getLockPreference(MainApp.getAppContext())); } private boolean deviceCredentialsShouldBeRequested(Long timestamp, Activity activity) { return (System.currentTimeMillis() - timestamp) > PASS_CODE_TIMEOUT && visibleActivitiesCounter <= 0 && deviceCredentialsAreEnabled(activity); } private boolean deviceCredentialsAreEnabled(Activity activity) { return SettingsActivity.LOCK_DEVICE_CREDENTIALS.equals(PreferenceManager.getLockPreference(MainApp.getAppContext())) || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && (PreferenceManager.isUseFingerprint(MainApp.getAppContext()) && DeviceCredentialUtils.areCredentialsAvailable(activity)); } }