package org.strongswan.android.logic;
import java.security.Security;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import org.strongswan.android.security.LocalCertificateKeyStoreProvider;
import org.strongswan.android.ui.MainActivity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.core.os.HandlerCompat;
public class StrongSwanApplication extends Application
{
private static Context mContext;
+ private final ExecutorService mExecutorService = Executors.newFixedThreadPool(4);
+ private final Handler mMainHandler = HandlerCompat.createAsync(Looper.getMainLooper());
static {
Security.addProvider(new LocalCertificateKeyStoreProvider());
return StrongSwanApplication.mContext;
}
+ /**
+ * Returns a thread pool to run tasks in separate threads
+ * @return thread pool
+ */
+ public Executor getExecutor()
+ {
+ return mExecutorService;
+ }
+
+ /**
+ * Returns a handler to execute stuff by the main thread.
+ * @return handler
+ */
+ public Handler getHandler()
+ {
+ return mMainHandler;
+ }
+
/*
* The libraries are extracted to /data/data/org.strongswan.android/...
* during installation. On newer releases most are loaded in JNI_OnLoad.
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.format.Formatter;
import org.strongswan.android.R;
import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.logic.StrongSwanApplication;
import org.strongswan.android.logic.TrustedCertificateManager;
import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
bar.setDisplayShowTitleEnabled(false);
bar.setIcon(R.mipmap.ic_app);
- /* load CA certificates in a background task */
- new LoadCertificatesTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ /* load CA certificates in a background thread */
+ ((StrongSwanApplication)getApplication()).getExecutor().execute(() -> {
+ TrustedCertificateManager.getInstance().load();
+ });
}
@Override
dialog.show(this.getSupportFragmentManager(), DIALOG_TAG);
}
- /**
- * Class that loads the cached CA certificates.
- */
- private class LoadCertificatesTask extends AsyncTask<Void, Void, TrustedCertificateManager>
- {
- @Override
- protected TrustedCertificateManager doInBackground(Void... params)
- {
- return TrustedCertificateManager.getInstance().load();
- }
- }
-
/**
* Dismiss dialog if shown
*/
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.security.KeyChainException;
import org.strongswan.android.data.VpnProfileDataSource;
import org.strongswan.android.data.VpnType;
import org.strongswan.android.data.VpnType.VpnTypeFeature;
+import org.strongswan.android.logic.StrongSwanApplication;
import org.strongswan.android.logic.TrustedCertificateManager;
import org.strongswan.android.security.TrustedCertificateEntry;
import org.strongswan.android.ui.adapter.CertificateIdentitiesAdapter;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
+import java.util.concurrent.Executor;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
useralias = savedInstanceState == null ? useralias : savedInstanceState.getString(VpnProfileDataSource.KEY_USER_CERTIFICATE);
if (useralias != null)
{
- UserCertificateLoader loader = new UserCertificateLoader(this, useralias);
mUserCertLoading = useralias;
- loader.execute();
+ UserCertificateLoader loader = new UserCertificateLoader(((StrongSwanApplication)getApplication()).getExecutor(),
+ ((StrongSwanApplication)getApplication()).getHandler());
+ loader.loadCertifiate(this, useralias, result -> {
+ if (result != null)
+ {
+ mUserCertEntry = new TrustedCertificateEntry(mUserCertLoading, result);
+ }
+ else
+ { /* previously selected certificate is not here anymore */
+ ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setError("");
+ mUserCertEntry = null;
+ }
+ mUserCertLoading = null;
+ updateCredentialView();
+ });
}
/* check if the user selected a CA certificate previously */
}
}
+ /**
+ * Callback interface for the user certificate loader.
+ */
+ private interface UserCertificateLoaderCallback {
+ void onComplete(X509Certificate result);
+ }
+
/**
* Load the selected user certificate asynchronously. This cannot be done
* from the main thread as getCertificateChain() calls back to our main
* thread to bind to the KeyChain service resulting in a deadlock.
*/
- private class UserCertificateLoader extends AsyncTask<Void, Void, X509Certificate>
+ private class UserCertificateLoader
{
- private final Context mContext;
- private final String mAlias;
+ private final Executor mExecutor;
+ private final Handler mHandler;
- public UserCertificateLoader(Context context, String alias)
+ public UserCertificateLoader(Executor executor, Handler handler)
{
- mContext = context;
- mAlias = alias;
+ mExecutor = executor;
+ mHandler = handler;
}
- @Override
- protected X509Certificate doInBackground(Void... params)
+ public void loadCertifiate(Context context, String alias, UserCertificateLoaderCallback callback)
{
- X509Certificate[] chain = null;
- try
- {
- chain = KeyChain.getCertificateChain(mContext, mAlias);
- }
- catch (KeyChainException | InterruptedException e)
- {
- e.printStackTrace();
- }
- if (chain != null && chain.length > 0)
- {
- return chain[0];
- }
- return null;
+ mExecutor.execute(() -> {
+ X509Certificate[] chain = null;
+ try
+ {
+ chain = KeyChain.getCertificateChain(context, alias);
+ }
+ catch (KeyChainException | InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ if (chain != null && chain.length > 0)
+ {
+ complete(chain[0], callback);
+ return;
+ }
+ complete(null, callback);
+ });
}
- @Override
- protected void onPostExecute(X509Certificate result)
+ protected void complete(X509Certificate result, UserCertificateLoaderCallback callback)
{
- if (result != null)
- {
- mUserCertEntry = new TrustedCertificateEntry(mAlias, result);
- }
- else
- { /* previously selected certificate is not here anymore */
- ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setError("");
- mUserCertEntry = null;
- }
- mUserCertLoading = null;
- updateCredentialView();
+ mHandler.post(() -> callback.onComplete(result));
}
}