aboutsummaryrefslogtreecommitdiffstats
path: root/src/org
diff options
context:
space:
mode:
authorMarkus Doits <markus.doits@gmail.com>2011-01-19 22:33:06 +0000
committerMarkus Doits <markus.doits@gmail.com>2011-01-19 22:33:06 +0000
commitbe2476e0ba56241c4681be11371177cfd4d5d876 (patch)
treedaa8b9a7a510cf184aa40c9db98ff15b6e66697e /src/org
parent79cf07f1e23f5b19c151b360cc25fc9c5a62589f (diff)
downloadopen-keychain-be2476e0ba56241c4681be11371177cfd4d5d876.tar.gz
open-keychain-be2476e0ba56241c4681be11371177cfd4d5d876.tar.bz2
open-keychain-be2476e0ba56241c4681be11371177cfd4d5d876.zip
Allow async execution of an AIDL call
Calls can now be executed asyncronously. Callback methods are supported, too. See comments of "set_callback()". First tries with javadoc.
Diffstat (limited to 'src/org')
-rw-r--r--src/org/thialfihar/android/apg/utils/ApgCon.java159
1 files changed, 141 insertions, 18 deletions
diff --git a/src/org/thialfihar/android/apg/utils/ApgCon.java b/src/org/thialfihar/android/apg/utils/ApgCon.java
index 3d9795a0f..ac94f27be 100644
--- a/src/org/thialfihar/android/apg/utils/ApgCon.java
+++ b/src/org/thialfihar/android/apg/utils/ApgCon.java
@@ -8,6 +8,7 @@ import android.content.ServiceConnection;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
@@ -21,10 +22,41 @@ import org.thialfihar.android.apg.IApgService;
*/
public class ApgCon {
+ public class call_async extends AsyncTask<String, Void, Void> {
+
+ @Override
+ protected Void doInBackground(String... arg) {
+ Log.d(TAG, "Async execution starting");
+ call(arg[0]);
+ return null;
+ }
+
+ protected void onPostExecute(Void result) {
+ Log.d(TAG, "Async execution finished");
+ async_running = false;
+ if (callback_object != null && callback_method != null) {
+ try {
+ callback_object.getClass().getMethod(callback_method).invoke(callback_object);
+ Log.d(TAG, "Callback executed");
+ } catch (NoSuchMethodException e) {
+ Log.w(TAG, "Exception in callback: Method '" + callback_method + "' not found");
+ warning_list.add("LOCAL: Could not execute callback, method '" + callback_method + "' not found");
+ } catch (Exception e) {
+ Log.w(TAG, "Exception on callback: " + e.getMessage());
+ warning_list.add("LOCAL: Could not execute callback");
+ }
+ }
+ }
+
+ }
+
private final static String TAG = "ApgCon";
private final static int api_version = 1; // aidl api-version it expects
private final Context mContext;
+ private boolean async_running = false;
+ private Object callback_object;
+ private String callback_method;
private final Bundle result = new Bundle();
private final Bundle args = new Bundle();
@@ -77,7 +109,7 @@ public class ApgCon {
Log.w(TAG, "Found ApgService API version" + inf.metaData.getInt("api_version") + " but exspected " + api_version);
Log.w(TAG, "This probably won't work!");
} else {
- Log.v(TAG, "Found api_version "+api_version+", everything should work");
+ Log.v(TAG, "Found api_version " + api_version + ", everything should work");
}
}
}
@@ -121,6 +153,14 @@ public class ApgCon {
return true;
}
+ public void disconnect() {
+ Log.v(TAG, "disconnecting apgService");
+ if (apgService != null) {
+ mContext.unbindService(apgConnection);
+ apgService = null;
+ }
+ }
+
private boolean initialize() {
if (apgService == null) {
if (!connect()) {
@@ -135,6 +175,11 @@ public class ApgCon {
return this.call(function, args, result);
}
+ public void call_async(String function) {
+ async_running = true;
+ new call_async().execute(function);
+ }
+
public boolean call(String function, Bundle pArgs) {
return this.call(function, pArgs, result);
}
@@ -145,14 +190,14 @@ public class ApgCon {
warning_list.clear();
if (!initialize()) {
- error_list.add("CLASS: Cannot bind to ApgService");
- pReturn.putInt("CLASS_ERROR", error.CANNOT_BIND_TO_APG.ordinal());
+ error_list.add("LOCAL: Cannot bind to ApgService");
+ pReturn.putInt("LOCAL_ERROR", error.CANNOT_BIND_TO_APG.ordinal());
return false;
}
if (function == null || function.length() == 0) {
- error_list.add("CLASS: Function to call missing");
- pReturn.putInt("CLASS_ERROR", error.CALL_MISSING.ordinal());
+ error_list.add("LOCAL: Function to call missing");
+ pReturn.putInt("LOCAL_ERROR", error.CALL_MISSING.ordinal());
return false;
}
@@ -163,13 +208,13 @@ public class ApgCon {
return ret;
} catch (NoSuchMethodException e) {
Log.e(TAG, e.getMessage());
- error_list.add("CLASS: " + e.getMessage());
- pReturn.putInt("CLASS_ERROR", error.CALL_NOT_KNOWN.ordinal());
+ error_list.add("LOCAL: " + e.getMessage());
+ pReturn.putInt("LOCAL_ERROR", error.CALL_NOT_KNOWN.ordinal());
return false;
} catch (Exception e) {
Log.e(TAG, "" + e.getMessage());
- error_list.add("CLASS: " + e.getMessage());
- pReturn.putInt("CLASS_ERROR", error.GENERIC.ordinal());
+ error_list.add("LOCAL: " + e.getMessage());
+ pReturn.putInt("LOCAL_ERROR", error.GENERIC.ordinal());
return false;
}
@@ -184,7 +229,11 @@ public class ApgCon {
for (String val : vals) {
list.add(val);
}
- args.putStringArrayList(key, list);
+ set_arg(key, list);
+ }
+
+ public void set_arg(String key, ArrayList<String> vals) {
+ args.putStringArrayList(key, vals);
}
public void set_arg(String key, boolean val) {
@@ -249,19 +298,93 @@ public class ApgCon {
result.clear();
}
+ /**
+ * Set a callback object and method
+ *
+ * <p>After an async execution is finished, obj.meth() will be called. You can
+ * use this in order to get notified, when encrypting/decrypting of long
+ * data finishes and do not have to poll {@link #is_running()} in your
+ * thread. Note, that if the call of the method fails for whatever reason,
+ * you won't get notified in any way - so you still should check
+ * {@link #is_running()} from time to time.</p>
+ *
+ * <p>It produces a warning fetchable with {@link #get_next_warning()} when the callback fails.</p>
+ *
+ * <pre>
+ * <code>
+ * .... your class ...
+ * public void callback() {
+ * // do something after encryption finished
+ * }
+ *
+ * public void encrypt() {
+ * ApgCon mEnc = new ApgCon(context);
+ * // set parameters
+ * mEnc.set_arg(key, value);
+ * ...
+ *
+ * // set callback object and method
+ * mEnc.set_callback( this, "callback" );
+ *
+ * // start asynchronous call
+ * mEnc.call_async( call );
+ *
+ * // when the call_async finishes, the method "callback()" will be called automatically
+ * }
+ * </code>
+ * </pre>
+ *
+ * @param obj
+ * The object, which has the public method meth
+ * @param meth
+ * Method to call on the object obj
+ */
+ public void set_callback(Object obj, String meth) {
+ set_callback_object(obj);
+ set_callback_method(meth);
+ }
+
+ /**
+ * Set a callback object
+ *
+ * @param obj
+ * a object to call back after async execution
+ * @see #set_callback(Object, String)
+ */
+ public void set_callback_object(Object obj) {
+ callback_object = obj;
+ }
+
+ /**
+ * Set a callback method
+ *
+ * @param meth
+ * a method to call on a callback object after async execution
+ * @see #set_callback(Object, String)
+ */
+ public void set_callback_method(String meth) {
+ callback_method = meth;
+ }
+
+ public void clear_callback_object() {
+ callback_object = null;
+ }
+
+ public void clear_callback_method() {
+ callback_method = null;
+ }
+
+ public boolean is_running() {
+ return async_running;
+ }
+
public void reset() {
clear_errors();
clear_warnings();
clear_args();
clear_result();
- }
-
- public void disconnect() {
- Log.v(TAG, "disconnecting apgService");
- if (apgService != null) {
- mContext.unbindService(apgConnection);
- apgService = null;
- }
+ clear_callback_object();
+ clear_callback_method();
}
}