Merge "Add repack_super_image"
diff --git a/build/sdk-android-x86.atree b/build/sdk-android-x86.atree
index da92d9e..913fce0 100644
--- a/build/sdk-android-x86.atree
+++ b/build/sdk-android-x86.atree
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-prebuilts/qemu-kernel/x86_64/4.14/kernel-qemu2 system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/kernel-ranchu-64
+prebuilts/qemu-kernel/x86_64/5.4/kernel-qemu2 system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/kernel-ranchu-64
 device/generic/goldfish/data/etc/encryptionkey.img system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/encryptionkey.img
 
 # version files for the SDK updater, from development.git
diff --git a/build/sdk-android-x86_64.atree b/build/sdk-android-x86_64.atree
index d78bfb4..0b2202e 100644
--- a/build/sdk-android-x86_64.atree
+++ b/build/sdk-android-x86_64.atree
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-prebuilts/qemu-kernel/${TARGET_ARCH}/4.14/kernel-qemu2 system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/kernel-ranchu
+prebuilts/qemu-kernel/${TARGET_ARCH}/5.4/kernel-qemu2 system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/kernel-ranchu
 device/generic/goldfish/data/etc/encryptionkey.img system-images/${PLATFORM_NAME}/${TARGET_CPU_ABI}/encryptionkey.img
 
 # version files for the SDK updater, from development.git
diff --git a/tools/privapp_permissions/privapp_permissions.py b/tools/privapp_permissions/privapp_permissions.py
index 4016573..d61319e 100755
--- a/tools/privapp_permissions/privapp_permissions.py
+++ b/tools/privapp_permissions/privapp_permissions.py
@@ -38,7 +38,7 @@
 Usage:
     Specify which apk to generate priv-app permissions for. If no apk is \
 specified, this will default to all APKs under "<ANDROID_PRODUCT_OUT>/ \
-system/priv-app".
+system/priv-app and (system/)product/priv-app".
 
 Examples:
 
@@ -156,9 +156,18 @@
                 'You must either set up your build environment, or specify a '
                 'device to run against. See --help for more info.')
 
-        self.privapp_apks = self._resolve_apks(apks)
-        self.permissions_dir = self._resolve_sys_path('system/etc/permissions')
-        self.sysconfig_dir = self._resolve_sys_path('system/etc/sysconfig')
+        self.system_privapp_apks, self.product_privapp_apks =(
+                self._resolve_apks(apks))
+        self.system_permissions_dir = (
+                self._resolve_sys_path('system/etc/permissions'))
+        self.system_sysconfig_dir = (
+                self._resolve_sys_path('system/etc/sysconfig'))
+        self.product_permissions_dir = (
+                self._resolve_sys_path('product/etc/permissions',
+                                       'system/product/etc/permissions'))
+        self.product_sysconfig_dir = (
+                self._resolve_sys_path('product/etc/sysconfig',
+                                       'system/product/etc/sysconfig'))
         self.framework_res_apk = self._resolve_sys_path('system/framework/'
                                                         'framework-res.apk')
 
