From 005f7295b53fb53935f991ba67eb5d5274f5b2a4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 1 Nov 2019 10:51:08 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/CardEnvironmentRepository.kt | 22 ------- .../src/main/java/com/tangem/CardManager.kt | 21 ++++--- .../java/com/tangem/CardManagerDelegate.kt | 8 ++- .../src/main/java/com/tangem/CardReader.kt | 1 + .../src/main/java/com/tangem/Executors.kt | 20 ------- .../com/tangem/commands/CheckWalletCommand.kt | 6 +- .../com/tangem/commands/ReadCardCommand.kt | 60 +++++++++---------- .../java/com/tangem/commands/SignCommand.kt | 8 +-- .../com/tangem/common/apdu/ResponseApdu.kt | 4 +- .../tangem/enums/{Status.kt => StatusWord.kt} | 4 +- .../main/java/com/tangem/tasks/ScanTask.kt | 26 ++++---- .../com/tangem/tasks/SingleCommandTask.kt | 14 ++++- .../src/main/java/com/tangem/tasks/Task.kt | 35 +++++------ 13 files changed, 99 insertions(+), 130 deletions(-) delete mode 100644 tangem-card-new/src/main/java/com/tangem/CardEnvironmentRepository.kt delete mode 100644 tangem-card-new/src/main/java/com/tangem/Executors.kt rename tangem-card-new/src/main/java/com/tangem/enums/{Status.kt => StatusWord.kt} (81%) diff --git a/tangem-card-new/src/main/java/com/tangem/CardEnvironmentRepository.kt b/tangem-card-new/src/main/java/com/tangem/CardEnvironmentRepository.kt deleted file mode 100644 index cc3793f8e3..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/CardEnvironmentRepository.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.tangem - -class CardEnvironmentRepository(val dataStorage: DataStorage?) { - - var cardEnvironment: CardEnvironment = initCardEnvironment() - set(value) { - if (cardEnvironment != value) { - saveCardEnvirnoment(value) - } - } - - private fun initCardEnvironment(): CardEnvironment { - return CardEnvironment( - dataStorage?.getPin1() ?: CardEnvironment.DEFAULT_PIN, - dataStorage?.getPin2() ?: CardEnvironment.DEFAULT_PIN2 - ) - } - - private fun saveCardEnvirnoment(cardEnvironment: CardEnvironment) { - //TODO: logic for saving fields in persistence storage - } -} diff --git a/tangem-card-new/src/main/java/com/tangem/CardManager.kt b/tangem-card-new/src/main/java/com/tangem/CardManager.kt index e04cc98de3..349289bb83 100644 --- a/tangem-card-new/src/main/java/com/tangem/CardManager.kt +++ b/tangem-card-new/src/main/java/com/tangem/CardManager.kt @@ -6,15 +6,15 @@ import com.tangem.commands.SignCommand import com.tangem.commands.SignResponse import com.tangem.crypto.initCrypto import com.tangem.tasks.* +import java.util.concurrent.Executors class CardManager( private val reader: CardReader, private val cardManagerDelegate: CardManagerDelegate? = null) { private var isBusy = false - private set - private val cardEnvironmentRepository = mutableMapOf() + private val cardManagerExecutor = Executors.newSingleThreadExecutor() init { initCrypto() @@ -44,8 +44,6 @@ class CardManager( fun runTask(task: Task, cardId: String? = null, callback: (result: TaskEvent) -> Unit) { -// AppExecutors.diskIO().execute { - if (isBusy) { callback(TaskEvent.Completion(TaskError.Busy())) return @@ -57,16 +55,17 @@ class CardManager( task.reader = reader task.delegate = cardManagerDelegate - task.run(environment) { - when (it) { - is TaskEvent.Event -> callback(it) - is TaskEvent.Completion -> { - isBusy = false - callback(it) + cardManagerExecutor.execute { + task.run(environment) { + when (it) { + is TaskEvent.Event -> callback(it) + is TaskEvent.Completion -> { + isBusy = false + callback(it) + } } } } -// } } private fun fetchCardEnvironment(cardId: String?): CardEnvironment { diff --git a/tangem-card-new/src/main/java/com/tangem/CardManagerDelegate.kt b/tangem-card-new/src/main/java/com/tangem/CardManagerDelegate.kt index 7409e253fa..82051b143d 100644 --- a/tangem-card-new/src/main/java/com/tangem/CardManagerDelegate.kt +++ b/tangem-card-new/src/main/java/com/tangem/CardManagerDelegate.kt @@ -1,13 +1,15 @@ package com.tangem +import com.tangem.common.CompletionResult import com.tangem.tasks.TaskError interface CardManagerDelegate { + fun onTaskStarted() fun showSecurityDelay(ms: Int) - fun requestPin(success: () -> String, error: (cardError: TaskError.CardError) -> TaskError.CardError) + fun onTaskCompleted() + fun onTaskError(error: TaskError? = null) - fun openNfcPopup() - fun closeNfcPopup() + fun requestPin(callback: (result: CompletionResult) -> Unit) } \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/CardReader.kt b/tangem-card-new/src/main/java/com/tangem/CardReader.kt index 2b45b88b6a..15f9fa9eea 100644 --- a/tangem-card-new/src/main/java/com/tangem/CardReader.kt +++ b/tangem-card-new/src/main/java/com/tangem/CardReader.kt @@ -8,4 +8,5 @@ interface CardReader { var readingActive: Boolean fun transceiveApdu(apdu: CommandApdu, callback: (response: CompletionResult) -> Unit) fun setStartSession() + fun closeSession() } \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/Executors.kt b/tangem-card-new/src/main/java/com/tangem/Executors.kt deleted file mode 100644 index 60fdb2380b..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/Executors.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem - -import java.util.concurrent.Executor -import java.util.concurrent.Executors - - -object AppExecutors { - - private val diskIO = Executors.newSingleThreadExecutor() - private val networkIO = Executors.newFixedThreadPool(3) - - fun diskIO(): Executor { - return diskIO - } - - fun networkIO(): Executor { - return networkIO - } - -} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/commands/CheckWalletCommand.kt b/tangem-card-new/src/main/java/com/tangem/commands/CheckWalletCommand.kt index 6f9356bcac..5bd42d45cd 100644 --- a/tangem-card-new/src/main/java/com/tangem/commands/CheckWalletCommand.kt +++ b/tangem-card-new/src/main/java/com/tangem/commands/CheckWalletCommand.kt @@ -41,9 +41,9 @@ class CheckWalletCommand( return try { val mapper = TlvMapper(tlvData) CheckWalletResponse( - mapper.map(TlvTag.CardId), - mapper.map(TlvTag.Salt), - mapper.map(TlvTag.Signature) + cardId = mapper.map(TlvTag.CardId), + salt = mapper.map(TlvTag.Salt), + walletSignature = mapper.map(TlvTag.Signature) ) } catch (exception: Exception) { throw TaskError.SerializeCommandError() diff --git a/tangem-card-new/src/main/java/com/tangem/commands/ReadCardCommand.kt b/tangem-card-new/src/main/java/com/tangem/commands/ReadCardCommand.kt index 16cc9e4677..3f740c48e2 100644 --- a/tangem-card-new/src/main/java/com/tangem/commands/ReadCardCommand.kt +++ b/tangem-card-new/src/main/java/com/tangem/commands/ReadCardCommand.kt @@ -67,7 +67,7 @@ class ReadCardResponse( val issuerPublicKey: ByteArray?, val curve: EllipticCurve?, val maxSignatures: Int?, - val signingMethpod: SigningMethod?, + val signingMethod: SigningMethod?, val pauseBeforePin2: Int?, val walletPublicKey: ByteArray?, val walletRemainingSignatures: Int?, @@ -116,38 +116,38 @@ class ReadCardCommand : CommandSerializer() { val tlvMapper = TlvMapper(tlvData) ReadCardResponse( - tlvMapper.map(TlvTag.CardId), - tlvMapper.map(TlvTag.ManufactureId), - tlvMapper.map(TlvTag.Status), + cardId = tlvMapper.map(TlvTag.CardId), + manufacturerName = tlvMapper.map(TlvTag.ManufactureId), + status = tlvMapper.map(TlvTag.Status), - tlvMapper.mapOptional(TlvTag.Firmware), - tlvMapper.mapOptional(TlvTag.CardPublicKey), - tlvMapper.mapOptional(TlvTag.SettingsMask), - tlvMapper.mapOptional(TlvTag.IssuerDataPublicKey), - tlvMapper.mapOptional(TlvTag.CurveId), - tlvMapper.mapOptional(TlvTag.MaxSignatures), - tlvMapper.mapOptional(TlvTag.SigningMethod), - tlvMapper.mapOptional(TlvTag.PauseBeforePin2), - tlvMapper.mapOptional(TlvTag.WalletPublicKey), - tlvMapper.mapOptional(TlvTag.RemainingSignatures), - tlvMapper.mapOptional(TlvTag.SignedHashes), - tlvMapper.mapOptional(TlvTag.Health), - tlvMapper.map(TlvTag.IsActivated), - tlvMapper.mapOptional(TlvTag.ActivationSeed), - tlvMapper.mapOptional(TlvTag.PaymentFlowVersion), - tlvMapper.mapOptional(TlvTag.UserCounter), - tlvMapper.map(TlvTag.TerminalIsLinked), + firmwareVersion = tlvMapper.mapOptional(TlvTag.Firmware), + cardPublicKey = tlvMapper.mapOptional(TlvTag.CardPublicKey), + settingsMask = tlvMapper.mapOptional(TlvTag.SettingsMask), + issuerPublicKey = tlvMapper.mapOptional(TlvTag.IssuerDataPublicKey), + curve = tlvMapper.mapOptional(TlvTag.CurveId), + maxSignatures = tlvMapper.mapOptional(TlvTag.MaxSignatures), + signingMethod = tlvMapper.mapOptional(TlvTag.SigningMethod), + pauseBeforePin2 = tlvMapper.mapOptional(TlvTag.PauseBeforePin2), + walletPublicKey = tlvMapper.mapOptional(TlvTag.WalletPublicKey), + walletRemainingSignatures = tlvMapper.mapOptional(TlvTag.RemainingSignatures), + walletSignedHashes = tlvMapper.mapOptional(TlvTag.SignedHashes), + health = tlvMapper.mapOptional(TlvTag.Health), + isActivated = tlvMapper.map(TlvTag.IsActivated), + activationSeed = tlvMapper.mapOptional(TlvTag.ActivationSeed), + paymentFlowVersion = tlvMapper.mapOptional(TlvTag.PaymentFlowVersion), + userCounter = tlvMapper.mapOptional(TlvTag.UserCounter), + terminalIsLinked = tlvMapper.map(TlvTag.TerminalIsLinked), - tlvMapper.mapOptional(TlvTag.Batch), - tlvMapper.mapOptional(TlvTag.ManufactureDateTime), - tlvMapper.mapOptional(TlvTag.IssuerId), - tlvMapper.mapOptional(TlvTag.BlockchainId), - tlvMapper.mapOptional(TlvTag.ManufacturerSignature), - tlvMapper.mapOptional(TlvTag.ProductMask), + batchId = tlvMapper.mapOptional(TlvTag.Batch), + manufactureDateTime = tlvMapper.mapOptional(TlvTag.ManufactureDateTime), + issuerName = tlvMapper.mapOptional(TlvTag.IssuerId), + blockchainName = tlvMapper.mapOptional(TlvTag.BlockchainId), + manufacturerSignature = tlvMapper.mapOptional(TlvTag.ManufacturerSignature), + productMask = tlvMapper.mapOptional(TlvTag.ProductMask), - tlvMapper.mapOptional(TlvTag.TokenSymbol), - tlvMapper.mapOptional(TlvTag.TokenContractAddress), - tlvMapper.mapOptional(TlvTag.TokenDecimal) + tokenSymbol = tlvMapper.mapOptional(TlvTag.TokenSymbol), + tokenContractAddress = tlvMapper.mapOptional(TlvTag.TokenContractAddress), + tokenDecimal = tlvMapper.mapOptional(TlvTag.TokenDecimal) ) } catch (exception: Exception) { throw TaskError.SerializeCommandError() diff --git a/tangem-card-new/src/main/java/com/tangem/commands/SignCommand.kt b/tangem-card-new/src/main/java/com/tangem/commands/SignCommand.kt index 1260749264..35dd60f001 100644 --- a/tangem-card-new/src/main/java/com/tangem/commands/SignCommand.kt +++ b/tangem-card-new/src/main/java/com/tangem/commands/SignCommand.kt @@ -67,10 +67,10 @@ class SignCommand(private val hashes: Array, private val cardId: Stri val tlvMapper = TlvMapper(tlvData) return SignResponse( - tlvMapper.map(TlvTag.CardId), - tlvMapper.map(TlvTag.Signature), - tlvMapper.map(TlvTag.RemainingSignatures), - tlvMapper.map(TlvTag.SignedHashes) + cardId= tlvMapper.map(TlvTag.CardId), + signature = tlvMapper.map(TlvTag.Signature), + remainingSignatures = tlvMapper.map(TlvTag.RemainingSignatures), + signedHashes = tlvMapper.map(TlvTag.SignedHashes) ) } } \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt b/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt index 8a4b7ba79f..7d1e5c2fbc 100644 --- a/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt +++ b/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt @@ -1,7 +1,7 @@ package com.tangem.common.apdu import com.tangem.common.tlv.Tlv -import com.tangem.enums.Status +import com.tangem.enums.StatusWord class ResponseApdu(val data: ByteArray) { @@ -10,7 +10,7 @@ class ResponseApdu(val data: ByteArray) { val sw: Int = sw1 shl 8 or sw2 - val status: Status = Status.byCode(sw) + val statusWord: StatusWord = StatusWord.byCode(sw) fun getTlvData(encryptionKey: ByteArray? = null): List? { val tlvs = when { diff --git a/tangem-card-new/src/main/java/com/tangem/enums/Status.kt b/tangem-card-new/src/main/java/com/tangem/enums/StatusWord.kt similarity index 81% rename from tangem-card-new/src/main/java/com/tangem/enums/Status.kt rename to tangem-card-new/src/main/java/com/tangem/enums/StatusWord.kt index 86e3cfb19c..9ba4e0d784 100644 --- a/tangem-card-new/src/main/java/com/tangem/enums/Status.kt +++ b/tangem-card-new/src/main/java/com/tangem/enums/StatusWord.kt @@ -1,6 +1,6 @@ package com.tangem.enums -enum class Status (val code: Int, val description: String){ +enum class StatusWord (val code: Int, val description: String){ ProcessCompleted(0x9000, "SW_PROCESS_COMPLETED"), InvalidParams(0x6A86, "SW_INVALID_PARAMS"), @@ -15,7 +15,7 @@ enum class Status (val code: Int, val description: String){ NeedPause(0x9789, "SW_NEED_PAUSE"); companion object { - fun byCode(code: Int): Status = values().find { it.code == code } ?: InvalidParams + fun byCode(code: Int): StatusWord = values().find { it.code == code } ?: InvalidParams } } diff --git a/tangem-card-new/src/main/java/com/tangem/tasks/ScanTask.kt b/tangem-card-new/src/main/java/com/tangem/tasks/ScanTask.kt index 75c2b4c52b..72590269d4 100644 --- a/tangem-card-new/src/main/java/com/tangem/tasks/ScanTask.kt +++ b/tangem-card-new/src/main/java/com/tangem/tasks/ScanTask.kt @@ -5,6 +5,7 @@ import com.tangem.commands.CheckWalletCommand import com.tangem.commands.EllipticCurve import com.tangem.commands.ReadCardCommand import com.tangem.commands.ReadCardResponse +import com.tangem.common.CompletionResult import com.tangem.crypto.generateRandomBytes import com.tangem.crypto.verify @@ -28,7 +29,7 @@ internal class ScanTask : Task() { sendCommand(readCommand, cardEnvironment) { readEvent -> when (readEvent) { - is TaskEvent.Event -> { + is CompletionResult.Success -> { readCardData = readEvent.data callback(TaskEvent.Event(ScanEvent.OnReadEvent(readCardData))) @@ -37,38 +38,41 @@ internal class ScanTask : Task() { curve = readCardData.curve!! walletPublickKey = readCardData.walletPublicKey!! } else { - delegate?.closeNfcPopup() + delegate?.onTaskError() callback(TaskEvent.Completion(TaskError.CardError())) } val checkWalletCommand = prepareCheckWalletCommand(cardEnvironment) sendCommand(checkWalletCommand, cardEnvironment) { checkWalletEvent -> - delegate?.closeNfcPopup() - when (checkWalletEvent) { - is TaskEvent.Event -> { + is CompletionResult.Success -> { val checkWalletResponse = checkWalletEvent.data val verified = verify(walletPublickKey, challenge + checkWalletResponse.salt, checkWalletResponse.walletSignature, curve) if (verified) { - callback(TaskEvent.Event(ScanEvent.OnVerifyEvent(true))) + delegate?.onTaskCompleted() callback(TaskEvent.Completion()) + callback(TaskEvent.Event(ScanEvent.OnVerifyEvent(true))) } else { + delegate?.onTaskError() callback(TaskEvent.Completion(TaskError.VefificationFailed())) } } - is TaskEvent.Completion -> - if (checkWalletEvent.error != null) - callback(TaskEvent.Completion(checkWalletEvent.error)) + is CompletionResult.Failure -> { + if (checkWalletEvent.error !is TaskError.UserCancelledError) delegate?.onTaskError() + callback(TaskEvent.Completion(checkWalletEvent.error)) + } } } } - is TaskEvent.Completion -> - if (readEvent.error != null) callback(TaskEvent.Completion(readEvent.error)) + is CompletionResult.Failure -> { + if (readEvent.error !is TaskError.UserCancelledError) delegate?.onTaskError() + callback(TaskEvent.Completion(readEvent.error)) + } } } } diff --git a/tangem-card-new/src/main/java/com/tangem/tasks/SingleCommandTask.kt b/tangem-card-new/src/main/java/com/tangem/tasks/SingleCommandTask.kt index a4952bbc89..7da0985efe 100644 --- a/tangem-card-new/src/main/java/com/tangem/tasks/SingleCommandTask.kt +++ b/tangem-card-new/src/main/java/com/tangem/tasks/SingleCommandTask.kt @@ -3,6 +3,7 @@ package com.tangem.tasks import com.tangem.CardEnvironment import com.tangem.commands.CommandResponse import com.tangem.commands.CommandSerializer +import com.tangem.common.CompletionResult class SingleCommandTask( private val commandSerializer: CommandSerializer) : Task() { @@ -10,8 +11,17 @@ class SingleCommandTask( override fun onRun(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { sendCommand(commandSerializer, cardEnvironment) { - delegate?.closeNfcPopup() - callback(it) + when (it) { + is CompletionResult.Success -> { + delegate?.onTaskCompleted() + callback(TaskEvent.Event(it.data)) + callback(TaskEvent.Completion()) + } + is CompletionResult.Failure -> { + if (it.error !is TaskError.UserCancelledError) delegate?.onTaskError() + callback(TaskEvent.Completion(it.error)) + } + } } } } diff --git a/tangem-card-new/src/main/java/com/tangem/tasks/Task.kt b/tangem-card-new/src/main/java/com/tangem/tasks/Task.kt index c27c548cd5..a7e5228781 100644 --- a/tangem-card-new/src/main/java/com/tangem/tasks/Task.kt +++ b/tangem-card-new/src/main/java/com/tangem/tasks/Task.kt @@ -7,7 +7,7 @@ import com.tangem.Log import com.tangem.commands.CommandResponse import com.tangem.commands.CommandSerializer import com.tangem.common.CompletionResult -import com.tangem.enums.Status +import com.tangem.enums.StatusWord abstract class Task { @@ -16,12 +16,10 @@ abstract class Task { fun run(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { - - delegate?.openNfcPopup() + delegate?.onTaskStarted() reader?.setStartSession() Log.i(this::class.simpleName!!, "Nfc task is started") onRun(cardEnvironment, callback) - } abstract fun onRun(cardEnvironment: CardEnvironment, @@ -30,7 +28,7 @@ abstract class Task { protected fun sendCommand( commandSerializer: CommandSerializer, cardEnvironment: CardEnvironment, - callback: (result: TaskEvent) -> Unit) { + callback: (result: CompletionResult) -> Unit) { Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} is initiated") @@ -41,27 +39,24 @@ abstract class Task { when (result) { is CompletionResult.Success -> { val responseApdu = result.data - when (responseApdu.status) { - Status.ProcessCompleted, Status.Pin1Changed, Status.Pin2Changed, Status.PinsChanged + when (responseApdu.statusWord) { + StatusWord.ProcessCompleted, StatusWord.Pin1Changed, StatusWord.Pin2Changed, StatusWord.PinsChanged -> { -// reader.readingActive = false -// reader.setStartSession() try { val responseData = commandSerializer.deserialize(cardEnvironment, responseApdu) Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} is completed") - callback(TaskEvent.Event(responseData as T)) - callback(TaskEvent.Completion()) + callback(CompletionResult.Success(responseData as T)) } catch (error: TaskError) { - callback(TaskEvent.Completion(error)) + callback(CompletionResult.Failure(error)) } } - Status.InvalidParams -> callback(TaskEvent.Completion(TaskError.InvalidParams())) - Status.ErrorProcessingCommand -> callback(TaskEvent.Completion(TaskError.ErrorProcessingCommand())) - Status.InvalidState -> callback(TaskEvent.Completion(TaskError.InvalidState())) + StatusWord.InvalidParams -> callback(CompletionResult.Failure(TaskError.InvalidParams())) + StatusWord.ErrorProcessingCommand -> callback(CompletionResult.Failure(TaskError.ErrorProcessingCommand())) + StatusWord.InvalidState -> callback(CompletionResult.Failure(TaskError.InvalidState())) - Status.InsNotSupported -> callback(TaskEvent.Completion(TaskError.InsNotSupported())) - Status.NeedEncryption -> callback(TaskEvent.Completion(TaskError.NeedEncryption())) - Status.NeedPause -> { + StatusWord.InsNotSupported -> callback(CompletionResult.Failure(TaskError.InsNotSupported())) + StatusWord.NeedEncryption -> callback(CompletionResult.Failure(TaskError.NeedEncryption())) + StatusWord.NeedPause -> { val remainingTime = commandSerializer.deserializeSecurityDelay(responseApdu, cardEnvironment) if (remainingTime != null) delegate?.showSecurityDelay(remainingTime) Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} triggered security delay of $remainingTime milliseconds") @@ -71,7 +66,7 @@ abstract class Task { } is CompletionResult.Failure -> if (result.error is TaskError.UserCancelledError) { - callback(TaskEvent.Completion(TaskError.UserCancelledError())) + callback(CompletionResult.Failure(TaskError.UserCancelledError())) reader?.readingActive = false } @@ -85,7 +80,7 @@ sealed class TaskError(description: String? = null) : Exception(description) { class MappingError : TaskError() class GenericError(description: String? = null) : TaskError(description) class UserCancelledError() : TaskError() - class Busy(): TaskError() + class Busy() : TaskError() class ErrorProcessingCommand : TaskError() class InvalidState : TaskError()