From 7bd8f2a24c7164bc61b1105057c9b4418f78284d Mon Sep 17 00:00:00 2001 From: bigbiff Date: Sun, 31 Jan 2021 10:25:33 -0500 Subject: [PATCH 01/26] make: Add soong module to import make variables. --- soong/makevars.mk | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 soong/makevars.mk diff --git a/soong/makevars.mk b/soong/makevars.mk new file mode 100644 index 0000000..8ad9e73 --- /dev/null +++ b/soong/makevars.mk @@ -0,0 +1,34 @@ +EXPORT_TO_SOONG := \ + TW_THEME \ + TW_CUSTOM_THEME \ + TW_INCLUDE_CRYPTO \ + DEVICE_RESOLUTION \ + TARGET_SCREEN_WIDTH \ + TARGET_SCREEN_HEIGHT \ + TW_DELAY_TOUCH_INIT_MS \ + TW_EVENT_LOGGING \ + TW_USE_KEY_CODE_TOUCH_SYNC \ + TW_OZIP_DECRYPT_KEY \ + TW_NO_SCREEN_BLANK \ + TW_NO_SCREEN_TIMEOUT \ + TW_OEM_BUILD \ + TW_X_OFFSET \ + TW_Y_OFFSET \ + TW_W_OFFSET \ + TW_H_OFFSET \ + TW_ROUND_SCREEN \ + TWRES_PATH \ + TWRP_CUSTOM_KEYBOARD \ + TW_EXTRA_LANGUAGES \ + TARGET_RECOVERY_ROOT_OUT + + +SOONG_CONFIG_NAMESPACES += makeVarsPlugin +SOONG_CONFIG_makeVarsPlugin := +#SOONG_CONFIG_makeVarsPlugin += TW_THEME +#SOONG_CONFIG_makeVarsPlugin_TW_THEME := $(TW_THEME) +define addVar + SOONG_CONFIG_makeVarsPlugin += $(1) + SOONG_CONFIG_makeVarsPlugin_$(1) := $$(subst ",\",$$($1)) +endef +$(foreach v,$(EXPORT_TO_SOONG),$(eval $(call addVar,$(v)))) From 6649057d74c013846591343e0a5580da00f7ea64 Mon Sep 17 00:00:00 2001 From: bigbiff Date: Sun, 14 Feb 2021 13:50:12 -0500 Subject: [PATCH 02/26] makevars: add pixel format --- soong/makevars.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soong/makevars.mk b/soong/makevars.mk index 8ad9e73..3e4c851 100644 --- a/soong/makevars.mk +++ b/soong/makevars.mk @@ -20,7 +20,8 @@ EXPORT_TO_SOONG := \ TWRES_PATH \ TWRP_CUSTOM_KEYBOARD \ TW_EXTRA_LANGUAGES \ - TARGET_RECOVERY_ROOT_OUT + TARGET_RECOVERY_ROOT_OUT \ + TARGET_RECOVERY_PIXEL_FORMAT SOONG_CONFIG_NAMESPACES += makeVarsPlugin From 40a477cef6967d19b4ec5a041147200f46237210 Mon Sep 17 00:00:00 2001 From: bigbiff Date: Sun, 7 Mar 2021 18:59:35 -0500 Subject: [PATCH 03/26] add AB_OTA_UPDATER --- soong/makevars.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soong/makevars.mk b/soong/makevars.mk index 3e4c851..48fca08 100644 --- a/soong/makevars.mk +++ b/soong/makevars.mk @@ -21,7 +21,8 @@ EXPORT_TO_SOONG := \ TWRP_CUSTOM_KEYBOARD \ TW_EXTRA_LANGUAGES \ TARGET_RECOVERY_ROOT_OUT \ - TARGET_RECOVERY_PIXEL_FORMAT + TARGET_RECOVERY_PIXEL_FORMAT \ + AB_OTA_UPDATER SOONG_CONFIG_NAMESPACES += makeVarsPlugin From 07831d7085b09a4dd4eb81ebf320c969b6a76522 Mon Sep 17 00:00:00 2001 From: bigbiff Date: Sat, 27 Mar 2021 15:13:26 -0400 Subject: [PATCH 04/26] vendor: add sdk version to soong and add repopick --- repopick.py | 442 ++++++++++++++++++++++++++++++++++++++++++++++ soong/makevars.mk | 3 +- vendorsetup.sh | 2 +- 3 files changed, 445 insertions(+), 2 deletions(-) create mode 100755 repopick.py diff --git a/repopick.py b/repopick.py new file mode 100755 index 0000000..135f475 --- /dev/null +++ b/repopick.py @@ -0,0 +1,442 @@ +#!/usr/bin/env python +# +# Copyright (C) 2013-15 The CyanogenMod Project +# (C) 2017 The LineageOS Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# Run repopick.py -h for a description of this utility. +# + +from __future__ import print_function + +import sys +import json +import os +import subprocess +import re +import argparse +import textwrap +from xml.etree import ElementTree + +try: + import requests +except ImportError: + try: + # For python3 + import urllib.error + import urllib.request + except ImportError: + # For python2 + import imp + import urllib2 + urllib = imp.new_module('urllib') + urllib.error = urllib2 + urllib.request = urllib2 + + +# Verifies whether pathA is a subdirectory (or the same) as pathB +def is_subdir(a, b): + a = os.path.realpath(a) + '/' + b = os.path.realpath(b) + '/' + return b == a[:len(b)] + + +def fetch_query_via_ssh(remote_url, query): + """Given a remote_url and a query, return the list of changes that fit it + This function is slightly messy - the ssh api does not return data in the same structure as the HTTP REST API + We have to get the data, then transform it to match what we're expecting from the HTTP RESET API""" + if remote_url.count(':') == 2: + (uri, userhost, port) = remote_url.split(':') + userhost = userhost[2:] + elif remote_url.count(':') == 1: + (uri, userhost) = remote_url.split(':') + userhost = userhost[2:] + port = 29418 + else: + raise Exception('Malformed URI: Expecting ssh://[user@]host[:port]') + + + out = subprocess.check_output(['ssh', '-x', '-p{0}'.format(port), userhost, 'gerrit', 'query', '--format=JSON --patch-sets --current-patch-set', query]) + if not hasattr(out, 'encode'): + out = out.decode() + reviews = [] + for line in out.split('\n'): + try: + data = json.loads(line) + # make our data look like the http rest api data + review = { + 'branch': data['branch'], + 'change_id': data['id'], + 'current_revision': data['currentPatchSet']['revision'], + 'number': int(data['number']), + 'revisions': {patch_set['revision']: { + 'number': int(patch_set['number']), + 'fetch': { + 'ssh': { + 'ref': patch_set['ref'], + 'url': 'ssh://{0}:{1}/{2}'.format(userhost, port, data['project']) + } + } + } for patch_set in data['patchSets']}, + 'subject': data['subject'], + 'project': data['project'], + 'status': data['status'] + } + reviews.append(review) + except: + pass + args.quiet or print('Found {0} reviews'.format(len(reviews))) + return reviews + + +def fetch_query_via_http(remote_url, query): + if "requests" in sys.modules: + auth = None + if os.path.isfile(os.getenv("HOME") + "/.gerritrc"): + f = open(os.getenv("HOME") + "/.gerritrc", "r") + for line in f: + parts = line.rstrip().split("|") + if parts[0] in remote_url: + auth = requests.auth.HTTPBasicAuth(username=parts[1], password=parts[2]) + statusCode = '-1' + if auth: + url = '{0}/a/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS'.format(remote_url, query) + data = requests.get(url, auth=auth) + statusCode = str(data.status_code) + if statusCode != '200': + #They didn't get good authorization or data, Let's try the old way + url = '{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS'.format(remote_url, query) + data = requests.get(url) + reviews = json.loads(data.text[5:]) + else: + """Given a query, fetch the change numbers via http""" + url = '{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS'.format(remote_url, query) + data = urllib.request.urlopen(url).read().decode('utf-8') + reviews = json.loads(data[5:]) + + for review in reviews: + review['number'] = review.pop('_number') + + return reviews + + +def fetch_query(remote_url, query): + """Wrapper for fetch_query_via_proto functions""" + if remote_url[0:3] == 'ssh': + return fetch_query_via_ssh(remote_url, query) + elif remote_url[0:4] == 'http': + return fetch_query_via_http(remote_url, query.replace(' ', '+')) + else: + raise Exception('Gerrit URL should be in the form http[s]://hostname/ or ssh://[user@]host[:port]') + +if __name__ == '__main__': + # Default to OmniRom Gerrit + default_gerrit = 'https://gerrit.omnirom.org' + + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent('''\ + repopick.py is a utility to simplify the process of cherry picking + patches from OmniRom's Gerrit instance (or any gerrit instance of your choosing) + + Given a list of change numbers, repopick will cd into the project path + and cherry pick the latest patch available. + + With the --start-branch argument, the user can specify that a branch + should be created before cherry picking. This is useful for + cherry-picking many patches into a common branch which can be easily + abandoned later (good for testing other's changes.) + + The --abandon-first argument, when used in conjunction with the + --start-branch option, will cause repopick to abandon the specified + branch in all repos first before performing any cherry picks.''')) + parser.add_argument('change_number', nargs='*', help='change number to cherry pick. Use {change number}/{patchset number} to get a specific revision.') + parser.add_argument('-i', '--ignore-missing', action='store_true', help='do not error out if a patch applies to a missing directory') + parser.add_argument('-s', '--start-branch', nargs=1, help='start the specified branch before cherry picking') + parser.add_argument('-r', '--reset', action='store_true', help='reset to initial state (abort cherry-pick) if there is a conflict') + parser.add_argument('-a', '--abandon-first', action='store_true', help='before cherry picking, abandon the branch specified in --start-branch') + parser.add_argument('-b', '--auto-branch', action='store_true', help='shortcut to "--start-branch auto --abandon-first --ignore-missing"') + parser.add_argument('-q', '--quiet', action='store_true', help='print as little as possible') + parser.add_argument('-v', '--verbose', action='store_true', help='print extra information to aid in debug') + parser.add_argument('-f', '--force', action='store_true', help='force cherry pick even if change is closed') + parser.add_argument('-p', '--pull', action='store_true', help='execute pull instead of cherry-pick') + parser.add_argument('-P', '--path', help='use the specified path for the change') + parser.add_argument('-t', '--topic', help='pick all commits from a specified topic') + parser.add_argument('-Q', '--query', help='pick all commits using the specified query') + parser.add_argument('-g', '--gerrit', default=default_gerrit, help='Gerrit Instance to use. Form proto://[user@]host[:port]') + parser.add_argument('-e', '--exclude', nargs=1, help='exclude a list of commit numbers separated by a ,') + parser.add_argument('-c', '--check-picked', type=int, default=10, help='pass the amount of commits to check for already picked changes') + args = parser.parse_args() + if not args.start_branch and args.abandon_first: + parser.error('if --abandon-first is set, you must also give the branch name with --start-branch') + if args.auto_branch: + args.abandon_first = True + args.ignore_missing = True + if not args.start_branch: + args.start_branch = ['auto'] + if args.quiet and args.verbose: + parser.error('--quiet and --verbose cannot be specified together') + + if (1 << bool(args.change_number) << bool(args.topic) << bool(args.query)) != 2: + parser.error('One (and only one) of change_number, topic, and query are allowed') + + # Change current directory to the top of the tree + if 'ANDROID_BUILD_TOP' in os.environ: + top = os.environ['ANDROID_BUILD_TOP'] + + if not is_subdir(os.getcwd(), top): + sys.stderr.write('ERROR: You must run this tool from within $ANDROID_BUILD_TOP!\n') + sys.exit(1) + os.chdir(os.environ['ANDROID_BUILD_TOP']) + + # Sanity check that we are being run from the top level of the tree + if not os.path.isdir('.repo'): + sys.stderr.write('ERROR: No .repo directory found. Please run this from the top of your tree.\n') + sys.exit(1) + + # If --abandon-first is given, abandon the branch before starting + if args.abandon_first: + # Determine if the branch already exists; skip the abandon if it does not + plist = subprocess.check_output(['repo', 'info']) + if not hasattr(plist, 'encode'): + plist = plist.decode() + needs_abandon = False + for pline in plist.splitlines(): + matchObj = re.match(r'Local Branches.*\[(.*)\]', pline) + if matchObj: + local_branches = re.split('\s*,\s*', matchObj.group(1)) + if any(args.start_branch[0] in s for s in local_branches): + needs_abandon = True + + if needs_abandon: + # Perform the abandon only if the branch already exists + if not args.quiet: + print('Abandoning branch: %s' % args.start_branch[0]) + subprocess.check_output(['repo', 'abandon', args.start_branch[0]]) + if not args.quiet: + print('') + + # Get the master manifest from repo + # - convert project name and revision to a path + project_name_to_data = {} + manifest = subprocess.check_output(['repo', 'manifest']) + xml_root = ElementTree.fromstring(manifest) + projects = xml_root.findall('project') + remotes = xml_root.findall('remote') + default_revision = xml_root.findall('default')[0].get('revision') + + #dump project data into the a list of dicts with the following data: + #{project: {path, revision}} + + for project in projects: + name = project.get('name') + path = project.get('path') + revision = project.get('revision') + if revision is None: + for remote in remotes: + if remote.get('name') == project.get('remote'): + revision = remote.get('revision') + if revision is None: + revision = default_revision + + if not name in project_name_to_data: + project_name_to_data[name] = {} + revision = revision.split('refs/heads/')[-1] + project_name_to_data[name][revision] = path + + # get data on requested changes + reviews = [] + change_numbers = [] + if args.topic: + reviews = fetch_query(args.gerrit, 'topic:{0}'.format(args.topic)) + change_numbers = sorted([str(r['number']) for r in reviews], key=int) + if args.query: + reviews = fetch_query(args.gerrit, args.query) + change_numbers = sorted([str(r['number']) for r in reviews], key=int) + if args.change_number: + for c in args.change_number: + if '-' in c: + templist = c.split('-') + for i in range(int(templist[0]), int(templist[1]) + 1): + change_numbers.append(str(i)) + else: + change_numbers.append(c) + reviews = fetch_query(args.gerrit, ' OR '.join('change:{0}'.format(x.split('/')[0]) for x in change_numbers)) + + # make list of things to actually merge + mergables = [] + + # If --exclude is given, create the list of commits to ignore + exclude = [] + if args.exclude: + exclude = args.exclude[0].split(',') + + for change in change_numbers: + patchset = None + if '/' in change: + (change, patchset) = change.split('/') + + if change in exclude: + continue + + change = int(change) + + if patchset is not None: + patchset = int(patchset) + + review = next((x for x in reviews if x['number'] == change), None) + if review is None: + print('Change %d not found, skipping' % change) + continue + + mergables.append({ + 'subject': review['subject'], + 'project': review['project'], + 'branch': review['branch'], + 'change_id': review['change_id'], + 'change_number': review['number'], + 'status': review['status'], + 'fetch': None + }) + mergables[-1]['fetch'] = review['revisions'][review['current_revision']]['fetch'] + mergables[-1]['id'] = change + if patchset: + try: + mergables[-1]['fetch'] = [review['revisions'][x]['fetch'] for x in review['revisions'] if review['revisions'][x]['_number'] == patchset][0] + mergables[-1]['id'] = '{0}/{1}'.format(change, patchset) + except (IndexError, ValueError): + args.quiet or print('ERROR: The patch set {0}/{1} could not be found, using CURRENT_REVISION instead.'.format(change, patchset)) + + for item in mergables: + args.quiet or print('Applying change number {0}...'.format(item['id'])) + # Check if change is open and exit if it's not, unless -f is specified + if (item['status'] != 'OPEN' and item['status'] != 'NEW' and item['status'] != 'DRAFT') and not args.query: + if args.force: + print('!! Force-picking a closed change !!\n') + else: + print('Change status is ' + item['status'] + '. Skipping the cherry pick.\nUse -f to force this pick.') + continue + + # Convert the project name to a project path + # - check that the project path exists + project_path = None + + if item['project'] in project_name_to_data and item['branch'] in project_name_to_data[item['project']]: + project_path = project_name_to_data[item['project']][item['branch']] + elif args.path: + project_path = args.path + elif args.ignore_missing: + print('WARNING: Skipping {0} since there is no project directory for: {1}\n'.format(item['id'], item['project'])) + continue + else: + sys.stderr.write('ERROR: For {0}, could not determine the project path for project {1}\n'.format(item['id'], item['project'])) + sys.exit(1) + + # If --start-branch is given, create the branch (more than once per path is okay; repo ignores gracefully) + if args.start_branch: + subprocess.check_output(['repo', 'start', args.start_branch[0], project_path]) + + # Determine the maximum commits to check already picked changes + check_picked_count = args.check_picked + branch_commits_count = int(subprocess.check_output(['git', 'rev-list', '--count', 'HEAD'], cwd=project_path)) + if branch_commits_count <= check_picked_count: + check_picked_count = branch_commits_count - 1 + + # Check if change is already picked to HEAD...HEAD~check_picked_count + found_change = False + for i in range(0, check_picked_count): + if subprocess.call(['git', 'cat-file', '-e', 'HEAD~{0}'.format(i)], cwd=project_path, stderr=open(os.devnull, 'wb')): + continue + output = subprocess.check_output(['git', 'show', '-q', 'HEAD~{0}'.format(i)], cwd=project_path).split() + if 'Change-Id:' in output: + head_change_id = '' + for j,t in enumerate(reversed(output)): + if t == 'Change-Id:': + head_change_id = output[len(output) - j] + break + if head_change_id.strip() == item['change_id']: + print('Skipping {0} - already picked in {1} as HEAD~{2}'.format(item['id'], project_path, i)) + found_change = True + break + if found_change: + continue + + # Print out some useful info + if not args.quiet: + print('--> Subject: "{0}"'.format(item['subject'].encode('utf-8'))) + print('--> Project path: {0}'.format(project_path)) + print('--> Change number: {0} (Patch Set {0})'.format(item['id'])) + + if 'anonymous http' in item['fetch']: + method = 'anonymous http' + else: + method = 'ssh' + + # Try fetching from GitHub first if using default gerrit + if args.gerrit == default_gerrit: + if args.verbose: + print('Trying to fetch the change from GitHub') + + if args.pull: + cmd = ['git pull --no-edit omnirom', item['fetch'][method]['ref']] + else: + cmd = ['git fetch omnirom', item['fetch'][method]['ref']] + if args.quiet: + cmd.append('--quiet') + else: + print(cmd) + result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True) + FETCH_HEAD = '{0}/.git/FETCH_HEAD'.format(project_path) + if result != 0 and os.stat(FETCH_HEAD).st_size != 0: + print('ERROR: git command failed') + sys.exit(result) + # Check if it worked + if args.gerrit != default_gerrit or os.stat(FETCH_HEAD).st_size == 0: + # If not using the default gerrit or github failed, fetch from gerrit. + if args.verbose: + if args.gerrit == default_gerrit: + print('Fetching from GitHub didn\'t work, trying to fetch the change from Gerrit') + else: + print('Fetching from {0}'.format(args.gerrit)) + + if args.pull: + cmd = ['git pull --no-edit', item['fetch'][method]['url'], item['fetch'][method]['ref']] + else: + cmd = ['git fetch', item['fetch'][method]['url'], item['fetch'][method]['ref']] + if args.quiet: + cmd.append('--quiet') + else: + print(cmd) + result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True) + if result != 0: + print('ERROR: git command failed') + sys.exit(result) + # Perform the cherry-pick + if not args.pull: + cmd = ['git cherry-pick FETCH_HEAD'] + if args.quiet: + cmd_out = open(os.devnull, 'wb') + else: + cmd_out = None + result = subprocess.call(cmd, cwd=project_path, shell=True, stdout=cmd_out, stderr=cmd_out) + if result != 0: + if args.reset: + print('ERROR: git command failed, aborting cherry-pick') + cmd = ['git cherry-pick --abort'] + subprocess.call(cmd, cwd=project_path, shell=True, stdout=cmd_out, stderr=cmd_out) + else: + print('ERROR: git command failed') + sys.exit(result) + if not args.quiet: + print('') diff --git a/soong/makevars.mk b/soong/makevars.mk index 48fca08..3dd8216 100644 --- a/soong/makevars.mk +++ b/soong/makevars.mk @@ -22,7 +22,8 @@ EXPORT_TO_SOONG := \ TW_EXTRA_LANGUAGES \ TARGET_RECOVERY_ROOT_OUT \ TARGET_RECOVERY_PIXEL_FORMAT \ - AB_OTA_UPDATER + AB_OTA_UPDATER \ + PLATFORM_SDK_VERSION SOONG_CONFIG_NAMESPACES += makeVarsPlugin diff --git a/vendorsetup.sh b/vendorsetup.sh index c5efd4d..4789850 100644 --- a/vendorsetup.sh +++ b/vendorsetup.sh @@ -1 +1 @@ -alias twrppick='repopick -g https://gerrit.twrp.me' +alias twrppick='./vendor/twrp/repopick.py -g https://gerrit.twrp.me' From 09f02a7b64e0aac0dbc314c57bae43023ef6dd37 Mon Sep 17 00:00:00 2001 From: bigbiff Date: Wed, 7 Apr 2021 15:40:32 -0400 Subject: [PATCH 05/26] vars: add TW_INCLUDE_CRYPTO_FBE --- soong/makevars.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soong/makevars.mk b/soong/makevars.mk index 3dd8216..39f898f 100644 --- a/soong/makevars.mk +++ b/soong/makevars.mk @@ -23,7 +23,8 @@ EXPORT_TO_SOONG := \ TARGET_RECOVERY_ROOT_OUT \ TARGET_RECOVERY_PIXEL_FORMAT \ AB_OTA_UPDATER \ - PLATFORM_SDK_VERSION + PLATFORM_SDK_VERSION \ + TW_INCLUDE_CRYPTO_FBE SOONG_CONFIG_NAMESPACES += makeVarsPlugin From 1cf2bc43fc8ac3511aa0ef0fa14d99b042189b8a Mon Sep 17 00:00:00 2001 From: nebrassy Date: Fri, 16 Apr 2021 23:10:57 +0200 Subject: [PATCH 06/26] add more makevars Change-Id: I6c8abbddf99b7d672a3e08618f7a59039fc06578 --- soong/makevars.mk | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/soong/makevars.mk b/soong/makevars.mk index 39f898f..d60da0d 100644 --- a/soong/makevars.mk +++ b/soong/makevars.mk @@ -24,8 +24,30 @@ EXPORT_TO_SOONG := \ TARGET_RECOVERY_PIXEL_FORMAT \ AB_OTA_UPDATER \ PLATFORM_SDK_VERSION \ - TW_INCLUDE_CRYPTO_FBE - + TW_INCLUDE_CRYPTO_FBE \ + TW_SUPPORT_INPUT_1_2_HAPTICS \ + TW_TARGET_USES_QCOM_BSP \ + TW_NEW_ION_HEAP \ + TW_INCLUDE_JPEG \ + RECOVERY_TOUCHSCREEN_SWAP_XY \ + RECOVERY_TOUCHSCREEN_FLIP_X \ + RECOVERY_TOUCHSCREEN_FLIP_Y \ + RECOVERY_GRAPHICS_FORCE_USE_LINELENGTH \ + RECOVERY_GRAPHICS_FORCE_SINGLE_BUFFER \ + TWRP_EVENT_LOGGING \ + TARGET_RECOVERY_FORCE_PIXEL_FORMAT \ + TARGET_RECOVERY_OVERSCAN_PERCENT \ + TW_SCREEN_BLANK_ON_BOOT \ + TW_FBIOPAN \ + TW_ROTATION \ + BOARD_HAS_FLIPPED_SCREEN \ + TW_IGNORE_MAJOR_AXIS_0 \ + TW_IGNORE_MT_POSITION_0 \ + TW_INPUT_BLACKLIST \ + TW_WHITELIST_INPUT \ + TW_HAPTICS_TSPDRV \ + TARGET_PREBUILT_KERNEL \ + TW_EXCLUDE_NANO SOONG_CONFIG_NAMESPACES += makeVarsPlugin SOONG_CONFIG_makeVarsPlugin := From 6e472d3adcee18860b0e5aa914a8992ad531f46c Mon Sep 17 00:00:00 2001 From: Captain Throwback Date: Fri, 3 Apr 2020 20:50:14 -0400 Subject: [PATCH 07/26] twrp: setup custom vendor for TWRP-only tree - Based on vendor_omni, renamed & cleaned up Change-Id: I4661f7cca770a4c55cfd428e60d29f994725033e --- Android.mk | 28 ++ build/core/certs.mk | 5 + build/core/qcom_target.mk | 27 ++ build/core/qcom_utils.mk | 242 +++++++++++ build/envsetup.sh | 147 +++++++ build/soong/Android.bp | 51 +++ build/soong/generator/generator.go | 309 ++++++++++++++ build/soong/generator/variables.go | 28 ++ .../target/product/security/lineage.x509.pem | 23 + build/target/product/security/magisk.x509.pem | 20 + build/target/product/security/omni.x509.pem | 23 + .../product/security/opengapps.x509.pem | 21 + build/tasks/dt_image.mk | 53 +++ build/tasks/kernel.mk | 398 ++++++++++++++++++ repopick.py => build/tools/repopick.py | 10 +- build/tools/roomservice.py | 356 ++++++++++++++++ config/BoardConfigKernel.mk | 158 +++++++ config/BoardConfigSoong.mk | 28 ++ config/BoardConfigTWRP.mk | 2 + config/common.mk | 18 + config/packages.mk | 21 + vendorsetup.sh | 1 - 22 files changed, 1963 insertions(+), 6 deletions(-) create mode 100644 Android.mk create mode 100644 build/core/certs.mk create mode 100644 build/core/qcom_target.mk create mode 100755 build/core/qcom_utils.mk create mode 100755 build/envsetup.sh create mode 100644 build/soong/Android.bp create mode 100644 build/soong/generator/generator.go create mode 100644 build/soong/generator/variables.go create mode 100644 build/target/product/security/lineage.x509.pem create mode 100644 build/target/product/security/magisk.x509.pem create mode 100644 build/target/product/security/omni.x509.pem create mode 100644 build/target/product/security/opengapps.x509.pem create mode 100644 build/tasks/dt_image.mk create mode 100644 build/tasks/kernel.mk rename repopick.py => build/tools/repopick.py (98%) create mode 100755 build/tools/roomservice.py create mode 100644 config/BoardConfigKernel.mk create mode 100644 config/BoardConfigSoong.mk create mode 100644 config/BoardConfigTWRP.mk create mode 100644 config/common.mk create mode 100644 config/packages.mk delete mode 100644 vendorsetup.sh diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..20bfbaf --- /dev/null +++ b/Android.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2011 The Android Open-Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# WARNING: Everything listed here will be built on ALL platforms, +# including x86, the emulator, and the SDK. Modules must be uniquely +# named (liblights.panda), and must build everywhere, or limit themselves +# to only building on ARM if they include assembly. Individual makefiles +# are responsible for having their own logic, for fine-grained control. + +LOCAL_PATH := $(call my-dir) + +# if some modules are built directly from this directory (not subdirectories), +# their rules should be written here. + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/build/core/certs.mk b/build/core/certs.mk new file mode 100644 index 0000000..f00e275 --- /dev/null +++ b/build/core/certs.mk @@ -0,0 +1,5 @@ +# Allow custom build keys +ifneq (${ROM_KEYS_PATH},) + PRODUCT_DEFAULT_DEV_CERTIFICATE := ${ROM_KEYS_PATH}/releasekey + PRODUCT_EXTRA_RECOVERY_KEYS := $(PRODUCT_DEFAULT_DEV_CERTIFICATE) +endif diff --git a/build/core/qcom_target.mk b/build/core/qcom_target.mk new file mode 100644 index 0000000..ef3a091 --- /dev/null +++ b/build/core/qcom_target.mk @@ -0,0 +1,27 @@ +# Bring in Qualcomm helper macros +include vendor/twrp/build/core/qcom_utils.mk + +# Target-specific configuration +ifeq ($(BOARD_USES_QCOM_HARDWARE),true) + qcom_flags := -DQCOM_HARDWARE + ifeq ($(TARGET_USES_QCOM_BSP),true) + qcom_flags += -DQCOM_BSP + qcom_flags += -DQTI_BSP + endif + +# TARGET_GLOBAL_CFLAGS += $(qcom_flags) +# TARGET_GLOBAL_CPPFLAGS += $(qcom_flags) + PRIVATE_TARGET_GLOBAL_CFLAGS += $(qcom_flags) + PRIVATE_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags) + + # Multiarch needs these too.. +# 2ND_TARGET_GLOBAL_CFLAGS += $(qcom_flags) +# 2ND_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags) +# 2ND_CLANG_TARGET_GLOBAL_CFLAGS += $(qcom_flags) +# 2ND_CLANG_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags) + + TARGET_COMPILE_WITH_MSM_KERNEL := true + MSM_VIDC_TARGET_LIST := msm8974 msm8610 msm8226 apq8084 msm8916 msm8937 msm8952 msm8953 msm8994 msm8909 msm8992 msm8996 msm8998 sdm660 sdm710 sdm845 +endif + + diff --git a/build/core/qcom_utils.mk b/build/core/qcom_utils.mk new file mode 100755 index 0000000..9c11c18 --- /dev/null +++ b/build/core/qcom_utils.mk @@ -0,0 +1,242 @@ +# Board platforms lists to be used for +# TARGET_BOARD_PLATFORM specific featurization +QCOM_BOARD_PLATFORMS := msm7627_surf +QCOM_BOARD_PLATFORMS += msm7627_6x +QCOM_BOARD_PLATFORMS += msm7627a +QCOM_BOARD_PLATFORMS += msm7630_surf +QCOM_BOARD_PLATFORMS += msm7630_fusion +QCOM_BOARD_PLATFORMS += msm8226 +QCOM_BOARD_PLATFORMS += msm8660 +QCOM_BOARD_PLATFORMS += msm8909 +QCOM_BOARD_PLATFORMS += msm8916 +QCOM_BOARD_PLATFORMS += msm8939 +QCOM_BOARD_PLATFORMS += msm8937 +QCOM_BOARD_PLATFORMS += msm8952 +QCOM_BOARD_PLATFORMS += msm8953 +QCOM_BOARD_PLATFORMS += msm8960 +QCOM_BOARD_PLATFORMS += msm8974 +QCOM_BOARD_PLATFORMS += msm8992 +QCOM_BOARD_PLATFORMS += msm8994 +QCOM_BOARD_PLATFORMS += msm8996 +QCOM_BOARD_PLATFORMS += msm8998 +QCOM_BOARD_PLATFORMS += apq8084 +QCOM_BOARD_PLATFORMS += sdm660 +QCOM_BOARD_PLATFORMS += sdm710 +QCOM_BOARD_PLATFORMS += sdm845 + +MSM7K_BOARD_PLATFORMS := msm7630_surf +MSM7K_BOARD_PLATFORMS += msm7630_fusion +MSM7K_BOARD_PLATFORMS += msm7627_surf +MSM7K_BOARD_PLATFORMS += msm7627_6x +MSM7K_BOARD_PLATFORMS += msm7627a +MSM7K_BOARD_PLATFORMS += msm7k + +QSD8K_BOARD_PLATFORMS := qsd8k + + +# vars for use by utils +empty := +space := $(empty) $(empty) +colon := $(empty):$(empty) +underscore := $(empty)_$(empty) + +# $(call match-word,w1,w2) +# checks if w1 == w2 +# How it works +# if (w1-w2 not empty or w2-w1 not empty) then not_match else match +# +# returns true or empty +#$(warning :$(1): :$(2): :$(subst $(1),,$(2)):) \ +#$(warning :$(2): :$(1): :$(subst $(2),,$(1)):) \ +# +define match-word +$(strip \ + $(if $(or $(subst $(1),$(empty),$(2)),$(subst $(2),$(empty),$(1))),,true) \ +) +endef + +# $(call find-word-in-list,w,wlist) +# finds an exact match of word w in word list wlist +# +# How it works +# fill wlist spaces with colon +# wrap w with colon +# search word w in list wl, if found match m, return stripped word w +# +# returns stripped word or empty +define find-word-in-list +$(strip \ + $(eval wl:= $(colon)$(subst $(space),$(colon),$(strip $(2)))$(colon)) \ + $(eval w:= $(colon)$(strip $(1))$(colon)) \ + $(eval m:= $(findstring $(w),$(wl))) \ + $(if $(m),$(1),) \ +) +endef + +# $(call match-word-in-list,w,wlist) +# does an exact match of word w in word list wlist +# How it works +# if the input word is not empty +# return output of an exact match of word w in wordlist wlist +# else +# return empty +# returns true or empty +define match-word-in-list +$(strip \ + $(if $(strip $(1)), \ + $(call match-word,$(call find-word-in-list,$(1),$(2)),$(strip $(1))), \ + ) \ +) +endef + +# $(call match-prefix,p,delim,w/wlist) +# matches prefix p in wlist using delimiter delim +# +# How it works +# trim the words in wlist w +# if find-word-in-list returns not empty +# return true +# else +# return empty +# +define match-prefix +$(strip \ + $(eval w := $(strip $(1)$(strip $(2)))) \ + $(eval text := $(patsubst $(w)%,$(1),$(3))) \ + $(if $(call match-word-in-list,$(1),$(text)),true,) \ +) +endef + +# ---- +# The following utilities are meant for board platform specific +# featurisation + +# $(call get-vendor-board-platforms,v) +# returns list of board platforms for vendor v +define get-vendor-board-platforms +$($(1)_BOARD_PLATFORMS) +endef + +# $(call is-board-platform,bp) +# returns true or empty +define is-board-platform +$(call match-word,$(1),$(TARGET_BOARD_PLATFORM)) +endef + +# $(call is-not-board-platform,bp) +# returns true or empty +define is-not-board-platform +$(if $(call match-word,$(1),$(TARGET_BOARD_PLATFORM)),,true) +endef + +# $(call is-board-platform-in-list,bpl) +# returns true or empty +define is-board-platform-in-list +$(call match-word-in-list,$(TARGET_BOARD_PLATFORM),$(1)) +endef + +# $(call is-vendor-board-platform,vendor) +# returns true or empty +define is-vendor-board-platform +$(strip \ + $(call match-word-in-list,$(TARGET_BOARD_PLATFORM),\ + $(call get-vendor-board-platforms,$(1)) \ + ) \ +) +endef + +# $(call is-chipset-in-board-platform,chipset) +# does a prefix match of chipset in TARGET_BOARD_PLATFORM +# uses underscore as a delimiter +# +# returns true or empty +define is-chipset-in-board-platform +$(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM)) +endef + +# $(call is-chipset-prefix-in-board-platform,prefix) +# does a chipset prefix match in TARGET_BOARD_PLATFORM +# assumes '_' and 'a' as the delimiter to the chipset prefix +# +# How it works +# if ($(prefix)_ or $(prefix)a match in board platform) +# return true +# else +# return empty +# +define is-chipset-prefix-in-board-platform +$(strip \ + $(eval delim_a := $(empty)a$(empty)) \ + $(if \ + $(or \ + $(call match-prefix,$(1),$(delim_a),$(TARGET_BOARD_PLATFORM)), \ + $(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM)), \ + ), \ + true, \ + ) \ +) +endef + +#---- +# The following utilities are meant for Android Code Name +# specific featurisation +# +# refer http://source.android.com/source/build-numbers.html +# for code names and associated sdk versions +CUPCAKE_SDK_VERSIONS := 3 +DONUT_SDK_VERSIONS := 4 +ECLAIR_SDK_VERSIONS := 5 6 7 +FROYO_SDK_VERSIONS := 8 +GINGERBREAD_SDK_VERSIONS := 9 10 +HONEYCOMB_SDK_VERSIONS := 11 12 13 +ICECREAM_SANDWICH_SDK_VERSIONS := 14 15 +JELLY_BEAN_SDK_VERSIONS := 16 17 18 +KITKAT_SDK_VERSIONS := 19 +LOLLIPOP_SDK_VERSIONS := 21 22 +MARSHMALLOW_SDK_VERSIONS := 23 +NOUGAT_SDK_VERSIONS := 24 25 +OREO_SDK_VERSIONS := 26 + +# $(call is-platform-sdk-version-at-least,version) +# version is a numeric SDK_VERSION defined above +define is-platform-sdk-version-at-least +$(strip \ + $(if $(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= $(1) ))" )), \ + true, \ + ) \ +) +endef + +# $(call is-android-codename,codename) +# codename is one of cupcake,donut,eclair,froyo,gingerbread,icecream +# please refer the $(codename)_SDK_VERSIONS declared above +define is-android-codename +$(strip \ + $(if \ + $(call match-word-in-list,$(PLATFORM_SDK_VERSION),$($(1)_SDK_VERSIONS)), \ + true, \ + ) \ +) +endef + +# $(call is-android-codename-in-list,cnlist) +# cnlist is combination/list of android codenames +define is-android-codename-in-list +$(strip \ + $(eval acn := $(empty)) \ + $(foreach \ + i,$(1),\ + $(eval acn += \ + $(if \ + $(call \ + match-word-in-list,\ + $(PLATFORM_SDK_VERSION),\ + $($(i)_SDK_VERSIONS)\ + ),\ + true,\ + )\ + )\ + ) \ + $(if $(strip $(acn)),true,) \ +) +endef diff --git a/build/envsetup.sh b/build/envsetup.sh new file mode 100755 index 0000000..5c2ce9c --- /dev/null +++ b/build/envsetup.sh @@ -0,0 +1,147 @@ +function __print_build_functions_help() { +cat < /dev/null` + do + echo "including $f" + . $f + done + unset f + + if [ $# -eq 0 ]; then + # No arguments, so let's have the full menu + lunch + else + echo "z$target" | grep -q "-" + if [ $? -eq 0 ]; then + # A buildtype was specified, assume a full device name + lunch $target + else + # This is probably just the model name + if [ -z "$variant" ]; then + variant="userdebug" + fi + lunch twrp_$target-$variant + fi + fi + return $? +} + +alias bib=breakfast + +function fixup_common_out_dir() { + common_out_dir=$(get_build_var OUT_DIR)/target/common + target_device=$(get_build_var TARGET_DEVICE) + if [ ! -z $ANDROID_FIXUP_COMMON_OUT ]; then + if [ -d ${common_out_dir} ] && [ ! -L ${common_out_dir} ]; then + mv ${common_out_dir} ${common_out_dir}-${target_device} + ln -s ${common_out_dir}-${target_device} ${common_out_dir} + else + [ -L ${common_out_dir} ] && rm ${common_out_dir} + mkdir -p ${common_out_dir}-${target_device} + ln -s ${common_out_dir}-${target_device} ${common_out_dir} + fi + else + [ -L ${common_out_dir} ] && rm ${common_out_dir} + mkdir -p ${common_out_dir} + fi +} + +# Make using all available CPUs +function mka() { + m "$@" +} + +function pushboot() { + if [ ! -f $OUT/$* ]; then + echo "File not found: $OUT/$*" + return 1 + fi + + adb root + sleep 1 + adb wait-for-device + adb remount + + adb push $OUT/$* /$* + adb reboot +} + +function repopick() { + set_stuff_for_environment + T=$(gettop) + $T/vendor/twrp/build/tools/repopick.py $@ +} + +function aospremote() +{ + if ! git rev-parse --git-dir &> /dev/null + then + echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up." + return 1 + fi + git remote rm aosp 2> /dev/null + local PROJECT=$(pwd -P | sed -e "s#$ANDROID_BUILD_TOP\/##; s#-caf.*##; s#\/default##") + # Google moved the repo location in Oreo + if [ $PROJECT = "build/make" ] + then + PROJECT="build" + fi + if (echo $PROJECT | grep -qv "^device") + then + local PFX="platform/" + fi + git remote add aosp https://android.googlesource.com/$PFX$PROJECT + echo "Remote 'aosp' created" +} + +function cafremote() +{ + if ! git rev-parse --git-dir &> /dev/null + then + echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up." + return 1 + fi + git remote rm caf 2> /dev/null + local PROJECT=$(pwd -P | sed -e "s#$ANDROID_BUILD_TOP\/##; s#-caf.*##; s#\/default##") + # Google moved the repo location in Oreo + if [ $PROJECT = "build/make" ] + then + PROJECT="build" + fi + if [[ $PROJECT =~ "qcom/opensource" ]]; + then + PROJECT=$(echo $PROJECT | sed -e "s#qcom\/opensource#qcom-opensource#") + fi + if (echo $PROJECT | grep -qv "^device") + then + local PFX="platform/" + fi + git remote add caf https://source.codeaurora.org/quic/la/$PFX$PROJECT + echo "Remote 'caf' created" +} + +# Enable SD-LLVM if available +if [ -d $(gettop)/vendor/qcom/sdclang ]; then + export SDCLANG=true + export SDCLANG_PATH="vendor/qcom/sdclang/4.0.2/prebuilt/linux-x86_64/bin" + export SDCLANG_LTO_DEFS="vendor/qcom/sdclang/sdllvm-lto-defs.mk" + export SDCLANG_CONFIG="vendor/qcom/sdclang/sdclang.json" + export SDCLANG_AE_CONFIG="vendor/qcom/sdclang/sdclangAE.json" +fi diff --git a/build/soong/Android.bp b/build/soong/Android.bp new file mode 100644 index 0000000..d04535a --- /dev/null +++ b/build/soong/Android.bp @@ -0,0 +1,51 @@ +// TWRP soong configs + +bootstrap_go_package { + name: "soong-twrp-generator", + pkgPath: "twrp/soong/generator", + deps: [ + "blueprint", + "blueprint-pathtools", + "soong", + "soong-android", + "soong-shared", + ], + srcs: [ + "generator/generator.go", + "generator/variables.go", + ], + pluginFor: ["soong_build"], +} + +twrp_generator { + name: "generated_kernel_includes", + + // The headers make command + cmd: "$(PATH_OVERRIDE_SOONG) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(TARGET_KERNEL_SOURCE) O=$(KERNEL_BUILD_OUT_PREFIX)$(genDir) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) headers_install", + + // Directories that can be imported by a cc_* module generated_headers property + export_include_dirs: [ + "usr/audio/include/uapi", + "usr/include", + "usr/include/audio/include/uapi", + "usr/techpack/audio/include", + ], + + // Sources for dependency tracking + dep_root: "$(TARGET_KERNEL_SOURCE)", + dep_files: [ + "Makefile", + "include/**/*", + "arch/$(KERNEL_ARCH)/include/**/*", + "techpack/audio/include/**/*", + ], +} + +cc_library_headers { + name: "generated_kernel_headers", + generated_headers: ["generated_kernel_includes"], + export_generated_headers: ["generated_kernel_includes"], + vendor_available: true, + recovery_available: true, +} + diff --git a/build/soong/generator/generator.go b/build/soong/generator/generator.go new file mode 100644 index 0000000..380f2ae --- /dev/null +++ b/build/soong/generator/generator.go @@ -0,0 +1,309 @@ +// Copyright 2015 Google Inc. All rights reserved. +// Copyright (C) 2018 The LineageOS Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package generator + +import ( + "fmt" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/bootstrap" + "github.com/google/blueprint/proptools" + + "android/soong/android" + "android/soong/shared" + "path/filepath" +) + +func init() { + android.RegisterModuleType("twrp_generator", GeneratorFactory) + + pctx.HostBinToolVariable("sboxCmd", "sbox") +} + +var String = proptools.String + +var ( + pctx = android.NewPackageContext("android/soong/generator") +) + +type HostToolProvider interface { + HostToolPath() android.OptionalPath +} + +type hostToolDependencyTag struct { + blueprint.BaseDependencyTag +} + +var hostToolDepTag hostToolDependencyTag + +type generatorProperties struct { + // The command to run on one or more input files. Cmd supports substitution of a few variables + // (the actual substitution is implemented in GenerateAndroidBuildActions below) + // + // Available variables for substitution: + // + // $(location): the path to the first entry in tools or tool_files + // $(location