Merge "Add a new system property persist.graphics.egl"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 4148002..9aa510b 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -16,14 +16,14 @@
                     "include-filter": "android.security.cts.SeamendcHostTest"
                 }
             ]
+        }
+    ],
+    "avf-presubmit": [
+        {
+            "name": "ComposHostTestCases"
         },
         {
             "name": "MicrodroidHostTestCases"
         }
-    ],
-    "avf-postsubmit": [
-        {
-            "name": "ComposHostTestCases"
-        }
     ]
 }
diff --git a/build/soong/service_fuzzer_bindings.go b/build/soong/service_fuzzer_bindings.go
index d91ef21..c8359f0 100644
--- a/build/soong/service_fuzzer_bindings.go
+++ b/build/soong/service_fuzzer_bindings.go
@@ -39,6 +39,7 @@
 		"android.hardware.boot.IBootControl/default":                              EXCEPTION_NO_FUZZER,
 		"android.hardware.automotive.can.ICanController/default":                  EXCEPTION_NO_FUZZER,
 		"android.hardware.automotive.evs.IEvsEnumerator/hw/1":                     EXCEPTION_NO_FUZZER,
+		"android.hardware.automotive.ivn.IIvnAndroidDevice/default":               EXCEPTION_NO_FUZZER,
 		"android.hardware.automotive.remoteaccess.IRemoteAccess/default":          EXCEPTION_NO_FUZZER,
 		"android.hardware.automotive.vehicle.IVehicle/default":                    EXCEPTION_NO_FUZZER,
 		"android.hardware.automotive.audiocontrol.IAudioControl/default":          EXCEPTION_NO_FUZZER,
diff --git a/private/compat/33.0/33.0.ignore.cil b/private/compat/33.0/33.0.ignore.cil
index d2a4be4..3bfdcc8 100644
--- a/private/compat/33.0/33.0.ignore.cil
+++ b/private/compat/33.0/33.0.ignore.cil
@@ -30,6 +30,7 @@
     hal_bluetooth_service
     hal_bootctl_service
     hal_cas_service
+    hal_ivn_service
     hal_remoteaccess_service
     hal_secure_element_service
     hal_tetheroffload_service
diff --git a/private/linkerconfig.te b/private/linkerconfig.te
index 2688102..7e78c19 100644
--- a/private/linkerconfig.te
+++ b/private/linkerconfig.te
@@ -11,7 +11,7 @@
 allow linkerconfig kmsg_device:chr_file w_file_perms;
 
 # Allow linkerconfig to be invoked with logwrapper from init.
-allow linkerconfig devpts:chr_file { read write };
+allow linkerconfig devpts:chr_file { getattr ioctl read write };
 
 # Allow linkerconfig to scan for apex modules
 allow linkerconfig apex_mnt_dir:dir r_dir_perms;
diff --git a/private/property_contexts b/private/property_contexts
index f19ae0c..51e6cf8 100644
--- a/private/property_contexts
+++ b/private/property_contexts
@@ -390,6 +390,10 @@
 # to enable head tracking for spatial audio
 ro.audio.headtracking_enabled u:object_r:audio_config_prop:s0 exact bool
 
+# Boolean property used in UsbAlsaManager to decide if only one or multiple
+# USB devices can be connected to audio system at a certain time
+ro.audio.multi_usb_mode u:object_r:audio_config_prop:s0 exact bool
+
 persist.config.calibration_fac u:object_r:camera_calibration_prop:s0 exact string
 
 config.disable_cameraservice u:object_r:camera_config_prop:s0 exact bool
diff --git a/private/service_contexts b/private/service_contexts
index 9755eaa..5fc14f3 100644
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -20,6 +20,7 @@
 android.hardware.automotive.can.ICanController/default               u:object_r:hal_can_controller_service:s0
 android.hardware.automotive.evs.IEvsEnumerator/hw/1                  u:object_r:hal_evs_service:s0
 android.hardware.automotive.audiocontrol.IAudioControl/default       u:object_r:hal_audiocontrol_service:s0
+android.hardware.automotive.ivn.IIvnAndroidDevice/default            u:object_r:hal_ivn_service:s0
 android.hardware.automotive.remoteaccess.IRemoteAccess/default       u:object_r:hal_remoteaccess_service:s0
 android.hardware.automotive.vehicle.IVehicle/default                 u:object_r:hal_vehicle_service:s0
 android.hardware.biometrics.face.IFace/default                       u:object_r:hal_face_service:s0
