use intent filters for USB only if app is resumed

This commit is contained in:
Adam Velebil 2022-09-29 16:52:33 +02:00
parent 9d92d2e1ef
commit 84f9147aed
No known key found for this signature in database
GPG Key ID: AC6D6B9D715FC084
2 changed files with 58 additions and 8 deletions

View File

@ -39,6 +39,13 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias
android:name=".AliasMainActivity"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
@ -47,7 +54,7 @@
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</activity-alias>
<activity
android:name=".NdefActivity"

View File

@ -1,9 +1,7 @@
package com.yubico.authenticator
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.*
import android.content.pm.PackageManager
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.nfc.NfcAdapter
@ -56,6 +54,27 @@ class MainActivity : FlutterFragmentActivity() {
setupYubiKitLogger()
}
/**
* Enables or disables .AliasMainActivity component. This activity alias adds intent-filter
* for android.hardware.usb.action.USB_DEVICE_ATTACHED. When enabled, the app will be opened
* when a compliant USB device (defined in `res/xml/device_filter.xml`) is attached.
*
* By default the activity alias is disabled through AndroidManifest.xml.
*
* @param enable if true, alias activity will be enabled
*/
private fun enableAliasMainActivityComponent(enable: Boolean) {
val componentName = ComponentName(packageName, "com.yubico.authenticator.AliasMainActivity")
applicationContext.packageManager.setComponentEnabledSetting(
componentName,
if (enable)
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
else
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP
)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
@ -121,12 +140,15 @@ class MainActivity : FlutterFragmentActivity() {
override fun onPause() {
stopNfcDiscovery()
enableAliasMainActivityComponent(false)
super.onPause()
}
override fun onResume() {
super.onResume()
enableAliasMainActivityComponent(true)
// Handle existing tag when launched from NDEF
val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag != null) {
@ -149,14 +171,27 @@ class MainActivity : FlutterFragmentActivity() {
startNfcDiscovery()
}
val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
if (UsbManager.ACTION_USB_DEVICE_ATTACHED == intent.action) {
val device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) as UsbDevice?
if (device != null) {
val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
// start the USB discover only if the user approved the app to use the device
if (usbManager.hasPermission(device)) {
startUsbDiscovery()
}
}
} else if (viewModel.connectedYubiKey.value == null) {
// if any YubiKeys are connected, use them directly
val deviceIterator = usbManager.deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if (device.vendorId == YUBICO_VENDOR_ID) {
// the device might not have a USB permission
// it will be requested during during the UsbDiscovery
startUsbDiscovery()
break
}
}
}
}
@ -199,8 +234,15 @@ class MainActivity : FlutterFragmentActivity() {
viewModel.appContext.observe(this) {
contextManager?.dispose()
contextManager = when(it) {
OperationContext.Oath -> OathManager(this, messenger, viewModel, oathViewModel, dialogManager, appPreferences)
contextManager = when (it) {
OperationContext.Oath -> OathManager(
this,
messenger,
viewModel,
oathViewModel,
dialogManager,
appPreferences
)
else -> null
}
viewModel.connectedYubiKey.value?.let(::processYubiKey)
@ -214,6 +256,7 @@ class MainActivity : FlutterFragmentActivity() {
companion object {
const val TAG = "MainActivity"
const val YUBICO_VENDOR_ID = 4176
const val FLAG_SECURE = WindowManager.LayoutParams.FLAG_SECURE
}