Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: build/android/rezip/RezipApk.java

Issue 608853005: Add rename and inflate support to the RezipApk tool. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't remove the rezip dependency. The bot needs it. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/gyp/finalize_apk.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 import java.io.File; 5 import java.io.File;
6 import java.io.FileOutputStream; 6 import java.io.FileOutputStream;
7 import java.io.IOException; 7 import java.io.IOException;
8 import java.io.InputStream; 8 import java.io.InputStream;
9 import java.io.OutputStream; 9 import java.io.OutputStream;
10 import java.util.ArrayList; 10 import java.util.ArrayList;
11 import java.util.Collections; 11 import java.util.Collections;
12 import java.util.Comparator; 12 import java.util.Comparator;
13 import java.util.Enumeration; 13 import java.util.Enumeration;
14 import java.util.HashMap;
14 import java.util.List; 15 import java.util.List;
16 import java.util.Map;
15 import java.util.jar.JarEntry; 17 import java.util.jar.JarEntry;
16 import java.util.jar.JarFile; 18 import java.util.jar.JarFile;
17 import java.util.jar.JarOutputStream; 19 import java.util.jar.JarOutputStream;
18 import java.util.regex.Pattern; 20 import java.util.regex.Pattern;
19 import java.util.zip.CRC32; 21 import java.util.zip.CRC32;
20 22
21 /** 23 /**
22 * Command line tool used to page align non-compressed libraries (*.so) in APK f iles. 24 * Command line tool used to build APKs which support loading the native code li brary
23 * Tool is designed so that running SignApk and/or zipalign on the resulting APK does not 25 * directly from the APK file. To construct the APK we rename the native library by
24 * break the page alignment. 26 * adding the prefix "crazy." to the filename. This is done to prevent the Andro id
27 * Package Manager from extracting the library. The native code must be page ali gned
28 * and uncompressed. The page alignment is implemented by adding a zero filled f ile
29 * in front of the the native code library. This tool is designed so that runnin g
30 * SignApk and/or zipalign on the resulting APK does not break the page alignmen t.
31 * This is achieved by outputing the filenames in the same canonical order used
32 * by SignApk and adding the same alignment fields added by zipalign.
25 */ 33 */
26 class RezipApk { 34 class RezipApk {
27 // Alignment to use for non-compressed files (must match zipalign). 35 // Alignment to use for non-compressed files (must match zipalign).
28 private static final int ALIGNMENT = 4; 36 private static final int ALIGNMENT = 4;
29 37
30 // Alignment to use for non-compressed *.so files 38 // Alignment to use for non-compressed *.so files
31 private static final int LIBRARY_ALIGNMENT = 4096; 39 private static final int LIBRARY_ALIGNMENT = 4096;
32 40
33 // Files matching this pattern are not copied to the output when adding alig nment. 41 // Files matching this pattern are not copied to the output when adding alig nment.
34 // When reordering and verifying the APK they are copied to the end of the f ile. 42 // When reordering and verifying the APK they are copied to the end of the f ile.
35 private static Pattern sMetaFilePattern = 43 private static Pattern sMetaFilePattern =
36 Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert ))|(" + 44 Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert ))|(" +
37 Pattern.quote(JarFile.MANIFEST_NAME) + ")$"); 45 Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
38 46
47 // Pattern for matching a shared library in the APK
48 private static Pattern sLibraryPattern = Pattern.compile("^lib/[^/]*/lib.*[. ]so$");
49 // Pattern for match the crazy linker in the APK
50 private static Pattern sCrazyLinkerPattern =
51 Pattern.compile("^lib/[^/]*/libchromium_android_linker.so$");
52 // Pattern for matching a crazy loaded shared library in the APK
53 private static Pattern sCrazyLibraryPattern =
54 Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$");
55
56 private static boolean isLibraryFilename(String filename) {
57 return sLibraryPattern.matcher(filename).matches() &&
58 !sCrazyLinkerPattern.matcher(filename).matches();
59 }
60
61 private static boolean isCrazyLibraryFilename(String filename) {
62 return sCrazyLibraryPattern.matcher(filename).matches();
63 }
64
65 private static String renameLibraryForCrazyLinker(String filename) {
66 int lastSlash = filename.lastIndexOf('/');
67 if (lastSlash == -1) {
68 return filename;
rmcilroy 2014/10/02 12:22:36 I think this should be an exceptino rather than ju
Anton 2014/10/02 14:43:54 I just removed it. This kind of defensive programm
69 }
70
71 // We rename the library, so that the Android Package Manager
72 // no longer extracts the library.
73 return filename.substring(0, lastSlash + 1) + "crazy." + filename.substr ing(lastSlash + 1);
74 }
75
39 /** 76 /**
40 * Wraps another output stream, counting the number of bytes written. 77 * Wraps another output stream, counting the number of bytes written.
41 */ 78 */
42 private static class CountingOutputStream extends OutputStream { 79 private static class CountingOutputStream extends OutputStream {
43 private long mCount = 0; 80 private long mCount = 0;
44 private OutputStream mOut; 81 private OutputStream mOut;
45 82
46 public CountingOutputStream(OutputStream out) { 83 public CountingOutputStream(OutputStream out) {
47 this.mOut = out; 84 this.mOut = out;
48 } 85 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 if (o1Matches != o2Matches) { 121 if (o1Matches != o2Matches) {
85 return o1Matches ? 1 : -1; 122 return o1Matches ? 1 : -1;
86 } else { 123 } else {
87 return o1.compareTo(o2); 124 return o1.compareTo(o2);
88 } 125 }
89 } 126 }
90 } 127 }
91 128
92 // Build an ordered list of filenames. Using the same deterministic ordering used 129 // Build an ordered list of filenames. Using the same deterministic ordering used
93 // by SignApk. If omitMetaFiles is true do not include the META-INF files. 130 // by SignApk. If omitMetaFiles is true do not include the META-INF files.
94 private static List<String> orderFilenames(JarFile jar, boolean omitMetaFile s) { 131 // Note we are sorting based on the output filenames (which maybe renamed), but
95 List<String> names = new ArrayList<String>(); 132 // we are returning the input filenames.
133 private static List<String> orderFilenames(
rmcilroy 2014/10/02 12:22:36 nit - rename to getOutputFileOrder()
Anton 2014/10/02 14:43:54 Done. Now getOutputFileOrderEntries() as it now re
134 JarFile jar, boolean omitMetaFiles, boolean rename) {
rmcilroy 2014/10/02 12:22:36 alignment...
Anton 2014/10/02 14:43:54 Done.
135 List<String> outNames = new ArrayList<String>();
136 Map<String, String> renameMap = new HashMap<String, String>();
96 for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) { 137 for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
97 JarEntry entry = e.nextElement(); 138 JarEntry entry = e.nextElement();
98 if (entry.isDirectory()) { 139 if (entry.isDirectory()) {
99 continue; 140 continue;
100 } 141 }
101 if (omitMetaFiles && 142 if (omitMetaFiles &&
102 sMetaFilePattern.matcher(entry.getName()).matches()) { 143 sMetaFilePattern.matcher(entry.getName()).matches()) {
103 continue; 144 continue;
104 } 145 }
105 names.add(entry.getName()); 146 String inName = entry.getName();
147 String outName = inName;
148 if (rename && entry.getSize() > 0 && isLibraryFilename(inName)) {
149 outName = renameLibraryForCrazyLinker(inName);
150 renameMap.put(outName, inName);
151 }
152 outNames.add(outName);
rmcilroy 2014/10/02 12:22:36 Could you not do this in the Comparator (e.g., com
Anton 2014/10/02 14:43:54 I have done this, but I don't know whether you rea
rmcilroy 2014/10/02 15:29:37 I think this is still better, thanks.
106 } 153 }
107 154
108 // We sort the input entries by name. When present META-INF files 155 // We sort the input entries by name. When present META-INF files
109 // are sorted to the end. 156 // are sorted to the end.
110 Collections.sort(names, new FilenameComparator()); 157 Collections.sort(outNames, new FilenameComparator());
111 return names; 158
159 if (!rename || renameMap.isEmpty()) {
160 return outNames;
161 }
162
163 // Return the input filenames names.
164 List<String> inNames = new ArrayList<String>();
165 for (String outName : outNames) {
166 String inName = renameMap.get(outName);
167 if (inName == null) {
168 // Not renamed.
169 inName = outName;
170 }
171 inNames.add(inName);
172 }
173 return inNames;
112 } 174 }
113 175
114 /** 176 /**
115 * Add a zero filled alignment file at this point in the zip file, 177 * Add a zero filled alignment file at this point in the zip file,
116 * The added file will be added before |name| and after |prevName|. 178 * The added file will be added before |name| and after |prevName|.
117 * The size of the alignment file is such that the location of the 179 * The size of the alignment file is such that the location of the
118 * file |name| will be on a LIBRARY_ALIGNMENT boundary. 180 * file |name| will be on a LIBRARY_ALIGNMENT boundary.
119 * 181 *
120 * Note this arrangement is devised so that running SignApk and/or zipalign on the resulting 182 * Note this arrangement is devised so that running SignApk and/or zipalign on the resulting
121 * file will not alter the alignment. 183 * file will not alter the alignment.
(...skipping 19 matching lines...) Expand all
141 return; 203 return;
142 } 204 }
143 205
144 // Check that there is not another file between the library and the 206 // Check that there is not another file between the library and the
145 // alignment file. 207 // alignment file.
146 String alignName = name.substring(0, name.length() - 2) + "align"; 208 String alignName = name.substring(0, name.length() - 2) + "align";
147 if (prevName != null && prevName.compareTo(alignName) >= 0) { 209 if (prevName != null && prevName.compareTo(alignName) >= 0) {
148 throw new UnsupportedOperationException( 210 throw new UnsupportedOperationException(
149 "Unable to insert alignment file, because there is " 211 "Unable to insert alignment file, because there is "
150 + "another file in front of the file to be aligned. " 212 + "another file in front of the file to be aligned. "
151 + "Other file: " + prevName + " Alignment file: " + alignName); 213 + "Other file: " + prevName + " Alignment file: " + alignName
214 + " file: " + name);
152 } 215 }
153 216
154 // Compute the size of the alignment file header. 217 // Compute the size of the alignment file header.
155 headerSize = JarFile.LOCHDR + alignName.length(); 218 headerSize = JarFile.LOCHDR + alignName.length();
156 // We are going to add an alignment file of type STORED. This file 219 // We are going to add an alignment file of type STORED. This file
157 // will itself induce a zipalign alignment adjustment. 220 // will itself induce a zipalign alignment adjustment.
158 int extraNeeded = 221 int extraNeeded =
159 (ALIGNMENT - (int) ((offset + headerSize) % ALIGNMENT)) % ALIGNM ENT; 222 (ALIGNMENT - (int) ((offset + headerSize) % ALIGNMENT)) % ALIGNM ENT;
160 headerSize += extraNeeded; 223 headerSize += extraNeeded;
161 224
(...skipping 18 matching lines...) Expand all
180 alignEntry.setExtra(new byte[extraNeeded]); 243 alignEntry.setExtra(new byte[extraNeeded]);
181 } 244 }
182 245
183 // Output the alignment file. 246 // Output the alignment file.
184 out.putNextEntry(alignEntry); 247 out.putNextEntry(alignEntry);
185 out.write(zeroBuffer); 248 out.write(zeroBuffer);
186 out.closeEntry(); 249 out.closeEntry();
187 out.flush(); 250 out.flush();
188 } 251 }
189 252
253 // Make a JarEntry for the output file which corresponds to the input
254 // file. The output file will be called |name|. The output file will always
255 // be uncompressed (STORED). If the input is not STORED it is necessary to i nflate
256 // it to compute the CRC and size of the output entry.
257 private static JarEntry makeStoredEntry(String name, JarEntry inEntry, JarFi le in)
258 throws IOException {
259 JarEntry outEntry = new JarEntry(name);
260 outEntry.setMethod(JarEntry.STORED);
261
262 if (inEntry.getMethod() == JarEntry.STORED) {
263 outEntry.setCrc(inEntry.getCrc());
264 outEntry.setSize(inEntry.getSize());
265 } else {
266 // We are inflating the file. We need to compute the CRC and size.
267 byte[] buffer = new byte[4096];
268 CRC32 crc = new CRC32();
269 int size = 0;
270 int num;
271 InputStream data = in.getInputStream(inEntry);
272 while ((num = data.read(buffer)) > 0) {
273 crc.update(buffer, 0, num);
274 size += num;
275 }
276 data.close();
277 outEntry.setCrc(crc.getValue());
278 outEntry.setSize(size);
279 }
280 return outEntry;
281 }
282
190 /** 283 /**
191 * Copy the contents of the input APK file to the output APK file. Uncompres sed files 284 * Copy the contents of the input APK file to the output APK file. If |renam e| is
192 * will be aligned in the output stream. Uncompressed native code libraries (*.so) 285 * true then non-empty libraries (*.so) in the input will be renamed by pref ixing
193 * will be aligned on a page boundary. Page alignment is implemented by addi ng a 286 * "crazy.". This is done to prevent the Android Package Manager extracting the
194 * zero filled file, regular alignment is implemented by adding a zero fille d extra 287 * library. Note the crazy linker itself is not renamed, for bootstrapping r easons.
195 * field to the zip file header. Care is take so that the output generated i n the 288 * Empty libraries are not renamed (they are in the APK to workaround a bug where
196 * same way as SignApk. This is important so that running SignApk and zipali gn on 289 * the Android Package Manager fails to delete old versions when upgrading).
197 * the output does not break the page alignment. The archive may not contain a "*.apk" 290 * There must be exactly one "crazy" library in the output stream. The "craz y"
198 * as SignApk has special nested signing logic that we do not support. 291 * library will be uncompressed and page aligned in the output stream. Page
292 * alignment is implemented by adding a zero filled file, regular alignment is
293 * implemented by adding a zero filled extra field to the zip file header. I f
294 * |addAlignment| is true a page alignment file is added, otherwise the "cra zy"
295 * library must already be page aligned. Care is taken so that the output is generated
296 * in the same way as SignApk. This is important so that running SignApk and
297 * zipalign on the output does not break the page alignment. The archive may not
298 * contain a "*.apk" as SignApk has special nested signing logic that we do not
299 * support.
199 * 300 *
200 * @param in The input APK File. 301 * @param in The input APK File.
201 * @param out The output APK stream. 302 * @param out The output APK stream.
202 * @param countOut Counting output stream (to measure the current offset). 303 * @param countOut Counting output stream (to measure the current offset).
203 * @param addAlignment Whether to add the alignment file or just check. 304 * @param addAlignment Whether to add the alignment file or just check.
305 * @param rename Whether to rename libraries to be "crazy".
204 * 306 *
205 * @throws IOException if the output file can not be written. 307 * @throws IOException if the output file can not be written.
206 */ 308 */
207 private static void copyAndAlignFiles( 309 private static void rezip(
208 JarFile in, JarOutputStream out, CountingOutputStream countOut, 310 JarFile in, JarOutputStream out, CountingOutputStream countOut,
209 boolean addAlignment) throws IOException { 311 boolean addAlignment, boolean rename) throws IOException {
210 312
211 List<String> names = orderFilenames(in, addAlignment); 313 List<String> names = orderFilenames(in, addAlignment, rename);
212 long timestamp = System.currentTimeMillis(); 314 long timestamp = System.currentTimeMillis();
213 byte[] buffer = new byte[4096]; 315 byte[] buffer = new byte[4096];
214 boolean firstEntry = true; 316 boolean firstEntry = true;
215 String prevName = null; 317 String prevName = null;
318 int numCrazy = 0;
319 boolean isCrazy = false;
rmcilroy 2014/10/02 12:22:36 This should just be local to the loop I think.
Anton 2014/10/02 14:43:54 Done.
216 for (String name : names) { 320 for (String name : names) {
217 JarEntry inEntry = in.getJarEntry(name); 321 JarEntry inEntry = in.getJarEntry(name);
218 JarEntry outEntry = null; 322 JarEntry outEntry = null;
219 if (name.endsWith(".apk")) { 323 if (name.endsWith(".apk")) {
220 throw new UnsupportedOperationException( 324 throw new UnsupportedOperationException(
221 "Nested APKs are not supported: " + name); 325 "Nested APKs are not supported: " + name);
222 } 326 }
223 if (inEntry.getMethod() == JarEntry.STORED) { 327
328 // Rename files, if specied.
329 if (rename && isLibraryFilename(name) && inEntry.getSize() > 0) {
330 name = renameLibraryForCrazyLinker(name);
331 }
332
333 // Build the header.
334 isCrazy = isCrazyLibraryFilename(name);
335 if (isCrazy) {
336 // "crazy" libraries are alway output uncompressed (STORED).
337 outEntry = makeStoredEntry(name, inEntry, in);
338 numCrazy++;
339 if (numCrazy > 1) {
340 throw new UnsupportedOperationException(
341 "Found more than one library\n"
342 + "Multiple libraries are not supported for APKs tha t use "
343 + "'load_library_from_zip_file'.\n"
344 + "See crbug/388223.\n"
345 + "Note, check that your build is clean.\n"
346 + "An unclean build can incorrectly incorporate old "
347 + "libraries in the APK.");
348 }
349 } else if (inEntry.getMethod() == JarEntry.STORED) {
224 // Preserve the STORED method of the input entry. 350 // Preserve the STORED method of the input entry.
225 outEntry = new JarEntry(inEntry); 351 outEntry = new JarEntry(inEntry);
226 outEntry.setExtra(null); 352 outEntry.setExtra(null);
227 } else { 353 } else {
228 // Create a new entry so that the compressed len is recomputed. 354 // Create a new entry so that the compressed len is recomputed.
229 outEntry = new JarEntry(name); 355 outEntry = new JarEntry(name);
230 } 356 }
231 outEntry.setTime(timestamp); 357 outEntry.setTime(timestamp);
232 358
359 // Compute and add alignment
233 long offset = countOut.getCount(); 360 long offset = countOut.getCount();
234 if (firstEntry) { 361 if (firstEntry) {
235 // The first entry in a jar file has an extra field of 362 // The first entry in a jar file has an extra field of
236 // four bytes that you can't get rid of; any extra 363 // four bytes that you can't get rid of; any extra
237 // data you specify in the JarEntry is appended to 364 // data you specify in the JarEntry is appended to
238 // these forced four bytes. This is JAR_MAGIC in 365 // these forced four bytes. This is JAR_MAGIC in
239 // JarOutputStream; the bytes are 0xfeca0000. 366 // JarOutputStream; the bytes are 0xfeca0000.
240 firstEntry = false; 367 firstEntry = false;
241 offset += 4; 368 offset += 4;
242 } 369 }
243 if (inEntry.getMethod() == JarEntry.STORED) { 370 if (outEntry.getMethod() == JarEntry.STORED) {
244 if (name.endsWith(".so")) { 371 if (isCrazy) {
245 if (addAlignment) { 372 if (addAlignment) {
246 addAlignmentFile(offset, timestamp, name, prevName, out) ; 373 addAlignmentFile(offset, timestamp, name, prevName, out) ;
247 } 374 }
248 // We check that we did indeed get to a page boundary. 375 // We check that we did indeed get to a page boundary.
249 offset = countOut.getCount() + JarFile.LOCHDR + name.length( ); 376 offset = countOut.getCount() + JarFile.LOCHDR + name.length( );
250 if ((offset % LIBRARY_ALIGNMENT) != 0) { 377 if ((offset % LIBRARY_ALIGNMENT) != 0) {
251 throw new AssertionError( 378 throw new AssertionError(
252 "Library was not page aligned when verifying page al ignment. " 379 "Library was not page aligned when verifying pag e alignment. "
253 + "Library name: " + name + " Expected alignment: " + LIBRARY_ALIGNMENT 380 + "Library name: " + name + " Expected alignment : "
254 + "Offset: " + offset + " Error: " + (offset % LIBRA RY_ALIGNMENT)); 381 + LIBRARY_ALIGNMENT + "Offset: " + offset + " Er ror: "
382 + (offset % LIBRARY_ALIGNMENT));
255 } 383 }
256 } else { 384 } else {
385 // This is equivalent to zipalign.
257 offset += JarFile.LOCHDR + name.length(); 386 offset += JarFile.LOCHDR + name.length();
258 int needed = (ALIGNMENT - (int) (offset % ALIGNMENT)) % ALIG NMENT; 387 int needed = (ALIGNMENT - (int) (offset % ALIGNMENT)) % ALIG NMENT;
259 if (needed != 0) { 388 if (needed != 0) {
260 outEntry.setExtra(new byte[needed]); 389 outEntry.setExtra(new byte[needed]);
261 } 390 }
262 } 391 }
263 } 392 }
264 out.putNextEntry(outEntry); 393 out.putNextEntry(outEntry);
265 394
395 // Copy the data from the input to the output
266 int num; 396 int num;
267 InputStream data = in.getInputStream(inEntry); 397 InputStream data = in.getInputStream(inEntry);
268 while ((num = data.read(buffer)) > 0) { 398 while ((num = data.read(buffer)) > 0) {
269 out.write(buffer, 0, num); 399 out.write(buffer, 0, num);
270 } 400 }
401 data.close();
271 out.closeEntry(); 402 out.closeEntry();
272 out.flush(); 403 out.flush();
273 prevName = name; 404 prevName = name;
274 } 405 }
406 if (numCrazy == 0) {
407 throw new AssertionError("There was no crazy library in the archive" );
408 }
275 } 409 }
276 410
277 private static void usage() { 411 private static void usage() {
278 System.err.println("Usage: prealignapk (addalignment|reorder) input.apk output.apk"); 412 System.err.println(
279 System.err.println(" addalignment - adds alignment file removes manifes t and signature"); 413 "Usage: prealignapk (addalignment|reorder) input.apk output.apk" );
280 System.err.println(" reorder - re-creates canonical ordering and c hecks alignment"); 414 System.err.println(
415 "\"crazy\" libraries are always inflated in the output");
416 System.err.println(
417 " renamealign - rename libraries with \"crazy.\" prefix and ad d alignment file");
418 System.err.println(
419 " align - add alignment file");
420 System.err.println(
421 " reorder - re-creates canonical ordering and checks align ment");
281 System.exit(2); 422 System.exit(2);
282 } 423 }
283 424
284 public static void main(String[] args) throws IOException { 425 public static void main(String[] args) throws IOException {
285 if (args.length != 3) usage(); 426 if (args.length != 3) usage();
286 427
287 boolean addAlignment = false; 428 boolean addAlignment = false;
288 if (args[0].equals("addalignment")) { 429 boolean rename = false;
430 if (args[0].equals("renamealign")) {
431 // Normal case. Before signing we rename the library and add an alig nment file.
289 addAlignment = true; 432 addAlignment = true;
433 rename = true;
434 } else if (args[0].equals("align")) {
435 // LGPL compliance case. Before signing, we add an alignment file to a
436 // reconstructed APK which already contains the "crazy" library.
437 addAlignment = true;
438 rename = false;
290 } else if (args[0].equals("reorder")) { 439 } else if (args[0].equals("reorder")) {
440 // Normal case. After jarsigning we write the file in the canonical order and check.
291 addAlignment = false; 441 addAlignment = false;
292 } else { 442 } else {
293 usage(); 443 usage();
294 } 444 }
295 445
296 String inputFilename = args[1]; 446 String inputFilename = args[1];
297 String outputFilename = args[2]; 447 String outputFilename = args[2];
298 448
299 JarFile inputJar = null; 449 JarFile inputJar = null;
300 FileOutputStream outputFile = null; 450 FileOutputStream outputFile = null;
301 451
302 try { 452 try {
303 inputJar = new JarFile(new File(inputFilename), true); 453 inputJar = new JarFile(new File(inputFilename), true);
304 outputFile = new FileOutputStream(outputFilename); 454 outputFile = new FileOutputStream(outputFilename);
305 455
306 CountingOutputStream outCount = new CountingOutputStream(outputFile) ; 456 CountingOutputStream outCount = new CountingOutputStream(outputFile) ;
307 JarOutputStream outputJar = new JarOutputStream(outCount); 457 JarOutputStream outputJar = new JarOutputStream(outCount);
308 458
309 // Match the compression level used by SignApk. 459 // Match the compression level used by SignApk.
310 outputJar.setLevel(9); 460 outputJar.setLevel(9);
311 461
312 copyAndAlignFiles(inputJar, outputJar, outCount, addAlignment); 462 rezip(inputJar, outputJar, outCount, addAlignment, rename);
313 outputJar.close(); 463 outputJar.close();
314 } finally { 464 } finally {
315 if (inputJar != null) inputJar.close(); 465 if (inputJar != null) inputJar.close();
316 if (outputFile != null) outputFile.close(); 466 if (outputFile != null) outputFile.close();
317 } 467 }
318 } 468 }
319 } 469 }
OLDNEW
« no previous file with comments | « build/android/gyp/finalize_apk.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698