diff --git a/public/attributes b/public/attributes
index 1e2dabb..09463e3 100644
--- a/public/attributes
+++ b/public/attributes
@@ -352,6 +352,7 @@
 hal_attribute(input_classifier);
 hal_attribute(input_processor);
 hal_attribute(ir);
+hal_attribute(ivn);
 hal_attribute(keymaster);
 hal_attribute(keymint);
 hal_attribute(light);
diff --git a/public/hal_ivn.te b/public/hal_ivn.te
new file mode 100644
index 0000000..b10e9f2
--- /dev/null
+++ b/public/hal_ivn.te
@@ -0,0 +1,4 @@
+# HwBinder IPC from client to server, and callbacks
+binder_call(hal_ivn_client, hal_ivn_server)
+
+hal_attribute_service(hal_ivn, hal_ivn_service)
\ No newline at end of file
diff --git a/public/service.te b/public/service.te
index 3dc9d85..0936cc4 100644
--- a/public/service.te
+++ b/public/service.te
@@ -296,6 +296,7 @@
 type hal_identity_service, protected_service, hal_service_type, service_manager_type;
 type hal_input_processor_service, protected_service, hal_service_type, service_manager_type;
 type hal_ir_service, protected_service, hal_service_type, service_manager_type;
+type hal_ivn_service, protected_service, hal_service_type, service_manager_type;
 type hal_keymint_service, protected_service, hal_service_type, service_manager_type;
 type hal_light_service, protected_service, hal_service_type, service_manager_type;
 type hal_memtrack_service, protected_service, hal_service_type, service_manager_type;
