Skip to content

Commit

Permalink
Avoid doing IO operations on Android main thread (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepone authored Jan 9, 2025
1 parent bcfee04 commit 048e6ed
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 78 deletions.
48 changes: 0 additions & 48 deletions java/android/hello/src/main/java/com/zeroc/hello/DeliveryMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,6 @@ enum DeliveryMode
DATAGRAM,
DATAGRAM_BATCH;

ObjectPrx apply(ObjectPrx prx)
{
switch (this)
{
case TWOWAY:
{
prx = prx.ice_twoway();
break;
}
case TWOWAY_SECURE:
{
prx = prx.ice_twoway().ice_secure(true);
break;
}
case ONEWAY:
{
prx = prx.ice_oneway();
break;
}
case ONEWAY_BATCH:
{
prx = prx.ice_batchOneway();
break;
}
case ONEWAY_SECURE:
{
prx = prx.ice_oneway().ice_secure(true);
break;
}
case ONEWAY_SECURE_BATCH:
{
prx = prx.ice_batchOneway().ice_secure(true);
break;
}
case DATAGRAM:
{
prx = prx.ice_datagram();
break;
}
case DATAGRAM_BATCH:
{
prx = prx.ice_batchDatagram();
break;
}
}
return prx;
}

public boolean isOneway()
{
return this == ONEWAY || this == ONEWAY_SECURE || this == DATAGRAM;
Expand Down
63 changes: 36 additions & 27 deletions java/android/hello/src/main/java/com/zeroc/hello/HelloApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

Expand Down Expand Up @@ -91,8 +92,6 @@ else if(m.what == MSG_EXCEPTION || m.what == MSG_RESPONSE)
{
InitializationData initData = new InitializationData();

initData.executor = (Runnable runnable, Connection connection) -> _uiHandler.post(runnable);

initData.properties = new Properties();
initData.properties.setProperty("Ice.Trace.Network", "3");

Expand All @@ -104,18 +103,23 @@ else if(m.what == MSG_EXCEPTION || m.what == MSG_RESPONSE)
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(getResources().openRawResource(R.raw.client), "password".toCharArray());

// Create a key manager manager factory that uses the certificates from our KeyStore.
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "password".toCharArray());

// Create a trust manager factory that uses the certificates from our KeyStore.
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

// Create a SSLContext for TLS and initialize it with our custom trust manager factory.
var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

// Setup the SSLEngine factory used by secure (TLS) client connections.
initData.clientSSLEngineFactory =
(String peerHost, int peerPort) -> sslContext.createSSLEngine(peerHost, peerPort);
(String peerHost, int peerPort) -> sslContext.createSSLEngine(peerHost, peerPort);

Communicator c = Util.initialize(initData);
_uiHandler.sendMessage(Message.obtain(_uiHandler, MSG_READY, new MessageReady(c, null)));
Expand All @@ -127,9 +131,9 @@ else if(m.what == MSG_EXCEPTION || m.what == MSG_RESPONSE)
catch (Exception e)
{
_uiHandler.sendMessage(Message.obtain(
_uiHandler,
MSG_READY,
new MessageReady(null, new InitializationException("Communicator initialization failed", e))));
_uiHandler,
MSG_READY,
new MessageReady(null, new InitializationException("Communicator initialization failed", e))));
}
}).start();
}
Expand Down Expand Up @@ -216,10 +220,8 @@ void shutdown()
try
{
updateProxy();
if(_proxy == null)
{
return;
}
assert(_proxy != null);

_proxy.shutdownAsync().whenComplete((result, ex) ->
{
if(ex != null)
Expand All @@ -245,7 +247,9 @@ void shutdownAsync()
try
{
updateProxy();
if(_proxy == null || _result != null)
assert (_proxy != null);

if(_result != null)
{
return;
}
Expand Down Expand Up @@ -322,7 +326,9 @@ void sayHelloAsync(int delay)
try
{
updateProxy();
if(_proxy == null || _result != null)
assert(_proxy != null);

if(_result != null)
{
return;
}
Expand Down Expand Up @@ -374,23 +380,26 @@ private void updateProxy()
return;
}

String s;
if(_useDiscovery)
{
s = "hello";
}
else
{
s = "hello:tcp -h " + _host + " -p 10000:ssl -h " + _host + " -p 10001:udp -h " + _host + " -p 10000";
}
ObjectPrx prx = _communicator.stringToProxy(s);
prx = _mode.apply(prx);
var prx = HelloPrx.createProxy(
_communicator,
_useDiscovery ? "hello" : "hello:tcp -h " + _host + " -p 10000:ssl -h " + _host + " -p 10001:udp -h " + _host + " -p 10000");

prx = switch (_mode) {
case TWOWAY -> prx.ice_twoway();
case TWOWAY_SECURE -> prx.ice_twoway().ice_secure(true);
case ONEWAY -> prx.ice_oneway();
case ONEWAY_BATCH -> prx.ice_batchOneway();
case ONEWAY_SECURE -> prx.ice_oneway().ice_secure(true);
case ONEWAY_SECURE_BATCH -> prx.ice_batchOneway().ice_secure(true);
case DATAGRAM -> prx.ice_datagram();
case DATAGRAM_BATCH -> prx.ice_batchDatagram();
};

if(_timeout != 0)
{
prx = prx.ice_invocationTimeout(_timeout);
}

_proxy = HelloPrx.uncheckedCast(prx);
_proxy = prx;
}

DeliveryMode getDeliveryMode()
Expand Down
18 changes: 15 additions & 3 deletions java/android/hello/src/main/java/com/zeroc/hello/HelloWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import com.zeroc.Ice.LocalException;

import java.util.concurrent.ExecutorService;

public class HelloWorld extends AppCompatActivity
{
public static class ErrorDialogFragment extends DialogFragment
Expand Down Expand Up @@ -109,6 +111,7 @@ public void onCreate(Bundle savedInstanceState)
final SharedPreferences prefs = getPreferences(MODE_PRIVATE);

_app = (HelloApp)getApplication();
_executor = java.util.concurrent.Executors.newSingleThreadExecutor();

useDiscoveryCheckBox.setOnClickListener(v -> {
final boolean checked = ((CheckBox)v).isChecked();
Expand Down Expand Up @@ -139,7 +142,11 @@ public void onCreate(Bundle savedInstanceState)
}
else
{
_app.sayHelloAsync(delaySeekBar.getProgress());
int delay = delaySeekBar.getProgress();
// sayHelloAsync is called on the executor to avoid IO operations on the main thread.
_executor.execute(() -> {
_app.sayHelloAsync(delay);
});
}
});

Expand All @@ -152,7 +159,10 @@ public void onCreate(Bundle savedInstanceState)
}
else
{
_app.shutdownAsync();
// shutdownAsync is called on the executor to avoid IO operations on the main thread.
_executor.execute(() -> {
_app.shutdownAsync();
});
}
});

Expand Down Expand Up @@ -199,7 +209,8 @@ public void onTextChanged(CharSequence s, int start, int count, int after)
});

flushButton.setOnClickListener(v -> {
_app.flush();
// flush is called on the executor to avoid IO operations on the main thread.
_executor.execute(() -> _app.flush());
flushButton.setEnabled(false);
statusTextView.setText(R.string.flushed_batch_requests);
});
Expand Down Expand Up @@ -413,5 +424,6 @@ protected void onDestroy()
private static final String BUNDLE_KEY_FLUSH_ENABLED = "zeroc:flush";

private HelloApp _app;
private ExecutorService _executor;
private Handler _handler;
}

0 comments on commit 048e6ed

Please sign in to comment.