PageRenderTime 75ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/atlas-gradle-plugin/atlas-plugin/src/main/java/com/taobao/android/builder/tasks/tpatch/TPatchTask.java

https://bitbucket.org/luo1291250810/atlas
Java | 536 lines | 246 code | 71 blank | 219 comment | 14 complexity | 9c3fa70df8191bb029d1e66c8fc984df MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, LGPL-3.0
  1. /*
  2. *
  3. *
  4. * Apache License
  5. * Version 2.0, January 2004
  6. * http://www.apache.org/licenses/
  7. *
  8. * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  9. *
  10. * 1. Definitions.
  11. *
  12. * "License" shall mean the terms and conditions for use, reproduction,
  13. * and distribution as defined by Sections 1 through 9 of this document.
  14. *
  15. * "Licensor" shall mean the copyright owner or entity authorized by
  16. * the copyright owner that is granting the License.
  17. *
  18. * "Legal Entity" shall mean the union of the acting entity and all
  19. * other entities that control, are controlled by, or are under common
  20. * control with that entity. For the purposes of this definition,
  21. * "control" means (i) the power, direct or indirect, to cause the
  22. * direction or management of such entity, whether by contract or
  23. * otherwise, or (ii) ownership of fifty percent (50%) or more of the
  24. * outstanding shares, or (iii) beneficial ownership of such entity.
  25. *
  26. * "You" (or "Your") shall mean an individual or Legal Entity
  27. * exercising permissions granted by this License.
  28. *
  29. * "Source" form shall mean the preferred form for making modifications,
  30. * including but not limited to software source code, documentation
  31. * source, and configuration files.
  32. *
  33. * "Object" form shall mean any form resulting from mechanical
  34. * transformation or translation of a Source form, including but
  35. * not limited to compiled object code, generated documentation,
  36. * and conversions to other media types.
  37. *
  38. * "Work" shall mean the work of authorship, whether in Source or
  39. * Object form, made available under the License, as indicated by a
  40. * copyright notice that is included in or attached to the work
  41. * (an example is provided in the Appendix below).
  42. *
  43. * "Derivative Works" shall mean any work, whether in Source or Object
  44. * form, that is based on (or derived from) the Work and for which the
  45. * editorial revisions, annotations, elaborations, or other modifications
  46. * represent, as a whole, an original work of authorship. For the purposes
  47. * of this License, Derivative Works shall not include works that remain
  48. * separable from, or merely link (or bind by name) to the interfaces of,
  49. * the Work and Derivative Works thereof.
  50. *
  51. * "Contribution" shall mean any work of authorship, including
  52. * the original version of the Work and any modifications or additions
  53. * to that Work or Derivative Works thereof, that is intentionally
  54. * submitted to Licensor for inclusion in the Work by the copyright owner
  55. * or by an individual or Legal Entity authorized to submit on behalf of
  56. * the copyright owner. For the purposes of this definition, "submitted"
  57. * means any form of electronic, verbal, or written communication sent
  58. * to the Licensor or its representatives, including but not limited to
  59. * communication on electronic mailing lists, source code control systems,
  60. * and issue tracking systems that are managed by, or on behalf of, the
  61. * Licensor for the purpose of discussing and improving the Work, but
  62. * excluding communication that is conspicuously marked or otherwise
  63. * designated in writing by the copyright owner as "Not a Contribution."
  64. *
  65. * "Contributor" shall mean Licensor and any individual or Legal Entity
  66. * on behalf of whom a Contribution has been received by Licensor and
  67. * subsequently incorporated within the Work.
  68. *
  69. * 2. Grant of Copyright License. Subject to the terms and conditions of
  70. * this License, each Contributor hereby grants to You a perpetual,
  71. * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  72. * copyright license to reproduce, prepare Derivative Works of,
  73. * publicly display, publicly perform, sublicense, and distribute the
  74. * Work and such Derivative Works in Source or Object form.
  75. *
  76. * 3. Grant of Patent License. Subject to the terms and conditions of
  77. * this License, each Contributor hereby grants to You a perpetual,
  78. * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  79. * (except as stated in this section) patent license to make, have made,
  80. * use, offer to sell, sell, import, and otherwise transfer the Work,
  81. * where such license applies only to those patent claims licensable
  82. * by such Contributor that are necessarily infringed by their
  83. * Contribution(s) alone or by combination of their Contribution(s)
  84. * with the Work to which such Contribution(s) was submitted. If You
  85. * institute patent litigation against any entity (including a
  86. * cross-claim or counterclaim in a lawsuit) alleging that the Work
  87. * or a Contribution incorporated within the Work constitutes direct
  88. * or contributory patent infringement, then any patent licenses
  89. * granted to You under this License for that Work shall terminate
  90. * as of the date such litigation is filed.
  91. *
  92. * 4. Redistribution. You may reproduce and distribute copies of the
  93. * Work or Derivative Works thereof in any medium, with or without
  94. * modifications, and in Source or Object form, provided that You
  95. * meet the following conditions:
  96. *
  97. * (a) You must give any other recipients of the Work or
  98. * Derivative Works a copy of this License; and
  99. *
  100. * (b) You must cause any modified files to carry prominent notices
  101. * stating that You changed the files; and
  102. *
  103. * (c) You must retain, in the Source form of any Derivative Works
  104. * that You distribute, all copyright, patent, trademark, and
  105. * attribution notices from the Source form of the Work,
  106. * excluding those notices that do not pertain to any part of
  107. * the Derivative Works; and
  108. *
  109. * (d) If the Work includes a "NOTICE" text file as part of its
  110. * distribution, then any Derivative Works that You distribute must
  111. * include a readable copy of the attribution notices contained
  112. * within such NOTICE file, excluding those notices that do not
  113. * pertain to any part of the Derivative Works, in at least one
  114. * of the following places: within a NOTICE text file distributed
  115. * as part of the Derivative Works; within the Source form or
  116. * documentation, if provided along with the Derivative Works; or,
  117. * within a display generated by the Derivative Works, if and
  118. * wherever such third-party notices normally appear. The contents
  119. * of the NOTICE file are for informational purposes only and
  120. * do not modify the License. You may add Your own attribution
  121. * notices within Derivative Works that You distribute, alongside
  122. * or as an addendum to the NOTICE text from the Work, provided
  123. * that such additional attribution notices cannot be construed
  124. * as modifying the License.
  125. *
  126. * You may add Your own copyright statement to Your modifications and
  127. * may provide additional or different license terms and conditions
  128. * for use, reproduction, or distribution of Your modifications, or
  129. * for any such Derivative Works as a whole, provided Your use,
  130. * reproduction, and distribution of the Work otherwise complies with
  131. * the conditions stated in this License.
  132. *
  133. * 5. Submission of Contributions. Unless You explicitly state otherwise,
  134. * any Contribution intentionally submitted for inclusion in the Work
  135. * by You to the Licensor shall be under the terms and conditions of
  136. * this License, without any additional terms or conditions.
  137. * Notwithstanding the above, nothing herein shall supersede or modify
  138. * the terms of any separate license agreement you may have executed
  139. * with Licensor regarding such Contributions.
  140. *
  141. * 6. Trademarks. This License does not grant permission to use the trade
  142. * names, trademarks, service marks, or product names of the Licensor,
  143. * except as required for reasonable and customary use in describing the
  144. * origin of the Work and reproducing the content of the NOTICE file.
  145. *
  146. * 7. Disclaimer of Warranty. Unless required by applicable law or
  147. * agreed to in writing, Licensor provides the Work (and each
  148. * Contributor provides its Contributions) on an "AS IS" BASIS,
  149. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  150. * implied, including, without limitation, any warranties or conditions
  151. * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  152. * PARTICULAR PURPOSE. You are solely responsible for determining the
  153. * appropriateness of using or redistributing the Work and assume any
  154. * risks associated with Your exercise of permissions under this License.
  155. *
  156. * 8. Limitation of Liability. In no event and under no legal theory,
  157. * whether in tort (including negligence), contract, or otherwise,
  158. * unless required by applicable law (such as deliberate and grossly
  159. * negligent acts) or agreed to in writing, shall any Contributor be
  160. * liable to You for damages, including any direct, indirect, special,
  161. * incidental, or consequential damages of any character arising as a
  162. * result of this License or out of the use or inability to use the
  163. * Work (including but not limited to damages for loss of goodwill,
  164. * work stoppage, computer failure or malfunction, or any and all
  165. * other commercial damages or losses), even if such Contributor
  166. * has been advised of the possibility of such damages.
  167. *
  168. * 9. Accepting Warranty or Additional Liability. While redistributing
  169. * the Work or Derivative Works thereof, You may choose to offer,
  170. * and charge a fee for, acceptance of support, warranty, indemnity,
  171. * or other liability obligations and/or rights consistent with this
  172. * License. However, in accepting such obligations, You may act only
  173. * on Your own behalf and on Your sole responsibility, not on behalf
  174. * of any other Contributor, and only if You agree to indemnify,
  175. * defend, and hold each Contributor harmless for any liability
  176. * incurred by, or claims asserted against, such Contributor by reason
  177. * of your accepting any such warranty or additional liability.
  178. *
  179. * END OF TERMS AND CONDITIONS
  180. *
  181. * APPENDIX: How to apply the Apache License to your work.
  182. *
  183. * To apply the Apache License to your work, attach the following
  184. * boilerplate notice, with the fields enclosed by brackets "[]"
  185. * replaced with your own identifying information. (Don't include
  186. * the brackets!) The text should be enclosed in the appropriate
  187. * comment syntax for the file format. We also recommend that a
  188. * file or class name and description of purpose be included on the
  189. * same "printed page" as the copyright notice for easier
  190. * identification within third-party archives.
  191. *
  192. * Copyright 2016 Alibaba Group
  193. *
  194. * Licensed under the Apache License, Version 2.0 (the "License");
  195. * you may not use this file except in compliance with the License.
  196. * You may obtain a copy of the License at
  197. *
  198. * http://www.apache.org/licenses/LICENSE-2.0
  199. *
  200. * Unless required by applicable law or agreed to in writing, software
  201. * distributed under the License is distributed on an "AS IS" BASIS,
  202. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  203. * See the License for the specific language governing permissions and
  204. * limitations under the License.
  205. *
  206. *
  207. */
  208. package com.taobao.android.builder.tasks.tpatch;
  209. import com.alibaba.fastjson.JSON;
  210. import com.android.build.gradle.internal.api.AppVariantContext;
  211. import com.android.build.gradle.internal.api.AppVariantOutputContext;
  212. import com.android.build.gradle.internal.scope.ConventionMappingHelper;
  213. import com.android.build.gradle.internal.tasks.BaseTask;
  214. import com.android.build.gradle.internal.variant.ApkVariantOutputData;
  215. import com.android.build.gradle.internal.variant.BaseVariantOutputData;
  216. import com.android.builder.signing.DefaultSigningConfig;
  217. import com.taobao.android.TPatchTool;
  218. import com.taobao.android.builder.AtlasBuildContext;
  219. import com.taobao.android.builder.extension.TBuildType;
  220. import com.taobao.android.builder.tasks.manager.MtlBaseTaskAction;
  221. import com.taobao.android.builder.tools.BuildHelper;
  222. import com.taobao.android.builder.tools.VersionUtils;
  223. import com.taobao.android.builder.tools.manifest.ManifestFileUtils;
  224. import com.taobao.android.builder.tools.update.UpdateInfo;
  225. import com.taobao.android.object.ApkFileList;
  226. import com.taobao.android.object.ArtifactBundleInfo;
  227. import com.taobao.android.object.BuildPatchInfos;
  228. import org.apache.commons.io.FileUtils;
  229. import org.apache.commons.lang.StringUtils;
  230. import org.dom4j.DocumentException;
  231. import org.gradle.api.tasks.Input;
  232. import org.gradle.api.tasks.OutputDirectory;
  233. import org.gradle.api.tasks.StopExecutionException;
  234. import org.gradle.api.tasks.TaskAction;
  235. import java.io.File;
  236. import java.io.IOException;
  237. import java.io.Serializable;
  238. import java.util.Set;
  239. import java.util.concurrent.Callable;
  240. /**
  241. * Andfix的patch的任务
  242. * Created by wuzhong
  243. */
  244. public class TPatchTask extends BaseTask {
  245. private TPatchContext patchContext;
  246. private DefaultSigningConfig signingConfig;
  247. private File outPatchFolder;
  248. @TaskAction
  249. public void doTPatch() throws Exception {
  250. patchContext = getPatchContext();
  251. signingConfig = getSigningConfig();
  252. outPatchFolder = getOutPatchFolder();
  253. // 获取容器版本
  254. String baseApkVersion = patchContext.getBaseVersionName();
  255. String newApkVersion = patchContext.versionName;
  256. File baseApk = patchContext.getBaseApk();
  257. File newApk = patchContext.diffApkFile;
  258. boolean retainMainBundleRes = true;
  259. if (null == newApk || !newApk.exists()) {
  260. newApk = patchContext.newApk;
  261. retainMainBundleRes = false;
  262. }
  263. getLogger().info("BaseApk:" +
  264. baseApk +
  265. ",baseVersion:" +
  266. baseApkVersion +
  267. ",newApk:" +
  268. newApk +
  269. ",newApkVersion:" +
  270. newApkVersion);
  271. TPatchTool tPatchTool = new TPatchTool(baseApk,
  272. newApk,
  273. baseApkVersion,
  274. newApkVersion,
  275. patchContext.diffBundleDex);
  276. tPatchTool.setMainBundleName(patchContext.mainBundleName);
  277. if (StringUtils.isNotBlank(patchContext.excludeFiles)) {
  278. tPatchTool.setNotIncludeFiles(patchContext.excludeFiles.split(","));
  279. }
  280. tPatchTool.setRetainMainBundleRes(retainMainBundleRes);
  281. if (null != patchContext.artifactBundleInfos) {
  282. tPatchTool.setArtifactBundleInfos(patchContext.artifactBundleInfos);
  283. }
  284. tPatchTool.setBaseApkFileList(patchContext.getBaseApkFiles());
  285. tPatchTool.setNewApkFileList(patchContext.getNewApkFiles());
  286. tPatchTool.setLogger(getILogger());
  287. tPatchTool.setOnlyIncludeModifyBundle(patchContext.onlyBuildModifyAwb);
  288. tPatchTool.setNoPatchBundles(patchContext.notPatchBundles);
  289. ApkFileList apkFileList = AtlasBuildContext.finalApkFileList;
  290. try {
  291. tPatchTool.setDexcode(apkFileList.getMainBundle().get("classes.dex"));
  292. FileUtils.writeStringToFile(new File(getOutPatchFolder(), "tpatch-bundles.json"),
  293. JSON.toJSONString(patchContext.artifactBundleInfos));
  294. getLogger().info("start to do patch");
  295. tPatchTool.doPatch(outPatchFolder,
  296. true,
  297. new File(getOutPatchFolder(), "patchs.json"),
  298. StringUtils.isNotEmpty(patchContext.tpatchHistoryUrl),
  299. patchContext.tpatchHistoryUrl,
  300. patchContext.appSignName);
  301. getLogger().info("finish do patch");
  302. File patchJson = new File(getOutPatchFolder(), "patchs.json");
  303. File updateJson = new File(getOutPatchFolder(), "update.json");
  304. String json = FileUtils.readFileToString(patchJson);
  305. BuildPatchInfos patchInfos = JSON.parseObject(json, BuildPatchInfos.class);
  306. UpdateInfo updateInfo = new UpdateInfo(patchInfos);
  307. FileUtils.writeStringToFile(updateJson, JSON.toJSONString(updateInfo, true));
  308. } catch (Exception e) {
  309. e.printStackTrace();
  310. throw new StopExecutionException(e.getMessage());
  311. }
  312. File baseVesrionApk = new File(patchContext.newApk.getParentFile(),
  313. patchContext.newApk.getName()
  314. .replace(".apk", "-" + baseApkVersion + ".apk"));
  315. FileUtils.copyFile(patchContext.getBaseApk(), baseVesrionApk);
  316. if (patchContext.writeBuildInfo && StringUtils.isNotEmpty(patchContext.buildId)) {
  317. File buildFile = new File(getOutPatchFolder(), "build.txt");
  318. FileUtils.writeStringToFile(buildFile,
  319. patchContext.buildId +
  320. "," +
  321. patchContext.versionName +
  322. "," +
  323. apkFileList.getMainBundle().get("classes.dex"));
  324. if (buildFile != null && buildFile.exists()) {
  325. getLogger().debug("write build to apk!");
  326. BuildHelper.writeFileToApk(buildFile, baseVesrionApk, "assets/build.txt");
  327. }
  328. BuildHelper.reSign(baseVesrionApk, signingConfig);
  329. }
  330. FileUtils.forceDelete(patchContext.newApk);
  331. }
  332. @OutputDirectory
  333. public File getOutPatchFolder() {
  334. return outPatchFolder;
  335. }
  336. public DefaultSigningConfig getSigningConfig() {
  337. return signingConfig;
  338. }
  339. @Input
  340. public TPatchContext getPatchContext() {
  341. return patchContext;
  342. }
  343. public static class ConfigAction extends MtlBaseTaskAction<TPatchTask> {
  344. private AppVariantContext appVariantContext;
  345. public ConfigAction(AppVariantContext appVariantContext,
  346. BaseVariantOutputData baseVariantOutputData) {
  347. super(appVariantContext, baseVariantOutputData);
  348. this.appVariantContext = appVariantContext;
  349. }
  350. @Override
  351. public String getName() {
  352. return scope.getTaskName("Create", "TPatch");
  353. }
  354. @Override
  355. public Class<TPatchTask> getType() {
  356. return TPatchTask.class;
  357. }
  358. @Override
  359. public void execute(TPatchTask tPatchTask) {
  360. super.execute(tPatchTask);
  361. final TBuildType tBuildType = appVariantContext.getBuildType();
  362. if (null == tBuildType ||
  363. null == tBuildType.getPatchConfig() ||
  364. !tBuildType.getPatchConfig().isCreateTPatch()) {
  365. tPatchTask.setEnabled(false);
  366. return;
  367. }
  368. final ApkVariantOutputData variantOutputData = (ApkVariantOutputData) scope.getVariantOutputData();
  369. ConventionMappingHelper.map(tPatchTask, "outPatchFolder", new Callable<File>() {
  370. @Override
  371. public File call() throws Exception {
  372. return getAppVariantOutputContext().getTPatchFolder();
  373. }
  374. });
  375. ConventionMappingHelper.map(tPatchTask,
  376. "signingConfig",
  377. new Callable<DefaultSigningConfig>() {
  378. @Override
  379. public DefaultSigningConfig call() throws Exception {
  380. return appVariantContext.getSigningConfig();
  381. }
  382. });
  383. ConventionMappingHelper.map(tPatchTask, "patchContext", new Callable<TPatchContext>() {
  384. @Override
  385. public TPatchContext call() throws Exception {
  386. TPatchContext tPatchContext = new TPatchContext();
  387. AppVariantOutputContext appVariantOutputContext = getAppVariantOutputContext();
  388. tPatchContext.diffApkFile = appVariantOutputContext.getDiffApk();
  389. tPatchContext.newApk = appVariantOutputContext.getApkOutputFile(true);
  390. tPatchContext.outPatchFolder = appVariantOutputContext.getTPatchFolder();
  391. tPatchContext.manifestFile = variantOutputData.manifestProcessorTask.getManifestOutputFile();
  392. tPatchContext.apExplodeFolder = appVariantContext.apContext.getApExploredFolder();
  393. tPatchContext.versionName = VersionUtils.getVersionName((ApkVariantOutputData) baseVariantOutputData,
  394. variantOutputData.manifestProcessorTask
  395. .getManifestOutputFile());
  396. tPatchContext.tpatchHistoryUrl = tBuildType.getPatchConfig()
  397. .getTpatchHistoryUrl();
  398. tPatchContext.onlyBuildModifyAwb = tBuildType.getPatchConfig()
  399. .getOnlyBuildModifyAwb();
  400. tPatchContext.artifactBundleInfos = appVariantOutputContext.artifactBundleInfos;
  401. tPatchContext.notPatchBundles = tBuildType.getPatchConfig().getNoPatchBundles();
  402. tPatchContext.mainBundleName = tBuildType.getPatchConfig()
  403. .getTpatchMainBundleName();
  404. tPatchContext.excludeFiles = tBuildType.getPatchConfig()
  405. .gettPatchNotIncludeFiles()
  406. .isEmpty() ? "" : StringUtils.join(tBuildType.getPatchConfig()
  407. .gettPatchNotIncludeFiles(),
  408. ",");
  409. tPatchContext.buildId = tBuildType.getPatchConfig().getBuildId();
  410. tPatchContext.writeBuildInfo = tBuildType.getPatchConfig()
  411. .isTpatchWriteBuildInfo();
  412. tPatchContext.diffBundleDex = tBuildType.getPatchConfig()
  413. .isOnlyIncrementInAwb();
  414. tPatchContext.appSignName = tBuildType.getPatchConfig().getAppSignName();
  415. return tPatchContext;
  416. }
  417. });
  418. }
  419. }
  420. public static class TPatchContext implements Serializable {
  421. public File diffApkFile;
  422. public File newApk;
  423. public File outPatchFolder;
  424. public File manifestFile;
  425. public File apExplodeFolder;
  426. public String versionName;
  427. public String tpatchHistoryUrl;
  428. public Boolean onlyBuildModifyAwb;
  429. public String notPatchBundles;
  430. public String buildId;
  431. public boolean writeBuildInfo;
  432. /**
  433. * 判断是否对bundle的dex文件进行diff操作
  434. */
  435. public boolean diffBundleDex;
  436. // @Parameter(property = "android.patch.mainBundleName", defaultValue = "libcom_taobao_maindex")
  437. public String mainBundleName;
  438. public Set<ArtifactBundleInfo> artifactBundleInfos;
  439. /**
  440. * patch需要排除的目录
  441. */
  442. public String excludeFiles;
  443. public String appSignName;
  444. public static final String APK_FILE_MD5 = "apk-files.txt";
  445. public File getNewApkFiles() throws IOException {
  446. ApkFileList apkFileList = AtlasBuildContext.finalApkFileList;
  447. File apkFiles = new File(outPatchFolder.getParentFile(), APK_FILE_MD5);
  448. FileUtils.writeStringToFile(apkFiles, JSON.toJSONString(apkFileList));
  449. return apkFiles;
  450. }
  451. public File getBaseApk() {
  452. File apkFile = new File(apExplodeFolder, "android.apk");
  453. return apkFile;
  454. }
  455. public File getBaseApkFiles() {
  456. File apkFileList = new File(apExplodeFolder, APK_FILE_MD5);
  457. return apkFileList;
  458. }
  459. public String getBaseVersionName() throws IOException, DocumentException {
  460. File apManifestFile = new File(apExplodeFolder, "AndroidManifest.xml");
  461. String baseVersionName = ManifestFileUtils.getVersionName(apManifestFile);
  462. return baseVersionName;
  463. }
  464. }
  465. }