Commit graph

24 commits

Author SHA1 Message Date
Yifan Hong
bb2658d5e2 releasetools: Really allow removing partitions
- Add hashtree_info to EmptyImage so that BlockDifference.Compute()
can accept EmptyImage() as target image, which is the case when
a partition is removed.

- BlockDifference also checks source_info_dict to determine
whether a partition is dynamic. When a partition is removed,
its name does not appear in target_info_dict.

- Add tests to ensure DynamicPartitionDifference() still works.

Test: DynamicPartitionDifferenceTest
Test: test_blockimgdiff

Change-Id: Iadb1db075f5dc344db6d5ade358c83b01231e443
2019-01-28 11:10:48 -08:00
Yifan Hong
45433e44dd Really support removing / adding partitions.
- When removing a partition, BlockDifference() object
will have tgt=EmptyImage(). Fix the asserts accordingly.
Also, BlockDifference object now allow tgt=None case.

- When adding a partition, BlockDifference() object
will have src=None. Fix the asserts accordingly.

Also, add unit tests to DynamicPartitionsDifference.

Test: create incremental OTA
Test: test_common.DynamicPartitionsDifferenceTest
Bug: 111801737

Change-Id: I3a35378ecf93111b8f44545cff6ae9696b6b4851
2019-01-18 17:09:33 -08:00
Tao Bao
65b94e92be releasetools: Add a common base class for unittests.
All the releasetools unittests extend the common base class of
test_utils.ReleaseToolsTestCase. Define tearDown() in the base class to
do the clean-up works.

Test: `pylint --rcfile=pylintrc test_*.py`
Test: `python -m unittest discover .`
Change-Id: I51775d964ef032dcdf3bb89c55e1a31371cde708
2018-10-11 23:01:09 -07:00
Tao Bao
986ee86854 releasetools: Move build_image.RunCommand into common.py.
build_image.RunCommand and common.Run are essentially doing the same
work, but with different interfaces and return values. This CL
consolidates them by moving build_image.RunCommand into common.py as
common.RunAndCheckOutput, with the former calling common.Run internally.

common.RunAndCheckOutput checks the exit code: it returns the output
string on success, or raises common.ExternalError otherwise.

Test: `m dist` with aosp_marlin-userdebug
Test: python -m unittest test_build_image
Test: python -m unittest test_common
Change-Id: I3cd0e9301c576572194618eba8dc00db06c3c35f
2018-10-10 18:13:24 -07:00
Tao Bao
410ad8bb92 releasetools: common.LoadInfoDict() takes a bool parameter for repacking.
It used to accept a non-None input_dir to indicate the need to
re-generate images (called from add_img_to_target_files.py). During that
flow, both of the two parameters redundantly refer to the same input
dir. This CL replaces the second parameter with a bool value instead.

Test: `python -m unittest test_common`
Test: `m dist` with aosp_taimen-userdebug
Test: `zip -d aosp_taimen-target_files-eng.zip IMAGES/\* &&
       add_img_to_target_files.py -a aosp_taimen-target_files-eng.zip`
Change-Id: I0a5a164366acb116407f94bb350872a3a0b207d1
2018-08-29 22:07:21 -07:00
Tao Bao
a57ab9f210 releasetools: Add test cases for common.LoadInfoDict().
Fixes: 113073663
Test: python -m unittest test_common
Change-Id: I352a2731849d175f94e0f23dd68b6cf28e554f64
2018-08-27 18:18:10 -07:00
Tao Bao
02a0859b3c releasetools: Support verifying AVB signed images with chained partitions.
For example, verify a target_files.zip that has system AVB-signed as a
chained partition.

  $ build/make/tools/releasetools/validate_target_files.py \
      signed-target_files-4904652.zip \
      --verity_key verifiedboot_pub.pem \
      --avb_system_key_path system_pub.pem

Note that verifiedboot_pub.pem should be the key (either public or
private) to verify vbmeta.img, and 'system_pub.pem' should be the key
(either public or private) for the chained partition of system.

testdata/testkey.key is the private key converted from
testdata/testkey.pk8 for testing purpose (`openssl pkcs8 -in
testdata/testkey.pk8 -inform DER -out testdata/testkey.key -nocrypt`).

Bug: 63706333
Test: python -m unittest test_common
Test: python -m unittest test_add_img_to_target_files
Test: `m dist` on aosp_walleye-userdebug; Run validate_target_files.py
      on the generated target_files.zip.
Test: Set up walleye with chained system partition; `m dist`; Run
      validate_target_files.py on the generated target_files.zip.
Change-Id: I38517ab39baf8a5bc1a6062fab2fe229b68e897d
2018-07-23 15:20:14 -07:00
Tao Bao
d3554e628f releasetools: Address two issues with system_root_image file map.
With system_root_image, e2fsdroid writes file map with extra leading
slashes in filenames (e.g. "//system/framework/am.jar"). This breaks the
detection of files with incomplete ranges, and thus fails the patch
generation. This CL addresses the issue by stripping out leading
slashes.

