From 0231abced864ad6f85c1e7b31f7223355fac8891 Mon Sep 17 00:00:00 2001 From: 9hm2 Date: Thu, 20 Jun 2024 21:59:07 +0200 Subject: [PATCH] Update UsbAPI.java Improved code with quick feedback with the usb permission intent --- .../main/java/com/termux/api/apis/UsbAPI.java | 157 +++++++++--------- 1 file changed, 75 insertions(+), 82 deletions(-) diff --git a/app/src/main/java/com/termux/api/apis/UsbAPI.java b/app/src/main/java/com/termux/api/apis/UsbAPI.java index e44f793e..c9fa4efb 100644 --- a/app/src/main/java/com/termux/api/apis/UsbAPI.java +++ b/app/src/main/java/com/termux/api/apis/UsbAPI.java @@ -8,6 +8,7 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; +import android.os.Handler; import android.os.Looper; import android.util.JsonWriter; import android.util.SparseArray; @@ -19,74 +20,52 @@ import java.io.IOException; import java.io.PrintWriter; -import java.util.Iterator; import java.util.HashMap; +import java.util.Iterator; import androidx.annotation.NonNull; public class UsbAPI { private static SparseArray openDevices = new SparseArray<>(); - private static final String LOG_TAG = "UsbAPI"; + private static final String ACTION_USB_PERMISSION = TermuxConstants.TERMUX_API_PACKAGE_NAME + ".USB_PERMISSION"; public static void onReceive(final TermuxApiReceiver apiReceiver, final Context context, final Intent intent) { Logger.logDebug(LOG_TAG, "onReceive"); - UsbDevice device; String action = intent.getAction(); if (action == null) { ResultReturner.returnData(apiReceiver, intent, out -> out.append("Missing action\n")); - } else { - switch (action) { - case "list": - ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultJsonWriter() { - @Override - public void writeJson(JsonWriter out) throws Exception { - listDevices(context, out); - } - }); - break; - case "permission": - device = getDevice(apiReceiver, context, intent); - if (device == null) return; - ResultReturner.returnData(apiReceiver, intent, out -> { - boolean result = getPermission(device, context, intent); - out.append(result ? "yes\n" : "no\n"); - }); - break; - case "open": - device = getDevice(apiReceiver, context, intent); - if (device == null) return; - ResultReturner.returnData(apiReceiver, intent, new ResultReturner.WithAncillaryFd() { - @Override - public void writeResult(PrintWriter out) { - if (getPermission(device, context, intent)) { - int result = open(device, context); - if (result < 0) { - out.append("Failed to open device\n"); - } else { - this.sendFd(out, result); - } - } else out.append("No permission\n"); - } - }); - - break; - default: - ResultReturner.returnData(apiReceiver, intent, out -> out.append("Invalid action\n")); - } + return; } + switch (action) { + case "list": + ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultJsonWriter() { + @Override + public void writeJson(JsonWriter out) throws Exception { + listDevices(context, out); + } + }); + break; + case "permission": + handlePermissionRequest(apiReceiver, context, intent); + break; + case "open": + handleOpenRequest(apiReceiver, context, intent); + break; + default: + ResultReturner.returnData(apiReceiver, intent, out -> out.append("Invalid action\n")); + } } private static void listDevices(final Context context, JsonWriter out) throws IOException { final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); HashMap deviceList = usbManager.getDeviceList(); - Iterator deviceIterator = deviceList.keySet().iterator(); out.beginArray(); - while (deviceIterator.hasNext()) { - out.value(deviceIterator.next()); + for (String deviceName : deviceList.keySet()) { + out.value(deviceName); } out.endArray(); } @@ -102,63 +81,74 @@ private static UsbDevice getDevice(final TermuxApiReceiver apiReceiver, final Co return device; } + private static void handlePermissionRequest(final TermuxApiReceiver apiReceiver, final Context context, final Intent intent) { + UsbDevice device = getDevice(apiReceiver, context, intent); + if (device == null) return; + + requestPermissionAsync(device, context, granted -> { + ResultReturner.returnData(apiReceiver, intent, out -> { + out.append(granted ? "yes\n" : "no\n"); + }); + }); + } + + private static void handleOpenRequest(final TermuxApiReceiver apiReceiver, final Context context, final Intent intent) { + UsbDevice device = getDevice(apiReceiver, context, intent); + if (device == null) return; + + requestPermissionAsync(device, context, granted -> { + ResultReturner.returnData(apiReceiver, intent, new ResultReturner.WithAncillaryFd() { + @Override + public void writeResult(PrintWriter out) { + if (granted) { + int result = open(device, context); + if (result < 0) { + out.append("Failed to open device\n"); + } else { + this.sendFd(out, result); + } + } else { + out.append("No permission\n"); + } + } + }); + }); + } + private static boolean hasPermission(final @NonNull UsbDevice device, final Context context) { final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); return usbManager.hasPermission(device); } - private static boolean requestPermission(final @NonNull UsbDevice device, final Context context) { - Looper.prepare(); - Looper looper = Looper.myLooper(); - final boolean[] result = new boolean[1]; + private static void requestPermissionAsync(final @NonNull UsbDevice device, final Context context, final PermissionCallback callback) { + if (hasPermission(device, context)) { + callback.onPermissionResult(true); + return; + } - final String ACTION_USB_PERMISSION = TermuxConstants.TERMUX_API_PACKAGE_NAME + ".USB_PERMISSION"; final BroadcastReceiver usbReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context usbContext, final Intent usbIntent) { - String action = usbIntent.getAction(); - if (ACTION_USB_PERMISSION.equals(action)) { - synchronized (this) { - UsbDevice device = usbIntent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - if (usbIntent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { - if (device != null) { - result[0] = true; - if (looper != null) looper.quit(); - } - } else { - result[0] = false; - if (looper != null) looper.quit(); - } - } - + if (ACTION_USB_PERMISSION.equals(usbIntent.getAction())) { + boolean granted = usbIntent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); + Logger.logDebug(LOG_TAG, "Permission result: " + granted); + callback.onPermissionResult(granted); + usbContext.unregisterReceiver(this); } } }; final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); - PendingIntent permissionIntent = PendingIntent.getBroadcast(context, 0, - new Intent(ACTION_USB_PERMISSION), 0); - IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); - context.getApplicationContext().registerReceiver(usbReceiver, filter); + PendingIntent permissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); + context.getApplicationContext().registerReceiver(usbReceiver, new IntentFilter(ACTION_USB_PERMISSION)); + Logger.logDebug(LOG_TAG, "Requesting permission for device: " + device.getDeviceName()); usbManager.requestPermission(device, permissionIntent); - Looper.loop(); - return result[0]; - } - - private static boolean getPermission(final @NonNull UsbDevice device, final Context context, final Intent intent) { - boolean request = intent.getBooleanExtra("request", false); - if(request) { - return requestPermission(device, context); - } else { - return hasPermission(device, context); - } } private static int open(final @NonNull UsbDevice device, final Context context) { final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); UsbDeviceConnection connection = usbManager.openDevice(device); - if (connection == null) - return -2; + if (connection == null) return -2; int fd = connection.getFileDescriptor(); if (fd == -1) { connection.close(); @@ -168,4 +158,7 @@ private static int open(final @NonNull UsbDevice device, final Context context) return fd; } + private interface PermissionCallback { + void onPermissionResult(boolean granted); + } }