#! /usr/bin/env python3
# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import argparse
import os
import re
import zipfile

from pylib.dex import dex_parser


class DexStatsCollector:
  """Tracks count of method/field/string/type as well as unique methods."""

  def __init__(self):
    # Signatures of all methods from all seen dex files.
    self._unique_methods = set()
    # Map of label -> { metric -> count }.
    self._counts_by_label = {}

  def _CollectFromDexfile(self, label, dexfile):
    assert label not in self._counts_by_label, 'exists: ' + label
    self._counts_by_label[label] = {
        'fields': dexfile.header.field_ids_size,
        'methods': dexfile.header.method_ids_size,
        'strings': dexfile.header.string_ids_size,
        'types': dexfile.header.type_ids_size,
    }
    self._unique_methods.update(dexfile.IterMethodSignatureParts())

  def CollectFromZip(self, label, path):
    """Add dex stats from an .apk/.jar/.aab/.zip."""
    with zipfile.ZipFile(path, 'r') as z:
      for subpath in z.namelist():
        if not re.match(r'.*classes\d*\.dex$', subpath):
          continue
        dexfile = dex_parser.DexFile(bytearray(z.read(subpath)))
        self._CollectFromDexfile('{}!{}'.format(label, subpath), dexfile)

  def CollectFromDex(self, label, path):
    """Add dex stats from a .dex file."""
    with open(path, 'rb') as f:
      dexfile = dex_parser.DexFile(bytearray(f.read()))
    self._CollectFromDexfile(label, dexfile)

  def MergeFrom(self, parent_label, other):
    """Add dex stats from another DexStatsCollector."""
    # pylint: disable=protected-access
    for label, other_counts in other._counts_by_label.items():
      new_label = '{}-{}'.format(parent_label, label)
      self._counts_by_label[new_label] = other_counts.copy()
    self._unique_methods.update(other._unique_methods)
    # pylint: enable=protected-access

  def GetUniqueMethodCount(self):
    """Returns total number of unique methods across encountered dex files."""
    return len(self._unique_methods)

  def GetCountsByLabel(self):
    """Returns dict of label -> {metric -> count}."""
    return self._counts_by_label

  def GetTotalCounts(self):
    """Returns dict of {metric -> count}, where |count| is sum(metric)."""
    ret = {}
    for metric in ('fields', 'methods', 'strings', 'types'):
      ret[metric] = sum(x[metric] for x in self._counts_by_label.values())
    return ret

  def GetDexCacheSize(self, pre_oreo):
    """Returns number of bytes of dirty RAM is consumed from all dex files."""
    # Dex Cache was optimized in Android Oreo:
    # https://source.android.com/devices/tech/dalvik/improvements#dex-cache-removal
    if pre_oreo:
      total = sum(self.GetTotalCounts().values())
    else:
      total = sum(c['methods'] for c in self._counts_by_label.values())
    return total * 4  # 4 bytes per entry.


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('paths', nargs='+')
  args = parser.parse_args()

  collector = DexStatsCollector()
  for path in args.paths:
    if os.path.splitext(path)[1] in ('.zip', '.apk', '.jar', '.aab'):
      collector.CollectFromZip(path, path)
    else:
      collector.CollectFromDex(path, path)

  counts_by_label = collector.GetCountsByLabel()
  for label, counts in sorted(counts_by_label.items()):
    print('{}:'.format(label))
    for metric, count in sorted(counts.items()):
      print('  {}:'.format(metric), count)
    print()

  if len(counts_by_label) > 1:
    print('Totals:')
    for metric, count in sorted(collector.GetTotalCounts().items()):
      print('  {}:'.format(metric), count)
    print()

  print('Unique Methods:', collector.GetUniqueMethodCount())
  print('DexCache (Pre-Oreo):', collector.GetDexCacheSize(pre_oreo=True),
        'bytes of dirty memory')
  print('DexCache (Oreo+):', collector.GetDexCacheSize(pre_oreo=False),
        'bytes of dirty memory')


if __name__ == '__main__':
  main()