Additionally, non-/system files (e.g "//sbin/charger") are not packed
under SYSTEM/ in a target_files.zip, despite being part of system.img.
We need to look for these files under ROOT/ instead.

This CL also asserts the availability of all files listed on a file map,
to avoid silently missing other edge cases.

Bug: 80380658
Test: python -m unittest test_common
Test: Successfully generated an incremental for a target using
      system_root_image that was previously failing.
Change-Id: I62a2460e882f3930e99add4d2b44291edf7a51a0
2018-07-10 16:05:14 -07:00
Tao Bao
f47bf0fecf releasetools: Fix an issue in GetMinSdkVersion.
The following is a buggy pattern that won't capture anything into err.
The issue is benign, since a failed run would be eventually captured by
a subsequent check.

  p = Run(["aapt", ...], stdout=subprocess.PIPE)
  output, err = p.communicate()
  if err:
    raise ...

This CL changes the error detection to be based on the return code from
aapt. It also adds some sanity test to ensure the call to aapt works.
The test app is built from AOSP com.android.cts.ctsshim (chosen mostly
because of its small size).

Test: python -m unittest test_common
Change-Id: I337f141bd0fc5f0801dfc628c601b88b7640789c
2018-03-22 10:27:04 -07:00
Tao Bao
dba59eeabd releasetools: Don't return ZipFile from common.UnzipTemp().
In addition to the unzipping work, common.UnzipTemp() kindly bundles an
open ZipFile object as part of the return value. It doesn't look very
helpful to the callers though. It also looks less obvious that the
caller needs to properly close the handle (missing the close here is
benign though). This CL just removes the ZipFile object out of the
return value, and leaves the work to callers.

Test: `m dist` on both of A/B and non-A/B target.
Test: python -m unittest test_add_img_to_target_files
Test: python -m unittest test_common
Test: python -m unittest test_ota_from_target_files
Test: Check the callers to common.UnzipTemp() in code search.
Change-Id: Id47da3fd42a0e76d6ae8851f05780db319ee48cf
2018-03-01 10:03:31 -08:00
Tao Bao
a0f55ee9eb Merge "releasetools: Add a testcase for common.ParseCertificate()." 2018-02-21 00:04:24 +00:00
Tao Bao
17e4e61691 releasetools: Add a testcase for common.ParseCertificate().
Also minor clean up to the function, to suppress the following lint
warning.
R:1813, 2: Redefinition of cert type from list to unicode (redefined-variable-type)

Test: python -m unittest -v test_common.CommonApkUtilsTest
Change-Id: Ib4b1dfa8b19e505fc70684b648efc36171c73bbf
2018-02-16 17:14:23 -08:00
Tao Bao
fc7e0e06b6 releasetools: Add unittest for common.GetSparseImage().
Add construct_sparse_image() to test_utils.py, which is a util function
to create sparse images. The new tests also partially cover the recent
changes that add 'incomplete' and 'uses_shard_blocks' tags.

Test: python -m unittest test_common
Change-Id: Ia15f5c4ad12423691216ebbad2c28f95c8427d7e
2018-02-14 15:12:52 -08:00
Tao Bao
04e1f012dd releasetools: Fix an issue with pubkey extraction.
When calling 'openssl x509 -pubkey' to extract the public key from a
certificate, openssl 1.0 and 1.1 handle the '-out' parameter
differently. openssl 1.0 doesn't write the output into the specified
filename, which leads to the payload verification failure in
check_ota_package_signature.VerifyAbOtaPayload(). This CL addresses
the issue by always collecting the output from stdout instead.

It also refactors the two copies into common.ExtractPublicKey(), and
adds unittest. get_testdata_dir() is moved into test_utils.py that holds
common utils for running the unittests.

Bug: 72884343
Test: python -m unittest test_common
Test: python -m unittest test_ota_from_target_files
Test: Run sign_target_files_apks with '--replace_ota_keys' on marlin
      target_files zip. Check the payload pubkey replacement.
Test: Trigger the tests with forrest, and tests no longer fail on
      machines with openssl 1.0.1.
Change-Id: Ib0389b360f064053e9aa7cc0546d718e7b23003b
2018-02-04 13:59:52 -08:00
Tao Bao
818ddf5e7e releasetools: Add tests for common.ReadApkCerts().
Test: python -m unittest test_common
Test: Run sign_target_files_apks.py on a target with compressed APKs.
Change-Id: I107a8b8f2f0f82e2d1947f14c8a8b3778f633b11
2018-01-05 11:53:55 -08:00
Tao Bao
1c830bfbaa releasetools: Add common.MakeTempDir().
This simplifies the work to track mkdtemp()'d dirs. This CL also cleans
up the temporary file creation in build_image.py.

Test: `m dist`
Test: python -m unittest test_common
Change-Id: Ied7d86126714b9b26e5df7bcca1dfdea21cfcf60
2018-01-02 12:22:01 -08:00
Tao Bao
89d7ab23e8 releasetools: Add common.ZipDelete().
We have been shelling out to 'zip -d' to delete existing ZIP entries in
add_img_to_target_files.py. This CL moves the function into common.py,
and calls that for the similar work in ota_from_target_files.py. This CL
also adds unittests for the newly added function.