@@ -289,7 +298,8 @@
             be found.
         """
         if not apks:
-            return self._resolve_all_privapps()
+            return (self._resolve_all_system_privapps(),
+                   self._resolve_all_product_privapps())
 
         ret_apks = []
         for apk in apks:
@@ -306,29 +316,77 @@
                 raise MissingResourceError('File "%s" does not exist.' % apk)
             else:
                 ret_apks.append(apk)
-        return ret_apks
+        return ret_apks, None
 
-    def _resolve_all_privapps(self):
+    def _resolve_all_system_privapps(self):
         """Extract package name and requested permissions."""
         if self._is_android_env:
-            priv_app_dir = os.path.join(os.environ['ANDROID_PRODUCT_OUT'],
-                                        'system/priv-app')
+            system_priv_app_dir = (
+                    os.path.join(os.environ['ANDROID_PRODUCT_OUT'],
+                                            'system/priv-app'))
         else:
             try:
-                priv_app_dir = self.adb.pull('/system/priv-app/')
+                system_priv_app_dir = self.adb.pull('/system/priv-app/')
             except subprocess.CalledProcessError:
                 raise MissingResourceError(
                     'Directory "/system/priv-app" could not be pulled from on '
                     'device "%s".' % self.adb.serial)
 
-        return get_output('find %s -name "*.apk"' % priv_app_dir).split()
+        return get_output('find %s -name "*.apk"' % system_priv_app_dir).split()
 
-    def _resolve_sys_path(self, file_path):
+    def _resolve_all_product_privapps(self):
+        """Extract package name and requested permissions."""
+        if self._is_android_env:
+            product_priv_app_dir = (
+                    os.path.join(os.environ['ANDROID_PRODUCT_OUT'],
+                                            'product/priv-app'))
+            if not os.path.exists(product_priv_app_dir):
+                product_priv_app_dir  = (
+                        os.path.join(os.environ['ANDROID_PRODUCT_OUT'],
+                                                'system/product/priv-app'))
+        else:
+            try:
+                product_priv_app_dir = self.adb.pull('/product/priv-app/')
+            except subprocess.CalledProcessError:
+                print('Warning: Directory "/product/priv-app" could not be '
+                        'pulled from on device "%s". Trying '
+                        '"/system/product/priv-app"' % self.adb.serial,
+                        file=sys.stderr)
+                try:
+                    product_priv_app_dir = (
+                            self.adb.pull('/system/product/priv-app/'))
+                except subprocess.CalledProcessError:
+                    raise MissingResourceError(
+                        'Directory "/system/product/priv-app" could not be '
+                        'pulled from on device "%s".' % self.adb.serial)
+
+        return get_output(
+                'find %s -name "*.apk"' % product_priv_app_dir).split()
+
+    def _resolve_sys_path(self, file_path, fallback_file_path=None):
         """Resolves a path that is a part of an Android System Image."""
         if self._is_android_env:
-            return os.path.join(os.environ['ANDROID_PRODUCT_OUT'], file_path)
+            sys_path = (
+                    os.path.join(os.environ['ANDROID_PRODUCT_OUT'], file_path))
+            if not os.path.exists(sys_path):
+                sys_path = (
+                        os.path.join(os.environ['ANDROID_PRODUCT_OUT'],
+                        fallback_file_path))
         else:
-            return self.adb.pull(file_path)
+            try:
+                sys_path = self.adb.pull(file_path)
+            except subprocess.CalledProcessError:
+                print('Warning: Directory %s could not be pulled from on device'
+                        '"%s". Trying "/system/product/priv-app"'
+                        % (file_path, self.adb.serial), file=sys.stderr)
+                try:
+                    sys_path = self.adb.pull(fallback_file_path)
+                except subprocess.CalledProcessError:
+                    raise MissingResourceError(
+                        'Directory %s could not be pulled from on '
+                        'device "%s".' % (fallback_file_path, self.adb.serial))
+
+        return sys_path
 
 
 def get_output(command):
@@ -390,17 +448,38 @@
         help='A list of paths to priv-app APKs to generate permissions for. '
              'To make a path device-side, prefix the path with "device:".'
     )
+    parser.add_argument(
+        '-w',
+        '--writetodisk',
+        action='store_true',
+        default=False,
+        required=False,
+        help='Whether or not to store the generated permissions directly to '
+             'a file. See --systemfile/--productfile for more information.'
+    )
+    parser.add_argument(
+        '--systemfile',
+        default='./system.xml',
+        required=False,
+        help='Path to system permissions file. Default value is ./system.xml'
+    )
+    parser.add_argument(
+        '--productfile',
+        default='./product.xml',
+        required=False,
+        help='Path to system permissions file. Default value is ./product.xml'
+    )
     cmd_args = parser.parse_args()
 
     return cmd_args
 
-
-def create_permission_file(resources):
+def create_permission_file(resources, privapp_apks, permissions_dir,
+            sysconfig_dir, file=None):
     # Parse base XML files in /etc dir, permissions listed there don't have
     # to be re-added
     base_permissions = {}
-    base_xml_files = itertools.chain(list_xml_files(resources.permissions_dir),
-                                     list_xml_files(resources.sysconfig_dir))
+    base_xml_files = itertools.chain(list_xml_files(permissions_dir),
+                                     list_xml_files(sysconfig_dir))
     for xml_file in base_xml_files:
         parse_config_xml(xml_file, base_permissions)
 
@@ -409,7 +488,7 @@
 
     apps_redefine_base = []
     results = {}
-    for priv_app in resources.privapp_apks:
+    for priv_app in privapp_apks:
         pkg_info = extract_pkg_and_requested_permissions(resources.aapt,
                                                          priv_app)
         pkg_name = pkg_info['package_name']
@@ -426,7 +505,8 @@
             results[pkg_name] = sorted(priv_perms)
 
     print_xml(results, apps_redefine_base)
-
+    if file is not None:
+        print_xml(results, apps_redefine_base, file)
 
 def print_xml(results, apps_redefine_base, fd=sys.stdout):
     """Print results to the given file."""
@@ -572,7 +652,43 @@
             serial=args.serial,
             apks=args.apks
         )
-        create_permission_file(tool_resources)
+        system_permission_file=None
+        product_permission_file=None
+        print('#' * 80)
+        print('#')
+        if args.writetodisk:
+            print('#System XML written to %s:' % args.systemfile)
+            system_permission_file = open(args.systemfile, 'w')
+        else:
+            print('#System XML:')
+        print('#')
+        print('#' * 80)
+        create_permission_file(
+            tool_resources,
+            tool_resources.system_privapp_apks,
+            tool_resources.system_permissions_dir,
+            tool_resources.system_sysconfig_dir,
+            system_permission_file)
+        if args.writetodisk:
+            system_permission_file.close()
+        if tool_resources.product_privapp_apks:
+            print('#' * 80)
+            print('#')
+            if args.writetodisk:
+                print('#Product XML written to %s:' % args.productfile)
+                product_permission_file = open(args.productfile, 'w')
+            else:
+                print('#Product XML:')
+            print('#')
+            print('#' * 80)
+            create_permission_file(
+                tool_resources,
+                tool_resources.product_privapp_apks,
+                tool_resources.product_permissions_dir,
+                tool_resources.product_sysconfig_dir,
+                product_permission_file)
+            if args.writetodisk:
+                product_permission_file.close()
     except MissingResourceError as e:
         print(str(e), file=sys.stderr)
         exit(1)
diff --git a/vndk/tools/header-checker/src/repr/symbol/so_file_parser.cpp b/vndk/tools/header-checker/src/repr/symbol/so_file_parser.cpp
index 9320a54..77356db 100644
--- a/vndk/tools/header-checker/src/repr/symbol/so_file_parser.cpp
+++ b/vndk/tools/header-checker/src/repr/symbol/so_file_parser.cpp
@@ -101,11 +101,18 @@
         LLVMToIRSymbolBinding(elf_sym->getBinding());
     std::string symbol_name = UnWrap(symbol_it.getName());
 
-    llvm::object::SymbolRef::Type type = UnWrap(symbol_it.getType());
-    if (type == llvm::object::SymbolRef::Type::ST_Function) {
-      exported_symbols_->AddFunction(symbol_name, symbol_binding);
-    } else if (type == llvm::object::SymbolRef::Type::ST_Data) {
-      exported_symbols_->AddVar(symbol_name, symbol_binding);
+    switch (symbol_it.getELFType()) {
+      case llvm::ELF::STT_OBJECT:
+      case llvm::ELF::STT_COMMON:
+      case llvm::ELF::STT_TLS:
+        exported_symbols_->AddVar(symbol_name, symbol_binding);
+        break;
+      case llvm::ELF::STT_FUNC:
+      case llvm::ELF::STT_GNU_IFUNC:
+        exported_symbols_->AddFunction(symbol_name, symbol_binding);
+        break;
+      default:
+        break;
     }
   }
 }
diff --git a/vndk/tools/header-checker/tests/integration/ifunc/Android.bp b/vndk/tools/header-checker/tests/integration/ifunc/Android.bp
new file mode 100644
index 0000000..207fd9b
--- /dev/null
+++ b/vndk/tools/header-checker/tests/integration/ifunc/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2020 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.
+//
+
+cc_library {
+    name: "libifunc",
+    srcs: [
+        "ifunc.c",
+    ],
+    enabled: false,
+}
diff --git a/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c b/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c
new file mode 100644
index 0000000..f2f84df
--- /dev/null
+++ b/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c
@@ -0,0 +1,5 @@
+__attribute__((used)) static void *ifunc_resolver() {
+  return 0;
+}
+
+void ifunc() __attribute__((ifunc("ifunc_resolver")));
diff --git a/vndk/tools/header-checker/tests/integration/ifunc/map.txt b/vndk/tools/header-checker/tests/integration/ifunc/map.txt
new file mode 100644
index 0000000..80649a4
--- /dev/null
+++ b/vndk/tools/header-checker/tests/integration/ifunc/map.txt
@@ -0,0 +1,4 @@
+libifunc {
+  global:
+    ifunc;
+};
diff --git a/vndk/tools/header-checker/tests/integration/ifunc/prebuilts/libifunc.so b/vndk/tools/header-checker/tests/integration/ifunc/prebuilts/libifunc.so
new file mode 100755
index 0000000..ce122ec
--- /dev/null
+++ b/vndk/tools/header-checker/tests/integration/ifunc/prebuilts/libifunc.so
Binary files differ
diff --git a/vndk/tools/header-checker/tests/module.py b/vndk/tools/header-checker/tests/module.py
index c339615..338058d 100755
--- a/vndk/tools/header-checker/tests/module.py
+++ b/vndk/tools/header-checker/tests/module.py
@@ -414,6 +414,17 @@
         export_include_dirs=['integration/c_and_cpp/include'],
     ),
     LsdumpModule(
+        name='libifunc',
+        srcs=['integration/ifunc/ifunc.c'],
+        version_script='integration/ifunc/map.txt',
+        export_include_dirs=[],
+        linker_flags=[
+            '-so', relative_to_abs_path(
+                'integration/ifunc/prebuilts/libifunc.so'
+            ),
+        ]
+    ),
+    LsdumpModule(
         name='libgolden_cpp_member_name_changed',
         srcs=[
             'integration/cpp/gold/golden_1.cpp',
diff --git a/vndk/tools/header-checker/tests/reference_dumps/arm/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/arm/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/arm/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/reference_dumps/arm64/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/arm64/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/arm64/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/reference_dumps/mips/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/mips/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/mips/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/reference_dumps/mips64/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/mips64/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/mips64/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/reference_dumps/x86/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/x86/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/x86/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/reference_dumps/x86_64/libifunc.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/x86_64/libifunc.so.lsdump
new file mode 100644
index 0000000..3ddc48c
--- /dev/null
+++ b/vndk/tools/header-checker/tests/reference_dumps/x86_64/libifunc.so.lsdump
@@ -0,0 +1,24 @@
+builtin_types {
+  type_info {
+    name: "void"
+    size: 0
+    alignment: 0
+    referenced_type: "_ZTIv"
+    source_file: ""
+    linker_set_key: "_ZTIv"
+    self_type: "_ZTIv"
+  }
+  is_unsigned: false
+  is_integral: false
+}
+functions {
+  return_type: "_ZTIv"
+  function_name: "ifunc"
+  source_file: "/development/vndk/tools/header-checker/tests/integration/ifunc/ifunc.c"
+  linker_set_key: "ifunc"
+  access: public_access
+}
+elf_functions {
+  name: "ifunc"
+  binding: Global
+}
diff --git a/vndk/tools/header-checker/tests/test.py b/vndk/tools/header-checker/tests/test.py
index b1da06b..0bbd4cd 100755
--- a/vndk/tools/header-checker/tests/test.py
+++ b/vndk/tools/header-checker/tests/test.py
@@ -372,6 +372,10 @@
         self.prepare_and_absolute_diff_all_archs(
             "libanonymous_enum_odr", "libanonymous_enum_odr")
 
+    def test_libifunc(self):
+        self.prepare_and_absolute_diff_all_archs(
+            "libifunc", "libifunc")
+
 
 if __name__ == '__main__':
     unittest.main()