Merge changes from topic "OMAPI_VNTF"

* changes:
  replaced android.se.omapi-V1-ndk_platform library with android.se.omapi-V1-ndk
  VTS tests added for OMAPI Vendor stable interface
  Support for OMAPI Vendor stable interface
diff --git a/Android.bp b/Android.bp
index 3686053..5851f43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -82,6 +82,7 @@
         ":framework-mca-filterpacks-sources",
         ":framework-media-sources",
         ":framework-mms-sources",
+        ":framework-omapi-sources",
         ":framework-opengl-sources",
         ":framework-rs-sources",
         ":framework-sax-sources",
@@ -268,6 +269,7 @@
         "android.hardware.vibrator-V1.2-java",
         "android.hardware.vibrator-V1.3-java",
         "android.hardware.vibrator-V2-java",
+        "android.se.omapi-V1-java",
         "android.system.suspend.control.internal-java",
         "devicepolicyprotosnano",
 
diff --git a/omapi/aidl/Android.bp b/omapi/aidl/Android.bp
new file mode 100644
index 0000000..2b81200
--- /dev/null
+++ b/omapi/aidl/Android.bp
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+    name: "android.se.omapi",
+    vendor_available: true,
+    srcs: ["android/se/omapi/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        rust: {
+            enabled: true,
+        },
+        ndk: {
+            separate_platform_variant: false,
+        },
+    },
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl
new file mode 100644
index 0000000..725013a
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021, 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.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementChannel {
+  void close();
+  boolean isClosed();
+  boolean isBasicChannel();
+  byte[] getSelectResponse();
+  byte[] transmit(in byte[] command);
+  boolean selectNext();
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl
new file mode 100644
index 0000000..77e1c53f
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017, 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.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementListener {
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl
new file mode 100644
index 0000000..2b10c47
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017, 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.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementReader {
+  boolean isSecureElementPresent();
+  android.se.omapi.ISecureElementSession openSession();
+  void closeSessions();
+  boolean reset();
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
new file mode 100644
index 0000000..ae63462
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017, 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.
+ *//*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementService {
+  String[] getReaders();
+  android.se.omapi.ISecureElementReader getReader(in String reader);
+  boolean[] isNFCEventAllowed(in String reader, in byte[] aid, in String[] packageNames);
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl
new file mode 100644
index 0000000..06287c5
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017, 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.
+ *//*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementSession {
+  byte[] getAtr();
+  void close();
+  void closeChannels();
+  boolean isClosed();
+  android.se.omapi.ISecureElementChannel openBasicChannel(in byte[] aid, in byte p2, in android.se.omapi.ISecureElementListener listener);
+  android.se.omapi.ISecureElementChannel openLogicalChannel(in byte[] aid, in byte p2, in android.se.omapi.ISecureElementListener listener);
+}
diff --git a/core/java/android/se/omapi/ISecureElementChannel.aidl b/omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
similarity index 94%
rename from core/java/android/se/omapi/ISecureElementChannel.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
index 4ae57ab..bbd3c14 100644
--- a/core/java/android/se/omapi/ISecureElementChannel.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
@@ -22,6 +22,7 @@
 import android.se.omapi.ISecureElementSession;
 
 /** @hide */
+@VintfStability
 interface ISecureElementChannel {
 
     /**
@@ -58,6 +59,9 @@
      * Transmits the specified command APDU and returns the response APDU.
      * MANAGE channel commands are not supported.
      * Selection of applets is not supported in logical channels.
+     *
+     * @param command Command APDU, its structure is defined in  ISO/IEC 7816-4
+     *                in Standard byte format
      */
     byte[] transmit(in byte[] command);
 
diff --git a/core/java/android/se/omapi/ISecureElementListener.aidl b/omapi/aidl/android/se/omapi/ISecureElementListener.aidl
similarity index 97%
rename from core/java/android/se/omapi/ISecureElementListener.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementListener.aidl
index e9dd181..479dcd7 100644
--- a/core/java/android/se/omapi/ISecureElementListener.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementListener.aidl
@@ -23,5 +23,6 @@
  * Interface to receive call-backs when the service is connected.
  * @hide
  */
+@VintfStability
 interface ISecureElementListener {
 }
diff --git a/core/java/android/se/omapi/ISecureElementReader.aidl b/omapi/aidl/android/se/omapi/ISecureElementReader.aidl
similarity index 94%
rename from core/java/android/se/omapi/ISecureElementReader.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementReader.aidl
index 41244ab..a6979fa 100644
--- a/core/java/android/se/omapi/ISecureElementReader.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementReader.aidl
@@ -22,6 +22,7 @@
 import android.se.omapi.ISecureElementSession;
 
 /** @hide */
+@VintfStability
 interface ISecureElementReader {
 
     /**
@@ -34,7 +35,7 @@
      * Connects to a secure element in this reader. <br>
      * This method prepares (initialises) the Secure Element for communication
      * before the Session object is returned (e.g. powers the Secure Element by
-     * ICC ON if its not already on). There might be multiple sessions opened at
+     * ICC ON if it is not already on). There might be multiple sessions opened at
      * the same time on the same reader. The system ensures the interleaving of
      * APDUs between the respective sessions.
      *
diff --git a/core/java/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
similarity index 69%
rename from core/java/android/se/omapi/ISecureElementService.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementService.aidl
index 4fa799e..61ae481 100644
--- a/core/java/android/se/omapi/ISecureElementService.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
@@ -28,23 +28,31 @@
  * SecureElement service interface.
  * @hide
  */
+@VintfStability
 interface ISecureElementService {
 
     /**
      * Returns the friendly names of available Secure Element readers.
+     * <ul>
+     * <li>If the reader is a SIM reader, then its name must be "SIM[Slot]".</li>
+     * <li>If the reader is a SD or micro SD reader, then its name must be "SD[Slot]"</li>
+     * <li>If the reader is a embedded SE reader, then its name must be "eSE[Slot]"</li>
+     * </ul>
+     * Slot is a decimal number without leading zeros. The Numbering must start with 1
+     * (e.g. SIM1, SIM2, ... or SD1, SD2, ... or eSE1, eSE2, ...).
      */
     String[] getReaders();
 
     /**
      * Returns SecureElement Service reader object to the given name.
      */
-    ISecureElementReader getReader(String reader);
+    ISecureElementReader getReader(in String reader);
 
     /**
      * Checks if the application defined by the package name is allowed to
      * receive NFC transaction events for the defined AID.
      */
-    boolean[] isNFCEventAllowed(String reader, in byte[] aid,
+    boolean[] isNFCEventAllowed(in String reader, in byte[] aid,
             in String[] packageNames);
 
 }
diff --git a/core/java/android/se/omapi/ISecureElementSession.aidl b/omapi/aidl/android/se/omapi/ISecureElementSession.aidl
similarity index 84%
rename from core/java/android/se/omapi/ISecureElementSession.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementSession.aidl
index 8ea599f..129ecc4 100644
--- a/core/java/android/se/omapi/ISecureElementSession.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementSession.aidl
@@ -27,6 +27,7 @@
 import android.se.omapi.ISecureElementListener;
 
 /** @hide */
+@VintfStability
 interface ISecureElementSession {
 
     /**
@@ -45,7 +46,6 @@
      */
     void closeChannels();
 
-
     /**
      * Tells if this session is closed.
      *
@@ -59,15 +59,19 @@
      * applet if aid != null.
      * Logical channels cannot be opened with this connection.
      * Use interface method openLogicalChannel() to open a logical channel.
+     * Listener is passed to secure element service and used to monitor whether
+     * the client application that uses OMAPI is still alive or not.
      */
     ISecureElementChannel openBasicChannel(in byte[] aid, in byte p2,
-            ISecureElementListener listener);
+            in ISecureElementListener listener);
 
     /**
      * Opens a connection using the next free logical channel of the card in the
      * specified reader. Selects the specified applet.
      * Selection of other applets with this connection is not supported.
+     * Listener is passed to secure element service and used to monitor whether
+     * the client application that uses OMAPI is still alive or not.
      */
     ISecureElementChannel openLogicalChannel(in byte[] aid, in byte p2,
-            ISecureElementListener listener);
+            in ISecureElementListener listener);
 }
diff --git a/omapi/aidl/vts/functional/AccessControlApp/Android.bp b/omapi/aidl/vts/functional/AccessControlApp/Android.bp
new file mode 100644
index 0000000..f03c3f6
--- /dev/null
+++ b/omapi/aidl/vts/functional/AccessControlApp/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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"],
+}
+
+cc_test {
+    name: "VtsHalOmapiSeAccessControlTestCases",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalOmapiSeAccessControlTestCases.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libnativehelper",
+        "libutils",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.se.omapi-V1-ndk",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+        "-Werror",
+    ],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp b/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp
new file mode 100644
index 0000000..9ea6543
--- /dev/null
+++ b/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <aidl/android/se/omapi/BnSecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementChannel.h>
+#include <aidl/android/se/omapi/ISecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementReader.h>
+#include <aidl/android/se/omapi/ISecureElementService.h>
+#include <aidl/android/se/omapi/ISecureElementSession.h>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/String16.h>
+
+using namespace std;
+using namespace ::testing;
+using namespace android;
+
+int main(int argc, char** argv) {
+    InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
+
+namespace {
+
+class OMAPISEAccessControlTest : public TestWithParam<std::string> {
+   protected:
+
+    class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
+
+    /**
+     * Verifies TLV data
+     *
+     * @return true if the data is tlv formatted, false otherwise
+     */
+    bool verifyBerTlvData(std::vector<uint8_t> tlv) {
+        if (tlv.size() == 0) {
+            LOG(ERROR) << "Invalid tlv, null";
+            return false;
+        }
+        int i = 0;
+        if ((tlv[i++] & 0x1F) == 0x1F) {
+            // extra byte for TAG field
+            i++;
+        }
+
+        int len = tlv[i++] & 0xFF;
+        if (len > 127) {
+            // more than 1 byte for length
+            int bytesLength = len - 128;
+            len = 0;
+            for (int j = bytesLength; j > 0; j--) {
+                len += (len << 8) + (tlv[i++] & 0xFF);
+            }
+        }
+        // Additional 2 bytes for the SW
+        return (tlv.size() == (i + len + 2));
+    }
+
+    void testSelectableAid(
+            std::vector<std::vector<uint8_t>> authorizedAids) {
+        for (auto aid : authorizedAids) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    std::vector<uint8_t> selectResponse = {};
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+
+                    bool status = false;
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+                }
+            }
+        }
+    }
+
+    void testUnauthorisedAid(
+            std::vector<std::vector<uint8_t>> unAuthorizedAids) {
+        for (auto aid : unAuthorizedAids) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+
+                    bool status = false;
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+
+                    if (!res.isOk()) {
+                        ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                        ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+                    }
+                }
+            }
+        }
+    }
+
+    void testTransmitAPDU(
+            std::vector<uint8_t> aid,
+            std::vector<std::vector<uint8_t>> apdus) {
+        for (auto apdu : apdus) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+                    bool status = false;
+                    std::vector<uint8_t> selectResponse = {};
+                    std::vector<uint8_t> transmitResponse = {};
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+
+                    res = channel->transmit(apdu, &transmitResponse);
+                    LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                              << " Message: " << res.getMessage();
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+                    ASSERT_TRUE(res.isOk()) << "failed to transmit";
+                }
+            }
+        }
+    }
+
+    void testUnauthorisedAPDU(
+            std::vector<uint8_t> aid,
+            std::vector<std::vector<uint8_t>> apdus) {
+        for (auto apdu : apdus) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+                    bool status = false;
+                    std::vector<uint8_t> selectResponse = {};
+                    std::vector<uint8_t> transmitResponse = {};
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+
+                    res = channel->transmit(apdu, &transmitResponse);
+                    LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                              << " Message: " << res.getMessage();
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+                    if (!res.isOk()) {
+                        ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                        ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+                    }
+                }
+            }
+        }
+    }
+
+    bool supportOMAPIReaders() {
+        return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
+    }
+
+    void getFirstApiLevel(int32_t* outApiLevel) {
+        int32_t firstApiLevel = property_get_int32(FEATURE_SE_API_LEVEL.c_str(), -1);
+        if (firstApiLevel < 0) {
+            firstApiLevel = property_get_int32(FEATURE_SE_SDK_VERSION.c_str(), -1);
+        }
+        ASSERT_GT(firstApiLevel, 0);  // first_api_level must exist
+        *outApiLevel = firstApiLevel;
+        return;
+    }
+
+    bool supportsHardware() {
+        bool lowRamDevice = property_get_bool(FEATURE_SE_LOW_RAM.c_str(), true);
+        return !lowRamDevice || deviceSupportsFeature(FEATURE_SE_HARDWARE_WATCH.c_str()) ||
+                deviceSupportsFeature(FEATURE_SE_OMAPI_SERVICE.c_str());  // android.se.omapi
+    }
+
+    void SetUp() override {
+        ASSERT_TRUE(supportsHardware());
+        int32_t apiLevel;
+        getFirstApiLevel(&apiLevel);
+        ASSERT_TRUE(apiLevel > 27);
+        ASSERT_TRUE(supportOMAPIReaders());
+        LOG(INFO) << "get OMAPI service with name:" << GetParam();
+        ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
+        mOmapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
+        ASSERT_TRUE(mOmapiSeService);
+
+        std::vector<std::string> readers = {};
+
+        if (mOmapiSeService != NULL) {
+            auto status = mOmapiSeService->getReaders(&readers);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            for (auto readerName : readers) {
+                // Filter eSE readers only
+                if (readerName.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+                    std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
+                    status = mOmapiSeService->getReader(readerName, &reader);
+                    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+                    mVSReaders[readerName] = reader;
+                }
+            }
+        }
+    }
+
+    void TearDown() override {
+        if (mOmapiSeService != nullptr) {
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    reader->closeSessions();
+                }
+            }
+        }
+    }
+
+    static inline std::string const ESE_READER_PREFIX = "eSE";
+    static inline std::string const FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese";
+    static inline std::string const FEATURE_SE_LOW_RAM = "ro.config.low_ram";
+    static inline std::string const FEATURE_SE_HARDWARE_WATCH = "android.hardware.type.watch";
+    static inline std::string const FEATURE_SE_OMAPI_SERVICE = "com.android.se";
+    static inline std::string const FEATURE_SE_SDK_VERSION = "ro.build.version.sdk";
+    static inline std::string const FEATURE_SE_API_LEVEL = "ro.product.first_api_level";
+
+    std::vector<uint8_t> AID_40 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x40};
+    std::vector<uint8_t> AID_41 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x41};
+    std::vector<uint8_t> AID_42 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x42};
+    std::vector<uint8_t> AID_43 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x43};
+    std::vector<uint8_t> AID_44 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x44};
+    std::vector<uint8_t> AID_45 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x45};
+    std::vector<uint8_t> AID_46 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x46};
+    std::vector<uint8_t> AID_47 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x47};
+    std::vector<uint8_t> AID_48 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x48};
+    std::vector<uint8_t> AID_49 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x49};
+    std::vector<uint8_t> AID_4A = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4A};
+    std::vector<uint8_t> AID_4B = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4B};
+    std::vector<uint8_t> AID_4C = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4C};
+    std::vector<uint8_t> AID_4D = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4D};
+    std::vector<uint8_t> AID_4E = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4E};
+    std::vector<uint8_t> AID_4F = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4F};
+
+    std::vector<std::vector<uint8_t>> AUTHORIZED_AID = {AID_40, AID_41, AID_42, AID_44, AID_45,
+                                                        AID_47, AID_48, AID_49, AID_4A, AID_4B,
+                                                        AID_4C, AID_4D, AID_4E, AID_4F};
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_AID = {AID_43, AID_46};
+
+    /* Authorized APDU for AID_40 */
+    std::vector<std::vector<uint8_t>> AUTHORIZED_APDU_AID_40 = {
+        {0x00, 0x06, 0x00, 0x00},
+        {0xA0, 0x06, 0x00, 0x00},
+    };
+    /* Unauthorized APDU for AID_40 */
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_APDU_AID_40 = {
+        {0x00, 0x08, 0x00, 0x00, 0x00},
+        {0x80, 0x06, 0x00, 0x00},
+        {0xA0, 0x08, 0x00, 0x00, 0x00},
+        {0x94, 0x06, 0x00, 0x00, 0x00},
+    };
+
+    /* Authorized APDU for AID_41 */
+    std::vector<std::vector<uint8_t>> AUTHORIZED_APDU_AID_41 = {
+        {0x94, 0x06, 0x00, 0x00},
+        {0x94, 0x08, 0x00, 0x00, 0x00},
+        {0x94, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0x94, 0x0A, 0x00, 0x00, 0x01, 0xAA}};
+    /* Unauthorized APDU for AID_41 */
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_APDU_AID_41 = {
+        {0x00, 0x06, 0x00, 0x00},
+        {0x80, 0x06, 0x00, 0x00},
+        {0xA0, 0x06, 0x00, 0x00},
+        {0x00, 0x08, 0x00, 0x00, 0x00},
+        {0x00, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0x80, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0xA0, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0x80, 0x08, 0x00, 0x00, 0x00},
+        {0xA0, 0x08, 0x00, 0x00, 0x00},
+        {0x00, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0x80, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0xA0, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+    };
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> mOmapiSeService;
+
+    std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
+        mVSReaders = {};
+};
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAID) {
+    testSelectableAid(AUTHORIZED_AID);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorizedAID) {
+    testUnauthorisedAid(UNAUTHORIZED_AID);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAPDUAID40) {
+    testTransmitAPDU(AID_40, AUTHORIZED_APDU_AID_40);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorisedAPDUAID40) {
+    testUnauthorisedAPDU(AID_40, UNAUTHORIZED_APDU_AID_40);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAPDUAID41) {
+    testTransmitAPDU(AID_41, AUTHORIZED_APDU_AID_41);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorisedAPDUAID41) {
+    testUnauthorisedAPDU(AID_41, UNAUTHORIZED_APDU_AID_41);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEAccessControlTest,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(
+                             aidl::android::se::omapi::ISecureElementService::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OMAPISEAccessControlTest);
+
+}  // namespace
diff --git a/omapi/aidl/vts/functional/omapi/Android.bp b/omapi/aidl/vts/functional/omapi/Android.bp
new file mode 100644
index 0000000..c3ab8d1
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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"],
+}
+
+cc_test {
+    name: "VtsHalOmapiSeServiceV1_TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalOmapiSeServiceV1_TargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libnativehelper",
+        "libutils",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.se.omapi-V1-ndk",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+        "-Werror",
+    ],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
new file mode 100644
index 0000000..319cb7e
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <aidl/android/se/omapi/BnSecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementChannel.h>
+#include <aidl/android/se/omapi/ISecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementReader.h>
+#include <aidl/android/se/omapi/ISecureElementService.h>
+#include <aidl/android/se/omapi/ISecureElementSession.h>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/String16.h>
+
+using namespace std;
+using namespace ::testing;
+using namespace android;
+
+int main(int argc, char** argv) {
+    InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
+
+namespace {
+
+class OMAPISEServiceHalTest : public TestWithParam<std::string> {
+   protected:
+    class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
+
+    void testSelectableAid(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> aid, std::vector<uint8_t>& selectResponse) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+        res = channel->getSelectResponse(&selectResponse);
+        ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+        ASSERT_GE(selectResponse.size(), 2);
+
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+
+        ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+        ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+    }
+
+    void testNonSelectableAid(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> aid) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+
+        LOG(ERROR) << res.getMessage();
+        ASSERT_FALSE(res.isOk()) << "expected to fail to open channel for this test";
+    }
+
+    /**
+     * Verifies TLV data
+     *
+     * @return true if the data is tlv formatted, false otherwise
+     */
+    bool verifyBerTlvData(std::vector<uint8_t> tlv) {
+        if (tlv.size() == 0) {
+            LOG(ERROR) << "Invalid tlv, null";
+            return false;
+        }
+        int i = 0;
+        if ((tlv[i++] & 0x1F) == 0x1F) {
+            // extra byte for TAG field
+            i++;
+        }
+
+        int len = tlv[i++] & 0xFF;
+        if (len > 127) {
+            // more than 1 byte for length
+            int bytesLength = len - 128;
+            len = 0;
+            for (int j = bytesLength; j > 0; j--) {
+                len += (len << 8) + (tlv[i++] & 0xFF);
+            }
+        }
+        // Additional 2 bytes for the SW
+        return (tlv.size() == (i + len + 2));
+    }
+
+    void internalTransmitApdu(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+        std::vector<uint8_t> selectResponse = {};
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+        res = channel->getSelectResponse(&selectResponse);
+        ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+        ASSERT_GE(selectResponse.size(), 2);
+
+        res = channel->transmit(apdu, &transmitResponse);
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+        LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                  << " Message: " << res.getMessage();
+        ASSERT_TRUE(res.isOk()) << "failed to transmit";
+    }
+
+    bool supportOMAPIReaders() {
+        return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
+    }
+
+    void SetUp() override {
+        LOG(INFO) << "get OMAPI service with name:" << GetParam();
+        ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
+        mOmapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
+        ASSERT_TRUE(mOmapiSeService);
+
+        std::vector<std::string> readers = {};
+
+        if (omapiSecureService() != NULL) {
+            auto status = omapiSecureService()->getReaders(&readers);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            for (auto readerName : readers) {
+                // Filter eSE readers only
+                if (readerName.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+                    std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
+                    status = omapiSecureService()->getReader(readerName, &reader);
+                    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+                    mVSReaders[readerName] = reader;
+                }
+            }
+        }
+    }
+
+    void TearDown() override {
+        if (mOmapiSeService != nullptr) {
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    reader->closeSessions();
+                }
+            }
+        }
+    }
+
+    bool isDebuggableBuild() {
+        char value[PROPERTY_VALUE_MAX] = {0};
+        property_get("ro.system.build.type", value, "");
+        if (strcmp(value, "userdebug") == 0) {
+            return true;
+        }
+        if (strcmp(value, "eng") == 0) {
+            return true;
+        }
+        return false;
+    }
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> omapiSecureService() {
+        return mOmapiSeService;
+    }
+
+    static inline std::string const ESE_READER_PREFIX = "eSE";
+    static inline std::string const FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese";
+
+    std::vector<uint8_t> SELECTABLE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                           0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31};
+    std::vector<uint8_t> LONG_SELECT_RESPONSE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+                                                     0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+                                                     0x43, 0x54, 0x53, 0x32};
+    std::vector<uint8_t> NON_SELECTABLE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                               0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0xFF};
+
+    std::vector<std::vector<uint8_t>> ILLEGAL_COMMANDS_TRANSMIT = {
+        {0x00, 0x70, 0x00, 0x00},
+        {0x00, 0x70, 0x80, 0x00},
+        {0x00, 0xA4, 0x04, 0x04, 0x10, 0x4A, 0x53, 0x52, 0x31, 0x37, 0x37,
+         0x54, 0x65, 0x73, 0x74, 0x65, 0x72, 0x20, 0x31, 0x2E, 0x30}};
+
+    /* OMAPI APDU Test case 1 and 3 */
+    std::vector<std::vector<uint8_t>> NO_DATA_APDU = {{0x00, 0x06, 0x00, 0x00},
+                                                      {0x80, 0x06, 0x00, 0x00},
+                                                      {0xA0, 0x06, 0x00, 0x00},
+                                                      {0x94, 0x06, 0x00, 0x00},
+                                                      {0x00, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0x80, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0xA0, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0x94, 0x0A, 0x00, 0x00, 0x01, 0xAA}};
+
+    /* OMAPI APDU Test case 2 and 4 */
+    std::vector<std::vector<uint8_t>> DATA_APDU = {{0x00, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x80, 0x08, 0x00, 0x00, 0x00},
+                                                   {0xA0, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x94, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x00, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0x80, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0xA0, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0x94, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00}};
+
+    /* Case 2 APDU command expects the P2 received in the SELECT command as 1-byte outgoing data */
+    std::vector<uint8_t> CHECK_SELECT_P2_APDU = {0x00, 0xF4, 0x00, 0x00, 0x00};
+
+    /* OMAPI APDU Test case 1 and 3 */
+    std::vector<std::vector<uint8_t>> SW_62xx_NO_DATA_APDU = {{0x00, 0xF3, 0x00, 0x06},
+                                                              {0x00, 0xF3, 0x00, 0x0A, 0x01, 0xAA}};
+
+    /* OMAPI APDU Test case 2 and 4 */
+    std::vector<uint8_t> SW_62xx_DATA_APDU = {0x00, 0xF3, 0x00, 0x08, 0x00};
+    std::vector<uint8_t> SW_62xx_VALIDATE_DATA_APDU = {0x00, 0xF3, 0x00, 0x0C, 0x01, 0xAA, 0x00};
+    std::vector<std::vector<uint8_t>> SW_62xx = {
+        {0x62, 0x00}, {0x62, 0x81}, {0x62, 0x82}, {0x62, 0x83}, {0x62, 0x85}, {0x62, 0xF1},
+        {0x62, 0xF2}, {0x63, 0xF1}, {0x63, 0xF2}, {0x63, 0xC2}, {0x62, 0x02}, {0x62, 0x80},
+        {0x62, 0x84}, {0x62, 0x86}, {0x63, 0x00}, {0x63, 0x81}};
+
+    std::vector<std::vector<uint8_t>> SEGMENTED_RESP_APDU = {
+        // Get response Case2 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC2, 0x08, 0x00, 0x00},
+        // Get response Case4 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC4, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
+        // Get response Case2 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC6, 0x08, 0x00, 0x00},
+        // Get response Case4 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC8, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
+        // Test device buffer capacity 7FFF data
+        {0x00, 0xC2, 0x7F, 0xFF, 0x00},
+        // Get response 6CFF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xCF, 0x08, 0x00, 0x00},
+        // Get response with another CLA  with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x94, 0xC2, 0x08, 0x00, 0x00}};
+    long SERVICE_CONNECTION_TIME_OUT = 3000;
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> mOmapiSeService;
+
+    std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
+        mVSReaders = {};
+};
+
+/** Tests getReaders API */
+TEST_P(OMAPISEServiceHalTest, TestGetReaders) {
+    std::vector<std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>> eseReaders =
+        {};
+
+    for (const auto& [name, reader] : mVSReaders) {
+        bool status = false;
+        LOG(INFO) << "Name of the reader: " << name;
+
+        if (reader) {
+            auto res = reader->isSecureElementPresent(&status);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+        }
+        ASSERT_TRUE(status);
+
+        if (name.find(ESE_READER_PREFIX) == std::string::npos) {
+            LOG(ERROR) << "Incorrect Reader name";
+            FAIL();
+        }
+
+        if (name.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+            eseReaders.push_back(reader);
+        } else {
+            LOG(INFO) << "Reader not supported: " << name;
+            FAIL();
+        }
+    }
+
+    if (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str())) {
+        ASSERT_GE(eseReaders.size(), 1);
+    } else {
+        ASSERT_TRUE(eseReaders.size() == 0);
+    }
+}
+
+/** Tests OpenBasicChannel API when aid is null */
+TEST_P(OMAPISEServiceHalTest, TestOpenBasicChannelNullAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    std::vector<uint8_t> aid = {};
+    auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            bool result = false;
+
+            auto status = reader->openSession(&session);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+            if (!session) {
+                LOG(ERROR) << "Could not open session";
+                FAIL();
+            }
+
+            status = session->openBasicChannel(aid, 0x00, seListener, &channel);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+
+            if (channel != nullptr) {
+                status = channel->isBasicChannel(&result);
+                ASSERT_TRUE(status.isOk()) << "Basic Channel cannot be opened";
+            }
+        }
+    }
+}
+
+/** Tests OpenBasicChannel API when aid is provided */
+TEST_P(OMAPISEServiceHalTest, TestOpenBasicChannelNonNullAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            bool result = false;
+
+            auto status = reader->openSession(&session);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+            if (!session) {
+                LOG(ERROR) << "Could not open session";
+                FAIL();
+            }
+
+            status = session->openBasicChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+
+            if (channel != nullptr) {
+                status = channel->isBasicChannel(&result);
+                ASSERT_TRUE(status.isOk()) << "Basic Channel cannot be opened";
+            }
+        }
+    }
+}
+
+/** Tests Select API */
+TEST_P(OMAPISEServiceHalTest, TestSelectableAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> selectResponse = {};
+            testSelectableAid(reader, SELECTABLE_AID, selectResponse);
+        }
+    }
+}
+
+/** Tests Select API */
+TEST_P(OMAPISEServiceHalTest, TestLongSelectResponse) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> selectResponse = {};
+            testSelectableAid(reader, LONG_SELECT_RESPONSE_AID, selectResponse);
+            ASSERT_TRUE(verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+        }
+    }
+}
+
+/** Test to fail open channel with wrong aid */
+TEST_P(OMAPISEServiceHalTest, TestWrongAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            testNonSelectableAid(reader, NON_SELECTABLE_AID);
+        }
+    }
+}
+
+/** Tests with invalid cmds in Transmit */
+TEST_P(OMAPISEServiceHalTest, TestSecurityExceptionInTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+            std::vector<uint8_t> selectResponse = {};
+
+            ASSERT_NE(reader, nullptr) << "reader is null";
+
+            bool status = false;
+            auto res = reader->isSecureElementPresent(&status);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_TRUE(status);
+
+            res = reader->openSession(&session);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_NE(session, nullptr) << "Could not open session";
+
+            res = session->openLogicalChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+            res = channel->getSelectResponse(&selectResponse);
+            ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+            ASSERT_GE(selectResponse.size(), 2);
+
+            ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+            ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+
+            for (auto cmd : ILLEGAL_COMMANDS_TRANSMIT) {
+                std::vector<uint8_t> response = {};
+                res = channel->transmit(cmd, &response);
+                ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+            }
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+        }
+    }
+}
+
+/**
+ * Tests Transmit API for all readers.
+ *
+ * Checks the return status and verifies the size of the
+ * response.
+ */
+TEST_P(OMAPISEServiceHalTest, TestTransmitApdu) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : NO_DATA_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                ASSERT_GE(response.size(), 2);
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            }
+
+            for (auto apdu : DATA_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                /* 256 byte data and 2 bytes of status word */
+                ASSERT_GE(response.size(), 258);
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            }
+        }
+    }
+}
+
+/**
+ * Tests if underlying implementations returns the correct Status Word
+ *
+ * TO verify that :
+ * - the device does not modify the APDU sent to the Secure Element
+ * - the warning code is properly received by the application layer as SW answer
+ * - the verify that the application layer can fetch the additionnal data (when present)
+ */
+TEST_P(OMAPISEServiceHalTest, testStatusWordTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : SW_62xx_NO_DATA_APDU) {
+                for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                    apdu[2] = i + 1;
+                    std::vector<uint8_t> response = {};
+                    internalTransmitApdu(reader, apdu, response);
+                    std::vector<uint8_t> SW = SW_62xx[i];
+                    ASSERT_GE(response.size(), 2);
+                    ASSERT_EQ(response[response.size() - 1], SW[1]);
+                    ASSERT_EQ(response[response.size() - 2], SW[0]);
+                }
+            }
+
+            for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                std::vector<uint8_t> apdu = SW_62xx_DATA_APDU;
+                apdu[2] = i + 1;
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                std::vector<uint8_t> SW = SW_62xx[i];
+                ASSERT_GE(response.size(), 3);
+                ASSERT_EQ(response[response.size() - 1], SW[1]);
+                ASSERT_EQ(response[response.size() - 2], SW[0]);
+            }
+
+            for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                std::vector<uint8_t> apdu = SW_62xx_VALIDATE_DATA_APDU;
+                apdu[2] = i + 1;
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                ASSERT_GE(response.size(), apdu.size() + 2);
+                std::vector<uint8_t> responseSubstring((response.begin() + 0),
+                                                       (response.begin() + apdu.size()));
+                // We should not care about which channel number is actually assigned.
+                responseSubstring[0] = apdu[0];
+                ASSERT_TRUE((responseSubstring == apdu));
+                std::vector<uint8_t> SW = SW_62xx[i];
+                ASSERT_EQ(response[response.size() - 1], SW[1]);
+                ASSERT_EQ(response[response.size() - 2], SW[0]);
+            }
+        }
+    }
+}
+
+/** Test if the responses are segmented by the underlying implementation */
+TEST_P(OMAPISEServiceHalTest, TestSegmentedResponseTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : SEGMENTED_RESP_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                int expectedLength = (0x00 << 24) | (0x00 << 16) | (apdu[2] << 8) | apdu[3];
+                ASSERT_EQ(response.size(), (expectedLength + 2));
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+                ASSERT_EQ((response[response.size() - 3] & 0xFF), (0xFF));
+            }
+        }
+    }
+}
+
+/**
+ * Tests the P2 value of the select command.
+ *
+ * Verifies that the default P2 value (0x00) is not modified by the underlying implementation.
+ */
+TEST_P(OMAPISEServiceHalTest, TestP2Value) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> response = {};
+            internalTransmitApdu(reader, CHECK_SELECT_P2_APDU, response);
+            ASSERT_GE(response.size(), 3);
+            ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+            ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            ASSERT_EQ((response[response.size() - 3] & 0xFF), (0x00));
+        }
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEServiceHalTest,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(
+                             aidl::android::se::omapi::ISecureElementService::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OMAPISEServiceHalTest);
+
+}  // namespace
diff --git a/omapi/java/Android.bp b/omapi/java/Android.bp
new file mode 100644
index 0000000..8d38da0
--- /dev/null
+++ b/omapi/java/Android.bp
@@ -0,0 +1,17 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "framework-omapi-sources",
+    srcs: [
+        "**/*.java",
+        "**/*.aidl",
+    ],
+    visibility: ["//frameworks/base"],
+}
diff --git a/core/java/android/se/OWNERS b/omapi/java/android/se/OWNERS
similarity index 100%
rename from core/java/android/se/OWNERS
rename to omapi/java/android/se/OWNERS
diff --git a/core/java/android/se/omapi/Channel.java b/omapi/java/android/se/omapi/Channel.java
similarity index 100%
rename from core/java/android/se/omapi/Channel.java
rename to omapi/java/android/se/omapi/Channel.java
diff --git a/core/java/android/se/omapi/OWNERS b/omapi/java/android/se/omapi/OWNERS
similarity index 100%
rename from core/java/android/se/omapi/OWNERS
rename to omapi/java/android/se/omapi/OWNERS
diff --git a/core/java/android/se/omapi/Reader.java b/omapi/java/android/se/omapi/Reader.java
similarity index 98%
rename from core/java/android/se/omapi/Reader.java
rename to omapi/java/android/se/omapi/Reader.java
index 90c934d..3c2135d9 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/omapi/java/android/se/omapi/Reader.java
@@ -170,7 +170,9 @@
             try {
                 closeSessions();
                 return mReader.reset();
-            } catch (RemoteException ignore) {return false;}
+            } catch (RemoteException ignore) {
+                return false;
+            }
         }
     }
 }
