提交 4b98b1dd 编写于 作者: S superq_sky

Optimized some code extensibility.

上级 a0fda07c
......@@ -16,6 +16,10 @@ public class Resources {
throw new RuntimeException("Stub!");
}
public int getColor(int id) throws NotFoundException {
throw new RuntimeException("Stub!");
}
public Configuration getConfiguration() {
throw new RuntimeException("Stub!");
}
......@@ -28,6 +32,10 @@ public class Resources {
throw new RuntimeException("Stub!");
}
public String getString(int id) throws NotFoundException {
throw new RuntimeException("Stub!");
}
public CharSequence getText(int id) throws NotFoundException {
throw new RuntimeException("Stub!");
}
......@@ -44,6 +52,10 @@ public class Resources {
throw new RuntimeException("Stub!");
}
public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
throw new RuntimeException("Stub!");
}
public final class Theme {
public void applyStyle(int resId, boolean force) {
......
......@@ -52,7 +52,8 @@ public abstract class ContentResolverWrapper extends ContentResolver {
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public void appNotRespondingViaProvider(IContentProvider icp) {
mBase.appNotRespondingViaProvider(icp);
// dark greylist in Android P
// mBase.appNotRespondingViaProvider(icp);
}
}
......@@ -31,17 +31,18 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.util.Singleton;
import com.didi.virtualapk.delegate.ActivityManagerProxy;
import com.didi.virtualapk.delegate.IContentProviderProxy;
import com.didi.virtualapk.delegate.RemoteContentProvider;
import com.didi.virtualapk.internal.ComponentsHandler;
import com.didi.virtualapk.internal.LoadedPlugin;
import com.didi.virtualapk.internal.PluginContentResolver;
import com.didi.virtualapk.internal.VAInstrumentation;
import com.didi.virtualapk.utils.PluginUtil;
import com.didi.virtualapk.internal.utils.PluginUtil;
import com.didi.virtualapk.utils.Reflector;
import com.didi.virtualapk.utils.RunUtil;
......@@ -66,14 +67,15 @@ public class PluginManager {
private static volatile PluginManager sInstance = null;
// Context of host app
private Context mContext;
private ComponentsHandler mComponentsHandler;
private Map<String, LoadedPlugin> mPlugins = new ConcurrentHashMap<>();
private final List<Callback> mCallbacks = new ArrayList<>();
protected final Context mContext;
protected final Application mApplication;
protected ComponentsHandler mComponentsHandler;
protected final Map<String, LoadedPlugin> mPlugins = new ConcurrentHashMap<>();
protected final List<Callback> mCallbacks = new ArrayList<>();
private VAInstrumentation mInstrumentation; // Hooked instrumentation
private IActivityManager mActivityManager; // Hooked IActivityManager binder
private IContentProvider mIContentProvider; // Hooked IContentProvider binder
protected VAInstrumentation mInstrumentation; // Hooked instrumentation
protected IActivityManager mActivityManager; // Hooked IActivityManager binder
protected IContentProvider mIContentProvider; // Hooked IContentProvider binder
public static PluginManager getInstance(Context base) {
if (sInstance == null) {
......@@ -89,14 +91,22 @@ public class PluginManager {
private static PluginManager createInstance(Context context) {
try {
String factoryClass = context.getPackageManager()
.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA)
.metaData.getString("VA_FACTORY");
Bundle metaData = context.getPackageManager()
.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA)
.metaData;
if (metaData == null) {
return new PluginManager(context);
}
String factoryClass = metaData.getString("VA_FACTORY");
if (factoryClass == null) {
return new PluginManager(context);
}
PluginManager pluginManager = Reflector.on(factoryClass).method("create", Context.class).call(context);
if (pluginManager != null) {
Log.d(TAG, "Created a instance of " + pluginManager.getClass());
return pluginManager;
......@@ -110,17 +120,25 @@ public class PluginManager {
}
protected PluginManager(Context context) {
Context app = context.getApplicationContext();
if (app == null) {
this.mContext = context;
if (context instanceof Application) {
this.mApplication = (Application) context;
this.mContext = mApplication.getBaseContext();
} else {
this.mContext = ((Application)app).getBaseContext();
final Context app = context.getApplicationContext();
if (app == null) {
this.mContext = context;
this.mApplication = ActivityThread.currentApplication();
} else {
this.mApplication = (Application) app;
this.mContext = mApplication.getBaseContext();
}
}
prepare();
mComponentsHandler = createComponentsHandler();
hookCurrentProcess();
}
private void prepare() {
mComponentsHandler = createComponentsHandler();
protected void hookCurrentProcess() {
hookInstrumentationAndHandler();
hookSystemServices();
hookDataBindingUtil();
......@@ -138,6 +156,10 @@ public class PluginManager {
protected void doInWorkThread() {
}
public Application getHostApplication() {
return this.mApplication;
}
protected ComponentsHandler createComponentsHandler() {
return new ComponentsHandler(this);
}
......@@ -208,10 +230,10 @@ public class PluginManager {
try {
ActivityThread activityThread = ActivityThread.currentActivityThread();
Instrumentation baseInstrumentation = activityThread.getInstrumentation();
if (baseInstrumentation.getClass().getName().contains("lbe")) {
// reject executing in paralell space, for example, lbe.
System.exit(0);
}
// if (baseInstrumentation.getClass().getName().contains("lbe")) {
// // reject executing in paralell space, for example, lbe.
// System.exit(0);
// }
final VAInstrumentation instrumentation = createInstrumentation(baseInstrumentation);
......@@ -225,14 +247,14 @@ public class PluginManager {
}
protected void hookIContentProviderAsNeeded() {
Uri uri = Uri.parse(PluginContentResolver.getUri(mContext));
Uri uri = Uri.parse(RemoteContentProvider.getUri(mContext));
mContext.getContentResolver().call(uri, "wakeup", null, null);
try {
Field authority = null;
Field mProvider = null;
Field provider = null;
ActivityThread activityThread = ActivityThread.currentActivityThread();
Map mProviderMap = Reflector.with(activityThread).field("mProviderMap").get();
Iterator iter = mProviderMap.entrySet().iterator();
Map providerMap = Reflector.with(activityThread).field("mProviderMap").get();
Iterator iter = providerMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
......@@ -247,12 +269,12 @@ public class PluginManager {
}
auth = (String) authority.get(key);
}
if (auth.equals(PluginContentResolver.getAuthority(mContext))) {
if (mProvider == null) {
mProvider = val.getClass().getDeclaredField("mProvider");
mProvider.setAccessible(true);
if (auth.equals(RemoteContentProvider.getAuthority(mContext))) {
if (provider == null) {
provider = val.getClass().getDeclaredField("mProvider");
provider.setAccessible(true);
}
IContentProvider rawProvider = (IContentProvider) mProvider.get(val);
IContentProvider rawProvider = (IContentProvider) provider.get(val);
IContentProvider proxy = IContentProviderProxy.newInstance(mContext, rawProvider);
mIContentProvider = proxy;
Log.d(TAG, "hookIContentProvider succeed : " + mIContentProvider);
......@@ -281,17 +303,16 @@ public class PluginManager {
}
LoadedPlugin plugin = createLoadedPlugin(apk);
if (null != plugin) {
this.mPlugins.put(plugin.getPackageName(), plugin);
synchronized (mCallbacks) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onAddedLoadedPlugin(plugin);
}
if (null == plugin) {
throw new RuntimeException("Can't load plugin which is invalid: " + apk.getAbsolutePath());
}
this.mPlugins.put(plugin.getPackageName(), plugin);
synchronized (mCallbacks) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onAddedLoadedPlugin(plugin);
}
// try to invoke plugin's application
plugin.invokeApplication();
} else {
throw new RuntimeException("Can't load plugin which is invalid: " + apk.getAbsolutePath());
}
}
......
......@@ -33,11 +33,10 @@ import android.os.ServiceManager;
import android.util.Log;
import com.didi.virtualapk.PluginManager;
import com.didi.virtualapk.utils.PluginUtil;
import com.didi.virtualapk.internal.utils.PluginUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author johnsonlee
......
......@@ -33,8 +33,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import static com.didi.virtualapk.delegate.RemoteContentProvider.KEY_WRAPPER_URI;
/**
* Created by renyugang on 16/12/8.
*/
......@@ -84,7 +82,7 @@ public class IContentProviderProxy implements InvocationHandler {
if (method.getName().equals("call")) {
bundleInCallMethod = getBundleParameter(args);
if (bundleInCallMethod != null) {
String uriString = bundleInCallMethod.getString(KEY_WRAPPER_URI);
String uriString = bundleInCallMethod.getString(RemoteContentProvider.KEY_WRAPPER_URI);
if (uriString != null) {
uri = Uri.parse(uriString);
}
......@@ -100,14 +98,9 @@ public class IContentProviderProxy implements InvocationHandler {
if (info != null) {
String pkg = info.packageName;
LoadedPlugin plugin = pluginManager.getLoadedPlugin(pkg);
String pluginUri = Uri.encode(uri.toString());
StringBuilder builder = new StringBuilder(PluginContentResolver.getUri(mContext));
builder.append("/?plugin=" + plugin.getLocation());
builder.append("&pkg=" + pkg);
builder.append("&uri=" + pluginUri);
Uri wrapperUri = Uri.parse(builder.toString());
Uri wrapperUri = PluginContentResolver.wrapperUri(plugin, uri);
if (method.getName().equals("call")) {
bundleInCallMethod.putString(KEY_WRAPPER_URI, wrapperUri.toString());
bundleInCallMethod.putString(RemoteContentProvider.KEY_WRAPPER_URI, wrapperUri.toString());
} else {
args[index] = wrapperUri;
}
......
......@@ -32,7 +32,7 @@ import android.util.Log;
import com.didi.virtualapk.PluginManager;
import com.didi.virtualapk.internal.LoadedPlugin;
import com.didi.virtualapk.utils.PluginUtil;
import com.didi.virtualapk.internal.utils.PluginUtil;
import com.didi.virtualapk.utils.Reflector;
import java.lang.reflect.Method;
......
......@@ -209,4 +209,12 @@ public class RemoteContentProvider extends ContentProvider {
return null;
}
public static String getAuthority(Context context) {
return context.getPackageName() + ".VirtualAPK.Provider";
}
public static String getUri(Context context) {
return "content://" + getAuthority(context);
}
}
package com.didi.virtualapk.internal;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.Application;
import android.os.Bundle;
import com.didi.virtualapk.utils.Reflector;
import java.util.ArrayList;
/**
* Created by qiaopu on 2017/8/9.
*/
class ActivityLifecycleCallbacksProxy implements Application.ActivityLifecycleCallbacks {
final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
Reflector.QuietReflector.with(ActivityThread.currentApplication()).field("mActivityLifecycleCallbacks").get();
Object[] collectActivityLifecycleCallbacks() {
if (mActivityLifecycleCallbacks == null) {
return null;
}
Object[] callbacks = null;
synchronized (mActivityLifecycleCallbacks) {
if (mActivityLifecycleCallbacks.size() > 0) {
callbacks = mActivityLifecycleCallbacks.toArray();
}
}
return callbacks;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(activity,
savedInstanceState);
}
}
}
@Override
public void onActivityStarted(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(activity);
}
}
}
@Override
public void onActivityResumed(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityResumed(activity);
}
}
}
@Override
public void onActivityPaused(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPaused(activity);
}
}
}
@Override
public void onActivityStopped(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStopped(activity);
}
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivitySaveInstanceState(activity,
outState);
}
}
}
@Override
public void onActivityDestroyed(Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityDestroyed(activity);
}
}
}
}
......@@ -47,17 +47,15 @@ import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import com.didi.virtualapk.PluginManager;
import com.didi.virtualapk.utils.DexUtil;
import com.didi.virtualapk.utils.PackageParserCompat;
import com.didi.virtualapk.utils.PluginUtil;
import com.didi.virtualapk.internal.utils.DexUtil;
import com.didi.virtualapk.internal.utils.PackageParserCompat;
import com.didi.virtualapk.internal.utils.PluginUtil;
import com.didi.virtualapk.utils.Reflector;
import com.didi.virtualapk.utils.RunUtil;
......@@ -74,35 +72,30 @@ import dalvik.system.DexClassLoader;
/**
* Created by renyugang on 16/8/9.
*/
public final class LoadedPlugin {
public class LoadedPlugin {
public static final String TAG = "LoadedPlugin";
protected ClassLoader createClassLoader(Context context, File apk, File libsDir, ClassLoader parent) {
File dexOutputDir = context.getDir(Constants.OPTIMIZE_DIR, Context.MODE_PRIVATE);
protected File getDir(Context context, String name) {
return context.getDir(name, Context.MODE_PRIVATE);
}
protected ClassLoader createClassLoader(Context context, File apk, File libsDir, ClassLoader parent) throws Exception {
File dexOutputDir = getDir(context, Constants.OPTIMIZE_DIR);
String dexOutputPath = dexOutputDir.getAbsolutePath();
DexClassLoader loader = new DexClassLoader(apk.getAbsolutePath(), dexOutputPath, libsDir.getAbsolutePath(), parent);
if (Constants.COMBINE_CLASSLOADER) {
try {
DexUtil.insertDex(loader, parent);
} catch (Exception e) {
e.printStackTrace();
}
DexUtil.insertDex(loader, parent);
}
return loader;
}
protected AssetManager createAssetManager(Context context, File apk) {
try {
AssetManager am = AssetManager.class.newInstance();
Reflector.with(am).method("addAssetPath", String.class).call(apk.getAbsolutePath());
return am;
} catch (Exception e) {
e.printStackTrace();
return null;
}
protected AssetManager createAssetManager(Context context, File apk) throws Exception {
AssetManager am = AssetManager.class.newInstance();
Reflector.with(am).method("addAssetPath", String.class).call(apk.getAbsolutePath());
return am;
}
protected Resources createResources(Context context, String packageName, File apk) throws Exception {
......@@ -151,11 +144,7 @@ public final class LoadedPlugin {
protected Application mApplication;
@UiThread
public LoadedPlugin(PluginManager pluginManager, Context context, File apk) throws Exception {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
throw new RuntimeException("plugin mast be created by UI thread.");
}
this.mPluginManager = pluginManager;
this.mHostContext = context;
this.mLocation = apk.getAbsolutePath();
......@@ -239,6 +228,9 @@ public final class LoadedPlugin {
}
this.mReceiverInfos = Collections.unmodifiableMap(receivers);
this.mPackageInfo.receivers = receivers.values().toArray(new ActivityInfo[receivers.size()]);
// try to invoke plugin's application
invokeApplication();
}
protected void tryToCopyNativeLib(File apk) throws Exception {
......@@ -289,7 +281,8 @@ public final class LoadedPlugin {
return mApplication;
}
public void invokeApplication() {
public void invokeApplication() throws Exception {
final Exception[] temp = new Exception[1];
// make sure application's callback is run on ui thread.
RunUtil.runOnUiThread(new Runnable() {
@Override
......@@ -297,9 +290,17 @@ public final class LoadedPlugin {
if (mApplication != null) {
return;
}
mApplication = makeApplication(false, mPluginManager.getInstrumentation());
try {
mApplication = makeApplication(false, mPluginManager.getInstrumentation());
} catch (Exception e) {
temp[0] = e;
}
}
}, true);
if (temp[0] != null) {
throw temp[0];
}
}
public String getPackageResourcePath() {
......@@ -379,7 +380,7 @@ public final class LoadedPlugin {
Reflector.QuietReflector.with(this.mResources).field("mThemeResId").set(resid);
}
protected Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
protected Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) throws Exception {
if (null != this.mApplication) {
return this.mApplication;
}
......@@ -388,15 +389,12 @@ public final class LoadedPlugin {
if (forceDefaultAppClass || null == appClass) {
appClass = "android.app.Application";
}
try {
this.mApplication = instrumentation.newApplication(this.mClassLoader, appClass, this.getPluginContext());
instrumentation.callApplicationOnCreate(this.mApplication);
return this.mApplication;
} catch (Exception e) {
e.printStackTrace();
return null;
}
this.mApplication = instrumentation.newApplication(this.mClassLoader, appClass, this.getPluginContext());
// inject activityLifecycleCallbacks of the host application
mApplication.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksProxy());
instrumentation.callApplicationOnCreate(this.mApplication);
return this.mApplication;
}
public ResolveInfo resolveActivity(Intent intent, int flags) {
......
......@@ -94,7 +94,7 @@ public class PluginContentResolver extends ContentResolverWrapper {
public static Uri wrapperUri(LoadedPlugin loadedPlugin, Uri pluginUri) {
String pkg = loadedPlugin.getPackageName();
String pluginUriString = Uri.encode(pluginUri.toString());
StringBuilder builder = new StringBuilder(PluginContentResolver.getUri(loadedPlugin.getHostContext()));
StringBuilder builder = new StringBuilder(RemoteContentProvider.getUri(loadedPlugin.getHostContext()));
builder.append("/?plugin=" + loadedPlugin.getLocation());
builder.append("&pkg=" + pkg);
builder.append("&uri=" + pluginUriString);
......@@ -104,12 +104,12 @@ public class PluginContentResolver extends ContentResolverWrapper {
@Deprecated
public static String getAuthority(Context context) {
return context.getPackageName() + ".VirtualAPK.Provider";
return RemoteContentProvider.getAuthority(context);
}
@Deprecated
public static String getUri(Context context) {
return "content://" + getAuthority(context);
return RemoteContentProvider.getUri(context);
}
@Keep
......
......@@ -61,7 +61,7 @@ class ResourcesManager {
return resources;
}
private static synchronized Resources createResourcesSimple(Context hostContext, String apk) throws Exception {
private static Resources createResourcesSimple(Context hostContext, String apk) throws Exception {
Resources hostResources = hostContext.getResources();
Resources newResources = null;
AssetManager assetManager;
......@@ -69,15 +69,24 @@ class ResourcesManager {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
assetManager = AssetManager.class.newInstance();
reflector.bind(assetManager);
reflector.call(hostContext.getApplicationInfo().sourceDir);
final int cookie1 = reflector.call(hostContext.getApplicationInfo().sourceDir);;
if (cookie1 == 0) {
throw new RuntimeException("createResources failed, can't addAssetPath for " + hostContext.getApplicationInfo().sourceDir);
}
} else {
assetManager = hostResources.getAssets();
reflector.bind(assetManager);
}
reflector.call(apk);
final int cookie2 = reflector.call(apk);
if (cookie2 == 0) {
throw new RuntimeException("createResources failed, can't addAssetPath for " + apk);
}
List<LoadedPlugin> pluginList = PluginManager.getInstance(hostContext).getAllLoadedPlugins();
for (LoadedPlugin plugin : pluginList) {
reflector.call(plugin.getLocation());
final int cookie3 = reflector.call(plugin.getLocation());
if (cookie3 == 0) {
throw new RuntimeException("createResources failed, can't addAssetPath for " + plugin.getLocation());
}
}
if (isMiUi(hostResources)) {
newResources = MiUiResourcesCompat.createResources(hostResources, assetManager);
......@@ -111,22 +120,14 @@ class ResourcesManager {
Object activityThread = ActivityThread.currentActivityThread();
Object resManager;
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
resManager = android.app.ResourcesManager.getInstance();
} else {
resManager = Reflector.with(activityThread).field("mResourcesManager").get();
}
if (Build.VERSION.SDK_INT < 24) {
Map<Object, WeakReference<Resources>> map = Reflector.with(resManager).field("mActiveResources").get();
Object key = map.keySet().iterator().next();
map.put(key, new WeakReference<>(resources));
} else {
// still hook Android N Resources, even though it's unnecessary, then nobody will be strange.
Map map = Reflector.QuietReflector.with(resManager).field("mResourceImpls").get();
Object key = map.keySet().iterator().next();
Object resourcesImpl = Reflector.QuietReflector.with(resources).field("mResourcesImpl").get();
map.put(key, new WeakReference<>(resourcesImpl));
}
Map<Object, WeakReference<Resources>> map = Reflector.with(resManager).field("mActiveResources").get();
Object key = map.keySet().iterator().next();
map.put(key, new WeakReference<>(resources));
} catch (Exception e) {
e.printStackTrace();
}
......@@ -279,6 +280,7 @@ class ResourcesManager {
private static final class ResourcesManagerCompatForN {
@TargetApi(Build.VERSION_CODES.KITKAT)
public static void resolveResourcesImplMap(Map<ResourcesKey, WeakReference<ResourcesImpl>> originalMap, Map<ResourcesKey, WeakReference<ResourcesImpl>> resolvedMap, String baseResDir, String newAssetPath) throws Exception {
for (Map.Entry<ResourcesKey, WeakReference<ResourcesImpl>> entry : originalMap.entrySet()) {
ResourcesKey key = entry.getKey();
......
......@@ -36,7 +36,7 @@ import android.util.Log;
import com.didi.virtualapk.PluginManager;
import com.didi.virtualapk.delegate.StubActivity;
import com.didi.virtualapk.utils.PluginUtil;
import com.didi.virtualapk.internal.utils.PluginUtil;
import com.didi.virtualapk.utils.Reflector;
import java.lang.ref.WeakReference;
......@@ -51,11 +51,11 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
public static final String TAG = "VAInstrumentation";
public static final int LAUNCH_ACTIVITY = 100;
private Instrumentation mBase;
protected Instrumentation mBase;
private final ArrayList<WeakReference<Activity>> mActivities = new ArrayList<>();
protected final ArrayList<WeakReference<Activity>> mActivities = new ArrayList<>();
PluginManager mPluginManager;
protected PluginManager mPluginManager;
public VAInstrumentation(PluginManager pluginManager, Instrumentation base) {
this.mPluginManager = pluginManager;
......@@ -130,12 +130,8 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
Activity activity = mBase.newActivity(plugin.getClassLoader(), targetClassName, intent);
activity.setIntent(intent);
try {
// for 4.1+
Reflector.with(activity).field("mResources").set(plugin.getResources());
} catch (Exception ignored) {
// ignored.
}
// for 4.1+
Reflector.QuietReflector.with(activity).field("mResources").set(plugin.getResources());
return newActivity(activity);
}
......
......@@ -14,13 +14,14 @@
* limitations under the License.
*/
package com.didi.virtualapk.utils;
package com.didi.virtualapk.internal.utils;
import android.app.ActivityThread;
import android.content.Context;
import android.os.Build;
import com.didi.virtualapk.internal.Constants;
import com.didi.virtualapk.utils.Reflector;
import java.io.File;
import java.lang.reflect.Array;
......
......@@ -14,12 +14,14 @@
* limitations under the License.
*/
package com.didi.virtualapk.utils;
package com.didi.virtualapk.internal.utils;
import android.content.Context;
import android.content.pm.PackageParser;
import android.os.Build;
import com.didi.virtualapk.utils.Reflector;
import java.io.File;
/**
......@@ -27,26 +29,30 @@ import java.io.File;
*/
public final class PackageParserCompat {
public static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) throws PackageParser.PackageParserException {
if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.PREVIEW_SDK_INT == 0) {
public static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) {
try {
if (Build.VERSION.SDK_INT >= 28
|| (Build.VERSION.SDK_INT == 27 && Build.VERSION.PREVIEW_SDK_INT != 0)) { // Android P Preview
return PackageParserPPreview.parsePackage(context, apk, flags);
} else if (Build.VERSION.SDK_INT >= 24) {
return PackageParserV24.parsePackage(context, apk, flags);
} else if (Build.VERSION.SDK_INT >= 21) {
return PackageParserLollipop.parsePackage(context, apk, flags);
} else {
return PackageParserPPreview.parsePackage(context, apk, flags);
return PackageParserLegacy.parsePackage(context, apk, flags);
}
} else if (Build.VERSION.SDK_INT >= 21) {
return PackageParserLollipop.parsePackage(context, apk, flags);
} else {
return PackageParserLegacy.parsePackage(context, apk, flags);
} catch (Throwable e) {
throw new RuntimeException("error", e);
}
}
private static final class PackageParserPPreview {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws PackageParser.PackageParserException {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable {
PackageParser parser = new PackageParser();
PackageParser.Package pkg = parser.parsePackage(apk, flags);
Reflector.QuietReflector.with(parser)
Reflector.with(parser)
.method("collectCertificates", PackageParser.Package.class, boolean.class)
.call(pkg, false);
return pkg;
......@@ -55,10 +61,10 @@ public final class PackageParserCompat {
private static final class PackageParserV24 {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws PackageParser.PackageParserException {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable {
PackageParser parser = new PackageParser();
PackageParser.Package pkg = parser.parsePackage(apk, flags);
Reflector.QuietReflector.with(parser)
Reflector.with(parser)
.method("collectCertificates", PackageParser.Package.class, int.class)
.call(pkg, flags);
return pkg;
......@@ -67,14 +73,10 @@ public final class PackageParserCompat {
private static final class PackageParserLollipop {
static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) throws PackageParser.PackageParserException {
static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) throws Throwable {
PackageParser parser = new PackageParser();
PackageParser.Package pkg = parser.parsePackage(apk, flags);
try {
parser.collectCertificates(pkg, flags);
} catch (Throwable e) {
// ignored
}
parser.collectCertificates(pkg, flags);
return pkg;
}
......@@ -82,10 +84,10 @@ public final class PackageParserCompat {
private static final class PackageParserLegacy {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) {
static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable {
PackageParser parser = new PackageParser(apk.getAbsolutePath());
PackageParser.Package pkg = parser.parsePackage(apk, apk.getAbsolutePath(), context.getResources().getDisplayMetrics(), flags);
Reflector.QuietReflector.with(parser)
Reflector.with(parser)
.method("collectCertificates", PackageParser.Package.class, int.class)
.call(pkg, flags);
return pkg;
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.didi.virtualapk.utils;
package com.didi.virtualapk.internal.utils;
import android.app.Activity;
import android.content.ComponentName;
......@@ -34,6 +34,7 @@ import android.util.Log;
import com.didi.virtualapk.PluginManager;
import com.didi.virtualapk.internal.Constants;
import com.didi.virtualapk.internal.LoadedPlugin;
import com.didi.virtualapk.utils.Reflector;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
......@@ -95,7 +96,7 @@ public class PluginUtil {
return appInfo.theme;
}
return PluginUtil.selectDefaultTheme(0, Build.VERSION.SDK_INT);
return selectDefaultTheme(0, Build.VERSION.SDK_INT);
}
public static int selectDefaultTheme(final int curTheme, final int targetSdkVersion) {
......@@ -106,7 +107,7 @@ public class PluginUtil {
android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
private static int selectSystemTheme(final int curTheme, final int targetSdkVersion, final int orig, final int holo, final int dark, final int deviceDefault) {
public static int selectSystemTheme(final int curTheme, final int targetSdkVersion, final int orig, final int holo, final int dark, final int deviceDefault) {
if (curTheme != 0) {
return curTheme;
}
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.didi.virtualapk.utils;
package com.didi.virtualapk.internal.utils;
import android.content.Context;
import android.content.SharedPreferences;
......
......@@ -52,7 +52,7 @@ public class RunUtil {
* @param waitUtilDone if set true, the caller thread will wait until the specific runnable finished.
*/
public static void runOnUiThread(Runnable runnable, boolean waitUtilDone) {
if (Looper.myLooper() == Looper.getMainLooper()) {
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
runnable.run();
return;
}
......@@ -121,11 +121,15 @@ public class RunUtil {
@Override
public void handleMessage(Message msg) {
if (msg.what == MESSAGE_RUN_ON_UITHREAD) {
Pair<Runnable, CountDownLatch> pair = (Pair<Runnable, CountDownLatch>)msg.obj;
Runnable runnable = pair.first;
runnable.run();
if (pair.second != null) {
pair.second.countDown();
Pair<Runnable, CountDownLatch> pair = (Pair<Runnable, CountDownLatch>) msg.obj;
try {
Runnable runnable = pair.first;
runnable.run();
} finally {
if (pair.second != null) {
pair.second.countDown();
}
}
}
}
......
......@@ -46,9 +46,13 @@ import java.util.zip.ZipFile;
public class ZipVerifyUtil {
public static boolean verifyZip(Context context, String zipPath) {
return verifyZip(context, zipPath, "test.cer");
}
public static boolean verifyZip(Context context, String zipPath, String cerName) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream in = context.getAssets().open("test.cer");
InputStream in = context.getAssets().open(cerName);
Certificate certificate = certificateFactory.generateCertificate(in);
in.close();
return verifyZip(zipPath, certificate);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册