Now there are two ways to hook into Plug in:
- Using Xposed Framework (Fairly simple)
- Directly injecting code into smali
Using Xposed to hook into plug in is very simple. All plug ins are loaded/managed by class com.oppo.camera.Plugin.PluginManager. Every time a plug in in installed, this class sets up environment to run that plug in by extracting libs and jar files. Have a look at following code
public static Map<String, ClassLoader> mClassLoaderIsLoaded; private void updatePluginClassLoader(Plugin plugin) { DexClassLoader dexClassLoader = new DexClassLoader(modeJar.toString(), this.mContext.getFilesDir().getAbsolutePath(), libraryPath, this.mContext.getClassLoader()); try { mClassLoaderIsLoaded.put(plugin.getCameraMode(), dexClassLoader); Constructor myConstructor = dexClassLoader.loadClass(plugin.getClassPackageName() + "." + plugin.getCameraModeClassName()).getDeclaredConstructor(new Class[]{Activity.class, CameraInterface.class, CameraUIInterface.class}); myConstructor.setAccessible(true); this.mPluginManagerListener.updateCameraMode((CapModeBase) myConstructor.newInstance(new Object[]{(Activity) this.mContext, this.mCameraInterface, this.mCameraUIInterface})); } catch (Exception e3) { e2 = e3; DexClassLoader dexClassLoader2 = dexClassLoader; } }On startup, updatePluginClassLoader() method puts all classloaders for plug ins into HashSet mClassLoaderIsLoaded. So you first need to hook into PluginManager class to retrieve mClassLoaderIsLoaded. This can be done easily by
Map<String, ClassLoader> loaders = (Map) XposedHelpers.getObjectField(param.thisObject, "mClassLoaderIsLoaded");Now you can retrieve plugin specific class loader by get method of Map like following snippet shows retrieval of classloader of Professional Camera Mode plug in
ClassLoader dexLoader = (DexClassLoader) loaders.get("professional");Once we have classloader we can use it to hook into many class of target plug in like
Class manualFocusController = XposedHelpers.findClass("com.oppo.camera.professional.ManualFocusController", dexLoader);You can find whole example code on pastebin
One problem is CameraApp is not loading plug in apk directly, instead it loads its jar file from assets directory. Code contained in jar file and classes.dex file are same. As usual we decompile classes.dex file and inject code into smali but things are a bit different here because classes.dex is never loaded, it is just placebo (may be because Android does not allow APKs without classes.dex?). So modifying smali code after normal decompilation will have no effect at run time. For that we need to decompile jar file included in assets directory. After modifying it, we also need to sign that jar file using same key used to sign APK file.