/* * * Copyright 2018 iQIYI.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.qiyi.pluginlibrary.runtime; import android.annotation.TargetApi; import android.app.Application; import android.app.Instrumentation; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.ContextWrapper; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.text.TextUtils; import android.webkit.WebViewFactory; import org.qiyi.pluginlibrary.Neptune; import org.qiyi.pluginlibrary.component.stackmgr.PActivityStackSupervisor; import org.qiyi.pluginlibrary.component.stackmgr.PServiceSupervisor; import org.qiyi.pluginlibrary.component.stackmgr.PluginServiceWrapper; import org.qiyi.pluginlibrary.component.wraper.PluginInstrument; import org.qiyi.pluginlibrary.component.wraper.ResourcesProxy; import org.qiyi.pluginlibrary.context.PluginContextWrapper; import org.qiyi.pluginlibrary.error.ErrorType; import org.qiyi.pluginlibrary.install.PluginInstaller; import org.qiyi.pluginlibrary.loader.PluginClassLoader; import org.qiyi.pluginlibrary.pm.PluginLiteInfo; import org.qiyi.pluginlibrary.pm.PluginPackageInfo; import org.qiyi.pluginlibrary.pm.PluginPackageManager; import org.qiyi.pluginlibrary.pm.PluginPackageManagerNative; import org.qiyi.pluginlibrary.provider.PluginContentResolver; import org.qiyi.pluginlibrary.utils.ClassLoaderInjectHelper; import org.qiyi.pluginlibrary.utils.ErrorUtil; import org.qiyi.pluginlibrary.utils.FileUtils; import org.qiyi.pluginlibrary.utils.PluginDebugLog; import org.qiyi.pluginlibrary.utils.ReflectionUtils; import org.qiyi.pluginlibrary.utils.ResourcesToolForPlugin; import org.qiyi.pluginlibrary.utils.RunUtil; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import dalvik.system.DexClassLoader; /** * 插件在内存中的表现形式: * 每一个{@link PluginLoadedApk}代表了一个插件实例, * 保存当前插件的{@link android.content.res.Resources}<br/> * {@link ClassLoader}, {@link PackageInfo}等信息 */ public class PluginLoadedApk { public static final ConcurrentMap<String, Vector<Method>> sMethods = new ConcurrentHashMap<String, Vector<Method>>(1); private static final String TAG = "PluginLoadedApk"; /* 保存注入到宿主ClassLoader的插件 */ private static Set<String> sInjectedPlugins = Collections.synchronizedSet(new HashSet<String>()); /* 保存所有的插件ClassLoader */ private static Map<String, DexClassLoader> sAllPluginClassLoader = new ConcurrentHashMap<>(); /* 宿主的Context */ private final Context mHostContext; /* 宿主的ClassLoader */ private final ClassLoader mHostClassLoader; /* 宿主的Resource对象 */ private final Resources mHostResource; /* 宿主的包名 */ private final String mHostPackageName; /* 插件的路径 */ private final String mPluginPath; /* 插件运行的进程名 */ private final String mProcessName; /* 插件ClassLoader的parent */ private ClassLoader mParent; /* 插件的类加载器 */ private DexClassLoader mPluginClassLoader; /* 插件的Resource对象 */ private Resources mPluginResource; /* 插件的AssetManager对象 */ private AssetManager mPluginAssetManager; /* 插件的全局默认主题 */ private Resources.Theme mPluginTheme; /* 插件的详细信息,主要通过解析AndroidManifest.xml获得 */ private PluginPackageInfo mPluginPackageInfo; /* 插件工程的包名 */ private String mPluginPackageName; /* 插件的Application */ private Application mPluginApplication; /* 自定义插件Context,主要用来改写其中的一些方法从而改变插件行为 */ private PluginContextWrapper mPluginAppContext; /* 自定义Instrumentation,对Activity跳转进行拦截 */ private PluginInstrument mPluginInstrument; /* 插件的ContentProvider对象,key是authority */ private Map<String, ContentProvider> mProviderMaps = new HashMap<>(); /* 插件的PluginContentResolver */ private PluginContentResolver mPluginContentResolver; /** * 动态通过资源名称获取资源id的工具类 */ @Deprecated private ResourcesToolForPlugin mResourceTool; /** * 当前插件的Activity栈 */ private PActivityStackSupervisor mActivityStackSupervisor; /** * 插件Application是否已经初始化 */ private volatile boolean isPluginInit = false; /** * 当前是否有正在启动的Intent */ private volatile boolean isLaunchingIntent = false; /** * 在启动插件时,需要先将插件以{@link PluginLoadedApk}的形式加载到内存 * * @param mHostContext 主工程的上下文 * @param mPluginPath 需要加载的插件apk文件 * @param mPluginPackageName 插件的包名 * @param mProcessName 插件运行的进程名称 * @throws Exception 当以上参数有一个为Null时,可能抛出{@link NullPointerException} * 当创建ClassLoader失败时,会抛出异常 */ public PluginLoadedApk(Context mHostContext, String mPluginPath, String mPluginPackageName, String mProcessName) throws Exception { if (mHostContext == null || TextUtils.isEmpty(mPluginPath) || TextUtils.isEmpty(mPluginPackageName)) { throw new NullPointerException("PluginLoadedApk Constructor' parameter is null!"); } this.mHostContext = mHostContext; this.mHostClassLoader = mHostContext.getClassLoader(); this.mHostResource = mHostContext.getResources(); this.mHostPackageName = mHostContext.getPackageName(); this.mPluginPath = mPluginPath; this.mPluginPackageName = mPluginPackageName; this.mActivityStackSupervisor = new PActivityStackSupervisor(this); this.mProcessName = mProcessName; // 提取插件Apk的信息 extraPluginPackageInfo(this.mPluginPackageName); // 创建插件ClassLoader if (Neptune.SEPARATED_CLASSLOADER) { if (!createNewClassLoader()) { String errMsg = "PluginLoadedApk init failed for createNewClassLoader failed:" + " apkFile: " + mPluginPath + " pluginPakName: " + mPluginPackageName; PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_CREATE_CLASSLOADER, errMsg); throw new RuntimeException(errMsg); } } else { if (!createClassLoader()) { String errMsg = "PluginLoadedApk init failed for createClassLoader failed:" + " apkFile: " + mPluginPath + " pluginPakName: " + mPluginPackageName; PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_CREATE_CLASSLOADER, errMsg); throw new RuntimeException(errMsg); } } PluginDebugLog.runtimeFormatLog(TAG, "plugin %s, class loader: %s", mPluginPackageName, mPluginClassLoader.toString()); // 创建插件资源 createPluginResource(); // 插件Application的Base Context this.mPluginAppContext = new PluginContextWrapper(((Application) mHostContext) .getBaseContext(), this, true); // 注册静态广播 installStaticReceiver(); } /** * 动态注册插件中的静态Receiver */ private void installStaticReceiver() { Map<String, PluginPackageInfo.ReceiverIntentInfo> mReceiverIntentInfos = mPluginPackageInfo.getReceiverIntentInfos(); if (mReceiverIntentInfos != null) { Set<Map.Entry<String, PluginPackageInfo.ReceiverIntentInfo>> mEntries = mReceiverIntentInfos.entrySet(); Context mGlobalContext = mHostContext.getApplicationContext(); for (Map.Entry<String, PluginPackageInfo.ReceiverIntentInfo> mEntry : mEntries) { PluginPackageInfo.ReceiverIntentInfo mReceiverInfo = mEntry.getValue(); if (mReceiverInfo != null) { try { BroadcastReceiver mReceiver = BroadcastReceiver.class.cast(mPluginClassLoader. loadClass(mReceiverInfo.mInfo.name).newInstance()); List<IntentFilter> mFilters = mReceiverInfo.mFilter; if (mFilters != null) { for (IntentFilter mItem : mFilters) { mGlobalContext.registerReceiver(mReceiver, mItem); } } } catch (Exception e) { e.printStackTrace(); } } } } } /** * 创建插件的Resource {@link ResourcesProxy},通过此Resource对象 * 插件可以访问主工程和插件的资源 */ private void createPluginResource() { PluginDebugLog.runtimeLog(TAG, "createPluginResource for " + mPluginPackageName); PackageManager pm = mHostContext.getPackageManager(); AssetManager am = null; try { Class<?>[] paramTypes = new Class[]{String.class}; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // Android 5.0以下系统方法创建的AssetManager不支持扩展资源表,始终new出来 am = AssetManager.class.newInstance(); ReflectionUtils.on(am).call("addAssetPath", sMethods, paramTypes, mPluginPath); } else { // Android 5.0以上使用PackageManager的公开方法创建, 避免反射 Resources resources = pm.getResourcesForApplication(mPluginPackageInfo.getApplicationInfo()); am = resources.getAssets(); } boolean shouldAddHostRes = !mPluginPackageInfo.isIndividualMode() && mPluginPackageInfo.isResourceNeedMerge(); if (shouldAddHostRes) { // 添加宿主的资源到插件的AssetManager ReflectionUtils.on(am).call("addAssetPath", sMethods, paramTypes, mHostContext.getApplicationInfo().sourceDir); PluginDebugLog.runtimeLog(TAG, "--- Resource merging into plugin @ " + mPluginPackageInfo.getPackageName()); } // 添加系统Webview资源, Android L+ if (mPluginPackageInfo.isNeedAddWebviewResource()) { addWebviewAssetPath(am); } mPluginAssetManager = am; } catch (Exception e) { ErrorUtil.throwErrorIfNeed(e); String errMsg = "create plugin resources failed: " + e.getMessage(); PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_INIT_RESOURCES, errMsg); } Configuration config = new Configuration(); config.setTo(mHostResource.getConfiguration()); if (mPluginPackageInfo.isIndividualMode()) { // 独立插件包,不依赖宿主的Resource mPluginResource = new Resources(mPluginAssetManager, mHostResource.getDisplayMetrics(), config); } else { mPluginResource = new ResourcesProxy(mPluginAssetManager, mHostResource.getDisplayMetrics(), config, mHostResource, mPluginPackageName); } mPluginTheme = mPluginResource.newTheme(); mPluginTheme.setTo(mHostContext.getTheme()); mResourceTool = new ResourcesToolForPlugin(mHostContext); } /** * 添加Webview的AssetPath到插件资源池 * 只有5.0以上设备使用, select下拉,长按复制才会有问题 * * <href>https://github.com/Qihoo360/RePlugin/blob/615cabf1b9d0e1f3e0d38c1ef1bb5a08dffa0ce5/replugin-sample/plugin/plugin-webview/app/src/main/java/com/qihoo360/replugin/sample/webview/utils/WebViewResourceHelper.java</href> */ private void addWebviewAssetPath(AssetManager assetManager) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { String webAsset = getWebViewAssetPath(); if (TextUtils.isEmpty(webAsset)) { PluginDebugLog.runtimeFormatLog(TAG, "--- webview resources not found for plugin @%s", webAsset, mPluginPackageInfo.getPackageName()); return; } Class<?>[] paramTypes = new Class[]{String.class}; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { try { // 7.0以上添加webview为SharedLibrary, 否则会存在packageID冲突 ReflectionUtils.on(assetManager).call("addAssetPathAsSharedLibrary", sMethods, paramTypes, webAsset); PluginDebugLog.runtimeFormatLog(TAG, "--- Add webview resources %s into plugin @%s for above nougat", webAsset, mPluginPackageInfo.getPackageName()); return; } catch (Exception e) { e.printStackTrace(); } } // 7.0以下系统 try { ReflectionUtils.on(assetManager).call("addAssetPath", sMethods, paramTypes, webAsset); PluginDebugLog.runtimeFormatLog(TAG, "--- Add webview resources %s into plugin @%s for below nougat", webAsset, mPluginPackageInfo.getPackageName()); } catch (Exception e) { ErrorUtil.throwErrorIfNeed(e); } } } /** * 获取系统Webview的Asset资源路径 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private String getWebViewAssetPath() { // Android L上WebViewFactory才存在getLoadedPackageInfo()方法 // see http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/webkit/WebViewFactory.java try { // 初始化WebviewProvider ReflectionUtils.on("android.webkit.WebViewFactory").call("getProvider"); // 获取Webview资源路径 PackageInfo pi = WebViewFactory.getLoadedPackageInfo(); if (pi != null && pi.applicationInfo != null && !TextUtils.isEmpty(pi.applicationInfo.sourceDir)) { return pi.applicationInfo.sourceDir; } } catch (Throwable e) { e.printStackTrace(); } String webPkgName = ""; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 通过webview_provider读取 webPkgName = Settings.Global.getString(mHostContext.getContentResolver(), "webview_provider"); } else { try { // 5.0~6.0存在该方法 webPkgName = ReflectionUtils.on("android.webkit.WebViewFactory").call("getWebViewPackageName").get(); } catch (Throwable tr) { ErrorUtil.throwErrorIfNeed(tr); } if (TextUtils.isEmpty(webPkgName)) { int resId = mHostResource.getIdentifier("config_webViewPackageName", "string", "android"); if (resId > 0) { webPkgName = mHostResource.getString(resId); } } } if (TextUtils.isEmpty(webPkgName)) { // hard code the webview pkgName webPkgName = "com.google.android.webview"; } try { PackageManager pm = mHostContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(webPkgName, PackageManager.GET_SHARED_LIBRARY_FILES); if (pi != null && pi.applicationInfo != null && !TextUtils.isEmpty(pi.applicationInfo.sourceDir)) { return pi.applicationInfo.sourceDir; } } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 创建插件的ClassLoader * * @return true:创建成功,false:创建失败 */ private boolean createClassLoader() { boolean dependence = handleDependencies(); PluginDebugLog.runtimeLog(TAG, "handleDependencies: " + dependence); if (!dependence) { return false; } PluginDebugLog.runtimeLog(TAG, "createClassLoader"); File optDir = getDataDir(mHostContext, mPluginPackageName); if (optDir != null && isOptDirAccessible(optDir)) { FileUtils.checkOtaFileValid(optDir, new File(mPluginPath)); // 创建ClassLoader之前check上次生成的oat文件是否损坏 mPluginClassLoader = new DexClassLoader(mPluginPath, optDir.getAbsolutePath(), mPluginPackageInfo.getNativeLibraryDir(), mHostClassLoader); // 把插件 classloader 注入到host程序中,方便host app 能够找到 插件 中的class if (mPluginPackageInfo.isClassNeedInject()) { if (!sInjectedPlugins.contains(mPluginPackageName)) { ClassLoaderInjectHelper.InjectResult injectResult = ClassLoaderInjectHelper.inject(mHostClassLoader, mPluginClassLoader, mPluginPackageInfo.getPackageName() + ".R"); PluginDebugLog.runtimeLog(TAG, "--- Class injecting @ " + mPluginPackageInfo.getPackageName()); if (injectResult != null && injectResult.mIsSuccessful) { sInjectedPlugins.add(mPluginPackageName); PluginDebugLog.runtimeLog(TAG, "inject class result success for " + mPluginPackageName); } else { PluginDebugLog.runtimeLog(TAG, "inject class result failed for " + mPluginPackageName); } } else { PluginDebugLog.runtimeLog(TAG, "--- Class injecting @ " + mPluginPackageInfo.getPackageName() + " already injected!"); } } else { PluginDebugLog.runtimeFormatLog(TAG, "plugin: " + "%s cannot inject to host classloader, inject meta: %s", String.valueOf(mPluginPackageInfo.isClassNeedInject())); } return true; } else if (optDir != null) { PluginDebugLog.runtimeLog(TAG, "createClassLoader failed as " + optDir.getAbsolutePath() + " exist: " + optDir.exists() + " can read: " + optDir.canRead() + " can write: " + optDir.canWrite()); } return false; } /** * 创建插件新的ClassLoader,不使用注入Host ClassLoader方案 */ private boolean createNewClassLoader() { PluginDebugLog.runtimeLog(TAG, "createNewClassLoader"); File optDir = getDataDir(mHostContext, mPluginPackageName); mParent = mPluginPackageInfo.isIndividualMode() ? mHostClassLoader.getParent() : mHostClassLoader; if (optDir != null && isOptDirAccessible(optDir)) { DexClassLoader classLoader = sAllPluginClassLoader.get(mPluginPackageName); if (classLoader == null) { FileUtils.checkOtaFileValid(optDir, new File(mPluginPath)); //检测oat文件是否损坏 mPluginClassLoader = new PluginClassLoader(mPluginPackageInfo, mPluginPath, optDir.getAbsolutePath(), mPluginPackageInfo.getNativeLibraryDir(), mParent); PluginDebugLog.runtimeLog(TAG, "createNewClassLoader success for plugin " + mPluginPackageName); sAllPluginClassLoader.put(mPluginPackageName, mPluginClassLoader); } else { PluginDebugLog.runtimeLog(TAG, "classloader find in cache, createNewClassLoader success for plugin " + mPluginPackageName); mPluginClassLoader = classLoader; } return handleNewDependencies(); } else if (optDir != null) { PluginDebugLog.runtimeLog(TAG, "createNewClassLoader failed as " + optDir.getAbsolutePath() + " exist: " + optDir.exists() + " can read: " + optDir.canRead() + " can write: " + optDir.canWrite()); } return false; } /** * 将插件中的类从主工程中删除 */ void ejectClassLoader() { if (Neptune.SEPARATED_CLASSLOADER) { PluginDebugLog.runtimeLog(TAG, "separated classloader mode, no need to eject classloader"); return; } if (mPluginClassLoader != null && mPluginPackageInfo.isClassNeedInject()) { PluginDebugLog.runtimeLog(TAG, "--- Class eject @ " + mPluginPackageInfo.getPackageName()); ClassLoaderInjectHelper.eject(mHostContext.getClassLoader(), mPluginClassLoader); } } /** * dexopt的目录是否可访问 */ private boolean isOptDirAccessible(File optDir) { return optDir.exists() && optDir.canRead() && optDir.canWrite(); } /** * 某些case下PluginLoadedApk初始化成功了,但是Application还没有初始化完成 */ public void invokeApplicationIfNeed() { if (hasPluginInit()) { // just ignore return; } try { PluginDebugLog.runtimeLog(TAG, "invokeApplicationIfNeed() called from NeptuneInstrumentation"); invokeApplication(); } catch (Exception e) { ErrorUtil.throwErrorIfNeed(e); } } /** * 初始化插件的Application * * @throws Exception */ void invokeApplication() throws Exception { final Exception[] temp = new Exception[1]; RunUtil.runOnUiThread(new Runnable() { @Override public void run() { try { if (makeApplication()) { PluginDebugLog.runtimeFormatLog(TAG, "plugin %s makeApplication success", mPluginPackageName); } else { temp[0] = new RuntimeException("init Application failed"); } } catch (Exception ex) { temp[0] = new RuntimeException("init Application failed", ex); } } }, true); if (temp[0] != null) { throw temp[0]; } } /** * 创建插件的Application对象 * * @return true:创建Application成功,false:创建失败 */ private synchronized boolean makeApplication() { if (hasPluginInit()) { return true; } String className = mPluginPackageInfo.getApplicationClassName(); if (TextUtils.isEmpty(className)) { className = "android.app.Application"; } Instrumentation hostInstr = Neptune.getHostInstrumentation(); mPluginInstrument = new PluginInstrument(hostInstr, mPluginPackageName); try { // load plugin Application and call Application#attach() this.mPluginApplication = hostInstr.newApplication(mPluginClassLoader, className, mPluginAppContext); } catch (Exception e) { String errMsg = "plugin newApplication failed: " + e.getMessage(); PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_LOAD_APPLICATION, errMsg); ErrorUtil.throwErrorIfNeed(e, true); return false; } // 注册Application回调 try { mHostContext.registerComponentCallbacks(new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { mPluginApplication.onTrimMemory(level); } @Override public void onConfigurationChanged(Configuration configuration) { updateConfiguration(configuration); } @Override public void onLowMemory() { mPluginApplication.onLowMemory(); } }); } catch (NoSuchMethodError e) { // java.lang.NoSuchMethodError: android.content.Context.registerComponentCallbacks // Vivo X3t, 4.2 ErrorUtil.throwErrorIfNeed(e); PluginDebugLog.runtimeLog(TAG, "register ComponentCallbacks for plugin failed, pkgName=" + mPluginPackageName); } // 安装插件Provider installContentProviders(); // 执行Application#onCreate()方法 try { mPluginApplication.onCreate(); } catch (Throwable tr) { String errMsg = "call plugin Application " + className + "#onCreate() failed: " + tr.getMessage(); PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_CREATE_APPLICATION, errMsg); PluginDebugLog.runtimeLog(TAG, "call plugin Application#onCreate() failed, pkgName=" + mPluginPackageName); ErrorUtil.throwErrorIfNeed(tr, true); return false; } // 支持注册多个ActivityLifeCycle到插件进程 for (Application.ActivityLifecycleCallbacks callback : PluginManager.sActivityLifecycleCallbacks) { mPluginApplication.registerActivityLifecycleCallbacks(callback); } isPluginInit = true; isLaunchingIntent = false; PluginManager.deliver(mHostContext, true, mPluginPackageName, ErrorType.SUCCESS, ""); return true; } private boolean isSupportProvider() { // 全局开关打开或插件自身配置打开 return Neptune.getConfig().isSupportProvider() || (mPluginPackageInfo != null && mPluginPackageInfo.isSupportProvider()); } /** * 安装插件的Provider */ private void installContentProviders() { if (!isSupportProvider()) { PluginDebugLog.runtimeLog(TAG, "Not support provider for plugin " + mPluginPackageName); return; } mPluginContentResolver = new PluginContentResolver(mHostContext); Map<String, PluginPackageInfo.ProviderIntentInfo> mProviderIntentInfos = mPluginPackageInfo.getProviderIntentInfos(); if (mProviderIntentInfos != null) { Set<Map.Entry<String, PluginPackageInfo.ProviderIntentInfo>> mEntries = mProviderIntentInfos.entrySet(); for (Map.Entry<String, PluginPackageInfo.ProviderIntentInfo> mEntry : mEntries) { PluginPackageInfo.ProviderIntentInfo mProviderInfo = mEntry.getValue(); if (mProviderInfo != null) { try { ContentProvider provider = ContentProvider.class.cast(mPluginClassLoader. loadClass(mProviderInfo.mInfo.name).newInstance()); if (provider != null) { // 调用attachInfo方法 provider.attachInfo(mPluginAppContext, mProviderInfo.mInfo); mProviderMaps.put(mProviderInfo.mInfo.authority, provider); } } catch (Exception e) { ErrorUtil.throwErrorIfNeed(e); } } } } } /** * 在插件中查找可以处理这个Uri的Provider */ public ContentProvider getContentProvider(Uri uri) { if (uri == null || TextUtils.isEmpty(uri.getAuthority())) { return null; } return mProviderMaps.get(uri.getAuthority()); } /** * 反射获取ActivityThread中的Instrumentation对象 * 从而拦截Activity跳转 */ @Deprecated private void hookInstrumentation() { try { Context contextImpl = ((ContextWrapper) mHostContext).getBaseContext(); Object activityThread = ReflectionUtils.getFieldValue(contextImpl, "mMainThread"); Field instrumentationF = activityThread.getClass().getDeclaredField("mInstrumentation"); instrumentationF.setAccessible(true); Instrumentation hostInstr = (Instrumentation) instrumentationF.get(activityThread); mPluginInstrument = new PluginInstrument(hostInstr, mPluginPackageName); } catch (Exception e) { ErrorUtil.throwErrorIfNeed(e); PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_HOOK_INSTRUMENTATION, "hookInstrumentation failed"); } } /** * 通过反射attach方法,让插件Application具备真正Application的能力 */ @Deprecated private void invokeApplicationAttach() { if (mPluginApplication == null) { PluginDebugLog.formatLog(TAG, "invokeApplicationAttach mPluginApplication is null! %s", mPluginPackageName); return; } // attach Method attachMethod; try { attachMethod = Application.class.getDeclaredMethod("attach", Context.class); attachMethod.setAccessible(true); attachMethod.invoke(mPluginApplication, mPluginAppContext); } catch (Exception e) { PluginManager.deliver(mHostContext, false, mPluginPackageName, ErrorType.ERROR_PLUGIN_APPLICATION_ATTACH_BASE, "call Application#attach() failed"); ErrorUtil.throwErrorIfNeed(e); } } /** * 提取插件apk中的PackageInfo信息,主要就是解析AndroidManifest.xml文件 * * @param mPluginPackage 需要提取信息的插件包名 */ private void extraPluginPackageInfo(String mPluginPackage) { PluginLiteInfo pkgInfo = PluginPackageManagerNative.getInstance(mHostContext) .getPackageInfo(mPluginPackage); if (pkgInfo != null) { mPluginPackageInfo = PluginPackageManagerNative.getInstance(mHostContext) .getPluginPackageInfo(mHostContext, pkgInfo); } if (mPluginPackageInfo == null) { mPluginPackageInfo = new PluginPackageInfo(mHostContext, new File(mPluginPath)); } } /** * 更新资源配置 * * @param newConfig 新的资源配置信息 */ public void updateConfiguration(Configuration newConfig) { mPluginApplication.onConfigurationChanged(newConfig); mPluginResource.updateConfiguration(newConfig, mHostResource != null ? mHostResource.getDisplayMetrics() : mPluginResource.getDisplayMetrics()); } /** * 处理当前插件的依赖关系 * * @return true:处理成功,false:处理失败 */ private boolean handleDependencies() { List<String> dependencies = PluginPackageManagerNative .getInstance(mHostContext).getPluginRefs(mPluginPackageName); //pkgInfo.pluginInfo.getPluginResfs(); if (null != dependencies) { PluginLiteInfo libraryInfo; ClassLoaderInjectHelper.InjectResult injectResult; for (int i = 0; i < dependencies.size(); i++) { libraryInfo = PluginPackageManagerNative.getInstance(mHostContext) .getPackageInfo(dependencies.get(i)); if (null != libraryInfo && !TextUtils.isEmpty(libraryInfo.packageName)) { if (!sInjectedPlugins.contains(libraryInfo.packageName)) { PluginDebugLog.runtimeLog(TAG, "handleDependences inject " + libraryInfo.packageName); PluginPackageManager.updateSrcApkPath(mHostContext, libraryInfo); File apkFile = new File(libraryInfo.srcApkPath); if (!apkFile.exists()) { PluginDebugLog.runtimeLog(TAG, "Special case apkFile not exist, notify client! packageName: " + libraryInfo.packageName); PluginPackageManager.notifyClientPluginException(mHostContext, libraryInfo.packageName, "Apk file not exist when handle dependencies!"); return false; } PluginDebugLog.runtimeLog(TAG, "handleDependences src apk path : " + libraryInfo.srcApkPath); File dataDir = new File(PluginInstaller.getPluginappRootPath(mHostContext), libraryInfo.packageName); String nativeLibraryDir = new File(dataDir, PluginInstaller.NATIVE_LIB_PATH).getAbsolutePath(); injectResult = ClassLoaderInjectHelper.inject(mHostContext, libraryInfo.srcApkPath, null, nativeLibraryDir); if (null != injectResult && injectResult.mIsSuccessful) { PluginDebugLog.runtimeLog(TAG, "handleDependences injectResult success for " + libraryInfo.packageName); sInjectedPlugins.add(libraryInfo.packageName); } else { PluginDebugLog.runtimeLog(TAG, "handleDependences injectResult faild for " + libraryInfo.packageName); return false; } } else { PluginDebugLog.runtimeLog(TAG, "handleDependences libraryInfo already handled!"); } } libraryInfo = null; injectResult = null; } } return true; } /** * 处理当前插件的依赖关系 * * @return true:处理成功,false:处理失败 */ private boolean handleNewDependencies() { List<String> dependencies = PluginPackageManagerNative .getInstance(mHostContext).getPluginRefs(mPluginPackageName); //pkgInfo.pluginInfo.getPluginResfs(); if (null != dependencies) { PluginLiteInfo libraryInfo; PluginPackageInfo libraryPackageInfo; DexClassLoader dependency; ClassLoaderInjectHelper.InjectResult injectResult; for (int i = 0; i < dependencies.size(); i++) { libraryInfo = PluginPackageManagerNative.getInstance(mHostContext) .getPackageInfo(dependencies.get(i)); if (null != libraryInfo && !TextUtils.isEmpty(libraryInfo.packageName)) { libraryPackageInfo = PluginPackageManagerNative.getInstance(mHostContext) .getPluginPackageInfo(mHostContext, libraryInfo); if (libraryPackageInfo == null) { PluginDebugLog.runtimeLog(TAG, "handleNewDependencies get libraryPackageInfo null " + libraryInfo.packageName); return false; } dependency = sAllPluginClassLoader.get(libraryInfo.packageName); if (dependency == null) { PluginDebugLog.runtimeLog(TAG, "handleNewDependencies not contain in cache " + libraryInfo.packageName); PluginPackageManager.updateSrcApkPath(mHostContext, libraryInfo); File apkFile = new File(libraryInfo.srcApkPath); if (!apkFile.exists()) { PluginDebugLog.runtimeLog(TAG, "Special case apkFile not exist, notify client! packageName: " + libraryInfo.packageName); PluginPackageManager.notifyClientPluginException(mHostContext, libraryInfo.packageName, "Apk file not exist when handle dependencies!"); return false; } PluginDebugLog.runtimeLog(TAG, "handleNewDependencies src apk path : " + libraryInfo.srcApkPath); String nativeLibraryDir = libraryPackageInfo.getNativeLibraryDir(); ClassLoader parent = libraryPackageInfo.isIndividualMode() ? mHostClassLoader.getParent() : mHostClassLoader; File optDir = PluginInstaller.getPluginInjectRootPath(mHostContext); FileUtils.checkOtaFileValid(optDir, new File(libraryInfo.srcApkPath)); //检查oat文件是否损坏 dependency = new PluginClassLoader(libraryPackageInfo, libraryInfo.srcApkPath, optDir.getAbsolutePath(), nativeLibraryDir, parent); sAllPluginClassLoader.put(libraryInfo.packageName, dependency); } // 把依赖插件的ClassLoader添加到当前的ClassLoader if (mPluginClassLoader instanceof PluginClassLoader) { ((PluginClassLoader) mPluginClassLoader).addDependency(dependency); PluginDebugLog.runtimeFormatLog(TAG, "handleNewDependencies addDependency %s into plugin %s success ", libraryInfo.packageName, mPluginPackageName); } else { // 注入到PluginClassLoader injectResult = ClassLoaderInjectHelper.inject(mPluginClassLoader, dependency, null); if (injectResult != null && injectResult.mIsSuccessful) { PluginDebugLog.runtimeFormatLog(TAG, "handleNewDependencies inject into %s success", mPluginPackageName); } else { PluginDebugLog.runtimeFormatLog(TAG, "handleNewDependencies inject into %s failed", mPluginPackageName); } return false; } } libraryInfo = null; injectResult = null; } } return true; } /** * 获取插件的数据目录 */ private File getDataDir(Context context, String packageName) { PluginDebugLog.runtimeLog(TAG, "packageName:" + packageName + " context:" + context); File dataDir = new File(mPluginPackageInfo.getDataDir()); if (!dataDir.exists()) { dataDir.mkdirs(); } return dataDir; } /** * 通过Activity的名字获取Theme id * * @param mActivityName 需要获取Theme id的Activity 类名 * @return -1表示获取失败,>0表示成功获取 */ public int getActivityThemeResourceByClassName(String mActivityName) { if (mPluginPackageInfo != null) { return mPluginPackageInfo.getThemeResource(mActivityName); } return -1; } /** * 通过类名获取ActivityInfo * * @param activityClsName 需要获取ActivityInfo的Activity的类名 * @return 返回对应的ActivityInfo,如果没找到返回null */ public ActivityInfo getActivityInfoByClassName(String activityClsName) { if (mPluginPackageInfo != null) { return mPluginPackageInfo.getActivityInfo(activityClsName); } return null; } /** * 通过authority获取ProviderInfo * * @param authority 需要获取ProviderInfo的authority名称 * @return 返回对应的ProviderInfo,如果没有找到则返回null */ public ProviderInfo getProviderInfoByAuthority(String authority) { if (mPluginPackageInfo != null) { return mPluginPackageInfo.resolveProvider(authority); } return null; } public void quitApp(boolean force) { quitApp(force, true); } void quitApp(boolean force, boolean notifyHost) { if (force) { PluginDebugLog.runtimeLog(TAG, "quitapp with " + mPluginPackageName); mActivityStackSupervisor.clearActivityStack(); PActivityStackSupervisor.clearLoadingIntent(mPluginPackageName); PActivityStackSupervisor.removeLoadingIntent(mPluginPackageName); for (Map.Entry<String, PluginServiceWrapper> entry : PServiceSupervisor.getAliveServices().entrySet()) { PluginServiceWrapper serviceWrapper = entry.getValue(); if (serviceWrapper != null) { if (!TextUtils.isEmpty(mPluginPackageName) && TextUtils.equals(mPluginPackageName, serviceWrapper.getPkgName())) { String identity = PluginServiceWrapper. getIdentify(mPluginPackageName, serviceWrapper.getServiceClassName()); if (!TextUtils.isEmpty(identity)) { PluginDebugLog.runtimeLog(TAG, mPluginPackageName + " quitapp with service: " + identity); ServiceConnection connection = PServiceSupervisor.getConnection(identity); if (connection != null && mPluginAppContext != null) { try { PluginDebugLog.runtimeLog(TAG, "quitapp unbindService" + connection); mPluginAppContext.unbindService(connection); } catch (Exception e) { // ignore } } } Service service = entry.getValue().getCurrentService(); if (service != null) { service.stopSelf(); } } } } } if (notifyHost) { PluginManager.doExitStuff(mPluginPackageName, force); } } /** * 插件是否初始化 * * @return true :初始化,false:没有初始化 */ boolean hasPluginInit() { return isPluginInit && mPluginApplication != null; } /** * 是否有正在启动的Intent */ boolean hasLaunchIngIntent() { return isLaunchingIntent; } /** * 获取插件的Application * * @return 返回插件的Application, 如果插件有自定义的Application,那么返回自定义的Application, * 否则返回Application实例 */ public Application getPluginApplication() { if (mPluginApplication == null) { RuntimeException re = new RuntimeException("getPluginApplication but PluginLoadedApk(@" + mPluginPackageName + ") has not init"); ErrorUtil.throwErrorIfNeed(re); } return mPluginApplication; } /** * 获取插件的Instrumentation * * @return 返回插件中使用的Instrumentation */ public PluginInstrument getPluginInstrument() { return mPluginInstrument; } /** * 返回插件的包的详细信息,这些信息主要是通过解析AndroidManifest.xml文件获得 */ public PluginPackageInfo getPluginPackageInfo() { return mPluginPackageInfo; } /** * 返回插件包的PackageInfo信息 */ public PackageInfo getPackageInfo() { if (mPluginPackageInfo != null) { return mPluginPackageInfo.getPackageInfo(); } return null; } /** * 获取插件的包名 */ public String getPluginPackageName() { return mPluginPackageName; } /** * 获取插件的ClassLoader */ public DexClassLoader getPluginClassLoader() { return mPluginClassLoader; } /** * 获取插件的ContentResolver */ public ContentResolver getPluginContentResolver() { if (isSupportProvider()) { return mPluginContentResolver; } return null; } /** * 获取主工程的Context */ public Context getHostContext() { return mHostContext; } /** * 返回宿主的资源工具 */ @Deprecated public ResourcesToolForPlugin getHostResourceTool() { return mResourceTool; } /** * 获取当前插件的Activity栈 */ public PActivityStackSupervisor getActivityStackSupervisor() { return mActivityStackSupervisor; } /** * 获取插件运行的进程名称(package:pluin or package:plugin1) * * @return 返回插件进程的名称,可以在Application的process中指定插件运行的进程 */ public String getProcessName() { return mProcessName; } /** * 获取当前插件的自定义Context * * @return */ public PluginContextWrapper getAppWrapper() { return mPluginAppContext; } /** * 获取主工程的包名 * * @return 主工程的包名 */ public String getHostPackageName() { return mHostPackageName; } /** * 获取插件的主题资源 * * @return 插件的主题 */ public Resources.Theme getPluginTheme() { return mPluginTheme; } /** * 获取插件的Resource * * @return 插件的Resource, 通过此Resource插件可以访问主工程和插件的资源 */ public Resources getPluginResource() { return mPluginResource; } /** * 获取插件的AssetManager * * @return 插件的AssetManager */ public AssetManager getPluginAssetManager() { if (mPluginAssetManager == null) { mPluginAssetManager = mPluginResource.getAssets(); } return mPluginAssetManager; } /** * 更新插件是否有正在启动的页面 状态 * * @param isLaunchingIntent true:有正在启动的intent,false:没有正在启动的intent */ void changeLaunchingIntentStatus(boolean isLaunchingIntent) { this.isLaunchingIntent = isLaunchingIntent; } /** * 查看插件是否创建了 ClassLoader * * @param packageName 包名 * @return true or false */ static boolean isPluginClassLoaderLoaded(String packageName) { if (packageName != null) { return sAllPluginClassLoader.containsKey(packageName); } return false; } }