Test: `m dist`
Test: python -m unittest test_common
Test: ota_from_target_files.py generates identical packages w/ and w/o
      the CL (so we know the streaming property computation is intact).
Test: Run 'add_img_to_target_files.py -a' that triggers a call to
      ReplaceUpdatedFiles().
Change-Id: Icaa6c3ea3ee2166023f78fa79275295f837ea842
2017-12-14 17:17:04 -08:00
Tao Bao
31b0807310 releasetools: Reduce the memory use in test_common.py.
test_common constructs a few 2GiB strings in memory, which leads to huge
memory footprint (18GiB). This CL moves away from in-memory strings to
generators, which reduces the memory use down to 41MiB. It also reduces
the time cost from 294s to 139s as an extra benefit for free.

The CL addresses some trivial pylint warnings as well.

* Before

$ /usr/bin/time -v python -m unittest -v test_common
...
----------------------------------------------------------------------
Ran 11 tests in 294.986s

OK
	Command being timed: "python -m unittest -v test_common"
	User time (seconds): 110.51
	System time (seconds): 109.34
	Percent of CPU this job got: 74%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 4:55.06
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 18894172
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 1
	Minor (reclaiming a frame) page faults: 20774908
	Voluntary context switches: 48
	Involuntary context switches: 3241
	Swaps: 0
	File system inputs: 184
	File system outputs: 8406424
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0

* After

$ /usr/bin/time -v python -m unittest -v test_common
...
----------------------------------------------------------------------
Ran 11 tests in 139.100s

OK
	Command being timed: "python -m unittest -v test_common"
	User time (seconds): 59.00
	System time (seconds): 4.73
	Percent of CPU this job got: 45%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 2:19.17
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 41252
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 106569
	Voluntary context switches: 44
	Involuntary context switches: 103
	Swaps: 0
	File system inputs: 8
	File system outputs: 8422808
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0

Fixes: 68988396
Test: See above.
Change-Id: I00f16603a4ee59fb085b189c6f5b5ee9d2378690
2017-11-08 17:10:33 -08:00
Tianjie Xu
df055580d0 Fix the imgdiff failure when running test_common unittest
imgdiff fails on plain strings after we put more checks the input
data. This leads to failure when running unittest
"test_recovery_from_boot". The CL fixes the issue by serving gzipped
dummy images as the test input.

Bug: 68988329
Test: InstallRecoveryScriptFormatTest passes
Change-Id: I1952b311681ac4f39c0e51aef1de1177aebeac43
2017-11-07 12:38:08 -08:00
Tianjie Xu
9c384d2ca5 Verify the contents in install-recovery.sh
Check the SHA1 of recovery.img and boot.img embedded in the
install-recovery.sh.

Bug: 35411009
Test: validation script detects mismatch for both full recovery and
recovery-from-boot.
Change-Id: I5f07a869d9fa17fad26a22ef9ca3ecb06b1b28e3
2017-06-20 17:28:35 -07:00
Tao Bao
58c1b96165 Fix the permission setting in common.ZipWriteStr()
When passing a ZipInfo instance to common.ZipWriteStr(), the
external_attr attribute should not be overwritten unless specified.
We didn't have the issue previously because we were calling
ZipFile.writestr() directly until [1] merged.

[1] commit 2ed665a033.

Bug: http://b/21309935
Change-Id: I8c0190362c60d7d78965ecfe5e484f8398ddc5f2
(cherry picked from commit 9773465409)
2015-05-20 13:29:03 -07:00
Tao Bao
f3282b4a7f Wrap zipfile.write(), writestr() and close()
In order to work around the zip 2GiB limit, we need to wrap the related
functions in zipfile. Calls to those functions should always be replaced
with calls to the wrappers instead.

Bug: 18015246
Change-Id: I499574cee51ec4804bc10cbefe0b17940afed918
(cherry picked from commit 2ed665a033)
2015-05-08 15:53:27 -07:00
Dan Albert
d6d1beb88c Run ZipFile.testzip() during zipfile tests.
This still doesn't catch the issue that [1] fixes, but it's probably a
good idea anyway.

[1]: https://android-review.googlesource.com/#/c/143469/

Change-Id: Iaa607ec7450d605b26114bd81ea41a14c6613c0e
2015-03-23 16:54:39 -07:00
Dan Albert
8e0178d41b Allow system images larger than 2GiB.
Python 2.7's zipfile implementation wrongly thinks that zip64 is
required for files larger than 2GiB. We can work around this by
adjusting their limit. Note that `zipfile.writestr()` will not work
for strings larger than 2GiB. The Python interpreter sometimes rejects
strings that large (though it isn't clear to me exactly what
circumstances cause this). `zipfile.write()` must be used directly to
work around this.

This mess can be avoided if we port to python3.

The bug (b/19364241) in original commit has been fixed.

Bug: 18015246
Bug: 19364241
Bug: 19839468

(cherry picked from commit cd082d4bfe)

Change-Id: I7b5cc310e0a9ba894533b53cb998afd5ce96d8c6
2015-03-19 13:59:01 -07:00