diff --git a/core/java/android/se/omapi/SEService.java b/omapi/java/android/se/omapi/SEService.java
similarity index 96%
rename from core/java/android/se/omapi/SEService.java
rename to omapi/java/android/se/omapi/SEService.java
index 333af91..f42ca36 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/omapi/java/android/se/omapi/SEService.java
@@ -230,20 +230,20 @@
       *         is not exist.
       * @return A Reader object for this uicc slot.
       */
-     public @NonNull Reader getUiccReader(int slotNumber) {
-         if (slotNumber < 1) {
-             throw new IllegalArgumentException("slotNumber should be larger than 0");
-         }
-         loadReaders();
+    public @NonNull Reader getUiccReader(int slotNumber) {
+        if (slotNumber < 1) {
+            throw new IllegalArgumentException("slotNumber should be larger than 0");
+        }
+        loadReaders();
 
-         String readerName = UICC_TERMINAL + slotNumber;
-         Reader reader = mReaders.get(readerName);
+        String readerName = UICC_TERMINAL + slotNumber;
+        Reader reader = mReaders.get(readerName);
 
-         if (reader == null) {
+        if (reader == null) {
             throw new IllegalArgumentException("Reader:" + readerName + " doesn't exist");
-         }
+        }
 
-         return reader;
+        return reader;
     }
 
     /**
diff --git a/core/java/android/se/omapi/Session.java b/omapi/java/android/se/omapi/Session.java
similarity index 100%
rename from core/java/android/se/omapi/Session.java
rename to omapi/java/android/se/omapi/Session.java