Search in sources :

Example 1 with ShareSecurityCheck

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

the class TinkerLoader method tryLoadPatchFilesInternal.

private void tryLoadPatchFilesInternal(TinkerApplication app, int tinkerFlag, boolean tinkerLoadVerifyFlag, Intent resultIntent) {
    if (!ShareTinkerInternals.isTinkerEnabled(tinkerFlag)) {
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_DISABLE);
        return;
    }
    //tinker
    File patchDirectoryFile = SharePatchFileUtil.getPatchDirectory(app);
    if (patchDirectoryFile == null) {
        Log.w(TAG, "tryLoadPatchFiles:getPatchDirectory == null");
        //treat as not exist
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_DIRECTORY_NOT_EXIST);
        return;
    }
    String patchDirectoryPath = patchDirectoryFile.getAbsolutePath();
    //check patch directory whether exist
    if (!patchDirectoryFile.exists()) {
        Log.w(TAG, "tryLoadPatchFiles:patch dir not exist:" + patchDirectoryPath);
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_DIRECTORY_NOT_EXIST);
        return;
    }
    //tinker/patch.info
    File patchInfoFile = SharePatchFileUtil.getPatchInfoFile(patchDirectoryPath);
    //check patch info file whether exist
    if (!patchInfoFile.exists()) {
        Log.w(TAG, "tryLoadPatchFiles:patch info not exist:" + patchInfoFile.getAbsolutePath());
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_INFO_NOT_EXIST);
        return;
    }
    //old = 641e634c5b8f1649c75caf73794acbdf
    //new = 2c150d8560334966952678930ba67fa8
    File patchInfoLockFile = SharePatchFileUtil.getPatchInfoLockFile(patchDirectoryPath);
    patchInfo = SharePatchInfo.readAndCheckPropertyWithLock(patchInfoFile, patchInfoLockFile);
    if (patchInfo == null) {
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_INFO_CORRUPTED);
        return;
    }
    String oldVersion = patchInfo.oldVersion;
    String newVersion = patchInfo.newVersion;
    if (oldVersion == null || newVersion == null) {
        //it is nice to clean patch
        Log.w(TAG, "tryLoadPatchFiles:onPatchInfoCorrupted");
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_INFO_CORRUPTED);
        return;
    }
    resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_OLD_VERSION, oldVersion);
    resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_NEW_VERSION, newVersion);
    boolean mainProcess = ShareTinkerInternals.isInMainProcess(app);
    boolean versionChanged = !(oldVersion.equals(newVersion));
    String version = oldVersion;
    if (versionChanged && mainProcess) {
        version = newVersion;
    }
    if (ShareTinkerInternals.isNullOrNil(version)) {
        Log.w(TAG, "tryLoadPatchFiles:version is blank, wait main process to restart");
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_INFO_BLANK);
        return;
    }
    //patch-641e634c
    String patchName = SharePatchFileUtil.getPatchVersionDirectory(version);
    if (patchName == null) {
        Log.w(TAG, "tryLoadPatchFiles:patchName is null");
        //we may delete patch info file
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_VERSION_DIRECTORY_NOT_EXIST);
        return;
    }
    //tinker/patch.info/patch-641e634c
    String patchVersionDirectory = patchDirectoryPath + "/" + patchName;
    File patchVersionDirectoryFile = new File(patchVersionDirectory);
    if (!patchVersionDirectoryFile.exists()) {
        Log.w(TAG, "tryLoadPatchFiles:onPatchVersionDirectoryNotFound");
        //we may delete patch info file
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_VERSION_DIRECTORY_NOT_EXIST);
        return;
    }
    //tinker/patch.info/patch-641e634c/patch-641e634c.apk
    File patchVersionFile = new File(patchVersionDirectoryFile.getAbsolutePath(), SharePatchFileUtil.getPatchVersionFile(version));
    if (!SharePatchFileUtil.isLegalFile(patchVersionFile)) {
        Log.w(TAG, "tryLoadPatchFiles:onPatchVersionFileNotFound");
        //we may delete patch info file
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_VERSION_FILE_NOT_EXIST);
        return;
    }
    ShareSecurityCheck securityCheck = new ShareSecurityCheck(app);
    int returnCode = ShareTinkerInternals.checkTinkerPackage(app, tinkerFlag, patchVersionFile, securityCheck);
    if (returnCode != ShareConstants.ERROR_PACKAGE_CHECK_OK) {
        Log.w(TAG, "tryLoadPatchFiles:checkTinkerPackage");
        resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_PACKAGE_PATCH_CHECK, returnCode);
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_PACKAGE_CHECK_FAIL);
        return;
    }
    resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_PACKAGE_CONFIG, securityCheck.getPackagePropertiesIfPresent());
    final boolean isEnabledForDex = ShareTinkerInternals.isTinkerEnabledForDex(tinkerFlag);
    if (isEnabledForDex) {
        //tinker/patch.info/patch-641e634c/dex
        boolean dexCheck = TinkerDexLoader.checkComplete(patchVersionDirectory, securityCheck, resultIntent);
        if (!dexCheck) {
            //file not found, do not load patch
            Log.w(TAG, "tryLoadPatchFiles:dex check fail");
            return;
        }
    }
    final boolean isEnabledForNativeLib = ShareTinkerInternals.isTinkerEnabledForNativeLib(tinkerFlag);
    if (isEnabledForNativeLib) {
        //tinker/patch.info/patch-641e634c/lib
        boolean libCheck = TinkerSoLoader.checkComplete(patchVersionDirectory, securityCheck, resultIntent);
        if (!libCheck) {
            //file not found, do not load patch
            Log.w(TAG, "tryLoadPatchFiles:native lib check fail");
            return;
        }
    }
    //check resource
    final boolean isEnabledForResource = ShareTinkerInternals.isTinkerEnabledForResource(tinkerFlag);
    Log.w(TAG, "tryLoadPatchFiles:isEnabledForResource:" + isEnabledForResource);
    if (isEnabledForResource) {
        boolean resourceCheck = TinkerResourceLoader.checkComplete(app, patchVersionDirectory, securityCheck, resultIntent);
        if (!resourceCheck) {
            //file not found, do not load patch
            Log.w(TAG, "tryLoadPatchFiles:resource check fail");
            return;
        }
    }
    //only work for art platform oat
    boolean isSystemOTA = ShareTinkerInternals.isVmArt() && ShareTinkerInternals.isSystemOTA(patchInfo.fingerPrint);
    resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_SYSTEM_OTA, isSystemOTA);
    //we should first try rewrite patch info file, if there is a error, we can't load jar
    if (isSystemOTA || (mainProcess && versionChanged)) {
        patchInfo.oldVersion = version;
        //update old version to new
        if (!SharePatchInfo.rewritePatchInfoFileWithLock(patchInfoFile, patchInfo, patchInfoLockFile)) {
            ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_REWRITE_PATCH_INFO_FAIL);
            Log.w(TAG, "tryLoadPatchFiles:onReWritePatchInfoCorrupted");
            return;
        }
    }
    if (!checkSafeModeCount(app)) {
        resultIntent.putExtra(ShareIntentUtil.INTENT_PATCH_EXCEPTION, new TinkerRuntimeException("checkSafeModeCount fail"));
        ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_UNCAUGHT_EXCEPTION);
        Log.w(TAG, "tryLoadPatchFiles:checkSafeModeCount fail");
        return;
    }
    //now we can load patch jar
    if (isEnabledForDex) {
        boolean loadTinkerJars = TinkerDexLoader.loadTinkerJars(app, tinkerLoadVerifyFlag, patchVersionDirectory, resultIntent, isSystemOTA);
        if (!loadTinkerJars) {
            Log.w(TAG, "tryLoadPatchFiles:onPatchLoadDexesFail");
            return;
        }
    }
    //now we can load patch resource
    if (isEnabledForResource) {
        boolean loadTinkerResources = TinkerResourceLoader.loadTinkerResources(app, tinkerLoadVerifyFlag, patchVersionDirectory, resultIntent);
        if (!loadTinkerResources) {
            Log.w(TAG, "tryLoadPatchFiles:onPatchLoadResourcesFail");
            return;
        }
    }
    //all is ok!
    ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_OK);
    Log.i(TAG, "tryLoadPatchFiles: load end, ok!");
    return;
}
Also used : ShareSecurityCheck(com.tencent.tinker.loader.shareutil.ShareSecurityCheck) File(java.io.File)

Example 2 with ShareSecurityCheck

use of com.tencent.tinker.loader.shareutil.ShareSecurityCheck 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)

Aggregations

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