diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt index ebf10bb03..fd57e7f74 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/DatabaseTaskProvider.kt @@ -128,25 +128,29 @@ class DatabaseTaskProvider(private var context: Context, } private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener { - override fun onStartAction(database: Database, - progressMessage: ProgressMessage) { + override fun onActionStarted(database: Database, + progressMessage: ProgressMessage) { if (showDialog) startDialog(progressMessage) } - override fun onUpdateAction(database: Database, - progressMessage: ProgressMessage) { + override fun onActionUpdated(database: Database, + progressMessage: ProgressMessage) { if (showDialog) updateDialog(progressMessage) } - override fun onStopAction(database: Database, - actionTask: String, - result: ActionRunnable.Result) { - onActionFinish?.invoke(database, actionTask, result) + override fun onActionStopped(database: Database) { // Remove the progress task stopDialog() } + + override fun onActionFinished(database: Database, + actionTask: String, + result: ActionRunnable.Result) { + onActionFinish?.invoke(database, actionTask, result) + onActionStopped(database) + } } private val mActionDatabaseListener = object: DatabaseChangedDialogFragment.ActionDatabaseChangedListener { @@ -225,6 +229,16 @@ class DatabaseTaskProvider(private var context: Context, private fun initServiceConnection() { if (serviceConnection == null) { serviceConnection = object : ServiceConnection { + override fun onBindingDied(name: ComponentName?) { + stopDialog() + super.onBindingDied(name) + } + + override fun onNullBinding(name: ComponentName?) { + stopDialog() + super.onNullBinding(name) + } + override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder?)?.apply { addServiceListeners(this) @@ -272,8 +286,6 @@ class DatabaseTaskProvider(private var context: Context, } fun registerProgressTask() { - stopDialog() - // Register a database task receiver to stop loading dialog when service finish the task databaseTaskBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { @@ -284,7 +296,6 @@ class DatabaseTaskProvider(private var context: Context, } DATABASE_STOP_TASK_ACTION -> { // Remove the progress task - stopDialog() unBindService() } } @@ -302,8 +313,6 @@ class DatabaseTaskProvider(private var context: Context, } fun unregisterProgressTask() { - stopDialog() - removeServiceListeners(mBinder) mBinder = null diff --git a/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt index d8a70e9e9..fe485e5e5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/services/DatabaseTaskNotificationService.kt @@ -79,7 +79,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress // Channel to connect asynchronously a response private var mResponseChallengeChannel: Channel? = null - private var mActionRunning = false + private var mActionRunning = 0 private var mTaskRemovedRequested = false private var mSaveState = false @@ -135,20 +135,14 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress } interface ActionTaskListener { - fun onStartAction(database: Database, - progressMessage: ProgressMessage) - fun onUpdateAction(database: Database, - progressMessage: ProgressMessage) - fun onStopAction(database: Database, - actionTask: String, - result: ActionRunnable.Result) - } - - interface RequestChallengeListener { - fun onChallengeResponseRequested( - hardwareKey: HardwareKey, - seed: ByteArray? - ) + fun onActionStarted(database: Database, + progressMessage: ProgressMessage) + fun onActionUpdated(database: Database, + progressMessage: ProgressMessage) + fun onActionStopped(database: Database) + fun onActionFinished(database: Database, + actionTask: String, + result: ActionRunnable.Result) } fun checkDatabase() { @@ -211,16 +205,24 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress } /** - * Force to call [ActionTaskListener.onStartAction] if the action is still running + * Force to call [ActionTaskListener.onActionStarted] if the action is still running + * or [ActionTaskListener.onActionStopped] if the action is no longer running */ fun checkAction() { mDatabase?.let { database -> - if (mActionRunning) { + // Check if action / sub-action is running + if (mActionRunning > 0) { mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStartAction( + actionTaskListener.onActionStarted( database, mProgressMessage ) } + } else { + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onActionStopped( + database + ) + } } } } @@ -330,81 +332,104 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress else -> null } + // Sub action is an action in another action, don't perform pre and post action + val isMainAction = intentAction != ACTION_CHALLENGE_RESPONDED + // Build and launch the action if (actionRunnable != null) { mainScope.launch { executeAction(this@DatabaseTaskNotificationService, { - TimeoutHelper.temporarilyDisableTimeout() + mActionRunning++ + if (isMainAction) { + TimeoutHelper.temporarilyDisableTimeout() - mActionRunning = true + sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { + putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId) + putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId) + putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId) + }) - sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { - putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId) - putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId) - putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId) - }) - - mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStartAction( - database, mProgressMessage - ) + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onActionStarted( + database, + mProgressMessage + ) + } } }, { actionRunnable }, { result -> - try { - mActionTaskListeners.forEach { actionTaskListener -> - mTaskRemovedRequested = false - actionTaskListener.onStopAction(database, intentAction!!, result) - } - } finally { - // Save the database info before performing action - when (intentAction) { - ACTION_DATABASE_LOAD_TASK, - ACTION_DATABASE_MERGE_TASK, - ACTION_DATABASE_RELOAD_TASK -> { - saveDatabaseInfo() + if (isMainAction) { + try { + mActionTaskListeners.forEach { actionTaskListener -> + mTaskRemovedRequested = false + actionTaskListener.onActionFinished( + database, + intentAction!!, + result + ) } - } - val save = !database.isReadOnly - && (intentAction == ACTION_DATABASE_SAVE - || intent?.getBooleanExtra(SAVE_DATABASE_KEY, false) == true) - // Save the database info after performing save action - if (save) { - database.fileUri?.let { - val newSnapFileDatabaseInfo = SnapFileDatabaseInfo.fromFileDatabaseInfo( - FileDatabaseInfo(applicationContext, it)) - mLastLocalSaveTime = System.currentTimeMillis() - mSnapFileDatabaseInfo = newSnapFileDatabaseInfo - } - } - removeIntentData(intent) - TimeoutHelper.releaseTemporarilyDisableTimeout() - // Stop service after save if user remove task - if (save && mTaskRemovedRequested) { - actionOnLock() - } else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) { - if (!database.loaded) { - stopSelf() - } else { - // Restart the service to open lock notification - try { - startService(Intent(applicationContext, - DatabaseTaskNotificationService::class.java)) - } catch (e: IllegalStateException) { - Log.w(TAG, "Cannot restart the database task service", e) + } finally { + // Save the database info before performing action + when (intentAction) { + ACTION_DATABASE_LOAD_TASK, + ACTION_DATABASE_MERGE_TASK, + ACTION_DATABASE_RELOAD_TASK -> { + saveDatabaseInfo() } } + val save = !database.isReadOnly + && (intentAction == ACTION_DATABASE_SAVE + || intent?.getBooleanExtra( + SAVE_DATABASE_KEY, + false + ) == true) + // Save the database info after performing save action + if (save) { + database.fileUri?.let { + val newSnapFileDatabaseInfo = + SnapFileDatabaseInfo.fromFileDatabaseInfo( + FileDatabaseInfo(applicationContext, it) + ) + mLastLocalSaveTime = System.currentTimeMillis() + mSnapFileDatabaseInfo = newSnapFileDatabaseInfo + } + } + removeIntentData(intent) + TimeoutHelper.releaseTemporarilyDisableTimeout() + // Stop service after save if user remove task + if (save && mTaskRemovedRequested) { + actionOnLock() + } else if (TimeoutHelper.checkTimeAndLockIfTimeout(this@DatabaseTaskNotificationService)) { + if (!database.loaded) { + stopSelf() + } else { + // Restart the service to open lock notification + try { + startService( + Intent( + applicationContext, + DatabaseTaskNotificationService::class.java + ) + ) + } catch (e: IllegalStateException) { + Log.w( + TAG, + "Cannot restart the database task service", + e + ) + } + } + } + mTaskRemovedRequested = false } - mTaskRemovedRequested = false + + sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) } - - sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) - - mActionRunning = false + mActionRunning-- } ) } @@ -577,7 +602,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress private fun notifyProgressMessage() { mDatabase?.let { database -> mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onUpdateAction( + actionTaskListener.onActionUpdated( database, mProgressMessage ) }