Merge "composer: 2.4: vts: Add missing COMPOSER_OVERLAY allocation flag"
diff --git a/bluetooth/audio/2.2/default/OWNERS b/bluetooth/audio/2.2/default/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/2.2/default/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
index e2a08a0..948c04a 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -37,11 +37,16 @@
   android.hardware.bluetooth.audio.CodecType codecType;
   android.hardware.bluetooth.audio.CodecCapabilities.Capabilities capabilities;
   @VintfStability
+  parcelable VendorCapabilities {
+    ParcelableHolder extension;
+  }
+  @VintfStability
   union Capabilities {
     android.hardware.bluetooth.audio.SbcCapabilities sbcCapabilities;
     android.hardware.bluetooth.audio.AacCapabilities aacCapabilities;
     android.hardware.bluetooth.audio.LdacCapabilities ldacCapabilities;
     android.hardware.bluetooth.audio.AptxCapabilities aptxCapabilities;
     android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+    android.hardware.bluetooth.audio.CodecCapabilities.VendorCapabilities vendorCapabilities;
   }
 }
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
index 34ebd60..32bccd8 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -40,11 +40,18 @@
   boolean isScmstEnabled;
   android.hardware.bluetooth.audio.CodecConfiguration.CodecSpecific config;
   @VintfStability
