package me.ele.amigo; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.Signature; import android.text.TextUtils; import android.util.Log; import java.io.File; import java.util.Map; import me.ele.amigo.utils.ArrayUtil; import me.ele.amigo.utils.CommonUtils; import me.ele.amigo.utils.CrcUtils; import me.ele.amigo.utils.PermissionChecker; import static me.ele.amigo.utils.CrcUtils.getCrc; import static me.ele.amigo.utils.FileUtils.copyFile; class PatchChecker { static String checkPatchAndCopy(Context context, File patchFile, boolean checkSignature) { PatchChecker.checkPatchApk(context, patchFile, checkSignature); String patchChecksum = CrcUtils.getCrc(patchFile); if (!PatchApks.getInstance(context).exists(patchChecksum)) { copyFile(patchFile, PatchApks.getInstance(context).patchFile(patchChecksum)); } return patchChecksum; } private static void checkPatchApk(Context context, File patchFile, boolean checkSignature) { if (patchFile == null) { throw new NullPointerException("param apkFile cannot be null"); } if (!patchFile.exists()) { throw new IllegalArgumentException("param apkFile doesn't exist"); } if (!patchFile.canRead()) { throw new IllegalArgumentException("param apkFile cannot be read"); } if (!PermissionChecker.checkPatchPermission(context, patchFile)) { throw new IllegalStateException("patch apk cannot request more permissions than host"); } if (checkSignature && !checkSignature(context, patchFile)) { throw new IllegalStateException("patch apk's signature is different with host"); } } private static boolean checkSignature(Context context, File patchFile) { try { Signature appSig = CommonUtils.getSignature(context); Signature patchSig = CommonUtils.getSignature(context, patchFile); return appSig.hashCode() == patchSig.hashCode(); } catch (Exception e) { e.printStackTrace(); } return false; } static void checkDexAndSo(Context context, String apkChecksum) throws Exception { Map<String, String> checksumMap = PatchInfoUtil.getPatchFileChecksum(context, apkChecksum); AmigoDirs amigoDirs = AmigoDirs.getInstance(context); File[] dexFiles = amigoDirs.dexDir(apkChecksum).listFiles(); assertChecksum(checksumMap, dexFiles, "dex"); File[] dexOptFiles = amigoDirs.dexOptDir(apkChecksum).listFiles(); assertChecksum(checksumMap, dexOptFiles, "opt dex"); File[] nativeFiles = amigoDirs.libDir(apkChecksum).listFiles(); assertChecksum(checksumMap, nativeFiles, "native lib"); } private static void assertChecksum(Map<String, String> checksumMap, File[] files, String type) { if (ArrayUtil.isEmpty(files)) { return; } for (File file : files) { String savedChecksum = checksumMap.get(file.getAbsolutePath()); String checksum = getCrc(file); if (!checksum.equals(savedChecksum)) { throw new IllegalStateException("wrong " + type + " checksum, expected is " + savedChecksum + ", actual is " + checksum); } } } static boolean checkUpgrade(Context context) { String workingChecksum = PatchInfoUtil.getWorkingChecksum(context); if (TextUtils.isEmpty(workingChecksum)) { return true; } String patchPath = PatchApks.getInstance(context).patchPath(workingChecksum); PackageInfo patchInfo = context.getPackageManager().getPackageArchiveInfo(patchPath, 0); int patchVersion = patchInfo.versionCode; int hostVersion = CommonUtils.getVersionCode(context); return hostVersion > patchVersion; } }