def _ResourceSizes(args):
  chartjson = _BASE_CHART.copy() if args.output_format else None
  reporter = _ChartJsonReporter(chartjson)
  # Create DexStatsCollector here to track unique methods across trichrome APKs.
  dex_stats_collector = method_count.DexStatsCollector()

  specs = [
      ('Chrome_', args.trichrome_chrome),
      ('WebView_', args.trichrome_webview),
      ('Library_', args.trichrome_library),
  ]
  for prefix, path in specs:
    if path:
      reporter.trace_title_prefix = prefix
      child_dex_stats_collector = _AnalyzeApkOrApks(reporter, path,
                                                    args.out_dir)
      dex_stats_collector.MergeFrom(prefix, child_dex_stats_collector)

  if any(path for _, path in specs):
    reporter.SynthesizeTotals(dex_stats_collector.GetUniqueMethodCount())
  else:
    _AnalyzeApkOrApks(reporter, args.input, args.out_dir)

  if chartjson:
    _DumpChartJson(args, chartjson)
        def do_measure(split_name, on_demand):
          logging.info('Measuring %s on_demand=%s', split_name, on_demand)
          # Use no-op reporting functions to get normalized size for DFMs.
          inner_report_func = report_func
          inner_dex_stats_collector = dex_stats_collector
          if on_demand:
            inner_report_func = lambda *_: None
            inner_dex_stats_collector = method_count.DexStatsCollector()

          size = _AnalyzeInternal(f.name,
                                  sdk_version,
                                  inner_report_func,
                                  inner_dex_stats_collector,
                                  out_dir,
                                  apks_path=apk_path,
                                  split_name=split_name)
          report_func('DFM_' + split_name, 'Size with hindi', size, 'bytes')
Exemple #3
0
def _AnalyzeApkOrApks(report_func, apk_path, args):
    # Create DexStatsCollector here to track unique methods across base & chrome
    # modules.
    dex_stats_collector = method_count.DexStatsCollector()
    out_dir, tool_prefix = _ConfigOutDirAndToolsPrefix(args.out_dir)

    if apk_path.endswith('.apk'):
        sdk_version, _, _ = _ParseManifestAttributes(apk_path)
        _AnalyzeInternal(apk_path, sdk_version, report_func,
                         dex_stats_collector, out_dir, tool_prefix)
    elif apk_path.endswith('.apks'):
        with tempfile.NamedTemporaryFile(suffix='.apk') as f:
            with zipfile.ZipFile(apk_path) as z:
                # Currently bundletool is creating two apks when .apks is created
                # without specifying an sdkVersion. Always measure the one with an
                # uncompressed shared library.
                try:
                    info = z.getinfo('splits/base-master_2.apk')
                except KeyError:
                    info = z.getinfo('splits/base-master.apk')
                _ExtractToTempFile(z, info.filename, f)
                sdk_version, _, _ = _ParseManifestAttributes(f.name)

                orig_report_func = report_func
                report_func = _AccumulatingReporter()

                def do_measure(split_name, on_demand):
                    logging.info('Measuring %s on_demand=%s', split_name,
                                 on_demand)
                    # Use no-op reporting functions to get normalized size for DFMs.
                    inner_report_func = report_func
                    inner_dex_stats_collector = dex_stats_collector
                    if on_demand:
                        inner_report_func = lambda *_: None
                        inner_dex_stats_collector = method_count.DexStatsCollector(
                        )

                    size = _AnalyzeInternal(f.name,
                                            sdk_version,
                                            inner_report_func,
                                            inner_dex_stats_collector,
                                            out_dir,
                                            tool_prefix,
                                            apks_path=apk_path,
                                            split_name=split_name)
                    report_func('DFM_' + split_name, 'Size with hindi', size,
                                'bytes')

                # Measure base outside of the loop since we've already extracted it.
                do_measure('base', on_demand=False)

                for subpath, split_name in _IterSplits(z.namelist()):
                    if split_name != 'base':
                        _ExtractToTempFile(z, subpath, f)
                        _, _, on_demand = _ParseManifestAttributes(f.name)
                        do_measure(split_name, on_demand=on_demand)

                report_func.DumpReports(orig_report_func)
                report_func = orig_report_func
    else:
        raise Exception('Unknown file type: ' + apk_path)

    # Report dex stats outside of _AnalyzeInternal() so that the "unique methods"
    # metric is not just the sum of the base and chrome modules.
    for metric, count in dex_stats_collector.GetTotalCounts().items():
        report_func('Dex', metric, count, 'entries')
    report_func('Dex', 'unique methods',
                dex_stats_collector.GetUniqueMethodCount(), 'entries')
    report_func('DexCache', 'DexCache',
                dex_stats_collector.GetDexCacheSize(pre_oreo=sdk_version < 26),
                'bytes')

    return dex_stats_collector