Search in sources :

Example 1 with SharePatchInfo

use of com.tencent.tinker.loader.shareutil.SharePatchInfo in project tinker by Tencent.

the class TinkerLoadResult method parseTinkerResult.

public boolean parseTinkerResult(Context context, Intent intentResult) {
    Tinker tinker = Tinker.with(context);
    loadCode = ShareIntentUtil.getIntentReturnCode(intentResult);
    costTime = ShareIntentUtil.getIntentPatchCostTime(intentResult);
    systemOTA = ShareIntentUtil.getBooleanExtra(intentResult, ShareIntentUtil.INTENT_PATCH_SYSTEM_OTA, false);
    TinkerLog.i(TAG, "parseTinkerResult loadCode:%d, systemOTA:%b", loadCode, systemOTA);
    //@Nullable
    final String oldVersion = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_OLD_VERSION);
    //@Nullable
    final String newVersion = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_NEW_VERSION);
    final File patchDirectory = tinker.getPatchDirectory();
    final File patchInfoFile = tinker.getPatchInfoFile();
    final boolean isMainProcess = tinker.isMainProcess();
    if (oldVersion != null && newVersion != null) {
        if (isMainProcess) {
            currentVersion = newVersion;
        } else {
            currentVersion = oldVersion;
        }
        TinkerLog.i(TAG, "parseTinkerResult oldVersion:%s, newVersion:%s, current:%s", oldVersion, newVersion, currentVersion);
        //current version may be nil
        String patchName = SharePatchFileUtil.getPatchVersionDirectory(currentVersion);
        if (!ShareTinkerInternals.isNullOrNil(patchName)) {
            patchVersionDirectory = new File(patchDirectory.getAbsolutePath() + "/" + patchName);
            patchVersionFile = new File(patchVersionDirectory.getAbsolutePath(), SharePatchFileUtil.getPatchVersionFile(currentVersion));
            dexDirectory = new File(patchVersionDirectory, ShareConstants.DEX_PATH);
            libraryDirectory = new File(patchVersionDirectory, ShareConstants.SO_PATH);
            resourceDirectory = new File(patchVersionDirectory, ShareConstants.RES_PATH);
            resourceFile = new File(resourceDirectory, ShareConstants.RES_NAME);
        }
        patchInfo = new SharePatchInfo(oldVersion, newVersion, Build.FINGERPRINT);
        versionChanged = !(oldVersion.equals(newVersion));
    }
    //found uncaught exception, just return
    Throwable exception = ShareIntentUtil.getIntentPatchException(intentResult);
    if (exception != null) {
        TinkerLog.i(TAG, "Tinker load have exception loadCode:%d", loadCode);
        int errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_UNKNOWN;
        switch(loadCode) {
            case ShareConstants.ERROR_LOAD_PATCH_UNKNOWN_EXCEPTION:
                errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_UNKNOWN;
                break;
            case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_LOAD_EXCEPTION:
                errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_DEX;
                break;
            case ShareConstants.ERROR_LOAD_PATCH_VERSION_PARALLEL_DEX_OPT_EXCEPTION:
                errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_DEX_OPT;
                break;
            case ShareConstants.ERROR_LOAD_PATCH_VERSION_RESOURCE_LOAD_EXCEPTION:
                errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_RESOURCE;
                break;
            case ShareConstants.ERROR_LOAD_PATCH_UNCAUGHT_EXCEPTION:
                errorCode = ShareConstants.ERROR_LOAD_EXCEPTION_UNCAUGHT;
                break;
        }
        tinker.getLoadReporter().onLoadException(exception, errorCode);
        return false;
    }
    switch(loadCode) {
        case ShareConstants.ERROR_LOAD_GET_INTENT_FAIL:
            TinkerLog.e(TAG, "can't get the right intent return code");
            throw new TinkerRuntimeException("can't get the right intent return code");
        //                    break;
        case ShareConstants.ERROR_LOAD_DISABLE:
            TinkerLog.w(TAG, "tinker is disable, just return");
            break;
        //                break;
        case ShareConstants.ERROR_LOAD_PATCH_DIRECTORY_NOT_EXIST:
        case ShareConstants.ERROR_LOAD_PATCH_INFO_NOT_EXIST:
            TinkerLog.w(TAG, "can't find patch file, is ok, just return");
            break;
        case ShareConstants.ERROR_LOAD_PATCH_INFO_CORRUPTED:
            TinkerLog.e(TAG, "path info corrupted");
            tinker.getLoadReporter().onLoadPatchInfoCorrupted(oldVersion, newVersion, patchInfoFile);
            break;
        case ShareConstants.ERROR_LOAD_PATCH_INFO_BLANK:
            TinkerLog.e(TAG, "path info blank, wait main process to restart");
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DIRECTORY_NOT_EXIST:
            TinkerLog.e(TAG, "patch version directory not found, current version:%s", currentVersion);
            tinker.getLoadReporter().onLoadFileNotFound(patchVersionDirectory, ShareConstants.TYPE_PATCH_FILE, true);
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_FILE_NOT_EXIST:
            TinkerLog.e(TAG, "patch version file not found, current version:%s", currentVersion);
            if (patchVersionFile == null) {
                throw new TinkerRuntimeException("error load patch version file not exist, but file is null");
            }
            tinker.getLoadReporter().onLoadFileNotFound(patchVersionFile, ShareConstants.TYPE_PATCH_FILE, false);
            break;
        case ShareConstants.ERROR_LOAD_PATCH_PACKAGE_CHECK_FAIL:
            TinkerLog.i(TAG, "patch package check fail");
            if (patchVersionFile == null) {
                throw new TinkerRuntimeException("error patch package check fail , but file is null");
            }
            int errorCode = intentResult.getIntExtra(ShareIntentUtil.INTENT_PATCH_PACKAGE_PATCH_CHECK, ShareConstants.ERROR_LOAD_GET_INTENT_FAIL);
            tinker.getLoadReporter().onLoadPackageCheckFail(patchVersionFile, errorCode);
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_DIRECTORY_NOT_EXIST:
            if (dexDirectory != null) {
                TinkerLog.e(TAG, "patch dex file directory not found:%s", dexDirectory.getAbsolutePath());
                tinker.getLoadReporter().onLoadFileNotFound(dexDirectory, ShareConstants.TYPE_DEX, true);
            } else {
                //should be not here
                TinkerLog.e(TAG, "patch dex file directory not found, warning why the path is null!!!!");
                throw new TinkerRuntimeException("patch dex file directory not found, warning why the path is null!!!!");
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_FILE_NOT_EXIST:
            String dexPath = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_MISSING_DEX_PATH);
            if (dexPath != null) {
                //we only pass one missing file
                TinkerLog.e(TAG, "patch dex file not found:%s", dexPath);
                tinker.getLoadReporter().onLoadFileNotFound(new File(dexPath), ShareConstants.TYPE_DEX, false);
            } else {
                TinkerLog.e(TAG, "patch dex file not found, but path is null!!!!");
                throw new TinkerRuntimeException("patch dex file not found, but path is null!!!!");
            //                        tinker.getLoadReporter().onLoadFileNotFound(null,
            //                            ShareConstants.TYPE_DEX, false);
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_OPT_FILE_NOT_EXIST:
            String dexOptPath = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_MISSING_DEX_PATH);
            if (dexOptPath != null) {
                //we only pass one missing file
                TinkerLog.e(TAG, "patch dex opt file not found:%s", dexOptPath);
                tinker.getLoadReporter().onLoadFileNotFound(new File(dexOptPath), ShareConstants.TYPE_DEX_OPT, false);
            } else {
                TinkerLog.e(TAG, "patch dex opt file not found, but path is null!!!!");
                throw new TinkerRuntimeException("patch dex opt file not found, but path is null!!!!");
            //                        tinker.getLoadReporter().onLoadFileNotFound(null,
            //                            ShareConstants.TYPE_DEX, false);
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_LIB_DIRECTORY_NOT_EXIST:
            if (patchVersionDirectory != null) {
                TinkerLog.e(TAG, "patch lib file directory not found:%s", libraryDirectory.getAbsolutePath());
                tinker.getLoadReporter().onLoadFileNotFound(libraryDirectory, ShareConstants.TYPE_LIBRARY, true);
            } else {
                //should be not here
                TinkerLog.e(TAG, "patch lib file directory not found, warning why the path is null!!!!");
                throw new TinkerRuntimeException("patch lib file directory not found, warning why the path is null!!!!");
            //                        tinker.getLoadReporter().onLoadFileNotFound(null,
            //                            ShareConstants.TYPE_LIBRARY, true);
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_LIB_FILE_NOT_EXIST:
            String libPath = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_MISSING_LIB_PATH);
            if (libPath != null) {
                //we only pass one missing file and then we break
                TinkerLog.e(TAG, "patch lib file not found:%s", libPath);
                tinker.getLoadReporter().onLoadFileNotFound(new File(libPath), ShareConstants.TYPE_LIBRARY, false);
            } else {
                TinkerLog.e(TAG, "patch lib file not found, but path is null!!!!");
                throw new TinkerRuntimeException("patch lib file not found, but path is null!!!!");
            //                        tinker.getLoadReporter().onLoadFileNotFound(null,
            //                            ShareConstants.TYPE_LIBRARY, false);
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_CLASSLOADER_NULL:
            TinkerLog.e(TAG, "patch dex load fail, classloader is null");
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_MD5_MISMATCH:
            String mismatchPath = ShareIntentUtil.getStringExtra(intentResult, ShareIntentUtil.INTENT_PATCH_MISMATCH_DEX_PATH);
            if (mismatchPath == null) {
                TinkerLog.e(TAG, "patch dex file md5 is mismatch, but path is null!!!!");
                throw new TinkerRuntimeException("patch dex file md5 is mismatch, but path is null!!!!");
            } else {
                TinkerLog.e(TAG, "patch dex file md5 is mismatch: %s", mismatchPath);
                tinker.getLoadReporter().onLoadFileMd5Mismatch(new File(mismatchPath), ShareConstants.TYPE_DEX);
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_REWRITE_PATCH_INFO_FAIL:
            TinkerLog.i(TAG, "rewrite patch info file corrupted");
            tinker.getLoadReporter().onLoadPatchInfoCorrupted(oldVersion, newVersion, patchInfoFile);
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_RESOURCE_DIRECTORY_NOT_EXIST:
            if (patchVersionDirectory != null) {
                TinkerLog.e(TAG, "patch resource file directory not found:%s", resourceDirectory.getAbsolutePath());
                tinker.getLoadReporter().onLoadFileNotFound(resourceDirectory, ShareConstants.TYPE_RESOURCE, true);
            } else {
                //should be not here
                TinkerLog.e(TAG, "patch resource file directory not found, warning why the path is null!!!!");
                throw new TinkerRuntimeException("patch resource file directory not found, warning why the path is null!!!!");
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_RESOURCE_FILE_NOT_EXIST:
            if (patchVersionDirectory != null) {
                TinkerLog.e(TAG, "patch resource file not found:%s", resourceFile.getAbsolutePath());
                tinker.getLoadReporter().onLoadFileNotFound(resourceFile, ShareConstants.TYPE_RESOURCE, false);
            } else {
                //should be not here
                TinkerLog.e(TAG, "patch resource file not found, warning why the path is null!!!!");
                throw new TinkerRuntimeException("patch resource file not found, warning why the path is null!!!!");
            }
            break;
        case ShareConstants.ERROR_LOAD_PATCH_VERSION_RESOURCE_MD5_MISMATCH:
            if (resourceFile == null) {
                TinkerLog.e(TAG, "resource file md5 mismatch, but patch resource file not found!");
                throw new TinkerRuntimeException("resource file md5 mismatch, but patch resource file not found!");
            }
            TinkerLog.e(TAG, "patch resource file md5 is mismatch: %s", resourceFile.getAbsolutePath());
            tinker.getLoadReporter().onLoadFileMd5Mismatch(resourceFile, ShareConstants.TYPE_RESOURCE);
            break;
        case ShareConstants.ERROR_LOAD_OK:
            TinkerLog.i(TAG, "oh yeah, tinker load all success");
            tinker.setTinkerLoaded(true);
            //get load dex
            dexes = ShareIntentUtil.getIntentPatchDexPaths(intentResult);
            libs = ShareIntentUtil.getIntentPatchLibsPaths(intentResult);
            packageConfig = ShareIntentUtil.getIntentPackageConfig(intentResult);
            if (isMainProcess && versionChanged) {
                //change the old version to new
                tinker.getLoadReporter().onLoadPatchVersionChanged(oldVersion, newVersion, patchDirectory, patchVersionDirectory.getName());
            }
            return true;
    }
    return false;
}
Also used : SharePatchInfo(com.tencent.tinker.loader.shareutil.SharePatchInfo) TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) File(java.io.File)

Example 2 with SharePatchInfo

use of com.tencent.tinker.loader.shareutil.SharePatchInfo in project tinker by Tencent.

the class UpgradePatch method tryPatch.

@Override
public boolean tryPatch(Context context, String tempPatchPath, PatchResult patchResult) {
    Tinker manager = Tinker.with(context);
    final File patchFile = new File(tempPatchPath);
    if (!manager.isTinkerEnabled() || !ShareTinkerInternals.isTinkerEnableWithSharedPreferences(context)) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:patch is disabled, just return");
        return false;
    }
    if (!SharePatchFileUtil.isLegalFile(patchFile)) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:patch file is not found, just return");
        return false;
    }
    //check the signature, we should create a new checker
    ShareSecurityCheck signatureCheck = new ShareSecurityCheck(context);
    int returnCode = ShareTinkerInternals.checkTinkerPackage(context, manager.getTinkerFlags(), patchFile, signatureCheck);
    if (returnCode != ShareConstants.ERROR_PACKAGE_CHECK_OK) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:onPatchPackageCheckFail");
        manager.getPatchReporter().onPatchPackageCheckFail(patchFile, returnCode);
        return false;
    }
    //it is a new patch, so we should not find a exist
    SharePatchInfo oldInfo = manager.getTinkerLoadResultIfPresent().patchInfo;
    String patchMd5 = SharePatchFileUtil.getMD5(patchFile);
    if (patchMd5 == null) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:patch md5 is null, just return");
        return false;
    }
    //use md5 as version
    patchResult.patchVersion = patchMd5;
    SharePatchInfo newInfo;
    //already have patch
    if (oldInfo != null) {
        if (oldInfo.oldVersion == null || oldInfo.newVersion == null) {
            TinkerLog.e(TAG, "UpgradePatch tryPatch:onPatchInfoCorrupted");
            manager.getPatchReporter().onPatchInfoCorrupted(patchFile, oldInfo.oldVersion, oldInfo.newVersion);
            return false;
        }
        if (!SharePatchFileUtil.checkIfMd5Valid(patchMd5)) {
            TinkerLog.e(TAG, "UpgradePatch tryPatch:onPatchVersionCheckFail md5 %s is valid", patchMd5);
            manager.getPatchReporter().onPatchVersionCheckFail(patchFile, oldInfo, patchMd5);
            return false;
        }
        newInfo = new SharePatchInfo(oldInfo.oldVersion, patchMd5, Build.FINGERPRINT);
    } else {
        newInfo = new SharePatchInfo("", patchMd5, Build.FINGERPRINT);
    }
    //check ok, we can real recover a new patch
    final String patchDirectory = manager.getPatchDirectory().getAbsolutePath();
    TinkerLog.i(TAG, "UpgradePatch tryPatch:patchMd5:%s", patchMd5);
    final String patchName = SharePatchFileUtil.getPatchVersionDirectory(patchMd5);
    final String patchVersionDirectory = patchDirectory + "/" + patchName;
    TinkerLog.i(TAG, "UpgradePatch tryPatch:patchVersionDirectory:%s", patchVersionDirectory);
    //it is a new patch, we first delete if there is any files
    //don't delete dir for faster retry
    //        SharePatchFileUtil.deleteDir(patchVersionDirectory);
    //copy file
    File destPatchFile = new File(patchVersionDirectory + "/" + SharePatchFileUtil.getPatchVersionFile(patchMd5));
    try {
        // check md5 first
        if (!patchMd5.equals(SharePatchFileUtil.getMD5(destPatchFile))) {
            SharePatchFileUtil.copyFileUsingStream(patchFile, destPatchFile);
            TinkerLog.w(TAG, "UpgradePatch copy patch file, src file: %s size: %d, dest file: %s size:%d", patchFile.getAbsolutePath(), patchFile.length(), destPatchFile.getAbsolutePath(), destPatchFile.length());
        }
    } catch (IOException e) {
        //            e.printStackTrace();
        TinkerLog.e(TAG, "UpgradePatch tryPatch:copy patch file fail from %s to %s", patchFile.getPath(), destPatchFile.getPath());
        manager.getPatchReporter().onPatchTypeExtractFail(patchFile, destPatchFile, patchFile.getName(), ShareConstants.TYPE_PATCH_FILE);
        return false;
    }
    //we use destPatchFile instead of patchFile, because patchFile may be deleted during the patch process
    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;
    }
    // just warn
    if (!DexDiffPatchInternal.waitDexOptFile()) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, check dex opt file failed");
    }
    final File patchInfoFile = manager.getPatchInfoFile();
    if (!SharePatchInfo.rewritePatchInfoFileWithLock(patchInfoFile, newInfo, SharePatchFileUtil.getPatchInfoLockFile(patchDirectory))) {
        TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, rewrite patch info failed");
        manager.getPatchReporter().onPatchInfoCorrupted(patchFile, newInfo.oldVersion, newInfo.newVersion);
        return false;
    }
    TinkerLog.w(TAG, "UpgradePatch tryPatch: done, it is ok");
    return true;
}
Also used : SharePatchInfo(com.tencent.tinker.loader.shareutil.SharePatchInfo) ShareSecurityCheck(com.tencent.tinker.loader.shareutil.ShareSecurityCheck) IOException(java.io.IOException) Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

