Add an option to show file sizes in Runtime APEX test scripts' tree output.

Add option `--size` to `build/apex/art_apex_test.py`, showing the size
of each file in the tree output.

Add option `--print-sizes` to `build/apex/runtests.sh`, enabling the
previous option when running `build/apex/art_apex_test.py`. Rename the
short option of `--skip-build` from `-s` to `-B`, and reassign `-s` as
a short option for `--print-sizes`.

Test: art/build/apex/runtests.sh --print-tree --print-sizes
Change-Id: Ifff37b5e075f8972755d09709b7df1ce9a7a19f4
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index cf78807..1d85ef5 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -28,14 +28,16 @@
 
 
 class FSObject:
-  def __init__(self, name, is_dir, is_exec, is_symlink):
+  def __init__(self, name, is_dir, is_exec, is_symlink, size):
     self.name = name
     self.is_dir = is_dir
     self.is_exec = is_exec
     self.is_symlink = is_symlink
+    self.size = size
 
   def __str__(self):
-    return '%s(dir=%r,exec=%r,symlink=%r)' % (self.name, self.is_dir, self.is_exec, self.is_symlink)
+    return '%s(dir=%r,exec=%r,symlink=%r,size=%d)' \
+             % (self.name, self.is_dir, self.is_exec, self.is_symlink, self.size)
 
 
 class TargetApexProvider:
@@ -97,6 +99,9 @@
         continue
       bits = comps[2]
       name = comps[5]
+      size_str = comps[6]
+      # Use a negative value as an indicator of undefined/unknown size.
+      size = int(size_str) if size_str != '' else -1
       if len(bits) != 6:
         logging.warning('Dont understand bits \'%s\'', bits)
         continue
@@ -107,7 +112,7 @@
 
       is_exec = is_exec_bit(bits[3]) and is_exec_bit(bits[4]) and is_exec_bit(bits[5])
       is_symlink = bits[1] == '2'
-      apex_map[name] = FSObject(name, is_dir, is_exec, is_symlink)
+      apex_map[name] = FSObject(name, is_dir, is_exec, is_symlink, size)
     self._folder_cache[apex_dir] = apex_map
     return apex_map
 
@@ -135,7 +140,8 @@
         is_dir = os.path.isdir(filepath)
         is_exec = os.access(filepath, os.X_OK)
         is_symlink = os.path.islink(filepath)
-        apex_map[basename] = FSObject(basename, is_dir, is_exec, is_symlink)
+        size = os.path.getsize(filepath)
+        apex_map[basename] = FSObject(basename, is_dir, is_exec, is_symlink, size)
     self._folder_cache[apex_dir] = apex_map
     return apex_map
 
@@ -200,11 +206,14 @@
             is_dir = get_octal(bits, 4) == 4
             is_symlink = get_octal(bits, 4) == 2
             is_exec = bits_is_exec(bits)
+            size = zipinfo.file_size
           else:
             is_exec = False  # Seems we can't get this easily?
             is_symlink = False
             is_dir = True
-          dir_map[base] = FSObject(base, is_dir, is_exec, is_symlink)
+            # Use a negative value as an indicator of undefined/unknown size.
+            size = -1
+          dir_map[base] = FSObject(base, is_dir, is_exec, is_symlink, size)
         is_zipinfo = False
         path = apex_dir
 
@@ -658,10 +667,11 @@
 
 
 class Tree:
-  def __init__(self, provider, title):
+  def __init__(self, provider, title, print_size):
     print('%s' % title)
     self._provider = provider
     self._has_next_list = []
+    self._print_size = print_size
 
   @staticmethod
   def get_vertical(has_next_list):
@@ -690,7 +700,13 @@
         prev = self.get_vertical(self._has_next_list)
         last = self.get_last_vertical(i == len(key_list) - 1)
         val = apex_map[key]
-        print('%s%s%s' % (prev, last, val.name))
+        if self._print_size:
+          if val.size < 0:
+            print('%s%s[    n/a    ]  %s' % (prev, last, val.name))
+          else:
+            print('%s%s[%11d]  %s' % (prev, last, val.size, val.name))
+        else:
+          print('%s%s%s' % (prev, last, val.name))
         if val.is_dir:
           self._has_next_list.append(i < len(key_list) - 1)
           val_path = os.path.join(path, val.name)
@@ -714,6 +730,9 @@
   if test_args.list and test_args.tree:
     logging.error("Both of --list and --tree set")
     return 1
+  if test_args.size and not test_args.tree:
+    logging.error("--size set but --tree not set")
+    return 1
   if not test_args.tmpdir:
     logging.error("Need a tmpdir.")
     return 1
@@ -736,7 +755,7 @@
     return 1
 
   if test_args.tree:
-    Tree(apex_provider, test_args.apex).print_tree()
+    Tree(apex_provider, test_args.apex, test_args.size).print_tree()
     return 0
   if test_args.list:
     List(apex_provider).print_list()
@@ -858,6 +877,7 @@
 
   parser.add_argument('--list', help='List all files', action='store_true')
   parser.add_argument('--tree', help='Print directory tree', action='store_true')
+  parser.add_argument('--size', help='Print file sizes in tree output', action='store_true')
 
   parser.add_argument('--tmpdir', help='Directory for temp files')
   parser.add_argument('--debugfs', help='Path to debugfs')
diff --git a/build/apex/runtests.sh b/build/apex/runtests.sh
index 74a6120..58bd28a 100755
--- a/build/apex/runtests.sh
+++ b/build/apex/runtests.sh
@@ -55,15 +55,17 @@
 build_apex_p=true
 list_image_files_p=false
 print_image_tree_p=false
+print_file_sizes_p=false
 
 function usage {
   cat <<EOF
 Usage: $0 [OPTION]
 Build (optional) and run tests on Android Runtime APEX package (on host).
 
-  -s, --skip-build    skip the build step
+  -B, --skip-build    skip the build step
   -l, --list-files    list the contents of the ext4 image (\`find\`-like style)
   -t, --print-tree    list the contents of the ext4 image (\`tree\`-like style)
+  -s, --print-sizes   print the size in bytes of each file in tree output
   -h, --help          display this help and exit
 
 EOF
@@ -72,9 +74,10 @@
 
 while [[ $# -gt 0 ]]; do
   case "$1" in
-    (-s|--skip-build) build_apex_p=false;;
-    (-l|--list-files) list_image_files_p=true;;
-    (-t|--print-tree) print_image_tree_p=true;;
+    (-B|--skip-build)  build_apex_p=false;;
+    (-l|--list-files)  list_image_files_p=true;;
+    (-t|--print-tree)  print_image_tree_p=true;;
+    (-s|--print-sizes) print_file_sizes_p=true;;
     (-h|--help) usage;;
     (*) die "Unknown option: '$1'
 Try '$0 --help' for more information.";;
@@ -102,7 +105,11 @@
   # List the contents of the apex in tree form.
   if $print_image_tree_p; then
     say "Printing image tree"
-    $SCRIPT_DIR/art_apex_test.py --tree $@
+    tree_options=()
+    if $print_file_sizes_p; then
+      tree_options+=(--size)
+    fi
+    $SCRIPT_DIR/art_apex_test.py --tree ${tree_options[@]} $@
   fi
 }