package me.ele.amigo.utils.component;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.util.DisplayMetrics;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.ele.amigo.Amigo;
import me.ele.amigo.PatchApks;
import me.ele.amigo.PatchInfoUtil;
import me.ele.amigo.reflect.FieldUtils;
import me.ele.amigo.reflect.MethodUtils;
class ComponentFinder {
static List<Activity> sReceivers = Collections.EMPTY_LIST;
static List<Service> sServices = Collections.EMPTY_LIST;
static List<Activity> sActivities = Collections.EMPTY_LIST;
static List<Object> sProviders = Collections.EMPTY_LIST;
private static boolean hasParsePackage = false;
static File getHotFixApk(Context context) {
String workingPatchApkChecksum = PatchInfoUtil.getWorkingChecksum(context);
return PatchApks.getInstance(context).patchFile(workingPatchApkChecksum);
}
static boolean isHotfixApkValid(Context context) {
File file = getHotFixApk(context);
return file != null && file.exists();
}
static void parsePackage(Context context) {
if (hasParsePackage) {
return;
}
if (!isHotfixApkValid(context)) {
return;
}
Object mPackageParser;
Object mPackage;
try {
File file = ActivityFinder.getHotFixApk(context);
Class sPackageParserClass = Class.forName("android.content.pm.PackageParser");
try {
mPackageParser = sPackageParserClass.newInstance();
mPackage = MethodUtils.invokeMethod(mPackageParser, "parsePackage", file, 0);
} catch (Exception e) {
mPackageParser = sPackageParserClass.getDeclaredConstructor(String.class)
.newInstance(file.getPath());
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
mPackage = MethodUtils.invokeMethod(mPackageParser, "parsePackage", file, file
.getPath(), metrics, 0);
}
List<Object> tempReceivers = (List<Object>) FieldUtils.readField(mPackage,
"receivers");
if (tempReceivers != null) {
final ArrayList<Activity> receivers = new ArrayList<>();
for (int i = tempReceivers.size() - 1; i >= 0; i--) {
Object obj = tempReceivers.get(i);
ActivityInfo activityInfo = (ActivityInfo) FieldUtils.readField(obj, "info");
List<IntentFilter> intentFilters = (List<IntentFilter>) FieldUtils.readField
(obj, "intents");
Bundle meta = (Bundle) FieldUtils.readField(obj, "metaData");
receivers.add(new Activity(meta, intentFilters, activityInfo));
}
sReceivers = receivers;
}
List<Object> tempProviders = (List<Object>) FieldUtils.readField(mPackage,
"providers");
if (tempProviders != null) {
sProviders = tempProviders;
}
List<Object> tempServices = (List<Object>) FieldUtils.readField(mPackage, "services");
if (tempServices != null) {
final ArrayList<Service> services = new ArrayList<>();
for (Object obj : tempServices) {
ServiceInfo serviceInfo = (ServiceInfo) FieldUtils.readField(obj, "info");
List<IntentFilter> intentFilters = (List<IntentFilter>) FieldUtils.readField
(obj, "intents");
Bundle meta = (Bundle) FieldUtils.readField(obj, "metaData");
services.add(new Service(meta, intentFilters, serviceInfo));
}
sServices = services;
}
List<Object> tempActivities = (List<Object>) FieldUtils.readField(mPackage,
"activities");
if (tempActivities != null) {
final ArrayList<Activity> activities = new ArrayList<>();
for (Object obj : tempActivities) {
ActivityInfo activityInfo = (ActivityInfo) FieldUtils.readField(obj, "info");
List<IntentFilter> intentFilters = (List<IntentFilter>) FieldUtils.readField
(obj, "intents");
Bundle meta = (Bundle) FieldUtils.readField(obj, "metaData");
activities.add(new Activity(meta, intentFilters, activityInfo));
}
sActivities = activities;
fillApplicationInfo(context, activities.get(0).activityInfo.applicationInfo);
}
} catch (Exception e) {
e.printStackTrace();
}
hasParsePackage = true;
}
static void fillApplicationInfo(Context context, ApplicationInfo applicationInfo) {
String patchPath = PatchApks.getInstance(context).patchPath(Amigo
.getWorkingPatchApkChecksum(context));
applicationInfo.sourceDir = patchPath;
applicationInfo.publicSourceDir = patchPath;
applicationInfo.uid = context.getApplicationInfo().uid;
// applicationInfo.packageName = context.getApplicationContext().getPackageName();
}
static class Component {
List<IntentFilter> filters;
Bundle metaData;
Component(Bundle metaData, List<IntentFilter> filters) {
this.metaData = metaData;
this.filters = filters;
}
}
static class Service extends Component {
ServiceInfo serviceInfo;
Service(Bundle metaData, List<IntentFilter> filters, ServiceInfo serviceInfo) {
super(metaData, filters);
this.serviceInfo = serviceInfo;
}
}
static class Activity extends Component {
ActivityInfo activityInfo;
Activity(Bundle metaData, List<IntentFilter> filters, ActivityInfo activityInfo) {
super(metaData, filters);
this.activityInfo = activityInfo;
}
}
}