summaryrefslogtreecommitdiff
path: root/apexer/apexer.py
diff options
context:
space:
mode:
Diffstat (limited to 'apexer/apexer.py')
-rw-r--r--apexer/apexer.py175
1 files changed, 114 insertions, 61 deletions
diff --git a/apexer/apexer.py b/apexer/apexer.py
index f698c8c..5d4d5c2 100644
--- a/apexer/apexer.py
+++ b/apexer/apexer.py
@@ -101,6 +101,13 @@ def ParseArgs(argv):
choices=['zip', 'image'],
help='type of APEX payload being built "zip" or "image"')
parser.add_argument(
+ '--payload_fs_type',
+ metavar='FS_TYPE',
+ required=False,
+ default='ext4',
+ choices=['ext4', 'f2fs'],
+ help='type of filesystem being used for payload image "ext4" or "f2fs"')
+ parser.add_argument(
'--override_apk_package_name',
required=False,
help='package name of the APK container. Default is the apex name in --manifest.'
@@ -162,7 +169,7 @@ def ParseArgs(argv):
parser.add_argument(
'--unsigned_payload_only',
action='store_true',
- help="""Outputs the unsigned payload image/zip only. Also, setting this flag implies
+ help="""Outputs the unsigned payload image/zip only. Also, setting this flag implies
--payload_only is set too."""
)
parser.add_argument(
@@ -182,7 +189,7 @@ def FindBinaryPath(binary):
':'.join(tool_path_list))
-def RunCommand(cmd, verbose=False, env=None):
+def RunCommand(cmd, verbose=False, env=None, expected_return_values={0}):
env = env or {}
env.update(os.environ.copy())
@@ -194,10 +201,10 @@ def RunCommand(cmd, verbose=False, env=None):
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
output, _ = p.communicate()
- if verbose or p.returncode is not 0:
+ if verbose or p.returncode not in expected_return_values:
print(output.rstrip())
- assert p.returncode is 0, 'Failed to execute: ' + ' '.join(cmd)
+ assert p.returncode in expected_return_values, 'Failed to execute: ' + ' '.join(cmd)
return (output, p.returncode)
@@ -378,6 +385,9 @@ def GenerateBuildInfo(args):
if args.logging_parent:
build_info.logging_parent = args.logging_parent
+ if args.payload_type == 'image':
+ build_info.payload_fs_type = args.payload_fs_type
+
return build_info
def AddLoggingParent(android_manifest, logging_parent_value):
@@ -450,9 +460,8 @@ def CreateApex(args, work_dir):
print("Cannot read manifest file: '" + args.manifest + "'")
return False
- # create an empty ext4 image that is sufficiently big
- # sufficiently big = size + 16MB margin
- size_in_mb = (GetDirSize(args.input_dir) / (1024 * 1024)) + 16
+ # create an empty image that is sufficiently big
+ size_in_mb = (GetDirSize(args.input_dir) / (1024 * 1024))
content_dir = os.path.join(work_dir, 'content')
os.mkdir(content_dir)
@@ -479,61 +488,105 @@ def CreateApex(args, work_dir):
return False
img_file = os.path.join(content_dir, 'apex_payload.img')
- # margin is for files that are not under args.input_dir. this consists of
- # n inodes for apex_manifest files and 11 reserved inodes for ext4.
- # TOBO(b/122991714) eliminate these details. use build_image.py which
- # determines the optimal inode count by first building an image and then
- # count the inodes actually used.
- inode_num_margin = GetFilesAndDirsCount(manifests_dir) + 11
- inode_num = GetFilesAndDirsCount(args.input_dir) + inode_num_margin
-
- cmd = ['mke2fs']
- cmd.extend(['-O', '^has_journal']) # because image is read-only
- cmd.extend(['-b', str(BLOCK_SIZE)])
- cmd.extend(['-m', '0']) # reserved block percentage
- cmd.extend(['-t', 'ext4'])
- cmd.extend(['-I', '256']) # inode size
- cmd.extend(['-N', str(inode_num)])
- uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
- cmd.extend(['-U', uu])
- cmd.extend(['-E', 'hash_seed=' + uu])
- cmd.append(img_file)
- cmd.append(str(size_in_mb) + 'M')
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
- # Compile the file context into the binary form
- compiled_file_contexts = os.path.join(work_dir, 'file_contexts.bin')
- cmd = ['sefcontext_compile']
- cmd.extend(['-o', compiled_file_contexts])
- cmd.append(args.file_contexts)
- RunCommand(cmd, args.verbose)
+ if args.payload_fs_type == 'ext4':
+ # sufficiently big = size + 16MB margin
+ size_in_mb += 16
+
+ # margin is for files that are not under args.input_dir. this consists of
+ # n inodes for apex_manifest files and 11 reserved inodes for ext4.
+ # TOBO(b/122991714) eliminate these details. use build_image.py which
+ # determines the optimal inode count by first building an image and then
+ # count the inodes actually used.
+ inode_num_margin = GetFilesAndDirsCount(manifests_dir) + 11
+ inode_num = GetFilesAndDirsCount(args.input_dir) + inode_num_margin
+
+ cmd = ['mke2fs']
+ cmd.extend(['-O', '^has_journal']) # because image is read-only
+ cmd.extend(['-b', str(BLOCK_SIZE)])
+ cmd.extend(['-m', '0']) # reserved block percentage
+ cmd.extend(['-t', 'ext4'])
+ cmd.extend(['-I', '256']) # inode size
+ cmd.extend(['-N', str(inode_num)])
+ uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
+ cmd.extend(['-U', uu])
+ cmd.extend(['-E', 'hash_seed=' + uu])
+ cmd.append(img_file)
+ cmd.append(str(size_in_mb) + 'M')
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ # Compile the file context into the binary form
+ compiled_file_contexts = os.path.join(work_dir, 'file_contexts.bin')
+ cmd = ['sefcontext_compile']
+ cmd.extend(['-o', compiled_file_contexts])
+ cmd.append(args.file_contexts)
+ RunCommand(cmd, args.verbose)
+
+ # Add files to the image file
+ cmd = ['e2fsdroid']
+ cmd.append('-e') # input is not android_sparse_file
+ cmd.extend(['-f', args.input_dir])
+ cmd.extend(['-T', '0']) # time is set to epoch
+ cmd.extend(['-S', compiled_file_contexts])
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.append('-s') # share dup blocks
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ cmd = ['e2fsdroid']
+ cmd.append('-e') # input is not android_sparse_file
+ cmd.extend(['-f', manifests_dir])
+ cmd.extend(['-T', '0']) # time is set to epoch
+ cmd.extend(['-S', compiled_file_contexts])
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.append('-s') # share dup blocks
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ # Resize the image file to save space
+ cmd = ['resize2fs']
+ cmd.append('-M') # shrink as small as possible
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+
+ elif args.payload_fs_type == 'f2fs':
+ # F2FS requires a ~100M minimum size (necessary for ART, could be reduced a bit for other)
+ # TODO(b/158453869): relax these requirements for readonly devices
+ size_in_mb += 100
+
+ # Create an empty image
+ cmd = ['/usr/bin/fallocate']
+ cmd.extend(['-l', str(size_in_mb)+'M'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose)
+
+ # Format the image to F2FS
+ cmd = ['make_f2fs']
+ cmd.extend(['-g', 'android'])
+ uu = str(uuid.uuid5(uuid.NAMESPACE_URL, 'www.android.com'))
+ cmd.extend(['-U', uu])
+ cmd.extend(['-T', '0'])
+ cmd.append('-r') # sets checkpointing seed to 0 to remove random bits
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose)
- # Add files to the image file
- cmd = ['e2fsdroid']
- cmd.append('-e') # input is not android_sparse_file
- cmd.extend(['-f', args.input_dir])
- cmd.extend(['-T', '0']) # time is set to epoch
- cmd.extend(['-S', compiled_file_contexts])
- cmd.extend(['-C', args.canned_fs_config])
- cmd.append('-s') # share dup blocks
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
- cmd = ['e2fsdroid']
- cmd.append('-e') # input is not android_sparse_file
- cmd.extend(['-f', manifests_dir])
- cmd.extend(['-T', '0']) # time is set to epoch
- cmd.extend(['-S', compiled_file_contexts])
- cmd.extend(['-C', args.canned_fs_config])
- cmd.append('-s') # share dup blocks
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
-
- # Resize the image file to save space
- cmd = ['resize2fs']
- cmd.append('-M') # shrink as small as possible
- cmd.append(img_file)
- RunCommand(cmd, args.verbose, {'E2FSPROGS_FAKE_TIME': '1'})
+ # Add files to the image
+ cmd = ['sload_f2fs']
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.extend(['-f', manifests_dir])
+ cmd.extend(['-s', args.file_contexts])
+ cmd.extend(['-T', '0'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, expected_return_values={0,1})
+
+ cmd = ['sload_f2fs']
+ cmd.extend(['-C', args.canned_fs_config])
+ cmd.extend(['-f', args.input_dir])
+ cmd.extend(['-s', args.file_contexts])
+ cmd.extend(['-T', '0'])
+ cmd.append(img_file)
+ RunCommand(cmd, args.verbose, expected_return_values={0,1})
+
+ # TODO(b/158453869): resize the image file to save space
if args.unsigned_payload_only:
shutil.copyfile(img_file, args.output)