Only globally synchronize open/close port methods on the native function call

This commit is contained in:
Will Hedgecock 2022-02-14 11:41:00 -06:00
parent 60b90199bf
commit a9444ffbad
3 changed files with 67 additions and 61 deletions

View File

@ -5,8 +5,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE := jSerialComm LOCAL_MODULE := jSerialComm
TARGET_OUT := ../../resources/Android/$(TARGET_ARCH_ABI) TARGET_OUT := ../../resources/Android/$(TARGET_ARCH_ABI)
LOCAL_SRC_FILES := ../SerialPort_Posix.c ../PosixHelperFunctions.c LOCAL_SRC_FILES := ../SerialPort_Posix.c ../PosixHelperFunctions.c
LOCAL_CFLAGS := -fsigned-char -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := -fsigned-char
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@ -1,3 +1,4 @@
APP_ABI := all APP_ABI := all
APP_PLATFORM := android-21 APP_PLATFORM := android-21
APP_MODULES := jSerialComm APP_MODULES := jSerialComm
APP_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

View File

@ -501,7 +501,9 @@ public final class SerialPort
serialPort.friendlyName = "User-Specified Port"; serialPort.friendlyName = "User-Specified Port";
serialPort.portDescription = "User-Specified Port"; serialPort.portDescription = "User-Specified Port";
serialPort.portLocation = "0-0"; serialPort.portLocation = "0-0";
serialPort.retrievePortDetails(); synchronized (SerialPort.class) {
serialPort.retrievePortDetails();
}
return serialPort; return serialPort;
} }
@ -584,60 +586,59 @@ public final class SerialPort
*/ */
public final synchronized boolean openPort(int safetySleepTime, int deviceSendQueueSize, int deviceReceiveQueueSize) public final synchronized boolean openPort(int safetySleepTime, int deviceSendQueueSize, int deviceReceiveQueueSize)
{ {
// Synchronize this method to the class scope as well // Set the send/receive internal buffer sizes, and return true if already opened
synchronized (SerialPort.class) safetySleepTimeMS = safetySleepTime;
{ sendDeviceQueueSize = (deviceSendQueueSize > 0) ? deviceSendQueueSize : sendDeviceQueueSize;
// Set the send/receive internal buffer sizes, and return true if already opened receiveDeviceQueueSize = (deviceReceiveQueueSize > 0) ? deviceReceiveQueueSize : receiveDeviceQueueSize;
safetySleepTimeMS = safetySleepTime; if (portHandle != 0)
sendDeviceQueueSize = (deviceSendQueueSize > 0) ? deviceSendQueueSize : sendDeviceQueueSize; return configPort(portHandle);
receiveDeviceQueueSize = (deviceReceiveQueueSize > 0) ? deviceReceiveQueueSize : receiveDeviceQueueSize;
if (portHandle != 0) // Force a sleep to ensure that the port does not become unusable due to rapid closing/opening on the part of the user
return configPort(portHandle); if (safetySleepTimeMS > 0)
try { Thread.sleep(safetySleepTimeMS); } catch (Exception e) { Thread.currentThread().interrupt(); }
// Force a sleep to ensure that the port does not become unusable due to rapid closing/opening on the part of the user
if (safetySleepTimeMS > 0) // If this is an Android root application, we must explicitly allow serial port access to the library
try { Thread.sleep(safetySleepTimeMS); } catch (Exception e) { Thread.currentThread().interrupt(); } File portFile = isAndroid ? new File(comPort) : null;
if (portFile != null && (!portFile.canRead() || !portFile.canWrite()))
// If this is an Android root application, we must explicitly allow serial port access to the library {
File portFile = isAndroid ? new File(comPort) : null; Process process = null;
if (portFile != null && (!portFile.canRead() || !portFile.canWrite())) try
{ {
Process process = null; process = Runtime.getRuntime().exec("su");
try DataOutputStream writer = new DataOutputStream(process.getOutputStream());
{ writer.writeBytes("chmod 666 " + comPort + "\n");
process = Runtime.getRuntime().exec("su"); writer.writeBytes("exit\n");
DataOutputStream writer = new DataOutputStream(process.getOutputStream()); writer.flush();
writer.writeBytes("chmod 666 " + comPort + "\n"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
writer.writeBytes("exit\n"); while (reader.readLine() != null);
writer.flush(); }
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); catch (Exception e)
while (reader.readLine() != null); {
} e.printStackTrace();
catch (Exception e) return false;
{ }
e.printStackTrace(); finally
{
if (process == null)
return false; return false;
} try { process.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
finally try { process.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
{ try { process.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
if (process == null) try { process.getErrorStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
return false; try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
try { process.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
try { process.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { process.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { process.getErrorStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
}
} }
}
// Open the serial port and start an event-based listener if registered
if ((portHandle = openPortNative()) != 0) // Natively open the serial port, and synchronize to the class scope since port enumeration methods are class-based,
{ // and this method may alter or read a global class structure in native code
if (serialEventListener != null) synchronized (SerialPort.class) {
serialEventListener.startListening(); portHandle = openPortNative();
} }
return (portHandle != 0);
} // Start an event-based listener if registered and the port is open
if ((portHandle != 0) && (serialEventListener != null))
serialEventListener.startListening();
return (portHandle != 0);
} }
/** /**
@ -684,15 +685,19 @@ public final class SerialPort
*/ */
public final synchronized boolean closePort() public final synchronized boolean closePort()
{ {
// Synchronize this method to the class scope as well // Stop a registered event listener
synchronized (SerialPort.class) if (serialEventListener != null)
{ serialEventListener.stopListening();
if (serialEventListener != null)
serialEventListener.stopListening(); // Natively close the port, and synchronize to the class scope since port enumeration methods are class-based,
if (portHandle != 0) // and this method may alter or read a global class structure in native code
if (portHandle != 0)
{
synchronized (SerialPort.class) {
portHandle = closePortNative(portHandle); portHandle = closePortNative(portHandle);
return (portHandle == 0); }
} }
return (portHandle == 0);
} }
/** /**