1#!/usr/bin/env python3
2#
3# Copyright (C) 2024 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17"""Downloads etm modules from the build server."""
18
19import argparse
20
21import logging
22import os
23from pathlib import Path
24import shutil
25import stat
26import textwrap
27
28
29ETM_MODULE_TARGET = 'etm_kernel_modules'
30
31ETM_MODULES = ['coresight.ko', 'coresight-etm4x.ko', 'coresight-funnel.ko', 'coresight-tmc.ko']
32
33
34def logger():
35    """Returns the main logger for this module."""
36    return logging.getLogger(__name__)
37
38
39def check_call(cmd):
40    """Proxy for subprocess.check_call with logging."""
41    import subprocess
42    logger().debug('check_call `%s`', ' '.join(cmd))
43    subprocess.check_call(cmd)
44
45
46def fetch_artifact(branch: str, build: str, target: str, name: str) -> None:
47    """Fetches and artifact from the build server."""
48    logger().info('Fetching %s from %s %s (artifacts matching %s)', build,
49                  target, branch, name)
50    fetch_artifact_path = '/google/data/ro/projects/android/fetch_artifact'
51    cmd = [fetch_artifact_path, '--branch', branch, '--target', target,
52           '--bid', build, name]
53    check_call(cmd)
54
55
56def fetch_etm_modules(branch: str, build: str, install_dir: str) -> None:
57    """Installs the device specific components of the release."""
58    install_dir = Path(install_dir)
59    install_dir.mkdir(exist_ok=True)
60    for name in ETM_MODULES:
61        fetch_artifact(branch, build, ETM_MODULE_TARGET, name)
62        dest_file = install_dir / name
63        if dest_file.is_file():
64            dest_file.unlink()
65        shutil.move(name, dest_file)
66
67
68def get_args():
69    """Parses and returns command line arguments."""
70    parser = argparse.ArgumentParser(description=__doc__)
71    parser.add_argument('-b', '--branch', default='kernel-android14-gs-pixel-6.1',
72                        choices=['kernel-android14-gs-pixel-6.1',
73                                 'kernel-android14-gs-pixel-5.15-24Q3'],
74                        help='Branch to pull build from.')
75    parser.add_argument('--build', required=True, help='Build number to pull.')
76    parser.add_argument('-o', dest='install_dir', required=True,
77                        help='Directory to store etm modules')
78    parser.add_argument('-v', '--verbose', action='count', default=0,
79                        help='Increase output verbosity.')
80    return parser.parse_args()
81
82
83def main():
84    """Program entry point."""
85    args = get_args()
86    verbose_map = (logging.WARNING, logging.INFO, logging.DEBUG)
87    verbosity = args.verbose
88    if verbosity > 2:
89        verbosity = 2
90    logging.basicConfig(level=verbose_map[verbosity])
91    logging.debug(f'args={args}')
92    fetch_etm_modules(args.branch, args.build, args.install_dir)
93
94
95if __name__ == '__main__':
96    main()
97