aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java/jogamp/android/launcher/ActivityLauncher.java14
-rw-r--r--src/java/jogamp/android/launcher/ClassLoaderUtil.java70
-rw-r--r--src/java/jogamp/android/launcher/LauncherUtil.java128
-rw-r--r--src/java/jogamp/android/launcher/MainLauncher.java2
4 files changed, 153 insertions, 61 deletions
diff --git a/src/java/jogamp/android/launcher/ActivityLauncher.java b/src/java/jogamp/android/launcher/ActivityLauncher.java
index 0ac940e..6e2f261 100644
--- a/src/java/jogamp/android/launcher/ActivityLauncher.java
+++ b/src/java/jogamp/android/launcher/ActivityLauncher.java
@@ -55,7 +55,7 @@ public class ActivityLauncher extends Activity {
data = LauncherUtil.DataSet.create(uri);
data.setSystemProperties();
- ClassLoader cl = ClassLoaderUtil.createClassLoader(this, data.getPackages(), false, null);
+ ClassLoader cl = ClassLoaderUtil.createClassLoader(this, data.getSysPackages(), data.getUsrPackages(), null);
if(null != cl) {
try {
activityClazz = Class.forName(data.getActivityName(), true, cl);
@@ -135,8 +135,18 @@ public class ActivityLauncher extends Activity {
Log.d(TAG, "onDestroy - S");
callMethod(activityObject, mOnDestroy);
if(null != data) {
+ activityObject=null;
+ mOnCreate=null;
+ mOnDestroy=null;
+ mOnPause=null;
+ mOnRestart=null;
+ mOnResume=null;
+ mOnStart=null;
+ mOnStop=null;
+ mSetRootActivity=null;
+ activityClazz = null;
data.clearSystemProperties();
- data = null;
+ data = null;
}
super.onDestroy();
Log.d(TAG, "onDestroy - X");
diff --git a/src/java/jogamp/android/launcher/ClassLoaderUtil.java b/src/java/jogamp/android/launcher/ClassLoaderUtil.java
index ae2918f..76dbf53 100644
--- a/src/java/jogamp/android/launcher/ClassLoaderUtil.java
+++ b/src/java/jogamp/android/launcher/ClassLoaderUtil.java
@@ -29,7 +29,7 @@
package jogamp.android.launcher;
import java.io.File;
-import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -41,15 +41,13 @@ import android.util.Log;
public class ClassLoaderUtil {
private static final String TAG = "JogampClassLoader";
- // FIXME: Need to generalize this .. (Note: native lib resources must be cached!)
- private static final String[] packagesJogAmp = { "com.jogamp.common", "javax.media.opengl" };
- private static ClassLoader jogAmpClassLoader = null;
+ private static HashMap<String, ClassLoader> cachedClassLoader = new HashMap<String, ClassLoader>();
// location where optimized dex files will be written
private static final String dexPathName= "jogampDex";
private static File dexPath = null;
- private static LauncherTempFileCache tmpFileCache = null;
+ private static LauncherTempFileCache tmpFileCache = null;
private static final String PATH_SEP = "/";
private static final String ELEM_SEP = ":";
@@ -69,45 +67,69 @@ public class ClassLoaderUtil {
}
}
- public static synchronized ClassLoader createClassLoader(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
- List<String> apkNames) {
- return createClassLoader(ctx, userPackageNames, addUserLibPath, apkNames, null);
+ /**
+ * @param ctx
+ * @param cachedPackageName list of package names w/ native libraries for which a ClassLoader shall be cached, i.e. persistence.
+ * This is usually required for native libraries.
+ * @param userPackageNames list of user package names w/o native libraries, the last entry shall reflect the Activity.
+ * @param userAPKNames optional non-cached user APKs
+ * @return
+ */
+ public static synchronized ClassLoader createClassLoader(Context ctx, List<String> cachedPackageName,
+ List<String> userPackageNames, List<String> userAPKNames) {
+ return createClassLoader(ctx, cachedPackageName, userPackageNames, userAPKNames, null);
}
- public static synchronized ClassLoader createClassLoader(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
- List<String> apkNames, ClassLoader parent) {
+ /**
+ * @param ctx
+ * @param cachedPackageNames list of package names w/ native libraries for which a ClassLoader shall be cached, i.e. persistence.
+ * This is usually required for native libraries.
+ * @param userPackageNames list of user package names w/o native libraries, the last entry shall reflect the Activity.
+ * @param userAPKNames optional non-cached user APKs
+ * @param parent
+ * @return
+ */
+ public static synchronized ClassLoader createClassLoader(Context ctx, List<String> cachedPackageNames,
+ List<String> userPackageNames, List<String> userAPKNames,
+ ClassLoader parent) {
init(ctx);
- if(null==jogAmpClassLoader) {
- jogAmpClassLoader = createClassLoaderImpl(ctx, Arrays.asList(packagesJogAmp), true, null,
- (null != parent ) ? parent : ctx.getClassLoader());
+ final String cacheKey = cachedPackageNames.toString();
+ ClassLoader clCached = cachedClassLoader.get(cacheKey);
+ if( null == clCached ) {
+ clCached = createClassLoaderImpl(ctx, cachedPackageNames, true, null, (null != parent ) ? parent : ctx.getClassLoader());
+ cachedClassLoader.put(cacheKey, clCached);
+ Log.d(TAG, "NEW cached-CL: cachedPackageNames: "+cacheKey);
+ } else {
+ Log.d(TAG, "REUSE cached-CL: cachedPackageNames: "+cacheKey);
}
- parent = jogAmpClassLoader;
- return createClassLoaderImpl(ctx, userPackageNames, addUserLibPath, apkNames, jogAmpClassLoader);
+ return createClassLoaderImpl(ctx, userPackageNames, false, userAPKNames, clCached);
}
/**
- *
* @param ctx
- * @param userPackageNames list of user package names, the last entry shall reflect the Activity
+ * @param packageNames list of package names
+ * @param addLibPath
+ * @param apkNames
+ * @param parent
* @return
*/
- private static synchronized ClassLoader createClassLoaderImpl(Context ctx, List<String> userPackageNames, boolean addUserLibPath,
+ private static synchronized ClassLoader createClassLoaderImpl(Context ctx, List<String> packageNames, boolean addLibPath,
List<String> apkNames, ClassLoader parent) {
final ApplicationInfo appInfoLauncher= ctx.getApplicationInfo();
final String appDirLauncher = new File(appInfoLauncher.dataDir).getParent();
final String libSubDef = "lib";
- Log.d(TAG, "S: userPackageNames: "+userPackageNames+"; Launcher: appDir "+appDirLauncher+", dataDir: "+appInfoLauncher.dataDir+", nativeLibraryDir "+appInfoLauncher.nativeLibraryDir);
+ Log.d(TAG, "S: userPackageNames: "+packageNames+"; Launcher: appDir "+appDirLauncher+", dataDir: "+appInfoLauncher.dataDir+", nativeLibraryDir "+appInfoLauncher.nativeLibraryDir);
final StringBuilder apks = new StringBuilder();
final StringBuilder libs = new StringBuilder();
int apkCount = 0;
String lastUserPackageName = null; // the very last one reflects the Activity
- if( null != userPackageNames ) {
- for(Iterator<String> i=userPackageNames.iterator(); i.hasNext(); ) {
+ if( null != packageNames ) {
+ for(Iterator<String> i=packageNames.iterator(); i.hasNext(); ) {
lastUserPackageName = i.next();
String userAPK = null;
@@ -125,14 +147,14 @@ public class ClassLoaderUtil {
if(null != userAPK) {
if(apkCount>0) {
apks.append(ELEM_SEP);
- if(addUserLibPath) {
+ if(addLibPath) {
libs.append(ELEM_SEP);
}
}
apks.append(userAPK);
Log.d(TAG, "APK["+apkCount+"] found: <"+lastUserPackageName+"> -> <"+userAPK+">");
Log.d(TAG, "APK["+apkCount+"] apks: <"+apks.toString()+">");
- if(addUserLibPath) {
+ if(addLibPath) {
if(null != nativeLibraryDir && nativeLibraryDir.length()>0 ) {
libs.append(nativeLibraryDir).append(PATH_SEP);
} else {
@@ -145,7 +167,7 @@ public class ClassLoaderUtil {
Log.d(TAG, "APK not found: <"+lastUserPackageName+">");
}
}
- if( userPackageNames.size() != apkCount ) {
+ if( packageNames.size() != apkCount ) {
Log.d(TAG, "User APKs incomplete, abort (1)");
return null;
}
diff --git a/src/java/jogamp/android/launcher/LauncherUtil.java b/src/java/jogamp/android/launcher/LauncherUtil.java
index b68768b..1dfc218 100644
--- a/src/java/jogamp/android/launcher/LauncherUtil.java
+++ b/src/java/jogamp/android/launcher/LauncherUtil.java
@@ -65,7 +65,9 @@ public class LauncherUtil {
/** The host <code>jogamp.org</code> */
public static final String HOST = "jogamp.org";
- static final String PKG = "pkg";
+ static final String SYS_PKG = "sys";
+
+ static final String USR_PKG = "pkg";
static final String ARG = "arg";
@@ -105,8 +107,11 @@ public class LauncherUtil {
/** Must return the downstream Activity class name */
public abstract String getActivityName();
- /** Must return a list of required packages, at least one. */
- public abstract List<String> getPackages();
+ /** Must return a list of required user packages, at least one containing the activity. */
+ public abstract List<String> getUsrPackages();
+
+ /** Return a list of required system packages w/ native libraries, may return null or a zero sized list. */
+ public abstract List<String> getSysPackages();
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -116,7 +121,8 @@ public class LauncherUtil {
final DataSet data = new DataSet();
data.setActivityName(getActivityName());
- data.addAllPackages(getPackages());
+ data.addAllSysPackages(getSysPackages());
+ data.addAllUsrPackages(getUsrPackages());
data.addAllProperties(props);
data.addAllArguments(args);
@@ -135,8 +141,11 @@ public class LauncherUtil {
ArrayList<String> keyList = new ArrayList<String>();
public final void setProperty(String key, String value) {
- if(key.equals(PKG)) {
- throw new IllegalArgumentException("Illegal property key, '"+PKG+"' is reserved");
+ if(key.equals(SYS_PKG)) {
+ throw new IllegalArgumentException("Illegal property key, '"+SYS_PKG+"' is reserved");
+ }
+ if(key.equals(USR_PKG)) {
+ throw new IllegalArgumentException("Illegal property key, '"+USR_PKG+"' is reserved");
}
if(key.equals(ARG)) {
throw new IllegalArgumentException("Illegal property key, '"+ARG+"' is reserved");
@@ -178,6 +187,17 @@ public class LauncherUtil {
public final List<String> getPropertyKeys() { return keyList; }
}
+ /**
+ * Data set to transfer from and to launch URI consisting out of:
+ * <ul>
+ * <li>system packages w/ native libraries used on Android, which may use a cached ClassLoader, see {@link DataSet#getSysPackages()}.</li>
+ * <li>user packages w/o native libraries used on Android, which do not use a cached ClassLoader, see {@link DataSet#getUsrPackages()}.</li>
+ * <li>activity name, used to launch an Android activity, see {@link DataSet#getActivityName()}.</li>
+ * <li>properties, which will be added to the system properties, see {@link DataSet#getProperties()}.</li>
+ * <li>arguments, used to launch a class main-entry, see {@link DataSet#getArguments()}.</li>
+ * </ul>
+ * {@link DataSet#getUri()} returns a URI representation of all components.
+ */
public static class DataSet {
static final char SLASH = '/';
static final char QMARK = '?';
@@ -187,20 +207,29 @@ public class LauncherUtil {
static final String EMPTY = "";
String activityName = null;
- ArrayList<String> packages = new ArrayList<String>();
+ ArrayList<String> sysPackages = new ArrayList<String>();
+ ArrayList<String> usrPackages = new ArrayList<String>();
OrderedProperties properties = new OrderedProperties();
ArrayList<String> arguments = new ArrayList<String>();
public final void setActivityName(String name) { activityName = name; }
public final String getActivityName() { return activityName; }
+
+ public final void addSysPackage(String p) {
+ sysPackages.add(p);
+ }
+ public final void addAllSysPackages(List<String> plist) {
+ sysPackages.addAll(plist);
+ }
+ public final List<String> getSysPackages() { return sysPackages; }
- public final void addPackage(String p) {
- packages.add(p);
+ public final void addUsrPackage(String p) {
+ usrPackages.add(p);
}
- public final void addAllPackages(List<String> plist) {
- packages.addAll(plist);
+ public final void addAllUsrPackages(List<String> plist) {
+ usrPackages.addAll(plist);
}
- public final List<String> getPackages() { return packages; }
+ public final List<String> getUsrPackages() { return usrPackages; }
public final void setProperty(String key, String value) {
properties.setProperty(key, value);
@@ -227,33 +256,58 @@ public class LauncherUtil {
public final Uri getUri() {
StringBuilder sb = new StringBuilder();
sb.append(SCHEME).append(COLSLASH2).append(HOST).append(SLASH).append(getActivityName());
+ boolean needsQMark = true;
boolean needsSep = false;
- if(packages.size()>0) {
- sb.append(QMARK);
- for(int i=0; i<packages.size(); i++) {
+ if(sysPackages.size()>0) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ for(int i=0; i<sysPackages.size(); i++) {
if(needsSep) {
sb.append(AMPER);
}
- sb.append(PKG).append(ASSIG).append(packages.get(i));
+ sb.append(SYS_PKG).append(ASSIG).append(sysPackages.get(i));
needsSep = true;
}
}
- Iterator<String> propKeys = properties.keyList.iterator();
- while(propKeys.hasNext()) {
+ if(usrPackages.size()>0) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ for(int i=0; i<usrPackages.size(); i++) {
if(needsSep) {
sb.append(AMPER);
}
- final String key = propKeys.next();
- sb.append(key).append(ASSIG).append(properties.map.get(key));
+ sb.append(USR_PKG).append(ASSIG).append(usrPackages.get(i));
needsSep = true;
+ }
+ }
+ Iterator<String> propKeys = properties.keyList.iterator();
+ while(propKeys.hasNext()) {
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ if(needsSep) {
+ sb.append(AMPER);
+ }
+ final String key = propKeys.next();
+ sb.append(key).append(ASSIG).append(properties.map.get(key));
+ needsSep = true;
}
Iterator<String> args = arguments.iterator();
while(args.hasNext()) {
- if(needsSep) {
- sb.append(AMPER);
- }
- sb.append(ARG).append(ASSIG).append(args.next());
- needsSep = true;
+ if( needsQMark ) {
+ sb.append(QMARK);
+ needsQMark = false;
+ }
+ if(needsSep) {
+ sb.append(AMPER);
+ }
+ sb.append(ARG).append(ASSIG).append(args.next());
+ needsSep = true;
}
return Uri.parse(sb.toString());
}
@@ -298,11 +352,16 @@ public class LauncherUtil {
// assignment
final String k = part.substring(0, assignment);
final String v = part.substring(assignment+1);
- if(k.equals(PKG)) {
+ if(k.equals(SYS_PKG)) {
+ if(v.length()==0) {
+ throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri);
+ }
+ data.addSysPackage(v);
+ } else if(k.equals(USR_PKG)) {
if(v.length()==0) {
throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri);
}
- data.addPackage(v);
+ data.addUsrPackage(v);
} else if(k.equals(ARG)) {
if(v.length()==0) {
throw new IllegalArgumentException("Empty argument name: part <"+part+">, query <"+q+"> of "+uri);
@@ -313,7 +372,7 @@ public class LauncherUtil {
}
} else {
// property key only
- if( part.equals(PKG) || part.equals(ARG) ) {
+ if( part.equals(USR_PKG) || part.equals(ARG) ) {
throw new IllegalArgumentException("Reserved key <"+part+"> in query <"+q+"> of "+uri);
}
data.setProperty(part, EMPTY);
@@ -338,12 +397,13 @@ public class LauncherUtil {
public static void main(String[] args) {
if(args.length==0) {
args = new String[] {
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&"+PKG+"=javax.pack2&"+PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&"+PKG+"=javax.pack2&"+PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
- SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3"
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&"+SYS_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&"+USR_PKG+"=com.jogamp.pack4&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=com.jogamp.pack2",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3",
+ SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3"
};
}
int errors = 0;
diff --git a/src/java/jogamp/android/launcher/MainLauncher.java b/src/java/jogamp/android/launcher/MainLauncher.java
index d4ac4ca..f37fa57 100644
--- a/src/java/jogamp/android/launcher/MainLauncher.java
+++ b/src/java/jogamp/android/launcher/MainLauncher.java
@@ -64,7 +64,7 @@ public class MainLauncher extends Activity {
data = LauncherUtil.DataSet.create(uri);
data.setSystemProperties();
- ClassLoader cl = ClassLoaderUtil.createClassLoader(this, data.getPackages(), false, Arrays.asList(frameworkAPKs));
+ ClassLoader cl = ClassLoaderUtil.createClassLoader(this, data.getSysPackages(), data.getUsrPackages(), Arrays.asList(frameworkAPKs));
if(null != cl) {
try {
staticContextClazz = Class.forName("jogamp.common.os.android.StaticContext", true, cl);