tangem-app-android-audited/app/src/main/java/com/tangem/presentation/activity/PinRequestActivity.kt
2018-12-04 11:05:20 +03:00

318 lines
No EOL
11 KiB
Kotlin

package com.tangem.presentation.activity
import android.Manifest
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.hardware.fingerprint.FingerprintManager
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.os.Build
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AppCompatActivity
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.Button
import com.tangem.data.fingerprint.StartFingerprintReaderTask
import com.tangem.tangemcard.reader.NfcManager
import com.tangem.data.fingerprint.FingerprintHelper
import com.tangem.tangemcard.data.PINStorage
import com.tangem.tangemcard.data.TangemCard
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_pin_request.*
import kotlinx.android.synthetic.main.layout_pin_buttons.*
import java.io.IOException
class PinRequestActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, FingerprintHelper.FingerprintHelperListener {
companion object {
const val KEY_ALIAS = "pinKey"
const val KEYSTORE = "AndroidKeyStore"
}
lateinit var mode: Mode
private var allowFingerprint = false
private var nfcManager: NfcManager? = null
var startFingerprintReaderTask: StartFingerprintReaderTask? = null
private var fingerprintManager: FingerprintManager? = null
private var fingerprintHelper: FingerprintHelper? = null
enum class Mode {
RequestPIN, RequestPIN2, RequestNewPIN, RequestNewPIN2, ConfirmNewPIN, ConfirmNewPIN2
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pin_request)
MainActivity.commonInit(applicationContext)
nfcManager = NfcManager(this, this)
mode = Mode.valueOf(intent.getStringExtra("mode"))
if (mode == Mode.RequestNewPIN)
if (PINStorage.haveEncryptedPIN()) {
allowFingerprint = true
tvPinPrompt.setText(R.string.enter_new_pin_or_use_fingerprint_scanner)
} else
tvPinPrompt.setText(R.string.enter_new_pin)
else if (mode == Mode.ConfirmNewPIN)
tvPinPrompt.setText(R.string.confirm_new_pin)
else if (mode == Mode.RequestPIN)
if (PINStorage.haveEncryptedPIN()) {
allowFingerprint = true
tvPinPrompt.setText(R.string.enter_pin_or_use_fingerprint_scanner)
} else
tvPinPrompt.setText(R.string.enter_pin)
else if (mode == Mode.RequestNewPIN2)
if (PINStorage.haveEncryptedPIN2()) {
allowFingerprint = true
tvPinPrompt.setText(R.string.enter_new_pin_2_or_use_fingerprint_scanner)
} else
tvPinPrompt.setText(R.string.enter_new_pin_2)
else if (mode == Mode.ConfirmNewPIN2)
tvPinPrompt.setText(R.string.confirm_new_pin_2)
else if (mode == Mode.RequestPIN2) {
val uid = intent.getStringExtra(TangemCard.EXTRA_UID)
val card = TangemCard(uid)
card.loadFromBundle(intent.getBundleExtra(TangemCard.EXTRA_CARD))
if (card.PIN2 == TangemCard.PIN2_Mode.DefaultPIN2 || card.PIN2 == TangemCard.PIN2_Mode.Unchecked) {
// if we know PIN2 or not try default previously - use it
PINStorage.setPIN2(PINStorage.getDefaultPIN2())
setResult(Activity.RESULT_OK)
finish()
return
}
if (PINStorage.haveEncryptedPIN2()) {
allowFingerprint = true
tvPinPrompt.setText(R.string.enter_pin_2_or_use_fingerprint_scanner)
} else
tvPinPrompt.setText(R.string.enter_pin_2)
}
if (!allowFingerprint)
tvPinPrompt.visibility = View.GONE
else
tvPinPrompt.visibility = View.VISIBLE
// set listeners
btn0.setOnClickListener { buttonClick(btn0) }
btn1.setOnClickListener { buttonClick(btn1) }
btn2.setOnClickListener { buttonClick(btn2) }
btn3.setOnClickListener { buttonClick(btn3) }
btn4.setOnClickListener { buttonClick(btn4) }
btn5.setOnClickListener { buttonClick(btn5) }
btn6.setOnClickListener { buttonClick(btn6) }
btn7.setOnClickListener { buttonClick(btn7) }
btn8.setOnClickListener { buttonClick(btn8) }
btn9.setOnClickListener { buttonClick(btn9) }
btnBackspace.setOnClickListener {
val s = tvPin!!.text.toString()
if (s.isNotEmpty())
tvPin!!.text = s.substring(0, s.length - 1)
}
btnContinue.setOnClickListener { doContinue() }
}
override fun onPause() {
super.onPause()
if (fingerprintHelper != null)
fingerprintHelper!!.cancel()
if (startFingerprintReaderTask != null) {
startFingerprintReaderTask!!.cancel(true)
startFingerprintReaderTask = null
}
nfcManager!!.onPause()
}
override fun onStop() {
super.onStop()
if (fingerprintHelper != null)
fingerprintHelper!!.cancel()
if (startFingerprintReaderTask != null) {
startFingerprintReaderTask!!.cancel(true)
startFingerprintReaderTask = null
}
nfcManager!!.onStop()
}
override fun onResume() {
super.onResume()
nfcManager!!.onResume()
if (allowFingerprint)
startFingerprintReader()
}
override fun onTagDiscovered(tag: Tag) {
try {
Log.w(javaClass.name, "Ignore discovered tag!")
nfcManager!!.ignoreTag(tag)
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun authenticationFailed(error: String) {
doLog(error)
}
@TargetApi(Build.VERSION_CODES.M)
override fun authenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
doLog("Authentication succeeded!")
val cipher = result.cryptoObject.cipher
if (mode == Mode.RequestNewPIN || mode == Mode.ConfirmNewPIN) {
val resultData = Intent()
val pin = PINStorage.loadEncryptedPIN(cipher)
resultData.putExtra("newPIN", pin)
resultData.putExtra("confirmPIN", pin)
setResult(Activity.RESULT_OK, resultData)
finish()
} else if (mode == Mode.RequestNewPIN2 || mode == Mode.ConfirmNewPIN2) {
val resultData = Intent()
val pin = PINStorage.loadEncryptedPIN2(cipher)
resultData.putExtra("newPIN2", pin)
resultData.putExtra("confirmPIN2", pin)
setResult(Activity.RESULT_OK, resultData)
finish()
} else if (mode == Mode.RequestPIN) {
PINStorage.loadEncryptedPIN(cipher)
setResult(Activity.RESULT_OK)
} else if (mode == Mode.RequestPIN2) {
PINStorage.loadEncryptedPIN2(cipher)
setResult(Activity.RESULT_OK)
}
finish()
}
fun doLog(text: String) {
// Log.e("FP", text);
}
@SuppressLint("SetTextI18n")
private fun buttonClick(button: Button) {
tvPin!!.text = tvPin!!.text.toString() + button.text as String
}
@SuppressLint("NewApi")
private fun testFingerPrintSettings(): Boolean {
doLog("Testing Fingerprint Settings")
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
fingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
if (!keyguardManager.isKeyguardSecure) {
doLog("User hasn't enabled Lock Screen")
return false
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
doLog("User hasn't granted permission to use Fingerprint")
return false
}
if (!fingerprintManager!!.hasEnrolledFingerprints()) {
doLog("User hasn't registered any fingerprints")
return false
}
doLog("Fingerprint authentication is set.\n")
return true
}
private fun startFingerprintReader() {
if (!testFingerPrintSettings())
return
if (!allowFingerprint)
return
fingerprintHelper = FingerprintHelper(this@PinRequestActivity)
startFingerprintReaderTask = StartFingerprintReaderTask(this, fingerprintManager, fingerprintHelper)
startFingerprintReaderTask!!.execute(null as Void?)
}
private fun doContinue() {
if (startFingerprintReaderTask != null)
return
// reset errors.
tvPin!!.error = null
// store values at the time of the login attempt.
val pin = tvPin!!.text.toString()
var cancel = false
var focusView: View? = null
if (mode == Mode.ConfirmNewPIN) {
if (pin != intent.getStringExtra("newPIN")) {
tvPin!!.error = getString(R.string.error_pin_confirmation_failed)
focusView = tvPin
cancel = true
}
} else if (mode == Mode.ConfirmNewPIN2) {
if (pin != intent.getStringExtra("newPIN2")) {
tvPin!!.error = getString(R.string.error_pin_confirmation_failed)
focusView = tvPin
cancel = true
}
} else {
if (TextUtils.isEmpty(pin)) {
tvPin!!.error = getString(R.string.error_empty_pin)
focusView = tvPin
cancel = true
}
}
if (cancel)
focusView!!.requestFocus()
else {
if (mode == Mode.RequestNewPIN || mode == Mode.ConfirmNewPIN) {
val resultData = Intent()
resultData.putExtra("newPIN", pin)
if (mode == Mode.ConfirmNewPIN)
resultData.putExtra("confirmPIN", pin)
setResult(Activity.RESULT_OK, resultData)
finish()
} else if (mode == Mode.RequestNewPIN2 || mode == Mode.ConfirmNewPIN2) {
val resultData = Intent()
resultData.putExtra("newPIN2", pin)
if (mode == Mode.ConfirmNewPIN2)
resultData.putExtra("confirmPIN2", pin)
setResult(Activity.RESULT_OK, resultData)
finish()
} else if (mode == Mode.RequestPIN) {
PINStorage.setUserPIN(pin)
setResult(Activity.RESULT_OK)
finish()
} else if (mode == Mode.RequestPIN2) {
PINStorage.setPIN2(pin)
setResult(Activity.RESULT_OK)
finish()
}
}
}
}