diff --git a/tests/Android.bp b/tests/Android.bp
index e271346..cc0bdc1 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -70,6 +70,44 @@
 }
 
 python_binary_host {
+    name: "apex_sepolicy_tests",
+    srcs: [
+        "apex_sepolicy_tests.py",
+    ],
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
+    libs: ["pysepolwrap"],
+    data: [
+        ":libsepolwrap",
+        ":precompiled_sepolicy",
+    ],
+}
+
+python_test_host {
+    name: "apex_sepolicy_tests_test",
+    srcs: [
+        "apex_sepolicy_tests.py",
+        "apex_sepolicy_tests_test.py",
+    ],
+    libs: ["pysepolwrap"],
+    data: [
+        ":libsepolwrap",
+        ":precompiled_sepolicy",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
+}
+
+python_binary_host {
     name: "searchpolicy",
     srcs: [
         "searchpolicy.py",
diff --git a/tests/apex_sepolicy_tests.py b/tests/apex_sepolicy_tests.py
new file mode 100644
index 0000000..2cdde3c
--- /dev/null
+++ b/tests/apex_sepolicy_tests.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python3
+#
+# Copyright 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.
+""" A tool to test APEX file_contexts
+
+Usage:
+    $ deapexer list -Z foo.apex > /tmp/fc
+    $ apex_sepolicy_tests -f /tmp/fc
+"""
+
+
+import argparse
+import os
+import pathlib
+import pkgutil
+import re
+import sys
+import tempfile
+from dataclasses import dataclass
+from typing import List
+
+import policy
+
+
+SHARED_LIB_EXTENSION = '.dylib' if sys.platform == 'darwin' else '.so'
+LIBSEPOLWRAP = "libsepolwrap" + SHARED_LIB_EXTENSION
+
+
+@dataclass
+class Is:
+    """Exact matcher for a path."""
+    path: str
+
+
+@dataclass
+class Glob:
+    """Path matcher with pathlib.PurePath.match"""
+    pattern: str
+
+
+@dataclass
+class Regex:
+    """Path matcher with re.match"""
+    pattern: str
+
+
+Matcher = Is | Glob | Regex
+
+@dataclass
+class AllowRead:
+    """Rule checking if scontext can read the entity"""
+    tclass: str
+    scontext: set[str]
+
+
+Rule = AllowRead
+
+
+def match_path(path: str, matcher: Matcher) -> bool:
+    """True if path matches with the given matcher"""
+    match matcher:
+        case Is(target):
+            return path == target
+        case Glob(pattern):
+            return pathlib.PurePath(path).match(pattern)
+        case Regex(pattern):
+            return re.match(pattern, path)
+
+
+def check_rule(pol, path: str, tcontext: str, rule: Rule) -> List[str]:
+    """Returns error message if scontext can't read the target"""
+    match rule:
+        case AllowRead(tclass, scontext):
+            te_rules = list(pol.QueryTERule(scontext=scontext,
+                                            tcontext={tcontext},
+                                            tclass={tclass},
+                                            perms={'read'}))
+            if len(te_rules) > 0:
+                return []  # no errors
+
+            return [f"Error: {path}: {scontext} can't read. (tcontext={tcontext})"]
+
+
+rules = [
+    # permissions
+    (Is('./etc/permissions/'), AllowRead('dir', {'system_server'})),
+    (Glob('./etc/permissions/*.xml'), AllowRead('file', {'system_server'})),
+    # init scripts with optional SDK version (e.g. foo.rc, foo.32rc)
+    (Regex('\./etc/.*\.\d*rc'), AllowRead('file', {'init'})),
+    # vintf fragments
+    (Is('./etc/vintf/'), AllowRead('dir', {'servicemanager', 'apexd'})),
+    (Glob('./etc/vintf/*.xml'), AllowRead('file', {'servicemanager', 'apexd'})),
+    # ./ and apex_manifest.pb
+    (Is('./apex_manifest.pb'), AllowRead('file', {'linkerconfig', 'apexd'})),
+    (Is('./'), AllowRead('dir', {'linkerconfig', 'apexd'})),
+]
+
+
+def check_line(pol: policy.Policy, line: str) -> List[str]:
+    """Parses a file_contexts line and runs checks"""
+    # skip empty/comment line
+    line = line.strip()
+    if line == '' or line[0] == '#':
+        return []
+
+    # parse
+    split = line.split()
+    if len(split) != 2:
+        return [f"Error: invalid file_contexts: {line}"]
+    path, context = split[0], split[1]
+    if len(context.split(':')) != 4:
+        return [f"Error: invalid file_contexts: {line}"]
+    tcontext = context.split(':')[2]
+
+    # check rules
+    errors = []
+    for matcher, rule in rules:
+        if match_path(path, matcher):
+            errors.extend(check_rule(pol, path, tcontext, rule))
+    return errors
+
+
+def extract_data(name, temp_dir):
+    out_path = os.path.join(temp_dir, name)
+    with open(out_path, 'wb') as f:
+        blob = pkgutil.get_data('apex_sepolicy_tests', name)
+        if not blob:
+            sys.exit(f"Error: {name} does not exist. Is this binary corrupted?\n")
+        f.write(blob)
+    return out_path
+
+
+def do_main(work_dir):
+    """Do testing"""
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-f', '--file_contexts', help='output of "deapexer list -Z"')
+    args = parser.parse_args()
+
+    lib_path = extract_data(LIBSEPOLWRAP, work_dir)
+    policy_path = extract_data('precompiled_sepolicy', work_dir)
+    pol = policy.Policy(policy_path, None, lib_path)
+
+    errors = []
+    with open(args.file_contexts, 'rt', encoding='utf-8') as file_contexts:
+        for line in file_contexts:
+            errors.extend(check_line(pol, line))
+    if len(errors) > 0:
+        sys.exit('\n'.join(errors))
+
+
+if __name__ == '__main__':
+    with tempfile.TemporaryDirectory() as temp_dir:
+        do_main(temp_dir)
diff --git a/tests/apex_sepolicy_tests_test.py b/tests/apex_sepolicy_tests_test.py
new file mode 100644
index 0000000..125290c
--- /dev/null
+++ b/tests/apex_sepolicy_tests_test.py
@@ -0,0 +1,93 @@
+# Copyright 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.
+"""Tests for apex_sepolicy_tests"""
+
+import re
+import shutil
+import tempfile
+import unittest
+
+import apex_sepolicy_tests as apex
+import policy
+
+
+# pylint: disable=missing-docstring
+class ApexSepolicyTests(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls) -> None:
+        cls.temp_dir = tempfile.mkdtemp()
+        lib_path = apex.extract_data(apex.LIBSEPOLWRAP, cls.temp_dir)
+        policy_path = apex.extract_data('precompiled_sepolicy', cls.temp_dir)
+        cls.pol = policy.Policy(policy_path, None,  lib_path)
+
+    @classmethod
+    def tearDownClass(cls) -> None:
+        shutil.rmtree(cls.temp_dir)
+
+    # helpers
+
+    @property
+    def pol(self):
+        return self.__class__.pol
+
+    def assert_ok(self, line: str):
+        errors = apex.check_line(self.pol, line)
+        self.assertEqual(errors, [], "Should be no errors")
+
+    def assert_error(self, line: str, expected_error: str):
+        pattern = re.compile(expected_error)
+        errors = apex.check_line(self.pol, line)
+        for err in errors:
+            if re.search(pattern, err):
+                return
+        self.fail(f"Expected error '{expected_error}' is not found in {errors}")
+
+    # tests
+
+    def test_parse_lines(self):
+        self.assert_ok('# commented line')
+        self.assert_ok('') # empty line
+        self.assert_error('./path1 invalid_contexts',
+                          r'Error: invalid file_contexts: .*')
+        self.assert_error('./path1 u:object_r:vendor_file',
+                          r'Error: invalid file_contexts: .*')
+        self.assert_ok('./path1 u:object_r:vendor_file:s0')
+
+    def test_vintf(self):
+        self.assert_ok('./etc/vintf/fragment.xml u:object_r:vendor_configs_file:s0')
+        self.assert_error('./etc/vintf/fragment.xml u:object_r:vendor_file:s0',
+                          r'Error: \./etc/vintf/fragment\.xml: .* can\'t read')
+
+    def test_permissions(self):
+        self.assert_ok('./etc/permissions/permisssion.xml u:object_r:vendor_configs_file:s0')
+        self.assert_error('./etc/permissions/permisssion.xml u:object_r:vendor_file:s0',
+                          r'Error: \./etc/permissions/permisssion.xml: .* can\'t read')
+
+    def test_initscripts(self):
+        # init reads .rc file
+        self.assert_ok('./etc/init.rc u:object_r:vendor_file:s0')
+        self.assert_error('./etc/init.rc u:object_r:unknown:s0',
+                          r'Error: .* can\'t read')
+        # init reads .#rc file
+        self.assert_ok('./etc/init.32rc u:object_r:vendor_file:s0')
+        self.assert_error('./etc/init.32rc u:object_r:unknown:s0',
+                          r'Error: .* can\'t read')
+        # init skips file with unknown extension => no errors
+        self.assert_ok('./etc/init.x32rc u:object_r:vendor_file:s0')
+        self.assert_ok('./etc/init.x32rc u:object_r:unknown:s0')
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
diff --git a/vendor/file_contexts b/vendor/file_contexts
index ac23351..a2e460d 100644
--- a/vendor/file_contexts
+++ b/vendor/file_contexts
@@ -12,6 +12,7 @@
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.can@1\.0-service  u:object_r:hal_can_socketcan_exec:s0
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.can-service  u:object_r:hal_can_socketcan_exec:s0
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.evs(.*)?          u:object_r:hal_evs_default_exec:s0
+/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.ivn@V1-(.*)-service u:object_r:hal_ivn_default_exec:s0
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@2\.0-((default|emulator)-)*(service|protocan-service)  u:object_r:hal_vehicle_default_exec:s0
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@V1-(default|emulator)-service u:object_r:hal_vehicle_default_exec:s0
 /(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.remoteaccess@V1-(.*)-service u:object_r:hal_remoteaccess_default_exec:s0
diff --git a/vendor/hal_ivn_default.te b/vendor/hal_ivn_default.te
new file mode 100644
index 0000000..26fa973
--- /dev/null
+++ b/vendor/hal_ivn_default.te
@@ -0,0 +1,9 @@
+type hal_ivn_default, domain;
+hal_server_domain(hal_ivn_default, hal_ivn)
+
+# May be started by init
+type hal_ivn_default_exec, exec_type, vendor_file_type, file_type;
+init_daemon_domain(hal_ivn_default)
+
+# Allow registering with service manager.
+binder_call(hal_ivn_default, servicemanager)
\ No newline at end of file