Tinker patch so 更新

patch so 生成

1、BsDiffDecoder.java 对so进行patch

@Override
public boolean patch(File oldFile, File newFile) throws IOException, TinkerPatchException {
    //first of all, we should check input files
    if (newFile == null || !newFile.exists()) {
        return false;
    }
    //new add file
    String newMd5 = MD5.getMD5(newFile);
    File bsDiffFile = getOutputPath(newFile).toFile();

    if (oldFile == null || !oldFile.exists()) {
        FileOperation.copyFileUsingStream(newFile, bsDiffFile);
        writeLogFiles(newFile, null, null, newMd5);
        return true;
    }

    //both file length is 0
    if (oldFile.length() == 0 && newFile.length() == 0) {
        return false;
    }
    if (oldFile.length() == 0 || newFile.length() == 0) {
        FileOperation.copyFileUsingStream(newFile, bsDiffFile);
        writeLogFiles(newFile, null, null, newMd5);
        return true;
    }

    //new add file
    String oldMd5 = MD5.getMD5(oldFile);

    if (oldMd5.equals(newMd5)) {
        return false;
    }

    if (!bsDiffFile.getParentFile().exists()) {
        bsDiffFile.getParentFile().mkdirs();
    }
    BSDiff.bsdiff(oldFile, newFile, bsDiffFile);

    if (Utils.checkBsDiffFileSize(bsDiffFile, newFile)) {
        writeLogFiles(newFile, oldFile, bsDiffFile, newMd5);
    } else {
        FileOperation.copyFileUsingStream(newFile, bsDiffFile);
        writeLogFiles(newFile, null, null, newMd5);
    }
    return true;
}

2、BSDiff.java 对so进行patch

public static void bsdiff(File oldFile, File newFile, File diffFile) throws IOException {
    InputStream oldInputStream = new BufferedInputStream(new FileInputStream(oldFile));
    InputStream newInputStream = new BufferedInputStream(new FileInputStream(newFile));
    OutputStream diffOutputStream = new FileOutputStream(diffFile);
    try {
        byte[] diffBytes = bsdiff(oldInputStream, (int) oldFile.length(), newInputStream, (int) newFile.length());
        diffOutputStream.write(diffBytes);
    } finally {
        diffOutputStream.close();
    }
}

patch so 合成
 

1、TinkerPatchService.java doApplyPatch

private static void doApplyPatch(Context context, Intent intent) {
    // Since we may retry with IntentService, we should prevent
    // racing here again.
    if (!sIsPatchApplying.compareAndSet(false, true)) {
        TinkerLog.w(TAG, "TinkerPatchService doApplyPatch is running by another runner.");
        return;
    }

    Tinker tinker = Tinker.with(context);
    tinker.getPatchReporter().onPatchServiceStart(intent);

    if (intent == null) {
        TinkerLog.e(TAG, "TinkerPatchService received a null intent, ignoring.");
        return;
    }
    String path = getPatchPathExtra(intent);
    if (path == null) {
        TinkerLog.e(TAG, "TinkerPatchService can't get the path extra, ignoring.");
        return;
    }
    File patchFile = new File(path);

    long begin = SystemClock.elapsedRealtime();
    boolean result;
    long cost;
    Throwable e = null;

    PatchResult patchResult = new PatchResult();
    try {
        if (upgradePatchProcessor == null) {
            throw new TinkerRuntimeException("upgradePatchProcessor is null.");
        }
        result = upgradePatchProcessor.tryPatch(context, path, patchResult);
    } catch (Throwable throwable) {
        e = throwable;
        result = false;
        tinker.getPatchReporter().onPatchException(patchFile, e);
    }

2、UpgradePatch.java tryPatch分别对dex、so、res patch加载

if (!DexDiffPatchInternal.tryRecoverDexFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) {
    TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch dex failed");
    return false;
}

if (!BsDiffPatchInternal.tryRecoverLibraryFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) {
    TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch library failed");
    return false;
}

if (!ResDiffPatchInternal.tryRecoverResourceFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) {
    TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch resource failed");
    return false;
}

3、BsDiffDecoder.java 对so进行patch
 

protected static boolean tryRecoverLibraryFiles(Tinker manager, ShareSecurityCheck checker, Context context,
                                                String patchVersionDirectory, File patchFile) {

    if (!manager.isEnabledForNativeLib()) {
        TinkerLog.w(TAG, "patch recover, library is not enabled");
        return true;
    }
    String libMeta = checker.getMetaContentMap().get(SO_META_FILE);

    if (libMeta == null) {
        TinkerLog.w(TAG, "patch recover, library is not contained");
        return true;
    }
    long begin = SystemClock.elapsedRealtime();
    boolean result = patchLibraryExtractViaBsDiff(context, patchVersionDirectory, libMeta, patchFile);
    long cost = SystemClock.elapsedRealtime() - begin;
    TinkerLog.i(TAG, "recover lib result:%b, cost:%d", result, cost);
    return result;
}
private static boolean patchLibraryExtractViaBsDiff(Context context, String patchVersionDirectory, String meta, File patchFile) {
    String dir = patchVersionDirectory + "/" + SO_PATH + "/";
    return extractBsDiffInternals(context, dir, meta, patchFile, TYPE_LIBRARY);
}

4、BsDiffPatchInternal.java  extractBsDiffInternals 进入BSPatch
 

InputStream oldStream = null;
InputStream newStream = null;
try {
    oldStream = apk.getInputStream(rawApkFileEntry);
    newStream = patch.getInputStream(patchFileEntry);
    BSPatch.patchFast(oldStream, newStream, extractedFile);
} finally {
    StreamUtil.closeQuietly(oldStream);
    StreamUtil.closeQuietly(newStream);
}

5、BSPatch.java 进行patch
 

public static int patchFast(InputStream oldInputStream, InputStream diffInputStream, File newFile) throws IOException {
    if (oldInputStream == null) {
        return RETURN_OLD_FILE_ERR;
    }
    if (newFile == null) {
        return RETURN_NEW_FILE_ERR;
    }
    if (diffInputStream == null) {
        return RETURN_DIFF_FILE_ERR;
    }

    byte[] oldBytes = BSUtil.inputStreamToByte(oldInputStream);
    byte[] diffBytes = BSUtil.inputStreamToByte(diffInputStream);

    byte[] newBytes = patchFast(oldBytes, oldBytes.length, diffBytes, diffBytes.length, 0);

    OutputStream newOutputStream = new FileOutputStream(newFile);
    try {
        newOutputStream.write(newBytes);
    } finally {
        newOutputStream.close();
    }
    return RETURN_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值