use of com.tencent.tinker.loader.shareutil.ShareBsDiffPatchInfo in project tinker by Tencent.
the class BsDiffPatchInternal method extractBsDiffInternals.
private static boolean extractBsDiffInternals(Context context, String dir, String meta, File patchFile, int type) {
//parse
ArrayList<ShareBsDiffPatchInfo> patchList = new ArrayList<>();
ShareBsDiffPatchInfo.parseDiffPatchInfo(meta, patchList);
if (patchList.isEmpty()) {
TinkerLog.w(TAG, "extract patch list is empty! type:%s:", ShareTinkerInternals.getTypeString(type));
return true;
}
File directory = new File(dir);
if (!directory.exists()) {
directory.mkdirs();
}
//I think it is better to extract the raw files from apk
Tinker manager = Tinker.with(context);
ApplicationInfo applicationInfo = context.getApplicationInfo();
if (applicationInfo == null) {
// Looks like running on a test Context, so just return without patching.
TinkerLog.w(TAG, "applicationInfo == null!!!!");
return false;
}
ZipFile apk = null;
ZipFile patch = null;
try {
String apkPath = applicationInfo.sourceDir;
apk = new ZipFile(apkPath);
patch = new ZipFile(patchFile);
for (ShareBsDiffPatchInfo info : patchList) {
long start = System.currentTimeMillis();
final String infoPath = info.path;
String patchRealPath;
if (infoPath.equals("")) {
patchRealPath = info.name;
} else {
patchRealPath = info.path + "/" + info.name;
}
final String fileMd5 = info.md5;
if (!SharePatchFileUtil.checkIfMd5Valid(fileMd5)) {
TinkerLog.w(TAG, "meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.name, info.md5);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
String middle;
middle = info.path + "/" + info.name;
File extractedFile = new File(dir + middle);
//check file whether already exist
if (extractedFile.exists()) {
if (fileMd5.equals(SharePatchFileUtil.getMD5(extractedFile))) {
//it is ok, just continue
TinkerLog.w(TAG, "bsdiff file %s is already exist, and md5 match, just continue", extractedFile.getPath());
continue;
} else {
TinkerLog.w(TAG, "have a mismatch corrupted dex " + extractedFile.getPath());
extractedFile.delete();
}
} else {
extractedFile.getParentFile().mkdirs();
}
String patchFileMd5 = info.patchMd5;
//it is a new file, just copy
ZipEntry patchFileEntry = patch.getEntry(patchRealPath);
if (patchFileEntry == null) {
TinkerLog.w(TAG, "patch entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
return false;
}
if (patchFileMd5.equals("0")) {
if (!extract(patch, patchFileEntry, extractedFile, fileMd5, false)) {
TinkerLog.w(TAG, "Failed to extract file " + extractedFile.getPath());
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
return false;
}
} else {
//we do not check the intermediate files' md5 to save time, use check whether it is 32 length
if (!SharePatchFileUtil.checkIfMd5Valid(patchFileMd5)) {
TinkerLog.w(TAG, "meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.name, patchFileMd5);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
ZipEntry rawApkFileEntry = apk.getEntry(patchRealPath);
if (rawApkFileEntry == null) {
TinkerLog.w(TAG, "apk entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
return false;
}
String rawApkCrc = info.rawCrc;
//check source crc instead of md5 for faster
String rawEntryCrc = String.valueOf(rawApkFileEntry.getCrc());
if (!rawEntryCrc.equals(rawApkCrc)) {
TinkerLog.e(TAG, "apk entry %s crc is not equal, expect crc: %s, got crc: %s", patchRealPath, rawApkCrc, rawEntryCrc);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
return false;
}
InputStream oldStream = null;
InputStream newStream = null;
try {
oldStream = apk.getInputStream(rawApkFileEntry);
newStream = patch.getInputStream(patchFileEntry);
BSPatch.patchFast(oldStream, newStream, extractedFile);
} finally {
SharePatchFileUtil.closeQuietly(oldStream);
SharePatchFileUtil.closeQuietly(newStream);
}
//go go go bsdiff get the
if (!SharePatchFileUtil.verifyFileMd5(extractedFile, fileMd5)) {
TinkerLog.w(TAG, "Failed to recover diff file " + extractedFile.getPath());
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
SharePatchFileUtil.safeDeleteFile(extractedFile);
return false;
}
TinkerLog.w(TAG, "success recover bsdiff file: %s, use time: %d", extractedFile.getPath(), (System.currentTimeMillis() - start));
}
}
} catch (Throwable e) {
// e.printStackTrace();
throw new TinkerRuntimeException("patch " + ShareTinkerInternals.getTypeString(type) + " extract failed (" + e.getMessage() + ").", e);
} finally {
SharePatchFileUtil.closeZip(apk);
SharePatchFileUtil.closeZip(patch);
}
return true;
}
use of com.tencent.tinker.loader.shareutil.ShareBsDiffPatchInfo in project tinker by Tencent.
the class TinkerSoLoader method checkComplete.
/**
* all the library files in meta file exist?
* fast check, only check whether exist
*
* @param directory
* @return boolean
*/
public static boolean checkComplete(String directory, ShareSecurityCheck securityCheck, Intent intentResult) {
String meta = securityCheck.getMetaContentMap().get(SO_MEAT_FILE);
//not found lib
if (meta == null) {
return true;
}
ArrayList<ShareBsDiffPatchInfo> libraryList = new ArrayList<>();
ShareBsDiffPatchInfo.parseDiffPatchInfo(meta, libraryList);
if (libraryList.isEmpty()) {
return true;
}
//tinker//patch-641e634c/lib
String libraryPath = directory + "/" + SO_PATH + "/";
HashMap<String, String> libs = new HashMap<>();
for (ShareBsDiffPatchInfo info : libraryList) {
if (!ShareBsDiffPatchInfo.checkDiffPatchInfo(info)) {
intentResult.putExtra(ShareIntentUtil.INTENT_PATCH_PACKAGE_PATCH_CHECK, ShareConstants.ERROR_PACKAGE_CHECK_LIB_META_CORRUPTED);
ShareIntentUtil.setIntentReturnCode(intentResult, ShareConstants.ERROR_LOAD_PATCH_PACKAGE_CHECK_FAIL);
return false;
}
String middle = info.path + "/" + info.name;
//unlike dex, keep the original structure
libs.put(middle, info.md5);
}
File libraryDir = new File(libraryPath);
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
ShareIntentUtil.setIntentReturnCode(intentResult, ShareConstants.ERROR_LOAD_PATCH_VERSION_LIB_DIRECTORY_NOT_EXIST);
return false;
}
//fast check whether there is any dex files missing
for (String relative : libs.keySet()) {
File libFile = new File(libraryPath + relative);
if (!SharePatchFileUtil.isLegalFile(libFile)) {
ShareIntentUtil.setIntentReturnCode(intentResult, ShareConstants.ERROR_LOAD_PATCH_VERSION_LIB_FILE_NOT_EXIST);
intentResult.putExtra(ShareIntentUtil.INTENT_PATCH_MISSING_LIB_PATH, libFile.getAbsolutePath());
return false;
}
}
//if is ok, add to result intent
intentResult.putExtra(ShareIntentUtil.INTENT_PATCH_LIBS_PATH, libs);
return true;
}
Aggregations