+  parcelable VendorConfiguration {
+    int vendorId;
+    char codecId;
+    ParcelableHolder codecConfig;
+  }
+  @VintfStability
   union CodecSpecific {
     android.hardware.bluetooth.audio.SbcConfiguration sbcConfig;
     android.hardware.bluetooth.audio.AacConfiguration aacConfig;
     android.hardware.bluetooth.audio.LdacConfiguration ldacConfig;
     android.hardware.bluetooth.audio.AptxConfiguration aptxConfig;
     android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+    android.hardware.bluetooth.audio.CodecConfiguration.VendorConfiguration vendorConfig;
   }
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
index 5bf0252..41e2431 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -30,12 +30,17 @@
 @VintfStability
 parcelable CodecCapabilities {
     @VintfStability
+    parcelable VendorCapabilities {
+        ParcelableHolder extension;
+    }
+    @VintfStability
     union Capabilities {
         SbcCapabilities sbcCapabilities;
         AacCapabilities aacCapabilities;
         LdacCapabilities ldacCapabilities;
         AptxCapabilities aptxCapabilities;
         Lc3Capabilities lc3Capabilities;
+        VendorCapabilities vendorCapabilities;
     }
     CodecType codecType;
     Capabilities capabilities;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
index 9e43f22..3679537 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -30,12 +30,19 @@
 @VintfStability
 parcelable CodecConfiguration {
     @VintfStability
+    parcelable VendorConfiguration {
+        int vendorId;
+        char codecId;
+        ParcelableHolder codecConfig;
+    }
+    @VintfStability
     union CodecSpecific {
         SbcConfiguration sbcConfig;
         AacConfiguration aacConfig;
         LdacConfiguration ldacConfig;
         AptxConfiguration aptxConfig;
         Lc3Configuration lc3Config;
+        VendorConfiguration vendorConfig;
     }
     CodecType codecType;
     /**
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
index 7e49074..5a413e0 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -88,8 +88,9 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
   *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                _aidl_return, *audio_config_);
+                                                &desc, *audio_config_);
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index 8e6cee7..1e55a0b 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProvidersFactory"
+#define LOG_TAG "BTAudioProviderFactoryAIDL"
 
 #include "BluetoothAudioProviderFactory.h"
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
index 96d888c..b38cfd2 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -18,13 +18,6 @@
 
 #include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
 
-#include "A2dpOffloadAudioProvider.h"
-#include "A2dpSoftwareAudioProvider.h"
-#include "BluetoothAudioProvider.h"
-#include "HearingAidAudioProvider.h"
-#include "LeAudioOffloadAudioProvider.h"
-#include "LeAudioSoftwareAudioProvider.h"
-
 namespace aidl {
 namespace android {
 namespace hardware {
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
index a993059..66ce93b 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -81,10 +81,10 @@
     *_aidl_return = DataMQDesc();
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
+  *_aidl_return = data_mq_->dupeDesc();
   auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
                                                 &desc, *audio_config_);
-  *_aidl_return = data_mq_->dupeDesc();
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 4078783..72ac9bd 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProviderLeAudioSW"
+#define LOG_TAG "BTAudioProviderLeAudioHW"
 
 #include "LeAudioOffloadAudioProvider.h"
 
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
index f9962fd..67b7d60 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProviderLeAudioHW"
+#define LOG_TAG "BTAudioProviderLeAudioSW"
 
 #include "LeAudioSoftwareAudioProvider.h"
 
@@ -88,6 +88,16 @@
       channel_mode_to_channel_count(pcm_config.channelMode) *
       (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
       buffer_modifier;
+  if (data_mq_size <= 0) {
+    LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
+               << ", SampleRateHz: " << pcm_config.sampleRateHz
+               << ", ChannelMode: " << toString(pcm_config.channelMode)
+               << ", BitsPerSample: "
+               << static_cast<int>(pcm_config.bitsPerSample)
+               << ", DataIntervalUs: " << pcm_config.dataIntervalUs
+               << ", SessionType: " << toString(session_type_);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
 
   LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size
             << " byte(s)";
@@ -113,8 +123,9 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
   *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                _aidl_return, *audio_config_);
+                                                &desc, *audio_config_);
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/OWNERS b/bluetooth/audio/aidl/default/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/aidl/default/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/vts/OWNERS b/bluetooth/audio/aidl/vts/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/OWNERS b/bluetooth/audio/utils/OWNERS
index ed92847..17ea464 100644
--- a/bluetooth/audio/utils/OWNERS
+++ b/bluetooth/audio/utils/OWNERS
@@ -1,3 +1,4 @@
 include platform/packages/modules/Bluetooth:/OWNERS
 
-cheneyni@google.com
\ No newline at end of file
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index 380732f..4693d97 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -356,7 +356,6 @@
         break;
       case CodecType::UNKNOWN:
       case CodecType::VENDOR:
-        codec_capability = {};
         break;
     }
   }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 95e473e..8052b01 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -114,11 +114,6 @@
 const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
-    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
-      return invalidOffloadAudioConfiguration;
-    } else {
-      return invalidSoftwareAudioConfiguration;
-    }
     switch (session_type_) {
       case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
         return invalidOffloadAudioConfiguration;
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
index 91e0238..8f7a177 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -93,16 +93,6 @@
     std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>>
     legacy_callback_table;
 
-const static std::unordered_map<SessionType_2_0, SessionType>
-    session_type_2_0_to_aidl_map{
-        {SessionType_2_0::A2DP_SOFTWARE_ENCODING_DATAPATH,
-         SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
-        {SessionType_2_0::A2DP_HARDWARE_OFFLOAD_DATAPATH,
-         SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
-        {SessionType_2_0::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
-         SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
-    };
-
 const static std::unordered_map<SessionType_2_1, SessionType>
     session_type_2_1_to_aidl_map{
         {SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH,
@@ -218,13 +208,6 @@
         {LeAudioMode::BROADCAST, LeAudioMode_2_2::BROADCAST},
     };
 
-inline SessionType from_session_type_2_0(
-    const SessionType_2_0& session_type_hidl) {
-  auto it = session_type_2_0_to_aidl_map.find(session_type_hidl);
-  if (it != session_type_2_0_to_aidl_map.end()) return it->second;
-  return SessionType::UNKNOWN;
-}
-
 inline SessionType from_session_type_2_1(
     const SessionType_2_1& session_type_hidl) {
   auto it = session_type_2_1_to_aidl_map.find(session_type_hidl);
@@ -232,6 +215,11 @@
   return SessionType::UNKNOWN;
 }
 
+inline SessionType from_session_type_2_0(
+    const SessionType_2_0& session_type_hidl) {
+  return from_session_type_2_1(static_cast<SessionType_2_1>(session_type_hidl));
+}
+
 inline HidlStatus to_hidl_status(const BluetoothAudioStatus& status) {
   switch (status) {
     case BluetoothAudioStatus::SUCCESS:
@@ -761,6 +749,13 @@
       from_session_type_2_1(session_type));
 }
 
+void HidlToAidlMiddleware_2_2::UpdateTracksMetadata(
+    const SessionType_2_1& session_type,
+    const struct source_metadata* source_metadata) {
+  return BluetoothAudioSessionControl::UpdateSourceMetadata(
+      from_session_type_2_1(session_type), *source_metadata);
+}
+
 void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
     const SessionType_2_1& session_type,
     const struct sink_metadata* sink_metadata) {
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
index 149e404..f6c3e5c 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
@@ -54,6 +54,10 @@
 
   static void StopStream(const SessionType_2_1& session_type);
 
+  static void UpdateTracksMetadata(
+      const SessionType_2_1& session_type,
+      const struct source_metadata* source_metadata);
+
   static void UpdateSinkMetadata(const SessionType_2_1& session_type,
                                  const struct sink_metadata* sink_metadata);
 };
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index 368939e..c270ef0 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -152,7 +152,7 @@
     std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
         BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      session_ptr->GetAudioSession()->UpdateTracksMetadata(source_metadata);
+      session_ptr->UpdateTracksMetadata(source_metadata);
     }
   }
 
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 4613ddc..ceb0662 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -31,9 +31,13 @@
 
 using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
 using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
+using ::android::hardware::audio::common::V5_0::AudioContentType;
 using ::android::hardware::audio::common::V5_0::AudioSource;
+using ::android::hardware::audio::common::V5_0::AudioUsage;
+using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
 using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
 using ::android::hardware::audio::common::V5_0::SinkMetadata;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
 using ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
@@ -128,6 +132,53 @@
   return audio_session_2_1;
 }
 
+void BluetoothAudioSession_2_2::UpdateTracksMetadata(
+    const struct source_metadata* source_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UpdateTracksMetadata(raw_session_type_,
+                                                          source_metadata);
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = source_metadata->track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+            << ", " << track_count << " track(s)";
+
+  if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
+    audio_session->UpdateTracksMetadata(source_metadata);
+    return;
+  }
+
+  struct playback_track_metadata* track = source_metadata->tracks;
+  SourceMetadata sourceMetadata;
+  PlaybackTrackMetadata* halMetadata;
+
+  sourceMetadata.tracks.resize(track_count);
+  halMetadata = sourceMetadata.tracks.data();
+  while (track_count && track) {
+    halMetadata->usage = static_cast<AudioUsage>(track->usage);
+    halMetadata->contentType =
+        static_cast<AudioContentType>(track->content_type);
+    halMetadata->gain = track->gain;
+    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+                 << ", usage=" << toString(halMetadata->usage)
+                 << ", content=" << toString(halMetadata->contentType)
+                 << ", gain=" << halMetadata->gain;
+    --track_count;
+    ++track;
+    ++halMetadata;
+  }
+  auto hal_retval = audio_session->stack_iface_->updateMetadata(sourceMetadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_2_1_) << " failed";
+  }
+}
+
 void BluetoothAudioSession_2_2::UpdateSinkMetadata(
     const struct sink_metadata* sink_metadata) {
   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index b6f96ab..e04ad80 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -152,6 +152,7 @@
   const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
   GetAudioConfig();
 
+  void UpdateTracksMetadata(const struct source_metadata* source_metadata);
   void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
 
   static constexpr ::android::hardware::bluetooth::audio::V2_2::
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 2d8a82e..f751efc 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -425,6 +425,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1.0</version>
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 1ed15b8..356cdb0 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -30,6 +30,7 @@
         "neuralnetworks_vts_functional_defaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    host_supported: true,
     srcs: [
         "BasicTests.cpp",
         "Callbacks.cpp",
@@ -46,18 +47,11 @@
     ],
     shared_libs: [
         "libbinder_ndk",
-        "libnativewindow",
-        "libvndksupport",
     ],
     static_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libaidlcommonsupport",
-        "libgmock",
-        "libhidlmemory",
         "libneuralnetworks_common",
         "libneuralnetworks_generated_test_harness",
-        "libsync",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_AIDL_V3_example",
@@ -73,6 +67,34 @@
     ],
     test_suites: [
         "general-tests",
-        "vts",
     ],
+    target: {
+        android: {
+            shared_libs: [
+                "libnativewindow",
+                "libvndksupport",
+            ],
+            static_libs: [
+                "libsync",
+            ],
+            test_suites: [
+                "vts",
+            ],
+            test_config: "AndroidTestDevice.xml",
+        },
+        host: {
+            shared_libs: [
+                "libtextclassifier_hash",
+            ],
+            static_libs: [
+                "neuralnetworks_canonical_sample_driver",
+                "neuralnetworks_utils_hal_adapter_aidl",
+            ],
+            exclude_static_libs: [
+                "VtsHalHidlTestUtils",
+                "libaidlvintf_gtest_helper",
+            ],
+            test_config: "AndroidTestHost.xml",
+        },
+    },
 }
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTest.xml b/neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
similarity index 100%
rename from neuralnetworks/aidl/vts/functional/AndroidTest.xml
rename to neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
new file mode 100644
index 0000000..7372a31
--- /dev/null
+++ b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalNeuralnetworksTargetTest.">
+    <test class="com.android.tradefed.testtype.HostGTest" >
+        <option name="module-name" value="VtsHalNeuralnetworksTargetTest" />
+        <option name="native-test-timeout" value="15m" />
+    </test>
+</configuration>
+
diff --git a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index 77208aa..7451f7e 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -23,7 +23,6 @@
 #include <fcntl.h>
 #include <ftw.h>
 #include <gtest/gtest.h>
-#include <hidlmemory/mapping.h>
 #include <unistd.h>
 
 #include <cstdio>
@@ -34,7 +33,6 @@
 
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
 #include "TestHarness.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
@@ -229,7 +227,11 @@
 
         // Create cache directory. The cache directory and a temporary cache file is always created
         // to test the behavior of prepareModelFromCache, even when caching is not supported.
+#ifdef __ANDROID__
         char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
+#else   // __ANDROID__
+        char cacheDirTemp[] = "/tmp/TestCompilationCachingXXXXXX";
+#endif  // __ANDROID__
         char* cacheDir = mkdtemp(cacheDirTemp);
         ASSERT_NE(cacheDir, nullptr);
         mCacheDir = cacheDir;
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index 8c8a87a..40f6cd1 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -20,7 +20,6 @@
 #include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
-#include <android/sync.h>
 #include <gtest/gtest.h>
 
 #include <algorithm>
@@ -30,7 +29,6 @@
 #include <numeric>
 #include <vector>
 
-#include <MemoryUtils.h>
 #include <android/binder_status.h>
 #include <nnapi/Result.h>
 #include <nnapi/SharedMemory.h>
@@ -43,6 +41,10 @@
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
+#ifdef __ANDROID__
+#include <android/sync.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks::vts::functional {
 
 namespace nn = ::android::nn;
@@ -281,10 +283,14 @@
 }  // namespace
 
 void waitForSyncFence(int syncFd) {
-    constexpr int kInfiniteTimeout = -1;
     ASSERT_GT(syncFd, 0);
+#ifdef __ANDROID__
+    constexpr int kInfiniteTimeout = -1;
     int r = sync_wait(syncFd, kInfiniteTimeout);
     ASSERT_GE(r, 0);
+#else   // __ANDROID__
+    LOG(FATAL) << "waitForSyncFence not supported on host";
+#endif  // __ANDROID__
 }
 
 Model createModel(const TestModel& testModel) {
@@ -895,7 +901,11 @@
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {false};
             executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
+#ifdef __ANDROID__
             memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
+#else   // __ANDROID__
+            memoryTypeList = {MemoryType::DEVICE};  // BLOB_AHWB is not supported on the host.
+#endif  // __ANDROID__
         } break;
         case TestKind::FENCED_COMPUTE: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 97760ae..f8341b1 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
 
 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModel.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_interface_utils.h>
@@ -33,7 +34,6 @@
 
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
@@ -191,7 +191,7 @@
 }
 
 // A placeholder invalid IPreparedModel class for MemoryDomainAllocateTest.InvalidPreparedModel
-class InvalidPreparedModel : public BnPreparedModel {
+class InvalidPreparedModel final : public IPreparedModel {
   public:
     ndk::ScopedAStatus executeSynchronously(const Request&, bool, int64_t, int64_t,
                                             ExecutionResult*) override {
@@ -225,6 +225,16 @@
         return ndk::ScopedAStatus::fromServiceSpecificError(
                 static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
     }
+    ndk::ScopedAStatus getInterfaceVersion(int32_t* /*interfaceVersion*/) {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::ScopedAStatus getInterfaceHash(std::string* /*interfaceHash*/) {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::SpAIBinder asBinder() override { return ::ndk::SpAIBinder{}; }
+    bool isRemote() override { return true; }
 };
 
 template <typename... Args>
diff --git a/neuralnetworks/aidl/vts/functional/Utils.cpp b/neuralnetworks/aidl/vts/functional/Utils.cpp
index efd5bca..1bc76f2 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.cpp
+++ b/neuralnetworks/aidl/vts/functional/Utils.cpp
@@ -21,18 +21,20 @@
 #include <aidl/android/hardware/neuralnetworks/OperandType.h>
 #include <android-base/logging.h>
 #include <android/binder_status.h>
-#include <android/hardware_buffer.h>
 
 #include <sys/mman.h>
 #include <iostream>
 #include <limits>
 #include <numeric>
 
-#include <MemoryUtils.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/hal/aidl/Conversions.h>
 #include <nnapi/hal/aidl/Utils.h>
 
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks {
 
 using test_helper::TestBuffer;
@@ -140,7 +142,8 @@
     return ahwb->mIsValid ? std::move(ahwb) : nullptr;
 }
 
-void TestBlobAHWB::initialize(uint32_t size) {
+void TestBlobAHWB::initialize([[maybe_unused]] uint32_t size) {
+#ifdef __ANDROID__
     mIsValid = false;
     ASSERT_GT(size, 0);
     const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
@@ -164,6 +167,9 @@
     mAidlMemory = utils::convert(mMemory).value();
 
     mIsValid = true;
+#else   // __ANDROID__
+    LOG(FATAL) << "TestBlobAHWB::initialize not supported on host";
+#endif  // __ANDROID__
 }
 
 std::string gtestCompliantName(std::string name) {
diff --git a/neuralnetworks/aidl/vts/functional/Utils.h b/neuralnetworks/aidl/vts/functional/Utils.h
index 0db3f8c..4e0a4aa 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -18,7 +18,6 @@
 #define ANDROID_HARDWARE_NEURALNETWORKS_AIDL_UTILS_H
 
 #include <android-base/logging.h>
-#include <android/hardware_buffer.h>
 #include <gtest/gtest.h>
 
 #include <algorithm>
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index ad93e6d..51b4805 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
+
 #include "VtsHalNeuralnetworks.h"
 
 #include <android-base/logging.h>
@@ -28,13 +29,19 @@
 #include <utility>
 
 #include <TestHarness.h>
-#include <aidl/Vintf.h>
 #include <nnapi/hal/aidl/Conversions.h>
 
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
 #include "Utils.h"
 
+#ifdef __ANDROID__
+#include <aidl/Vintf.h>
+#else  // __ANDROID__
+#include <CanonicalDevice.h>
+#include <nnapi/hal/aidl/Adapter.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks::vts::functional {
 
 using implementation::PreparedModelCallback;
@@ -111,6 +118,7 @@
     ASSERT_TRUE(deviceIsResponsive);
 }
 
+#ifdef __ANDROID__
 static NamedDevice makeNamedDevice(const std::string& name) {
     ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
     return {name, IDevice::fromBinder(binder)};
@@ -127,6 +135,14 @@
     std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
     return namedDevices;
 }
+#else   // __ANDROID__
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+    const std::string name = "nnapi-sample";
+    auto device = std::make_shared<const ::android::nn::sample::Device>(name);
+    auto aidlDevice = adapter::adapt(device);
+    return {{name, aidlDevice}};
+}
+#endif  // __ANDROID__
 
 const std::vector<NamedDevice>& getNamedDevices() {
     const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
diff --git a/nfc/OWNERS b/nfc/OWNERS
new file mode 100644
index 0000000..7867204
--- /dev/null
+++ b/nfc/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 48448
+alisher@google.com
+georgekgchang@google.com
+jackcwyu@google.com
+
+
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
new file mode 100644
index 0000000..d390c7e
--- /dev/null
+++ b/nfc/aidl/Android.bp
@@ -0,0 +1,34 @@
+// 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.
+
+aidl_interface {
+    name: "android.hardware.nfc",
+    vendor_available: true,
+    srcs: ["android/hardware/nfc/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..7a0ae54
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@VintfStability
+interface INfc {
+  void open(in android.hardware.nfc.INfcClientCallback clientCallback);
+  void close(in android.hardware.nfc.NfcCloseType type);
+  void coreInitialized();
+  void factoryReset();
+  android.hardware.nfc.NfcConfig getConfig();
+  void powerCycle();
+  void preDiscover();
+  int write(in byte[] data);
+  void setEnableVerboseLogging(in boolean enable);
+  boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..8150e81
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@VintfStability
+interface INfcClientCallback {
+  void sendData(in byte[] data);
+  void sendEvent(in android.hardware.nfc.NfcEvent event, in android.hardware.nfc.NfcStatus status);
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..7d44d48
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcCloseType {
+  DISABLE = 0,
+  HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..92e0a9a
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@VintfStability
+parcelable NfcConfig {
+  boolean nfaPollBailOutMode;
+  android.hardware.nfc.PresenceCheckAlgorithm presenceCheckAlgorithm;
+  android.hardware.nfc.ProtocolDiscoveryConfig nfaProprietaryCfg;
+  byte defaultOffHostRoute;
+  byte defaultOffHostRouteFelica;
+  byte defaultSystemCodeRoute;
+  byte defaultSystemCodePowerState;
+  byte defaultRoute;
+  byte offHostESEPipeId;
+  byte offHostSIMPipeId;
+  int maxIsoDepTransceiveLength;
+  byte[] hostAllowlist;
+  byte[] offHostRouteUicc;
+  byte[] offHostRouteEse;
+  byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..dda258e
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcEvent {
+  OPEN_CPLT = 0,
+  CLOSE_CPLT = 1,
+  POST_INIT_CPLT = 2,
+  PRE_DISCOVER_CPLT = 3,
+  HCI_NETWORK_RESET = 4,
+  ERROR = 5,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..2632480
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcStatus {
+  OK = 0,
+  FAILED = 1,
+  ERR_TRANSPORT = 2,
+  ERR_CMD_TIMEOUT = 3,
+  REFUSED = 4,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..9a9be21
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@Backing(type="byte") @VintfStability
+enum PresenceCheckAlgorithm {
+  DEFAULT = 0,
+  I_BLOCK = 1,
+  ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..021dfe2
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.hardware.nfc;
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+  byte protocol18092Active;
+  byte protocolBPrime;
+  byte protocolDual;
+  byte protocol15693;
+  byte protocolKovio;
+  byte protocolMifare;
+  byte discoveryPollKovio;
+  byte discoveryPollBPrime;
+  byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfc.aidl b/nfc/aidl/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..662f8d4
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,143 @@
+/*
+ * 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 android.hardware.nfc;
+
+import android.hardware.nfc.INfcClientCallback;
+import android.hardware.nfc.NfcCloseType;
+import android.hardware.nfc.NfcConfig;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfc {
+    /**
+     * Opens the NFC controller device and performs initialization.
+     * This may include patch download and other vendor-specific initialization.
+     *
+     * If open completes successfully, the controller must be ready to perform NCI
+     * initialization - ie accept CORE_RESET and subsequent commands through the write()
+     * call.
+     *
+     * Returns ok() if initialization starts successfully.
+     * If open() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+     * callback before continuing.
+     * If a NfcEvent.OPEN_CPLT callback received with status NfcStatus::OK, the controller
+     * must be ready to perform  NCI initialization - ie accept CORE_RESET and subsequent
+     * commands through the write() call.
+     */
+    void open(in INfcClientCallback clientCallback);
+
+    /**
+     * Close the NFC HAL and setup NFC controller close type.
+     * Associated resources such as clientCallback must be released.
+     * The clientCallback reference from open() must be invalid after close().
+     * If close() returns ok(), the NCI stack must wait for a NfcEvent.CLOSE_CPLT
+     * callback before continuing.
+     * Returns an error if close may be called more than once.
+     * Calls to any other method which expect a callback after this must return
+     * a service-specific error NfcStatus::FAILED.
+     * HAL close automatically if the client drops the reference to the HAL or
+     * crashes.
+     */
+    void close(in NfcCloseType type);
+
+    /**
+     * coreInitialized() is called after the CORE_INIT_RSP is received from the
+     * NFCC. At this time, the HAL can do any chip-specific configuration.
+     *
+     * If coreInitialized() returns ok(), the NCI stack must wait for a
+     * NfcEvent.POST_INIT_CPLT before continuing.
+     * If coreInitialized() returns an error, the NCI stack must continue immediately.
+     *
+     * coreInitialized() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     *
+     */
+    void coreInitialized();
+
+    /**
+     * Clears the NFC chip.
+     *
+     * Must be called during factory reset and/or before the first time the HAL is
+     * initialized after a factory reset.
+     */
+    void factoryReset();
+
+    /**
+     * Fetches vendor specific configurations.
+     * @return NfcConfig indicates support for certain features and
+     * populates the vendor specific configs.
+     */
+    NfcConfig getConfig();
+
+    /**
+     * Restart controller by power cyle;
+     * It's similar to open but just reset the controller without initialize all the
+     * resources.
+     *
+     * If powerCycle() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+     * before continuing.
+     *
+     * powerCycle() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     */
+    void powerCycle();
+
+    /**
+     * preDiscover is called every time before starting RF discovery.
+     * It is a good place to do vendor-specific configuration that must be
+     * performed every time RF discovery is about to be started.
+     *
+     * If preDiscover() returns ok(), the NCI stack must wait for a
+     * NfcEvent.PREDISCOVER_CPLT before continuing.
+     *
+     * preDiscover() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     *
+     * If preDiscover() reports an error, the NCI stack must start RF discovery immediately.
+     */
+    void preDiscover();
+
+    /**
+     * Performs an NCI write.
+     *
+     * This method may queue writes and return immediately. The only
+     * requirement is that the writes are executed in order.
+     *
+     * @param data
+     * Data packet to transmit NCI Commands and Data Messages over write.
+     * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+     * https://nfc-forum.org/our-work/specification-releases/
+     *
+     * @return number of bytes written to the NFCC.
+     */
+    int write(in byte[] data);
+
+    /**
+     * Set the logging flag for NFC HAL to enable it's verbose logging.
+     * If verbose logging is not supported, the call must not have any effect on logging verbosity.
+     * However, isVerboseLoggingEnabled() must still return the value set by the last call to
+     * setEnableVerboseLogging().
+     * @param enable for setting the verbose logging flag to HAL
+     */
+    void setEnableVerboseLogging(in boolean enable);
+
+    /**
+     * Get the verbose logging flag value from NFC HAL.
+     * @return true if verbose logging flag value is enabled, false if disabled.
+     */
+    boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..43d4f5c
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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 android.hardware.nfc;
+
+import android.hardware.nfc.NfcEvent;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfcClientCallback {
+    /**
+     * The callback passed in from the NFC stack that the HAL
+     * can use to pass incomming response data to the stack.
+     *
+     * @param data
+     * Data packet to transmit NCI Responses, Notifications, and Data
+     * Messages over sendData.
+     * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+     * https://nfc-forum.org/our-work/specification-releases/
+     */
+    void sendData(in byte[] data);
+
+    /**
+     * The callback passed in from the NFC stack that the HAL
+     * can use to pass events back to the stack.
+     */
+    void sendEvent(in NfcEvent event, in NfcStatus status);
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..5160532
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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 android.hardware.nfc;
+
+/**
+ * Different closing types for NFC HAL.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcCloseType {
+    /**
+     * Close the NFC controller and free NFC HAL resources.
+     */
+    DISABLE = 0,
+
+    /**
+     * Switch the NFC controller operation mode and free NFC HAL resources.
+     * Enable NFC functionality for off host card emulation usecases in
+     * device(host) power off(switched off) state, if the device
+     * supports power off use cases. If the device doesn't support power
+     * off use cases, this call should be same as DISABLE.
+     */
+    HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..1b4fcfb
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,89 @@
+/*
+ * 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 android.hardware.nfc;
+
+import android.hardware.nfc.PresenceCheckAlgorithm;
+import android.hardware.nfc.ProtocolDiscoveryConfig;
+
+/**
+ * Define Nfc related configurations based on:
+ * NFC Controller Interface (NCI) Technical Specification
+ * https://nfc-forum.org/our-work/specification-releases/
+ */
+@VintfStability
+parcelable NfcConfig {
+    /**
+     * If true, NFCC is using bail out mode for either Type A or Type B poll
+     * based on: Nfc-Forum Activity Technical Specification
+     * https://nfc-forum.org/our-work/specification-releases/
+     */
+    boolean nfaPollBailOutMode;
+    PresenceCheckAlgorithm presenceCheckAlgorithm;
+    ProtocolDiscoveryConfig nfaProprietaryCfg;
+    /**
+     * Default off-host route. 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte defaultOffHostRoute;
+    /**
+     * Default off-host route for Felica. 0x00 if there aren't any. Refer to
+     * NCI spec.
+     */
+    byte defaultOffHostRouteFelica;
+    /**
+     * Default system code route. 0x00 if there aren't any. Refer NCI spec.
+     */
+    byte defaultSystemCodeRoute;
+    /**
+     * Default power state for system code route. 0x00 if there aren't any.
+     * Refer to NCI spec.
+     */
+    byte defaultSystemCodePowerState;
+    /**
+     * Default route for all remaining protocols and technology which haven't
+     * been configured.
+     * Device Host(0x00) is the default. Refer to NCI spec.
+     *
+     */
+    byte defaultRoute;
+    /**
+     * Pipe ID for eSE. 0x00 if there aren't any.
+     */
+    byte offHostESEPipeId;
+    /**
+     * Pipe ID for UICC. 0x00 if there aren't any.
+     */
+    byte offHostSIMPipeId;
+    /**
+     * Extended APDU length for ISO_DEP. If not supported default length is 261
+     */
+    int maxIsoDepTransceiveLength;
+    /**
+     * list of allowed host ids, as per ETSI TS 102 622
+     * https://www.etsi.org/
+     */
+    byte[] hostAllowlist;
+    /**
+     * NFCEE ID for offhost UICC & eSE secure element.
+     * 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte[] offHostRouteUicc;
+    byte[] offHostRouteEse;
+    /**
+     * Default IsoDep route. 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..a78b1cd
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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 android.hardware.nfc;
+
+/**
+ * Nfc event to notify nfc status change.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcEvent {
+    /**
+     * Open complete event to notify upper layer when NFC HAL and NFCC
+     * initialization complete.
+     */
+    OPEN_CPLT = 0,
+    /**
+     * Close complete event to notify upper layer when HAL close is done.
+     */
+    CLOSE_CPLT = 1,
+    /**
+     * Post init complete event to notify upper layer when post init operations
+     * are done.
+     */
+    POST_INIT_CPLT = 2,
+    /**
+     * Pre-discover complete event to notify upper layer when pre-discover
+     * operations are done.
+     */
+    PRE_DISCOVER_CPLT = 3,
+    /**
+     * HCI network reset event to notify upplayer when HCI network needs to
+     * be re-initialized in case of an error.
+     */
+    HCI_NETWORK_RESET = 4,
+    /**
+     * Error event to notify upper layer when there's an unknown error.
+     */
+    ERROR = 5,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..a38d370
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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 android.hardware.nfc;
+
+/**
+ * Used to specify the status of the NfcEvent
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcStatus {
+    /**
+     * Default status when NfcEvent with status OK.
+     */
+    OK = 0,
+    /**
+     * Generic error.
+     */
+    FAILED = 1,
+    /**
+     * Transport error.
+     */
+    ERR_TRANSPORT = 2,
+    /**
+     * Command timeout error.
+     */
+    ERR_CMD_TIMEOUT = 3,
+    /**
+     * Refused error when command is rejected.
+     */
+    REFUSED = 4,
+}
diff --git a/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..20e7bff
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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 android.hardware.nfc;
+
+/*
+ * Presence Check Algorithm as defined in ISO/IEC 14443-4:
+ * https://www.iso.org/standard/73599.html
+ */
+@VintfStability
+@Backing(type="byte")
+enum PresenceCheckAlgorithm {
+    /**
+     * Let the stack select an algorithm
+     */
+    DEFAULT = 0,
+    /**
+     * ISO-DEP protocol's empty I-block
+     */
+    I_BLOCK = 1,
+    /**
+     * Type - 4 tag protocol iso-dep nak presence check command is sent waiting for
+     * response and notification.
+     */
+    ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..f8e3228
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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 android.hardware.nfc;
+
+/**
+ * Vendor Specific Proprietary Protocol & Discovery Configuration.
+ * Set to 0xFF if not supported.
+ * discovery* fields map to "RF Technology and Mode" in NCI Spec
+ * protocol* fields map to "RF protocols" in NCI Spec
+ */
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+    byte protocol18092Active;
+    byte protocolBPrime;
+    byte protocolDual;
+    byte protocol15693;
+    byte protocolKovio;
+    byte protocolMifare;
+    byte discoveryPollKovio;
+    byte discoveryPollBPrime;
+    byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/default/Android.bp b/nfc/aidl/default/Android.bp
new file mode 100644
index 0000000..907d23d
--- /dev/null
+++ b/nfc/aidl/default/Android.bp
@@ -0,0 +1,23 @@
+cc_binary {
+    name: "android.hardware.nfc-service.example",
+    relative_install_path: "hw",
+    init_rc: ["nfc-service-example.rc"],
+    vintf_fragments: ["nfc-service-example.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+        "libbinder_ndk",
+        "android.hardware.nfc-V1-ndk",
+    ],
+    srcs: [
+        "main.cpp",
+        "Nfc.cpp",
+        "Vendor_hal_api.cpp",
+    ],
+}
diff --git a/nfc/aidl/default/Nfc.cpp b/nfc/aidl/default/Nfc.cpp
new file mode 100644
index 0000000..a31ac5e
--- /dev/null
+++ b/nfc/aidl/default/Nfc.cpp
@@ -0,0 +1,163 @@
+/*
+ * 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 "Nfc.h"
+
+#include <android-base/logging.h>
+
+#include "Vendor_hal_api.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+std::shared_ptr<INfcClientCallback> Nfc::mCallback = nullptr;
+AIBinder_DeathRecipient* clientDeathRecipient = nullptr;
+
+void OnDeath(void* cookie) {
+    if (Nfc::mCallback != nullptr && !AIBinder_isAlive(Nfc::mCallback->asBinder().get())) {
+        LOG(INFO) << __func__ << " Nfc service has died";
+        Nfc* nfc = static_cast<Nfc*>(cookie);
+        nfc->close(NfcCloseType::DISABLE);
+    }
+}
+
+::ndk::ScopedAStatus Nfc::open(const std::shared_ptr<INfcClientCallback>& clientCallback) {
+    LOG(INFO) << "open";
+    if (clientCallback == nullptr) {
+        LOG(INFO) << "Nfc::open null callback";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    } else {
+        Nfc::mCallback = clientCallback;
+
+        clientDeathRecipient = AIBinder_DeathRecipient_new(OnDeath);
+        auto linkRet = AIBinder_linkToDeath(clientCallback->asBinder().get(), clientDeathRecipient,
+                                            this /* cookie */);
+        if (linkRet != STATUS_OK) {
+            LOG(ERROR) << __func__ << ": linkToDeath failed: " << linkRet;
+            // Just ignore the error.
+        }
+
+        int ret = Vendor_hal_open(eventCallback, dataCallback);
+        return ret == 0 ? ndk::ScopedAStatus::ok()
+                        : ndk::ScopedAStatus::fromServiceSpecificError(
+                                  static_cast<int32_t>(NfcStatus::FAILED));
+        return ndk::ScopedAStatus::ok();
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::close(NfcCloseType type) {
+    LOG(INFO) << "close";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    int ret = 0;
+    if (type == NfcCloseType::HOST_SWITCHED_OFF) {
+        ret = Vendor_hal_close_off();
+    } else {
+        ret = Vendor_hal_close();
+    }
+    Nfc::mCallback = nullptr;
+    AIBinder_DeathRecipient_delete(clientDeathRecipient);
+    clientDeathRecipient = nullptr;
+    return ret == 0 ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromServiceSpecificError(
+                              static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::coreInitialized() {
+    LOG(INFO) << "coreInitialized";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    int ret = Vendor_hal_core_initialized();
+
+    return ret == 0 ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromServiceSpecificError(
+                              static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::factoryReset() {
+    LOG(INFO) << "factoryReset";
+    Vendor_hal_factoryReset();
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::getConfig(NfcConfig* _aidl_return) {
+    LOG(INFO) << "getConfig";
+    NfcConfig nfcVendorConfig;
+    Vendor_hal_getConfig(nfcVendorConfig);
+
+    *_aidl_return = nfcVendorConfig;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::powerCycle() {
+    LOG(INFO) << "powerCycle";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    return Vendor_hal_power_cycle() ? ndk::ScopedAStatus::fromServiceSpecificError(
+                                              static_cast<int32_t>(NfcStatus::FAILED))
+                                    : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::preDiscover() {
+    LOG(INFO) << "preDiscover";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    return Vendor_hal_pre_discover() ? ndk::ScopedAStatus::fromServiceSpecificError(
+                                               static_cast<int32_t>(NfcStatus::FAILED))
+                                     : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::write(const std::vector<uint8_t>& data, int32_t* _aidl_return) {
+    LOG(INFO) << "write";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    *_aidl_return = Vendor_hal_write(data.size(), &data[0]);
+    return ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus Nfc::setEnableVerboseLogging(bool enable) {
+    LOG(INFO) << "setVerboseLogging";
+    Vendor_hal_setVerboseLogging(enable);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::isVerboseLoggingEnabled(bool* _aidl_return) {
+    *_aidl_return = Vendor_hal_getVerboseLogging();
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace nfc
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/nfc/aidl/default/Nfc.h b/nfc/aidl/default/Nfc.h
new file mode 100644
index 0000000..1b14534
--- /dev/null
+++ b/nfc/aidl/default/Nfc.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/INfcClientCallback.h>
+#include <android-base/logging.h>
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+using ::aidl::android::hardware::nfc::NfcCloseType;
+using ::aidl::android::hardware::nfc::NfcConfig;
+using ::aidl::android::hardware::nfc::NfcStatus;
+
+// Default implementation that reports no support NFC.
+struct Nfc : public BnNfc {
+  public:
+    Nfc() = default;
+
+    ::ndk::ScopedAStatus open(const std::shared_ptr<INfcClientCallback>& clientCallback) override;
+    ::ndk::ScopedAStatus close(NfcCloseType type) override;
+    ::ndk::ScopedAStatus coreInitialized() override;
+    ::ndk::ScopedAStatus factoryReset() override;
+    ::ndk::ScopedAStatus getConfig(NfcConfig* _aidl_return) override;
+    ::ndk::ScopedAStatus powerCycle() override;
+    ::ndk::ScopedAStatus preDiscover() override;
+    ::ndk::ScopedAStatus write(const std::vector<uint8_t>& data, int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus setEnableVerboseLogging(bool enable) override;
+    ::ndk::ScopedAStatus isVerboseLoggingEnabled(bool* _aidl_return) override;
+
+    static void eventCallback(uint8_t event, uint8_t status) {
+        if (mCallback != nullptr) {
+            auto ret = mCallback->sendEvent((NfcEvent)event, (NfcStatus)status);
+            if (!ret.isOk()) {
+                LOG(ERROR) << "Failed to send event!";
+            }
+        }
+    }
+
+    static void dataCallback(uint16_t data_len, uint8_t* p_data) {
+        std::vector<uint8_t> data(p_data, p_data + data_len);
+        if (mCallback != nullptr) {
+            auto ret = mCallback->sendData(data);
+            if (!ret.isOk()) {
+                LOG(ERROR) << "Failed to send data!";
+            }
+        }
+    }
+
+    static std::shared_ptr<INfcClientCallback> mCallback;
+};
+
+}  // namespace nfc
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/nfc/aidl/default/Vendor_hal_api.cpp b/nfc/aidl/default/Vendor_hal_api.cpp
new file mode 100644
index 0000000..66a2ebc
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 <android-base/properties.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "Vendor_hal_api.h"
+
+bool logging = false;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback) {
+    (void)p_cback;
+    (void)p_data_cback;
+    // nothing to open in this example
+    return -1;
+}
+
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data) {
+    (void)data_len;
+    (void)p_data;
+    return -1;
+}
+
+int Vendor_hal_core_initialized() {
+    return -1;
+}
+
+int Vendor_hal_pre_discover() {
+    return -1;
+}
+
+int Vendor_hal_close() {
+    return -1;
+}
+
+int Vendor_hal_close_off() {
+    return -1;
+}
+
+int Vendor_hal_power_cycle() {
+    return -1;
+}
+
+void Vendor_hal_factoryReset() {}
+
+void Vendor_hal_getConfig(NfcConfig& config) {
+    (void)config;
+}
+
+void Vendor_hal_setVerboseLogging(bool enable) {
+    logging = enable;
+}
+
+bool Vendor_hal_getVerboseLogging() {
+    return logging;
+}
diff --git a/nfc/aidl/default/Vendor_hal_api.h b/nfc/aidl/default/Vendor_hal_api.h
new file mode 100644
index 0000000..595c2dd
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <aidl/android/hardware/nfc/NfcConfig.h>
+#include <aidl/android/hardware/nfc/NfcEvent.h>
+#include <aidl/android/hardware/nfc/NfcStatus.h>
+#include <aidl/android/hardware/nfc/PresenceCheckAlgorithm.h>
+#include <aidl/android/hardware/nfc/ProtocolDiscoveryConfig.h>
+#include "hardware_nfc.h"
+
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+using aidl::android::hardware::nfc::ProtocolDiscoveryConfig;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback);
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data);
+
+int Vendor_hal_core_initialized();
+
+int Vendor_hal_pre_discover();
+
+int Vendor_hal_close();
+
+int Vendor_hal_close_off();
+
+int Vendor_hal_power_cycle();
+
+void Vendor_hal_factoryReset();
+
+void Vendor_hal_getConfig(NfcConfig& config);
+
+void Vendor_hal_setVerboseLogging(bool enable);
+
+bool Vendor_hal_getVerboseLogging();
diff --git a/nfc/aidl/default/hardware_nfc.h b/nfc/aidl/default/hardware_nfc.h
new file mode 100644
index 0000000..0f856c5
--- /dev/null
+++ b/nfc/aidl/default/hardware_nfc.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+#pragma once
+
+typedef uint8_t nfc_event_t;
+typedef uint8_t nfc_status_t;
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass events back to the stack.
+ */
+typedef void(nfc_stack_callback_t)(nfc_event_t event, nfc_status_t event_status);
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass incomming data to the stack.
+ */
+typedef void(nfc_stack_data_callback_t)(uint16_t data_len, uint8_t* p_data);
diff --git a/nfc/aidl/default/main.cpp b/nfc/aidl/default/main.cpp
new file mode 100644
index 0000000..0cc51e7
--- /dev/null
+++ b/nfc/aidl/default/main.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Nfc.h"
+using ::aidl::android::hardware::nfc::Nfc;
+
+int main() {
+    LOG(INFO) << "NFC HAL starting up";
+    if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+        LOG(INFO) << "failed to set thread pool max thread count";
+        return 1;
+    }
+    std::shared_ptr<Nfc> nfc_service = ndk::SharedRefBase::make<Nfc>();
+
+    const std::string instance = std::string() + Nfc::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(nfc_service->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+    ABinderProcess_joinThreadPool();
+    return 0;
+}
diff --git a/nfc/aidl/default/nfc-service-example.rc b/nfc/aidl/default/nfc-service-example.rc
new file mode 100644
index 0000000..7d7052e
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.rc
@@ -0,0 +1,4 @@
+service nfc_hal_service /vendor/bin/hw/android.hardware.nfc-service.st
+    class hal
+    user nfc
+    group nfc
diff --git a/nfc/aidl/default/nfc-service-example.xml b/nfc/aidl/default/nfc-service-example.xml
new file mode 100644
index 0000000..70fed20
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.nfc</name>
+        <fqname>INfc/default</fqname>
+    </hal>
+</manifest>
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..99eecd0
--- /dev/null
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsAidlHalNfcTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsAidlHalNfcTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.nfc-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
new file mode 100644
index 0000000..977b25c
--- /dev/null
+++ b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "nfc_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/BnNfcClientCallback.h>
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <chrono>
+#include <future>
+
+using aidl::android::hardware::nfc::INfc;
+using aidl::android::hardware::nfc::INfcClientCallback;
+using aidl::android::hardware::nfc::NfcCloseType;
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+
+using android::getAidlHalInstanceNames;
+using android::PrintInstanceNameToString;
+using android::base::StringPrintf;
+using ndk::enum_range;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+
+constexpr static int kCallbackTimeoutMs = 10000;
+
+// 261 bytes is the default and minimum transceive length
+constexpr unsigned int MIN_ISO_DEP_TRANSCEIVE_LENGTH = 261;
+
+// Range of valid off host route ids
+constexpr uint8_t MIN_OFFHOST_ROUTE_ID = 0x01;
+constexpr uint8_t MAX_OFFHOST_ROUTE_ID = 0xFE;
+
+class NfcClientCallback : public aidl::android::hardware::nfc::BnNfcClientCallback {
+  public:
+    NfcClientCallback(const std::function<void(NfcEvent, NfcStatus)>& on_hal_event_cb,
+                      const std::function<void(const std::vector<uint8_t>&)>& on_nci_data_cb)
+        : on_nci_data_cb_(on_nci_data_cb), on_hal_event_cb_(on_hal_event_cb) {}
+    virtual ~NfcClientCallback() = default;
+
+    ::ndk::ScopedAStatus sendEvent(NfcEvent event, NfcStatus event_status) override {
+        on_hal_event_cb_(event, event_status);
+        return ::ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus sendData(const std::vector<uint8_t>& data) override {
+        on_nci_data_cb_(data);
+        return ::ndk::ScopedAStatus::ok();
+    };
+
+  private:
+    std::function<void(const std::vector<uint8_t>&)> on_nci_data_cb_;
+    std::function<void(NfcEvent, NfcStatus)> on_hal_event_cb_;
+};
+
+class NfcAidl : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+        infc_ = INfc::fromBinder(binder);
+        ASSERT_NE(infc_, nullptr);
+    }
+    std::shared_ptr<INfc> infc_;
+};
+
+/*
+ * OpenAndCloseForDisable:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::DISABLE) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForDisable) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                LOG(INFO) << StringPrintf("%s,%d ", __func__, event);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close DISABLE";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    LOG(INFO) << "wait for close";
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAndCloseForHostSwitchedOff:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::HOST_SWITCHED_OFF) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForHostSwitchedOff) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close HOST_SWITCHED_OFF";
+    EXPECT_TRUE(infc_->close(NfcCloseType::HOST_SWITCHED_OFF).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAfterOpen:
+ * Calls open() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, OpenAfterOpen) {
+    int open_count = 0;
+    std::promise<void> open_cb_promise;
+    std::promise<void> open2_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto open2_cb_future = open2_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &open2_cb_promise, &open_count](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) {
+                    open_count == 0 ? open_cb_promise.set_value() : open2_cb_promise.set_value();
+                    open_count++;
+                }
+            },
+            [](auto) {});
+
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Open again and wait for OPEN_CPLT
+    LOG(INFO) << "open again";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open2_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CloseAfterClose:
+ * Calls close() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, CloseAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+    // Close again should fail.
+    LOG(INFO) << "close again";
+    EXPECT_TRUE(!(infc_->close(NfcCloseType::DISABLE).isOk()));
+}
+
+/*
+ * PowerCycleAfterOpen:
+ * Calls powerCycle() after open
+ * Waits for NfcEvent.OPEN_CPLT
+ * Checks status
+ */
+TEST_P(NfcAidl, PowerCycleAfterOpen) {
+    int open_cplt_count = 0;
+    std::promise<void> open_cb_promise;
+    std::promise<void> power_cycle_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto power_cycle_cb_future = power_cycle_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise, &power_cycle_cb_promise, &open_cplt_count](
+                    auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) {
+                    if (open_cplt_count == 0) {
+                        open_cplt_count++;
+                        open_cb_promise.set_value();
+                    } else {
+                        power_cycle_cb_promise.set_value();
+                    }
+                }
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // PowerCycle and wait for OPEN_CPLT
+    LOG(INFO) << "PowerCycle";
+    EXPECT_TRUE(infc_->powerCycle().isOk());
+    EXPECT_EQ(power_cycle_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * PowerCycleAfterClose:
+ * Calls powerCycle() after close
+ * PowerCycle should fail immediately
+ */
+TEST_P(NfcAidl, PowerCycleAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // PowerCycle should fail
+    LOG(INFO) << "PowerCycle";
+    EXPECT_TRUE(!(infc_->powerCycle().isOk()));
+}
+
+/*
+ * CoreInitializedAfterOpen:
+ * Calls coreInitialized() after open
+ * Waits for NfcEvent.POST_INIT_CPLT
+ */
+TEST_P(NfcAidl, CoreInitializedAfterOpen) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> core_init_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto core_init_cb_future = core_init_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise, &core_init_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::POST_INIT_CPLT) core_init_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // CoreInitialized and wait for POST_INIT_CPLT
+    LOG(INFO) << "coreInitialized";
+    EXPECT_TRUE(infc_->coreInitialized().isOk());
+    EXPECT_EQ(core_init_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CoreInitializedAfterClose:
+ * Calls coreInitialized() after close
+ * coreInitialized() should fail immediately
+ */
+TEST_P(NfcAidl, CoreInitializedAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // coreInitialized should fail
+    LOG(INFO) << "CoreInitialized";
+    EXPECT_TRUE(!(infc_->coreInitialized().isOk()));
+}
+
+/*
+ * PreDiscoverAfterClose:
+ * Call preDiscover() after close
+ * preDiscover() should fail immediately
+ */
+TEST_P(NfcAidl, PreDiscoverAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // preDiscover should fail
+    LOG(INFO) << "preDiscover";
+    EXPECT_TRUE(!(infc_->preDiscover().isOk()));
+}
+
+/*
+ * checkGetConfigValues:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_P(NfcAidl, CheckGetConfigValues) {
+    NfcConfig configValue;
+    EXPECT_TRUE(infc_->getConfig(&configValue).isOk());
+    EXPECT_GE(configValue.maxIsoDepTransceiveLength, MIN_ISO_DEP_TRANSCEIVE_LENGTH);
+    LOG(INFO) << StringPrintf("configValue.maxIsoDepTransceiveLength = %x",
+                              configValue.maxIsoDepTransceiveLength);
+    for (auto uicc : configValue.offHostRouteUicc) {
+        LOG(INFO) << StringPrintf("offHostRouteUicc = %x", uicc);
+        EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
+    }
+    for (auto ese : configValue.offHostRouteEse) {
+        LOG(INFO) << StringPrintf("offHostRouteEse = %x", ese);
+        EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
+    }
+    if (configValue.defaultIsoDepRoute != 0) {
+        EXPECT_GE((uint8_t)configValue.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE((uint8_t)configValue.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
+    }
+}
+
+/*
+ * CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging:
+ * Calls setEnableVerboseLogging()
+ * checks the return value of isVerboseLoggingEnabled
+ */
+TEST_P(NfcAidl, CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging) {
+    bool enabled = false;
+    EXPECT_TRUE(infc_->setEnableVerboseLogging(true).isOk());
+    EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+    EXPECT_TRUE(enabled);
+    EXPECT_TRUE(infc_->setEnableVerboseLogging(false).isOk());
+    EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+    EXPECT_TRUE(!enabled);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcAidl);
+INSTANTIATE_TEST_SUITE_P(Nfc, NfcAidl,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
+                         ::android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_startThreadPool();
+    std::system("/system/bin/svc nfc disable"); /* Turn off NFC */
+    sleep(5);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    std::system("/system/bin/svc nfc enable"); /* Turn on NFC */
+    sleep(5);
+    return status;
+}