Example 3 with SharePatchInfo

use of com.tencent.tinker.loader.shareutil.SharePatchInfo in project tinker by Tencent.

the class DefaultLoadReporter method checkAndCleanPatch.

/**
     * other process may have installed old patch version,
     * if we try to clean patch, we should kill other process first
     */
public void checkAndCleanPatch() {
    Tinker tinker = Tinker.with(context);
    //only main process can load a new patch
    if (tinker.isMainProcess()) {
        TinkerLoadResult tinkerLoadResult = tinker.getTinkerLoadResultIfPresent();
        //if versionChange and the old patch version is not ""
        if (tinkerLoadResult.versionChanged) {
            SharePatchInfo sharePatchInfo = tinkerLoadResult.patchInfo;
            if (sharePatchInfo != null && !ShareTinkerInternals.isNullOrNil(sharePatchInfo.oldVersion)) {
                TinkerLog.w(TAG, "checkAndCleanPatch, oldVersion %s is not null, try kill all other process", sharePatchInfo.oldVersion);
                ShareTinkerInternals.killAllOtherProcess(context);
            }
        }
    }
    tinker.cleanPatch();
}
Also used : SharePatchInfo(com.tencent.tinker.loader.shareutil.SharePatchInfo) TinkerLoadResult(com.tencent.tinker.lib.tinker.TinkerLoadResult) Tinker(com.tencent.tinker.lib.tinker.Tinker)

Aggregations

SharePatchInfo (com.tencent.tinker.loader.shareutil.SharePatchInfo)3 Tinker (com.tencent.tinker.lib.tinker.Tinker)2 File (java.io.File)2 TinkerLoadResult (com.tencent.tinker.lib.tinker.TinkerLoadResult)1 TinkerRuntimeException (com.tencent.tinker.loader.TinkerRuntimeException)1 ShareSecurityCheck (com.tencent.tinker.loader.shareutil.ShareSecurityCheck)1 IOException (java.io.IOException)1