16k: VTS: Check vendor ELFs are 64KB aligned

Check that ELF files on the vendor partition are at least
64KB aligned starting from U (34). Android makes sparse copies
of the files so the *real* disk space usage is the same as 4KB
aligned binaries. Note tools like `ls` will still show an
increase in disk space usage, but that is only the apparent file
size, as the same 4KB block size is used in the read only
partitions.

Bug: 277360995
Test: atest -c vendor_elf_alignment_test -s <serial>
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Change-Id: Id1da3c44391f6ebc42c0d94e7f11424a90674234
diff --git a/page_size_16kb/Android.bp b/page_size_16kb/Android.bp
new file mode 100644
index 0000000..e64db54
--- /dev/null
+++ b/page_size_16kb/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2023 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.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+sh_test {
+    name: "vendor_elf_alignment_test",
+    src: "vendor_elf_alignment_test.sh",
+    test_suites: [
+        "device-tests",
+        "vts",
+    ],
+    test_config: "vendor_elf_alignment_test.xml",
+}
diff --git a/page_size_16kb/OWNERS b/page_size_16kb/OWNERS
new file mode 100644
index 0000000..392e306
--- /dev/null
+++ b/page_size_16kb/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1261834
+jyescas@google.com
+kaleshsingh@google.com
+surenb@google.com
diff --git a/page_size_16kb/vendor_elf_alignment_test.sh b/page_size_16kb/vendor_elf_alignment_test.sh
new file mode 100755
index 0000000..0d6802d
--- /dev/null
+++ b/page_size_16kb/vendor_elf_alignment_test.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+# Copyright (C) 2023 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.
+
+# Check that vendor ELF files have the required 16KB [or 64KB] load segment
+# alignment on devices.
+
+# Requirement added in U (34)
+MIN_VENDOR_API_LEVEL=34
+
+DEFAULT_VENDOR_API_LEVEL=0
+
+# Default to 64KB max page size unless otherwise specified.
+DEFAULT_MAX_PAGE_SIZE=65536
+
+# Device is only low RAM if explicitly stated
+DEFAULT_CONFIG_LOW_RAM=false
+
+fail() { #msg
+    echo "FAILED: $1"
+    exit 1
+}
+
+pass() { #msg
+    echo "PASSED: $1"
+    exit 0
+}
+
+skip() { #msg
+    echo "SKIPPED: $1"
+    exit 0
+}
+
+# Skip test if vendor API level < U (34)
+vendor_api_level="$(adb shell getprop ro.vendor.api_level $DEFAULT_VENDOR_API_LEVEL)"
+if [ "$vendor_api_level" -lt "$MIN_VENDOR_API_LEVEL" ]; then
+    skip "Vendor API level ($vendor_api_level) < Min vendor API level ($MIN_VENDOR_API_LEVEL)"
+fi
+
+# Android Go and other low RAM devices do not support larger than 4KB page size
+config_low_ram="$(adb shell getprop ro.config.low_ram $DEFAULT_CONFIG_LOW_RAM)"
+if [ "$config_low_ram" != "$DEFAULT_CONFIG_LOW_RAM" ]; then
+    skip "Low RAM devices only support 4096 max page size"
+fi
+
+# Some devices may choose to opt out of 64KB max page size support
+max_page_size="$(adb shell getprop ro.product.cpu.pagesize.max $DEFAULT_MAX_PAGE_SIZE)"
+if [ $max_page_size -lt $DEFAULT_MAX_PAGE_SIZE ]; then
+    skip "Device only supports $max_page_size max page size"
+fi
+
+
+unaligned_elfs=()
+
+get_unaligned_elfs() {
+    adb shell '
+        # Find all vendor ELF files
+        paths=()
+        for i in `find /vendor -type f -exec file {} \; | grep ELF | awk -F: "{ print \\$1 }"`; do
+            paths+=( $i )
+        done
+
+        unaligned=()
+        for path in "${paths[@]}"; do
+            load_alignment=$( readelf -l $path | grep LOAD | head -n1 | awk "{ print \$NF }" )
+
+            # Require 64KB alignment for future proofing. Android uses sparse files so
+            # the real disk space impact is not significant.
+            if [ "$load_alignment" != "0x10000" ]; then
+                unaligned+=( $path )
+            fi
+        done
+
+        echo "${unaligned[@]}"'
+}
+
+print_unaligned_elfs() { # arr_unaligned_elfs
+    elfs=("$@")
+
+    echo ""
+    echo "=== Unaligned vendor ELF files found ==="
+    echo ""
+    for elf in ${elfs[@]}; do
+        echo "    $elf"
+    done
+    echo ""
+    echo "Please rebuild the above artifacts with 64KB aligned load segments."
+    echo ""
+    echo "    This can be done by specifying the following linker flag:"
+    echo "        -Wl,-z,max-page-size=65536"
+    echo ""
+    echo "This is required in devices with Vendor API Level >= $MIN_VENDOR_API_LEVEL"
+    echo ""
+}
+
+# @VsrTest = 3.3-005
+vendor_elf_alignment_test() {
+    unaligned_elfs+=( $(get_unaligned_elfs) )
+    nr_unaligned="${#unaligned_elfs[@]}"
+
+    if [ "$nr_unaligned" == "0" ]; then
+        pass "All vendor ELF files have the required load segment alignment"
+    else
+        print_unaligned_elfs "${unaligned_elfs[@]}"
+        fail "Vendor ELF files with unaligned load segments found"
+    fi
+}
+
+vendor_elf_alignment_test
diff --git a/page_size_16kb/vendor_elf_alignment_test.xml b/page_size_16kb/vendor_elf_alignment_test.xml
new file mode 100644
index 0000000..7c372c1
--- /dev/null
+++ b/page_size_16kb/vendor_elf_alignment_test.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<configuration description="64KB Vendor ELF Alignment Test">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+    <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
+        <option name="binary" value="vendor_elf_alignment_test" />
+        <option name="per-binary-timeout" value="5m" />
+    </test>
+</configuration>