From 1a338de47e7d9faa73a3bc6eda51cb47a18dc91b Mon Sep 17 00:00:00 2001 From: Markus Doits Date: Wed, 5 Jan 2011 14:07:09 +0000 Subject: [PATCH] Redesign AIDL-Interface once more Using Bundles makes passing data easier and does not need to redefine the interface if the internel functions change. The helper class has been updated accordingly. In addition, it wrappes completely around all input and output (if wanted). --- .../thialfihar/android/apg/ApgService.java | 103 +++++++++++++++--- .../thialfihar/android/apg/IApgService.aidl | 33 +++++- .../thialfihar/android/apg/utils/ApgCon.java | 81 ++++++++++---- 3 files changed, 179 insertions(+), 38 deletions(-) diff --git a/src/org/thialfihar/android/apg/ApgService.java b/src/org/thialfihar/android/apg/ApgService.java index bb5b6463a..316e9a22c 100644 --- a/src/org/thialfihar/android/apg/ApgService.java +++ b/src/org/thialfihar/android/apg/ApgService.java @@ -4,12 +4,11 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.ArrayList; +import java.util.Iterator; import android.content.Intent; +import android.os.Bundle; import android.os.IBinder; import android.util.Log; @@ -22,11 +21,45 @@ public class ApgService extends Service { return mBinder; } + private enum error { + ARGUMENTS_MISSING, + APG_FAILURE + } + private final IApgService.Stub mBinder = new IApgService.Stub() { - public String encrypt_with_passphrase(List args) { - String msg = args.remove(0); - String passphrase = args.remove(0); + public boolean encrypt_with_passphrase(Bundle pArgs, Bundle pReturn) { + ArrayList errors = new ArrayList(); + ArrayList warnings = new ArrayList(); + + pReturn.putStringArrayList("ERRORS", errors); + pReturn.putStringArrayList("WARNINGS", warnings); + + String msg = pArgs.getString("MSG"); + pArgs.remove("MSG"); + + String passphrase = pArgs.getString("SYM_KEY"); + pArgs.remove("SYM_KEY"); + + if (msg == null) { + errors.add("Message to encrypt (MSG) missing"); + } + + if (passphrase == null) { + errors.add("Symmetric key (SYM_KEY) missing"); + } + + if (!pArgs.isEmpty()) { + Iterator iter = pArgs.keySet().iterator(); + while (iter.hasNext()) { + warnings.add("Unknown key: " + iter.next()); + } + } + + if (errors.size() != 0) { + pReturn.putInt("ERROR", error.ARGUMENTS_MISSING.ordinal()); + return false; + } Preferences mPreferences = Preferences.getPreferences(getBaseContext(), true); InputStream inStream = new ByteArrayInputStream(msg.getBytes()); @@ -52,16 +85,50 @@ public class ApgService extends Service { ); } catch (Exception e) { Log.d(TAG, "Exception in encrypt"); - e.printStackTrace(); - return null; + errors.add("Internal failure in APG when encrypting: " + e.getMessage()); + + pReturn.putInt("ERROR", error.APG_FAILURE.ordinal()); + return false; } + Log.d(TAG, "Encrypted"); - return out.toString(); + pReturn.putString("RESULT", out.toString()); + return true; } - public String decrypt_with_passphrase(List args) { - String encrypted_msg = args.remove(0); - String passphrase = args.remove(0); + public boolean decrypt_with_passphrase(Bundle pArgs, Bundle pReturn) { + ArrayList errors = new ArrayList(); + ArrayList warnings = new ArrayList(); + + pReturn.putStringArrayList("ERRORS", errors); + pReturn.putStringArrayList("WARNINGS", warnings); + + String encrypted_msg = pArgs.getString("MSG"); + pArgs.remove("MSG"); + + String passphrase = pArgs.getString("SYM_KEY"); + pArgs.remove("SYM_KEY"); + + if (encrypted_msg == null) { + errors.add("Message to decrypt (MSG) missing"); + } + + if (passphrase == null) { + errors.add("Symmetric key (SYM_KEY) missing"); + } + + if (!pArgs.isEmpty()) { + Iterator iter = pArgs.keySet().iterator(); + while (iter.hasNext()) { + warnings.add("Unknown key: " + iter.next()); + } + } + + if (errors.size() != 0) { + pReturn.putStringArrayList("ERROR", errors); + pReturn.putInt("ERROR", error.ARGUMENTS_MISSING.ordinal()); + return false; + } InputStream inStream = new ByteArrayInputStream(encrypted_msg.getBytes()); InputData in = new InputData(inStream, 9999); // XXX what size in @@ -73,11 +140,15 @@ public class ApgService extends Service { ); } catch (Exception e) { Log.d(TAG, "Exception in decrypt"); - e.printStackTrace(); - return null; + errors.add("Internal failure in APG when decrypting: " + e.getMessage()); + + pReturn.putInt("ERROR", error.APG_FAILURE.ordinal()); + pReturn.putStringArrayList("ERROR", errors); + return false; } - return out.toString(); + pReturn.putString("RESULT", out.toString()); + return true; } }; } diff --git a/src/org/thialfihar/android/apg/IApgService.aidl b/src/org/thialfihar/android/apg/IApgService.aidl index 65d2653d5..f31265f8e 100644 --- a/src/org/thialfihar/android/apg/IApgService.aidl +++ b/src/org/thialfihar/android/apg/IApgService.aidl @@ -1,6 +1,35 @@ package org.thialfihar.android.apg; interface IApgService { - String encrypt_with_passphrase(in List params); - String decrypt_with_passphrase(in List params); + + /** All functions fill the return_vals Bundle with the following keys: + * + * ArrayList "WARNINGS" = Warnings, if any + * ArrayList "ERRORS" = Human readable error descriptions, why function call failed + * int "ERROR" = Numeric representation of error + */ + + /** Encrypt something with a symmetric key + * + * Bundle params: + * (optional/required) TYPE "STRING KEY" = EXPLANATION + * + * (required) String "MSG" = Message to encrypt + * (required) String "SYM_KEY" = Symmetric key to use + * + * Bundle return_vals (in addition to the ERRORS/WARNINGS above): + * String "RESULT" = Encrypted MSG + */ + boolean encrypt_with_passphrase(in Bundle params, out Bundle return_vals); + + /** Decrypt something with a symmetric key + * + * Bundle params: + * (required) String "MSG" = Message to decrypt + * (required) String "SYM_KEY" = Symmetric key to use + * + * Bundle return_vals: + * String "RESULT" = Decrypted MSG + */ + boolean decrypt_with_passphrase(in Bundle params, out Bundle return_vals); } \ No newline at end of file diff --git a/src/org/thialfihar/android/apg/utils/ApgCon.java b/src/org/thialfihar/android/apg/utils/ApgCon.java index 174bce5dc..6234e1b88 100644 --- a/src/org/thialfihar/android/apg/utils/ApgCon.java +++ b/src/org/thialfihar/android/apg/utils/ApgCon.java @@ -1,14 +1,14 @@ package org.thialfihar.android.apg.utils; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.ArrayList; import android.content.Context; import android.content.ComponentName; import android.content.ServiceConnection; import android.content.Intent; +import android.os.Bundle; import android.os.IBinder; +import android.os.Parcelable; import android.util.Log; import org.thialfihar.android.apg.IApgService; @@ -25,6 +25,11 @@ public class ApgCon { private final Context mContext; + private Bundle result = new Bundle(); + private Bundle args = new Bundle(); + private ArrayList error_list = new ArrayList(); + private ArrayList warning_list = new ArrayList(); + /** Remote service for decrypting and encrypting data */ private IApgService apgService = null; @@ -41,13 +46,6 @@ public class ApgCon { } }; - /** Possible fields which are returned to the application */ - public static enum retKey { - ERROR, // error enum, see below - ERROR_DESC, // human readable description - RESULT, // if everything went fine, result - } - public static enum error { GENERIC, // no special type CANNOT_BIND_TO_APG, // connection to apg service not possible @@ -101,35 +99,78 @@ public class ApgCon { return true; } - public boolean call(String function, Map return_map, String... function_params) { + public boolean call(String function) { + return this.call(function, args, result); + } + + public boolean call(String function, Bundle pArgs) { + return this.call(function, pArgs, result); + } + + public boolean call(String function, Bundle pArgs, Bundle pReturn) { if (!initialize()) { - return_map.put(retKey.ERROR, error.CANNOT_BIND_TO_APG); + error_list.add("CLASS: Cannot bind to ApgService"); + pReturn.putInt("CLASS_ERROR", error.CANNOT_BIND_TO_APG.ordinal()); return false; } if (function == null || function.length() == 0) { - return_map.put(retKey.ERROR, error.CALL_MISSING); + error_list.add("CLASS: Function to call missing"); + pReturn.putInt("CLASS_ERROR", error.CALL_MISSING.ordinal()); return false; } try { - List params_list = Arrays.asList(function_params); - return_map.put(retKey.RESULT, IApgService.class.getMethod(function, List.class).invoke(apgService, params_list)); + Boolean ret = (Boolean) IApgService.class.getMethod(function, Bundle.class, Bundle.class).invoke(apgService, pArgs, pReturn); + error_list = new ArrayList(pReturn.getStringArrayList("ERRORS")); + warning_list = new ArrayList(pReturn.getStringArrayList("WARNINGS")); + return ret; } catch (NoSuchMethodException e) { Log.d(TAG, e.getMessage()); - return_map.put(retKey.ERROR, error.CALL_NOT_KNOWN); - return_map.put(retKey.ERROR_DESC, e.getMessage()); + error_list.add("CLASS: " + e.getMessage()); + pReturn.putInt("CLASS_ERROR", error.CALL_NOT_KNOWN.ordinal()); return false; } catch (Exception e) { Log.d(TAG, e.getMessage()); - return_map.put(retKey.ERROR, error.GENERIC); - return_map.put(retKey.ERROR_DESC, e.getMessage()); + error_list.add("CLASS: " + e.getMessage()); + pReturn.putInt("CLASS_ERROR", error.GENERIC.ordinal()); return false; } - return true; + } + public void set_arg(String key, String val) { + args.putString(key, val); + } + + public void set_arg(String key, boolean val) { + args.putBoolean(key, val); + } + + public Object get_arg(String key) { + return args.get(key); + } + + public String get_next_error() { + String bla = "abc"; + return error_list.remove(0); + } + + public boolean has_next_error() { + return error_list.size() != 0; + } + + public String get_next_warning() { + return warning_list.remove(0); + } + + public boolean has_next_warning() { + return warning_list.size() != 0; + } + + public String get_result() { + return result.getString("RESULT"); } private void disconnect() {