Skip to content

Commit 5710103

Browse files
p1gp1gmar-v-in
authored andcommitted
Fido: Re-request permission when result isn't received
It may happen that the OS doesn't ask for the permission: We re-request the permission every seconds until it is correctly received, with a maximum of 5 attempts, or when the user navigate back to the USB selection
1 parent bb00114 commit 5710103

1 file changed

Lines changed: 39 additions & 2 deletions

File tree

play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/transport/usb/UsbDevicePermissionManager.kt

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ import android.content.BroadcastReceiver
99
import android.content.Context
1010
import android.content.Intent
1111
import android.content.IntentFilter
12+
import android.util.Log
1213
import android.hardware.usb.UsbDevice
1314
import android.hardware.usb.UsbManager
15+
import android.os.Build
1416
import androidx.core.app.PendingIntentCompat
1517
import androidx.core.content.ContextCompat
1618
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED
1719
import kotlinx.coroutines.CompletableDeferred
20+
import java.util.Timer
21+
import java.util.TimerTask
1822

1923
private val Context.usbPermissionCallbackAction
2024
get() = "$packageName.USB_PERMISSION_CALLBACK"
@@ -40,6 +44,10 @@ private object UsbDevicePermissionReceiver : BroadcastReceiver() {
4044
}
4145
}
4246

47+
fun isDeferred(device: UsbDevice): Boolean = synchronized(this) {
48+
return pendingRequests.containsKey(device)
49+
}
50+
4351
fun unregister(context: Context) = synchronized(this) {
4452
if (registered) {
4553
context.unregisterReceiver(this)
@@ -75,10 +83,39 @@ class UsbDevicePermissionManager(private val context: Context) {
7583
if (context.usbManager?.hasPermission(device) == true) return true
7684
val res = CompletableDeferred<Boolean>()
7785
if (UsbDevicePermissionReceiver.addDeferred(device, res)) {
86+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
87+
Log.d(TAG, "PermissionReceiver added for ${device.productName} (${context.packageName})")
88+
}
7889
UsbDevicePermissionReceiver.register(context)
79-
val intent = PendingIntentCompat.getBroadcast(context, 0, Intent(context.usbPermissionCallbackAction).apply { `package` = context.packageName }, 0, true)
80-
context.usbManager?.requestPermission(device, intent)
90+
schedulePermissionRequest(device, 5)
91+
} else {
92+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
93+
Log.d(TAG, "PermissionReceiver already added for ${device.productName}")
94+
}
8195
}
96+
requestPermission(device)
8297
return res.await()
8398
}
99+
100+
// In case we couldn't ask for permission, retry every secondes, with a maximum of `maxRetries`
101+
private fun schedulePermissionRequest(device: UsbDevice, maxRetries: Int) {
102+
if (maxRetries < 1) return
103+
Timer().schedule(object : TimerTask() {
104+
override fun run() {
105+
if (UsbDevicePermissionReceiver.isDeferred(device)) {
106+
requestPermission(device)
107+
schedulePermissionRequest(device, maxRetries - 1)
108+
}
109+
}
110+
}, 1000)
111+
}
112+
113+
private fun requestPermission(device: UsbDevice) {
114+
val intent = PendingIntentCompat.getBroadcast(context, 0, Intent(context.usbPermissionCallbackAction).apply { `package` = context.packageName }, 0, true)
115+
context.usbManager?.requestPermission(device, intent)
116+
}
117+
118+
companion object {
119+
private const val TAG = "UsbDevicePermissionMan"
120+
}
84121
}

0 commit comments

Comments
 (0)