Merge "Revert "Merge "Revert "VTS for IRadio AIDL"" am: 3a16f8fe50"" into stage-aosp-master
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
index d7d5476..6e8c1d7 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -41,12 +41,8 @@
     BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
 LeAudioOutputAudioProvider
     BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
-LeAudioOffloadOutputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
 LeAudioInputAudioProvider
     BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
-LeAudioOffloadInputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
 
 Return<void> BluetoothAudioProvidersFactory::openProvider(
     const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
@@ -94,15 +90,9 @@
     case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
       provider = &leaudio_output_provider_instance_;
       break;
-    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
-      provider = &leaudio_offload_output_provider_instance_;
-      break;
     case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
       provider = &leaudio_input_provider_instance_;
       break;
-    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
-      provider = &leaudio_offload_input_provider_instance_;
-      break;
     default:
       status = BluetoothAudioStatus::FAILURE;
   }
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
index f8f557e..714d738 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -56,8 +56,6 @@
   static HearingAidAudioProvider hearing_aid_provider_instance_;
   static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
   static LeAudioInputAudioProvider leaudio_input_provider_instance_;
-  static LeAudioOffloadOutputAudioProvider leaudio_offload_output_provider_instance_;
-  static LeAudioOffloadInputAudioProvider leaudio_offload_input_provider_instance_;
 };
 
 extern "C" IBluetoothAudioProvidersFactory*
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
index bc16b01..f577537 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
@@ -59,4 +59,14 @@
      */
     startSession_2_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
                 generates (Status status, fmq_sync<uint8_t> dataMQ);
+
+    /**
+     * Called when the audio configuration of the stream has been changed.
+     *
+     * @param audioConfig The audio configuration negotiated with the remote
+     *    device. The PCM parameters are set if software based encoding,
+     *    otherwise the correct codec configuration is used for hardware
+     *    encoding.
+     */
+    updateAudioConfiguration(AudioConfiguration audioConfig);
 };
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
index 7fb5b6c..ae9c598 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
@@ -48,4 +48,26 @@
      */
     openProvider_2_2(SessionType sessionType)
         generates (Status status, IBluetoothAudioProvider provider);
+
+    /**
+     * Gets a list of audio capabilities for a session type.
+     *
+     * For software encoding, the PCM capabilities are returned.
+     * For hardware encoding, the supported codecs and their capabilities are
+     * returned.
+     *
+     * @param sessionType The session type (e.g.
+     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
+     * @return audioCapabilities A list containing all the capabilities
+     *    supported by the sesson type. The capabilities is a list of
+     *    available options when configuring the codec for the session.
+     *    For software encoding it is the PCM data rate.
+     *    For hardware encoding it is the list of supported codecs and their
+     *    capabilities.
+     *    If a provider isn't supported, an empty list should be returned.
+     *    Note: Only one entry should exist per codec when using hardware
+     *    encoding.
+     */
+     getProviderCapabilities_2_2(SessionType sessionType)
+         generates (vec<AudioCapabilities> audioCapabilities);
 };
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
index 18ac292..202cfb9 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
@@ -186,6 +186,29 @@
   return Void();
 }
 
+Return<void> BluetoothAudioProvider::updateAudioConfiguration(
+    const AudioConfiguration& audioConfig) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ == nullptr) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+    return Void();
+  }
+
+  if (audioConfig.getDiscriminator() != audio_config_.getDiscriminator()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " audio config type is not match";
+    return Void();
+  }
+
+  audio_config_ = audioConfig;
+  BluetoothAudioSessionReport_2_2::ReportAudioConfigChanged(session_type_,
+                                                            audio_config_);
+
+  return Void();
+}
+
 }  // namespace implementation
 }  // namespace V2_2
 }  // namespace audio
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
index 0f1f3c6..425ea3b 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
@@ -53,6 +53,8 @@
   Return<void> streamStarted(BluetoothAudioStatus status) override;
   Return<void> streamSuspended(BluetoothAudioStatus status) override;
   Return<void> endSession() override;
+  Return<void> updateAudioConfiguration(
+      const AudioConfiguration& audioConfig) override;
 
  protected:
   sp<BluetoothAudioDeathRecipient> death_recipient_;
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
index 51ee422..9435311 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
@@ -98,15 +98,9 @@
     case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
       provider = &leaudio_output_provider_instance_;
       break;
-    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
-      provider = &leaudio_offload_output_provider_instance_;
-      break;
     case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
       provider = &leaudio_input_provider_instance_;
       break;
-    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
-      provider = &leaudio_offload_input_provider_instance_;
-      break;
     default:
       status = BluetoothAudioStatus::FAILURE;
   }
@@ -221,6 +215,47 @@
   return Void();
 }
 
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2(
+    const V2_1::SessionType sessionType,
+    getProviderCapabilities_2_2_cb _hidl_cb) {
+  hidl_vec<V2_2::AudioCapabilities> audio_capabilities =
+      hidl_vec<V2_2::AudioCapabilities>(0);
+  if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    std::vector<CodecCapabilities> db_codec_capabilities =
+        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+    if (db_codec_capabilities.size()) {
+      audio_capabilities.resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+      }
+    }
+  } else if (sessionType == V2_1::SessionType::
+                                LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+             sessionType == V2_1::SessionType::
+                                LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    std::vector<LeAudioCodecCapabilitiesPair> db_codec_capabilities =
+        android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
+            sessionType);
+    if (db_codec_capabilities.size()) {
+      audio_capabilities.resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        audio_capabilities[i].leAudioCapabilities(db_codec_capabilities[i]);
+      }
+    }
+  } else if (sessionType != V2_1::SessionType::UNKNOWN) {
+    std::vector<V2_1::PcmParameters> db_pcm_capabilities =
+        android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
+    if (db_pcm_capabilities.size() == 1) {
+      audio_capabilities.resize(1);
+      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+    }
+  }
+  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+            << " supports " << audio_capabilities.size() << " codecs";
+  _hidl_cb(audio_capabilities);
+  return Void();
+}
+
 IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
     const char* /* name */) {
   return new BluetoothAudioProvidersFactory();
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
index 658249b..4f549d9 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
@@ -53,6 +53,10 @@
       const V2_1::SessionType sessionType,
       getProviderCapabilities_2_1_cb _hidl_cb) override;
 
+  Return<void> getProviderCapabilities_2_2(
+      const V2_1::SessionType sessionType,
+      getProviderCapabilities_2_2_cb _hidl_cb) override;
+
  private:
   static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
   static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
index d5f8a3f..8ec3660 100644
--- a/bluetooth/audio/2.2/types.hal
+++ b/bluetooth/audio/2.2/types.hal
@@ -19,6 +19,8 @@
 import @2.1::Lc3Parameters;
 import @2.1::PcmParameters;
 import @2.0::CodecConfiguration;
+import @2.0::CodecCapabilities;
+import @2.1::CodecType;
 
 enum LeAudioMode : uint8_t {
     UNKNOWN = 0x00,
@@ -26,6 +28,12 @@
     BROADCAST = 0x02,
 };
 
+enum AudioLocation : uint8_t {
+  UNKNOWN = 0,
+  FRONT_LEFT = 1,
+  FRONT_RIGHT = 2,
+};
+
 struct UnicastStreamMap {
     /* The connection handle used for a unicast or a broadcast group. */
     uint16_t streamHandle;
@@ -70,3 +78,37 @@
     CodecConfiguration codecConfig;
     LeAudioConfiguration leAudioConfig;
 };
+
+/** Used to specify the capabilities of the different session types */
+safe_union AudioCapabilities {
+    PcmParameters pcmCapabilities;
+    CodecCapabilities codecCapabilities;
+    LeAudioCodecCapabilitiesPair leAudioCapabilities;
+};
+
+/**
+ * Used to specify th le audio capabilities pair of the Hardware offload encode and decode.
+ */
+struct LeAudioCodecCapabilitiesPair{
+    LeAudioMode mode;
+    LeAudioCodecCapability encodeCapability;
+    LeAudioCodecCapability decodeCapability;
+};
+
+/**
+ * Used to specify the le audio capabilities of the codecs supported by Hardware offload
+ * for encode or decode.
+ */
+struct LeAudioCodecCapability {
+    CodecType codecType;
+    AudioLocation supportedChannel;
+
+    // The number of connected device
+    uint8_t deviceCount;
+
+    // Supported channel count for each device
+    uint8_t channelCountPerDevice;
+
+    // Should use safe union when there is more than one codec
+    Lc3Parameters capabilities;
+};
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index 71ab464..368939e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -48,20 +48,38 @@
     std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
         BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      return session_ptr->GetAudioSession()->RegisterStatusCback(cbacks);
+      PortStatusCallbacks_2_2 cb = {
+          .control_result_cb_ = cbacks.control_result_cb_,
+          .session_changed_cb_ = cbacks.session_changed_cb_,
+          .audio_configuration_changed_cb_ = nullptr};
+      return session_ptr->RegisterStatusCback(cb);
+    }
+    return kObserversCookieUndefined;
+  }
+
+  // The control API helps the bluetooth_audio module to register
+  // PortStatusCallbacks_2_2
+  // @return: cookie - the assigned number to this bluetooth_audio output
+  static uint16_t RegisterControlResultCback(
+      const SessionType_2_1& session_type,
+      const PortStatusCallbacks_2_2& cbacks) {
+    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->RegisterStatusCback(cbacks);
     }
     return kObserversCookieUndefined;
   }
 
   // The control API helps the bluetooth_audio module to unregister
-  // PortStatusCallbacks
+  // PortStatusCallbacks and PortStatusCallbacks_2_2
   // @param: cookie - indicates which bluetooth_audio output is
   static void UnregisterControlResultCback(const SessionType_2_1& session_type,
                                            uint16_t cookie) {
     std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
         BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      session_ptr->GetAudioSession()->UnregisterStatusCback(cookie);
+      session_ptr->UnregisterStatusCback(cookie);
     }
   }
 
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
index 79121cc..17e140e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
@@ -60,7 +60,20 @@
     std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
         BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      session_ptr->GetAudioSession()->ReportControlStatus(start_resp, status);
+      session_ptr->ReportControlStatus(start_resp, status);
+    }
+  }
+  // The API reports the Bluetooth stack has replied the changed of the audio
+  // configuration, and will inform registered bluetooth_audio outputs
+  static void ReportAudioConfigChanged(
+      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+          session_type,
+      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+          audio_config) {
+    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportAudioConfigChanged(audio_config);
     }
   }
 };
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index db1619b..60ac4ec 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -359,7 +359,7 @@
       audio_session->stack_iface_ = stack_iface;
       LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
                 << ", AudioConfiguration=" << toString(audio_config);
-      audio_session->ReportSessionStatus();
+      ReportSessionStatus();
     };
   }
 }
@@ -386,7 +386,150 @@
   audio_session->stack_iface_ = nullptr;
   audio_session->UpdateDataPath(nullptr);
   if (toggled) {
+    ReportSessionStatus();
+  }
+}
+
+// The control function helps the bluetooth_audio module to register
+// PortStatusCallbacks_2_2
+// @return: cookie - the assigned number to this bluetooth_audio output
+uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
+    const PortStatusCallbacks_2_2& cbacks) {
+  if (session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    PortStatusCallbacks cb = {
+        .control_result_cb_ = cbacks.control_result_cb_,
+        .session_changed_cb_ = cbacks.session_changed_cb_};
+    return audio_session->RegisterStatusCback(cb);
+  }
+
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  uint16_t cookie = ObserversCookieGetInitValue(session_type_2_1_);
+  uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_2_1_);
+
+  while (cookie < cookie_upper_bound) {
+    if (observers_.find(cookie) == observers_.end()) {
+      break;
+    }
+    ++cookie;
+  }
+  if (cookie >= cookie_upper_bound) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+               << " has " << observers_.size()
+               << " observers already (No Resource)";
+    return kObserversCookieUndefined;
+  }
+  std::shared_ptr<struct PortStatusCallbacks_2_2> cb =
+      std::make_shared<struct PortStatusCallbacks_2_2>();
+  *cb = cbacks;
+  observers_[cookie] = cb;
+  return cookie;
+}
+
+// The control function helps the bluetooth_audio module to unregister
+// PortStatusCallbacks_2_2
+// @param: cookie - indicates which bluetooth_audio output is
+void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  if (session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    audio_session->UnregisterStatusCback(cookie);
+    return;
+  }
+  if (observers_.erase(cookie) != 1) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+                 << " no such provider=0x"
+                 << android::base::StringPrintf("%04x", cookie);
+  }
+}
+
+// invoking the registered session_changed_cb_
+void BluetoothAudioSession_2_2::ReportSessionStatus() {
+  // This is locked already by OnSessionStarted / OnSessionEnded
+  if (session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
     audio_session->ReportSessionStatus();
+    return;
+  }
+  if (observers_.empty()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+              << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+              << " notify to bluetooth_audio=0x"
+              << android::base::StringPrintf("%04x", cookie);
+    cb->session_changed_cb_(cookie);
+  }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession_2_2::ReportControlStatus(
+    bool start_resp, const BluetoothAudioStatus& status) {
+  if (session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    audio_session->ReportControlStatus(start_resp, status);
+    return;
+  }
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+    LOG(INFO) << __func__ << " - status=" << toString(status)
+              << " for SessionType=" << toString(session_type_2_1_)
+              << ", bluetooth_audio=0x"
+              << android::base::StringPrintf("%04x", cookie)
+              << (start_resp ? " started" : " suspended");
+    cb->control_result_cb_(cookie, start_resp, status);
+  }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession_2_2::ReportAudioConfigChanged(
+    const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+        audio_config) {
+  if (session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_2_1_ !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return;
+  }
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  audio_config_2_2_ = audio_config;
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+    LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_2_1_)
+              << ", bluetooth_audio=0x"
+              << android::base::StringPrintf("%04x", cookie);
+    if (cb->audio_configuration_changed_cb_ != nullptr) {
+      cb->audio_configuration_changed_cb_(cookie);
+    }
   }
 }
 
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 6ac0188..3673fd8 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -28,6 +28,40 @@
 namespace bluetooth {
 namespace audio {
 
+inline uint16_t ObserversCookieGetInitValue(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+         kObserversCookieSize;
+}
+
+struct PortStatusCallbacks_2_2 {
+  // control_result_cb_ - when the Bluetooth stack reports results of
+  // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+  // this callback to report to the bluetooth_audio module.
+  // @param: cookie - indicates which bluetooth_audio output should handle
+  // @param: start_resp - this report is for startStream or not
+  // @param: status - the result of startStream
+  std::function<void(uint16_t cookie, bool start_resp,
+                     const BluetoothAudioStatus& status)>
+      control_result_cb_;
+  // session_changed_cb_ - when the Bluetooth stack start / end session, the
+  // BluetoothAudioProvider will invoke this callback to notify to the
+  // bluetooth_audio module.
+  // @param: cookie - indicates which bluetooth_audio output should handle
+  std::function<void(uint16_t cookie)> session_changed_cb_;
+  // audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
+  // configuration, the BluetoothAudioProvider will invoke this callback to
+  // notify to the bluetooth_audio module.
+  // @param: cookie - indicates which bluetooth_audio output should handle
+  std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
+};
+
 class BluetoothAudioSession_2_2 {
  private:
   std::shared_ptr<BluetoothAudioSession> audio_session;
@@ -50,6 +84,13 @@
   static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
       invalidLeOffloadAudioConfiguration;
 
+  // saving those registered bluetooth_audio's callbacks
+  std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks_2_2>>
+      observers_;
+
+  // invoking the registered session_changed_cb_
+  void ReportSessionStatus();
+
  public:
   BluetoothAudioSession_2_2(
       const ::android::hardware::bluetooth::audio::V2_1::SessionType&
@@ -82,6 +123,29 @@
   bool SuspendStream();
   void StopStream();
 
+  // The control function helps the bluetooth_audio module to register
+  // PortStatusCallbacks_2_2
+  // @return: cookie - the assigned number to this bluetooth_audio output
+  uint16_t RegisterStatusCback(const PortStatusCallbacks_2_2& cbacks);
+
+  // The control function helps the bluetooth_audio module to unregister
+  // PortStatusCallbacks_2_2
+  // @param: cookie - indicates which bluetooth_audio output is
+  void UnregisterStatusCback(uint16_t cookie);
+
+  // The report function is used to report that the Bluetooth stack has notified
+  // the result of startStream or suspendStream, and will invoke
+  // control_result_cb_ to notify registered bluetooth_audio outputs
+  void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
+
+  // The report function is used to report that the Bluetooth stack has notified
+  // the audio configuration changed, and will invoke
+  // audio_configuration_changed_cb_ to notify registered bluetooth_audio
+  // outputs
+  void ReportAudioConfigChanged(
+      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+          audio_config);
+
   // The control function is for the bluetooth_audio module to get the current
   // AudioConfiguration
   const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
index 5becdaa..34cfd7e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
@@ -24,9 +24,59 @@
 namespace bluetooth {
 namespace audio {
 
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_1::CodecType;
+using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_2::AudioLocation;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapability;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
 using SessionType_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::SessionType;
 
+// Stores the list of offload supported capability
+std::vector<LeAudioCodecCapabilitiesPair> kDefaultOffloadLeAudioCapabilities;
+
+static const LeAudioCodecCapability kInvalidLc3Capability = {
+    .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Parameters kLc3Capability_16_1 = {
+    .samplingFrequency = SampleRate::RATE_16000,
+    .frameDuration = Lc3FrameDuration::DURATION_7500US,
+    .octetsPerFrame = 30};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Parameters kLc3Capability_16_2 = {
+    .samplingFrequency = SampleRate::RATE_16000,
+    .frameDuration = Lc3FrameDuration::DURATION_10000US,
+    .octetsPerFrame = 40};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Parameters kLc3Capability_48_4 = {
+    .samplingFrequency = SampleRate::RATE_48000,
+    .frameDuration = Lc3FrameDuration::DURATION_10000US,
+    .octetsPerFrame = 120};
+
+static const std::vector<Lc3Parameters> supportedLc3CapabilityList = {
+    kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+    AudioLocation::FRONT_LEFT | AudioLocation::FRONT_RIGHT);
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+    supportedDeviceSetting = {std::make_tuple(stereoAudio, 2, 1),
+                              std::make_tuple(monoAudio, 1, 2),
+                              std::make_tuple(monoAudio, 1, 1)};
+
 bool IsOffloadLeAudioConfigurationValid(
     const ::android::hardware::bluetooth::audio::V2_1::SessionType&
         session_type,
@@ -44,6 +94,60 @@
   return true;
 }
 
+LeAudioCodecCapability composeLc3Capability(AudioLocation audioLocation,
+                                            uint8_t deviceCnt,
+                                            uint8_t channelCount,
+                                            Lc3Parameters capability) {
+  return LeAudioCodecCapability{.codecType = CodecType::LC3,
+                                .supportedChannel = audioLocation,
+                                .deviceCount = deviceCnt,
+                                .channelCountPerDevice = channelCount,
+                                .capabilities = capability};
+}
+
+std::vector<LeAudioCodecCapabilitiesPair> GetLeAudioOffloadCodecCapabilities(
+    const SessionType_2_1& session_type) {
+  if (session_type !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type !=
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return std::vector<LeAudioCodecCapabilitiesPair>(0);
+  }
+
+  if (kDefaultOffloadLeAudioCapabilities.empty()) {
+    for (auto [audioLocation, deviceCnt, channelCount] :
+         supportedDeviceSetting) {
+      for (auto capability : supportedLc3CapabilityList) {
+        LeAudioCodecCapability lc3Capability = composeLc3Capability(
+            audioLocation, deviceCnt, channelCount, capability);
+        LeAudioCodecCapability lc3MonoCapability =
+            composeLc3Capability(monoAudio, 1, 1, capability);
+
+        // Adds the capability for encode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.mode = LeAudioMode::UNICAST,
+             .encodeCapability = lc3Capability,
+             .decodeCapability = kInvalidLc3Capability});
+
+        // Adds the capability for decode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.mode = LeAudioMode::UNICAST,
+             .encodeCapability = kInvalidLc3Capability,
+             .decodeCapability = lc3Capability});
+
+        // Adds the capability for the case that encode and decode exist at the
+        // same time
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.mode = LeAudioMode::UNICAST,
+             .encodeCapability = lc3Capability,
+             .decodeCapability = lc3MonoCapability});
+      }
+    }
+  }
+
+  return kDefaultOffloadLeAudioCapabilities;
+}
+
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
index 8321616..89da6a3 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
@@ -30,6 +30,11 @@
         session_type,
     const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
         le_audio_codec_config);
+
+std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair>
+GetLeAudioOffloadCodecCapabilities(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type);
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace android
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index e18eade..22d836b 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -34,7 +34,6 @@
             enabled: false,
         },
         ndk: {
-            separate_platform_variant: false,
             vndk: {
                 enabled: true,
             },
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index 6e2f1d4..22bb4fa 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -37,7 +37,6 @@
             sdk_version: "module_current",
         },
         ndk: {
-            separate_platform_variant: false,
             vndk: {
                 enabled: true,
             },
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index 8aa7638..8eab997 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -120,6 +120,15 @@
     },
 }
 
+// Users of libhealth_aidl_impl should use this defaults.
+cc_defaults {
+    name: "libhealth_aidl_impl_user",
+    defaults: [
+        "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
+    ],
+}
+
 // AIDL version of android.hardware.health@2.1-service.
 // Default binder service of the health HAL.
 cc_defaults {
@@ -127,8 +136,7 @@
     relative_install_path: "hw",
     vintf_fragments: ["android.hardware.health-service.example.xml"],
     defaults: [
-        "libhealth_aidl_common_defaults",
-        "libhealth_aidl_charger_defaults",
+        "libhealth_aidl_impl_user",
     ],
     static_libs: [
         "libhealth_aidl_impl",
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 8741157..6dacb85 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -25,7 +25,6 @@
             sdk_version: "module_current",
         },
         ndk: {
-            separate_platform_variant: false,
             vndk: {
                 // TODO(b/206116595) enable this
                 enabled: false,
diff --git a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
index e2fa6e4..af3641a 100644
--- a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -1158,12 +1158,15 @@
     auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0}, kTestOperand.dimensions);
     if (buffer == nullptr) return;
 
-    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
-    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    // Use an incompatible dimension and make sure the length matches with the bad dimension.
     auto badDimensions = kTestOperand.dimensions;
     badDimensions[0] = 2;
+    const uint32_t badTestOperandDataSize = kTestOperandDataSize * 2;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(badTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
     RequestArgument sharedMemoryArg = {
-            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize},
+            .location = {.poolIndex = 0, .offset = 0, .length = badTestOperandDataSize},
             .dimensions = badDimensions};
     RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
     RequestArgument deviceMemoryArgWithBadDimensions = {.location = {.poolIndex = 1},
diff --git a/neuralnetworks/OWNERS b/neuralnetworks/OWNERS
index def3ea9..04c5d72 100644
--- a/neuralnetworks/OWNERS
+++ b/neuralnetworks/OWNERS
@@ -1,10 +1,2 @@
 # Bug component: 195575
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-ianhua@google.com
-jeanluc@google.com
-miaowang@google.com
-pszczepaniak@google.com
-xusongw@google.com
+include platform/packages/modules/NeuralNetworks:/NNAPI_OWNERS  # Neuralnetworks team
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index cfcd42c..3342619 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -52,6 +52,8 @@
   int mtuV6;
   boolean preferred;
   boolean persistent;
+  boolean alwaysOn;
+  @nullable android.hardware.radio.data.TrafficDescriptor trafficDescriptor;
   const int ID_DEFAULT = 0;
   const int ID_TETHERED = 1;
   const int ID_IMS = 2;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
index a648675..dc6092a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
@@ -46,7 +46,7 @@
   oneway void setDataThrottling(in int serial, in android.hardware.radio.data.DataThrottlingAction dataThrottlingAction, in long completionDurationMillis);
   oneway void setInitialAttachApn(in int serial, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
   oneway void setResponseFunctions(in android.hardware.radio.data.IRadioDataResponse radioDataResponse, in android.hardware.radio.data.IRadioDataIndication radioDataIndication);
-  oneway void setupDataCall(in int serial, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo, in boolean roamingAllowed, in android.hardware.radio.data.DataRequestReason reason, in android.hardware.radio.data.LinkAddress[] addresses, in String[] dnses, in int pduSessionId, in @nullable android.hardware.radio.data.SliceInfo sliceInfo, in @nullable android.hardware.radio.data.TrafficDescriptor trafficDescriptor, in boolean matchAllRuleAllowed);
+  oneway void setupDataCall(in int serial, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo, in boolean roamingAllowed, in android.hardware.radio.data.DataRequestReason reason, in android.hardware.radio.data.LinkAddress[] addresses, in String[] dnses, in int pduSessionId, in @nullable android.hardware.radio.data.SliceInfo sliceInfo, in boolean matchAllRuleAllowed);
   oneway void startHandover(in int serial, in int callId);
   oneway void startKeepalive(in int serial, in android.hardware.radio.data.KeepaliveRequest keepalive);
   oneway void stopKeepalive(in int serial, in int sessionHandle);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
index e496c7b..b0cc1eb 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -37,5 +37,5 @@
   oneway void dataCallListChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SetupDataCallResult[] dcList);
   oneway void keepaliveStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.KeepaliveStatus status);
   oneway void pcoData(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.PcoDataInfo pco);
-  oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in String apn);
+  oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 16433be..c618791 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -68,4 +68,6 @@
   oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
   oneway void stopNetworkScan(in int serial);
   oneway void supplyNetworkDepersonalization(in int serial, in String netPin);
+  oneway void setUsageSetting(in int serial, in android.hardware.radio.network.UsageSetting usageSetting);
+  oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index ff95396..8cf4c31 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -67,4 +67,6 @@
   oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void stopNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void supplyNetworkDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void setUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.UsageSetting usageSetting);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..7fdf831
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.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.radio.network;
+@Backing(type="int") @VintfStability
+enum UsageSetting {
+  VOICE_CENTRIC = 1,
+  DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index a1c3c27..b5cf633 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -42,7 +42,13 @@
      */
     String eid;
     /**
-     * PortInfo contains the ICCID, logical slot ID, and port state
+     * PortInfo contains the ICCID, logical slot ID, and port state.
+     * Cardstate has no relationship with whether the slot is active or inactive. Should always
+     * report up at least 1 port otherwise the logicalSlotIndex and portActive info will be lost.
+     * For example, the pSIM can be removed, but the slot can still be active. In that case, the
+     * SIM_STATUS reported for the corresponding logical stack will show CARDSTATE_ABSENT.
+     * Similarly, even if there is no profile enabled on the eSIM, that port can still be the
+     * active port in the slot mapping.
      */
     SimPortInfo[] portInfo;
 }
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index 7657fc9..0f06119 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.data.ApnAuthType;
 import android.hardware.radio.data.ApnTypes;
 import android.hardware.radio.data.PdpProtocolType;
+import android.hardware.radio.data.TrafficDescriptor;
 
 @VintfStability
 parcelable DataProfileInfo {
@@ -115,4 +116,19 @@
      * If the same data profile exists, this data profile must overwrite it.
      */
     boolean persistent;
+    /**
+     * Indicates the PDU session brought up by this data profile should be always-on.
+     * An always-on PDU Session is a PDU Session for which User Plane resources have to be
+     * activated during every transition from CM-IDLE mode to CM-CONNECTED state.
+     * See 3GPP TS 23.501 section 5.6.13 for the details.
+     */
+    boolean alwaysOn;
+    /**
+     * TrafficDescriptor for which data connection needs to be established.
+     * It is used for URSP traffic matching as described in TS 24.526 Section 4.2.2.
+     * It includes an optional DNN which, if present, must be used for traffic matching --
+     * it does not specify the end point to be used for the data call. The end point is specified by
+     * apn; apn must be used as the end point if one is not specified through URSP rules.
+     */
+    @nullable TrafficDescriptor trafficDescriptor;
 }
diff --git a/radio/aidl/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
index 9f5ba4c..54a045c 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
@@ -219,12 +219,6 @@
      *        EPDG to 5G. It is valid only when accessNetwork is AccessNetwork:NGRAN. If the slice
      *        passed from EPDG is rejected, then the data failure cause must be
      *        DataCallFailCause:SLICE_REJECTED.
-     * @param trafficDescriptor TrafficDescriptor for which data connection needs to be established.
-     *        It is used for URSP traffic matching as described in TS 24.526 Section 4.2.2.
-     *        It includes an optional DNN which, if present, must be used for traffic matching --
-     *        it does not specify the end point to be used for the data call. The end point is
-     *        specified by DataProfileInfo.apn; DataProfileInfo.apn must be used as the end point if
-     *        one is not specified through URSP rules.
      * @param matchAllRuleAllowed bool to indicate if using default match-all URSP rule for this
      *        request is allowed. If false, this request must not use the match-all URSP rule and if
      *        a non-match-all rule is not found (or if URSP rules are not available) it should
@@ -238,7 +232,6 @@
             in DataProfileInfo dataProfileInfo, in boolean roamingAllowed,
             in DataRequestReason reason, in LinkAddress[] addresses, in String[] dnses,
             in int pduSessionId, in @nullable SliceInfo sliceInfo,
-            in @nullable TrafficDescriptor trafficDescriptor,
             in boolean matchAllRuleAllowed);
 
     /**
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
index 8e73ee3..1772c88 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -17,6 +17,7 @@
 package android.hardware.radio.data;
 
 import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.data.DataProfileInfo;
 import android.hardware.radio.data.KeepaliveStatus;
 import android.hardware.radio.data.PcoDataInfo;
 import android.hardware.radio.data.SetupDataCallResult;
@@ -68,7 +69,7 @@
      * is sent, AOSP will no longer throttle calls to IRadioData.SetupDataCall for the given APN.
      *
      * @param type Type of radio indication
-     * @param apn Apn to unthrottle
+     * @param dataProfileInfo Data profile info.
      */
-    void unthrottleApn(in RadioIndicationType type, in String apn);
+    void unthrottleApn(in RadioIndicationType type, in DataProfileInfo dataProfileInfo);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 1081a75..aaf432a 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -27,6 +27,7 @@
 import android.hardware.radio.network.RadioAccessSpecifier;
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.SignalThresholdInfo;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -416,4 +417,25 @@
      * Response function is IRadioNetworkResponse.supplyNetworkDepersonalizationResponse()
      */
     void supplyNetworkDepersonalization(in int serial, in String netPin);
+
+    /**
+     * Set the UE usage setting for data/voice centric usage.
+     *
+     * <p>Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     * <p>This value must be independently preserved for each SIM; (setting the value is not a
+     * "global" override).
+     *
+     * @param serial Serial number of request.
+     * @param usageSetting the usage setting for the current SIM.
+     */
+    oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+
+    /**
+     * Get the UE usage setting for data/voice centric usage.
+     *
+     * <p>Gets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     *
+     * @param serial Serial number of request.
+     */
+    oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 429b5a8..30f4221 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -31,6 +31,7 @@
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.RegStateResult;
 import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * Interface declaring response functions to solicited radio requests for network APIs.
@@ -549,4 +550,30 @@
      *   RadioError:SIM_ABSENT
      */
     void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void setUsageSettingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     * @param usageSetting the usage setting for the current SIM.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
 }
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..ba8fe93
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.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.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Cellular usage setting with values according to 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
+ * Annex A.
+ */
+@VintfStability
+@Backing(type="int")
+enum UsageSetting {
+    /**
+     * UE operates in voice-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not remain camped on a cell or attached to a network unless that cell/network provides
+     * voice service.
+     */
+    VOICE_CENTRIC = 1,
+
+    /**
+     * UE operates in data-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not reselect away from a cell/network that only provides data services.
+     */
+    DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index c731caf..7923b14 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -205,6 +205,12 @@
      * Open a new logical channel and select the given application. This command
      * reflects TS 27.007 "open logical channel" operation (+CCHO).
      *
+     * For MEP-A(Multiple enabled profile), only dedicated port 0 is ISDR selectable.
+     * e.g., Port0 - for ISDR access and Port1/Port2 - the currently active ports/subscriptions.
+     * Port 0 should be transparent to AP and iccLogicalChannel API should remain the same.
+     * Even if the ISDR request comes over port1 or port2, Modem would just internally convert the
+     * portID to port0 and add the real port index as the payload of MANAGE_CHANNEL command.
+     *
      * @param serial Serial number of request.
      * @param aid AID value, See ETSI 102.221 and 101.220.
      * @param p2 P2 value, described in ISO 7816-4. Ignore if equal to RadioConst:P2_CONSTANT_NO_P2
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index 43d9378..487d91b 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -28,7 +28,6 @@
     cflags: [
         "-Wall",
         "-Wextra",
-        //"-Wold-style-cast",  // TODO(b/203699028) enable after aosp/1900880 gets merged
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     shared_libs: [
@@ -56,7 +55,10 @@
         "libutils",
     ],
     srcs: [
+        "CallbackManager.cpp",
+        "DriverContext.cpp",
         "RadioCompatBase.cpp",
+        "RadioIndication.cpp",
         "RadioResponse.cpp",
         "commonStructs.cpp",
         "config/RadioConfig.cpp",
diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
new file mode 100644
index 0000000..c2eaed1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 <libradiocompat/CallbackManager.h>
+
+#include <android-base/logging.h>
+
+using namespace std::literals::chrono_literals;
+
+namespace android::hardware::radio::compat {
+
+/**
+ * How much setter thread will wait with setting response functions after the last
+ * setResponseFunctions call from the framework. Subsequent calls from the framework reset the
+ * clock, so this number should be larger than the longest time between setResponseFunctions calls
+ * from the framework.
+ *
+ * Real world measurements with Cuttlefish give <10ms delay between Modem and Data and <2ms delays
+ * between all others.
+ */
+static constexpr auto kDelayedSetterDelay = 100ms;
+
+CallbackManager::CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal)
+    : mHidlHal(hidlHal),
+      mRadioResponse(sp<compat::RadioResponse>::make(context)),
+      mRadioIndication(sp<compat::RadioIndication>::make(context)),
+      mDelayedSetterThread(&CallbackManager::delayedSetterThread, this) {}
+
+CallbackManager::~CallbackManager() {
+    {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        mDelayedSetterDeadline = std::nullopt;
+        mDestroy = true;
+        mDelayedSetterCv.notify_all();
+    }
+    mDelayedSetterThread.join();
+}
+
+RadioResponse& CallbackManager::response() const {
+    return *mRadioResponse;
+}
+
+void CallbackManager::setResponseFunctionsDelayed() {
+    std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+    mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay;
+    mDelayedSetterCv.notify_all();
+}
+
+void CallbackManager::delayedSetterThread() {
+    while (!mDestroy) {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        auto deadline = mDelayedSetterDeadline;
+
+        // not waiting to set response functions
+        if (!deadline) {
+            mDelayedSetterCv.wait(lock);
+            continue;
+        }
+
+        // waiting to set response functions, but not yet
+        if (*deadline > std::chrono::steady_clock::now()) {
+            mDelayedSetterCv.wait_until(lock, *deadline);
+            continue;
+        }
+
+        mHidlHal->setResponseFunctions(mRadioResponse, mRadioIndication).assertOk();
+        mDelayedSetterDeadline = std::nullopt;
+    }
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/DriverContext.cpp b/radio/aidl/compat/libradiocompat/DriverContext.cpp
new file mode 100644
index 0000000..a07173e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/DriverContext.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 <libradiocompat/DriverContext.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio;
+
+void DriverContext::addDataProfile(const aidl::data::DataProfileInfo& profile) {
+    mDataProfiles[profile.apn] = profile;
+}
+
+aidl::data::DataProfileInfo DriverContext::getDataProfile(const std::string& apn) {
+    const auto it = mDataProfiles.find(apn);
+    if (it != mDataProfiles.end()) return it->second;
+
+    // if not found in cache, return a made up default
+    return {
+            .apn = apn,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
index a9eac68..2a2d7a3 100644
--- a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
@@ -20,16 +20,11 @@
 
 namespace android::hardware::radio::compat {
 
-RadioCompatBase::RadioCompatBase(sp<V1_5::IRadio> hidlHal, sp<RadioResponse> radioResponse,
-                                 sp<RadioIndication> radioIndication)
-    : mHal1_5(hidlHal),
+RadioCompatBase::RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+                                 std::shared_ptr<CallbackManager> cbMgr)
+    : mContext(context),
+      mHal1_5(hidlHal),
       mHal1_6(V1_6::IRadio::castFrom(hidlHal)),
-      mRadioResponse(radioResponse),
-      mRadioIndication(radioIndication) {}
-
-V1_6::IRadioResponse& RadioCompatBase::respond() {
-    CHECK(mRadioResponse) << "This shouldn't happen (response functions are passed in constructor)";
-    return *mRadioResponse;
-}
+      mCallbackManager(cbMgr) {}
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioIndication.cpp b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
new file mode 100644
index 0000000..30ef6a0
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
@@ -0,0 +1,23 @@
+/*
+ * 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 <libradiocompat/RadioIndication.h>
+
+namespace android::hardware::radio::compat {
+
+RadioIndication::RadioIndication(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
index 35b0ac1..dab70cc 100644
--- a/radio/aidl/compat/libradiocompat/RadioResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -22,15 +22,20 @@
 
 namespace android::hardware::radio::compat {
 
+RadioResponse::RadioResponse(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
 Return<void> RadioResponse::acknowledgeRequest(int32_t serial) {
     LOG_CALL << serial;
-    // TODO(b/203699028): send to correct requestor or confirm if spam is not a problem
-    if (mDataCb) mDataCb->acknowledgeRequest(serial);
-    if (mMessagingCb) mMessagingCb->acknowledgeRequest(serial);
-    if (mModemCb) mModemCb->acknowledgeRequest(serial);
-    if (mNetworkCb) mNetworkCb->acknowledgeRequest(serial);
-    if (mSimCb) mSimCb->acknowledgeRequest(serial);
-    if (mVoiceCb) mVoiceCb->acknowledgeRequest(serial);
+    /* We send ACKs to all callbacks instead of the one requested it to make implementation simpler.
+     * If it turns out to be a problem, we would have to track where serials come from and make sure
+     * this tracking data (e.g. a map) doesn't grow indefinitely.
+     */
+    if (mDataCb) mDataCb.get()->acknowledgeRequest(serial);
+    if (mMessagingCb) mMessagingCb.get()->acknowledgeRequest(serial);
+    if (mModemCb) mModemCb.get()->acknowledgeRequest(serial);
+    if (mNetworkCb) mNetworkCb.get()->acknowledgeRequest(serial);
+    if (mSimCb) mSimCb.get()->acknowledgeRequest(serial);
+    if (mVoiceCb) mVoiceCb.get()->acknowledgeRequest(serial);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.cpp b/radio/aidl/compat/libradiocompat/commonStructs.cpp
index c25768d..6e4c873 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.cpp
+++ b/radio/aidl/compat/libradiocompat/commonStructs.cpp
@@ -20,11 +20,11 @@
 
 namespace aidl = ::aidl::android::hardware::radio;
 
-V1_6::RadioResponseInfo notSupported(int32_t serial) {
+aidl::RadioResponseInfo notSupported(int32_t serial) {
     return {
-            .type = V1_0::RadioResponseType::SOLICITED,
+            .type = aidl::RadioResponseType::SOLICITED,
             .serial = serial,
-            .error = V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+            .error = aidl::RadioError::REQUEST_NOT_SUPPORTED,
     };
 }
 
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.h b/radio/aidl/compat/libradiocompat/commonStructs.h
index b859916..a4a4869 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.h
+++ b/radio/aidl/compat/libradiocompat/commonStructs.h
@@ -21,7 +21,7 @@
 
 namespace android::hardware::radio::compat {
 
-V1_6::RadioResponseInfo notSupported(int32_t serial);
+aidl::android::hardware::radio::RadioResponseInfo notSupported(int32_t serial);
 
 std::string toAidl(const hidl_string& str);
 hidl_string toHidl(const std::string& str);
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
index d0d6f7a..b450418 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -16,12 +16,12 @@
 
 #include <libradiocompat/RadioConfig.h>
 
-#include "RadioConfigIndication.h"
-#include "RadioConfigResponse.h"
 #include "commonStructs.h"
 #include "debug.h"
 #include "structs.h"
 
+#include "collections.h"
+
 #define RADIO_MODULE "Config"
 
 namespace android::hardware::radio::compat {
@@ -31,11 +31,13 @@
 constexpr auto ok = &ScopedAStatus::ok;
 
 RadioConfig::RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal)
-    : mHal1_1(hidlHal), mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)) {}
+    : mHal1_1(hidlHal),
+      mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)),
+      mRadioConfigResponse(sp<RadioConfigResponse>::make()),
+      mRadioConfigIndication(sp<RadioConfigIndication>::make()) {}
 
-config::V1_3::IRadioConfigResponse& RadioConfig::respond() {
-    CHECK(mRadioConfigResponse) << "setResponseFunctions was not called yet";
-    return *mRadioConfigResponse;
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfig::respond() {
+    return mRadioConfigResponse->respond();
 }
 
 ScopedAStatus RadioConfig::getHalDeviceCapabilities(int32_t serial) {
@@ -43,7 +45,7 @@
     if (mHal1_3) {
         mHal1_3->getHalDeviceCapabilities(serial);
     } else {
-        respond().getHalDeviceCapabilitiesResponse(notSupported(serial), false);
+        respond()->getHalDeviceCapabilitiesResponse(notSupported(serial), false);
     }
     return ok();
 }
@@ -86,9 +88,9 @@
     CHECK(radioConfigResponse);
     CHECK(radioConfigIndication);
 
-    mRadioConfigResponse = sp<RadioConfigResponse>::make(radioConfigResponse);
-    mRadioConfigIndication = sp<RadioConfigIndication>::make(radioConfigIndication);
-    mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication);
+    mRadioConfigResponse->setResponseFunction(radioConfigResponse);
+    mRadioConfigIndication->setResponseFunction(radioConfigIndication);
+    mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication).assertOk();
 
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
index 0320ad7..c1e32c1 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "RadioConfigIndication.h"
+#include <libradiocompat/RadioConfigIndication.h>
 
 #include "commonStructs.h"
 #include "debug.h"
@@ -28,20 +28,26 @@
 
 namespace aidl = ::aidl::android::hardware::radio::config;
 
-RadioConfigIndication::RadioConfigIndication(std::shared_ptr<aidl::IRadioConfigIndication> callback)
-    : mCallback(callback) {}
+void RadioConfigIndication::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigIndication> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigIndication> RadioConfigIndication::indicate() {
+    return mCallback.get();
+}
 
 Return<void> RadioConfigIndication::simSlotsStatusChanged(
         V1_0::RadioIndicationType type, const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
     LOG_CALL << type;
-    mCallback->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
     return {};
 }
 
 Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
         V1_0::RadioIndicationType type, const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
     LOG_CALL << type;
-    mCallback->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
index 7066ae4..523c504 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "RadioConfigResponse.h"
+#include <libradiocompat/RadioConfigResponse.h>
 
 #include "commonStructs.h"
 #include "debug.h"
@@ -28,14 +28,20 @@
 
 namespace aidl = ::aidl::android::hardware::radio::config;
 
-RadioConfigResponse::RadioConfigResponse(std::shared_ptr<aidl::IRadioConfigResponse> callback)
-    : mCallback(callback) {}
+void RadioConfigResponse::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigResponse> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfigResponse::respond() {
+    return mCallback.get();
+}
 
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
     LOG_CALL << info.serial;
-    mCallback->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
     return {};
 };
 
@@ -43,47 +49,47 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
     LOG_CALL << info.serial;
-    mCallback->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
     return {};
 };
 
 Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setSimSlotsMappingResponse(toAidl(info));
+    respond()->setSimSlotsMappingResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
         const V1_0::RadioResponseInfo& info, const config::V1_1::PhoneCapability& phoneCapability) {
     LOG_CALL << info.serial;
-    mCallback->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
+    respond()->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
     return {};
 };
 
 Return<void> RadioConfigResponse::setPreferredDataModemResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setPreferredDataModemResponse(toAidl(info));
+    respond()->setPreferredDataModemResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::setModemsConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    mCallback->setNumOfLiveModemsResponse(toAidl(info));
+    respond()->setNumOfLiveModemsResponse(toAidl(info));
     return {};
 };
 
 Return<void> RadioConfigResponse::getModemsConfigResponse(
         const V1_0::RadioResponseInfo& info, const config::V1_1::ModemsConfig& modemsConfig) {
     LOG_CALL << info.serial;
-    mCallback->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
+    respond()->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
     return {};
 };
 
 Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
         const V1_6::RadioResponseInfo& info, bool modemReducedFeatureSet1) {
     LOG_CALL << info.serial;
-    mCallback->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
+    respond()->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
     return {};
 };
 
diff --git a/radio/aidl/compat/libradiocompat/config/structs.cpp b/radio/aidl/compat/libradiocompat/config/structs.cpp
index 9ba5623..39ad944 100644
--- a/radio/aidl/compat/libradiocompat/config/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/config/structs.cpp
@@ -24,14 +24,11 @@
 
 namespace aidl = ::aidl::android::hardware::radio::config;
 
-hidl_vec<uint32_t> toHidl(const std::vector<aidl::SlotPortMapping>& slotMap) {
-    hidl_vec<uint32_t> out(slotMap.size());
-    for (const auto& el : slotMap) {
-        CHECK_GE(el.portId, 0);
-        CHECK_LT(static_cast<size_t>(el.portId), out.size());
-        out[el.portId] = el.physicalSlotId;
+uint32_t toHidl(const aidl::SlotPortMapping& slotPortMapping) {
+    if (slotPortMapping.portId != 0) {
+        LOG(ERROR) << "Port ID " << slotPortMapping.portId << " != 0 not supported by HIDL HAL";
     }
-    return out;
+    return slotPortMapping.physicalSlotId;
 }
 
 aidl::SimSlotStatus toAidl(const config::V1_0::SimSlotStatus& sst) {
diff --git a/radio/aidl/compat/libradiocompat/config/structs.h b/radio/aidl/compat/libradiocompat/config/structs.h
index b8a0385..6ea4e4a 100644
--- a/radio/aidl/compat/libradiocompat/config/structs.h
+++ b/radio/aidl/compat/libradiocompat/config/structs.h
@@ -23,8 +23,7 @@
 
 namespace android::hardware::radio::compat {
 
-hidl_vec<uint32_t>  //
-toHidl(const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap);
+uint32_t toHidl(const aidl::android::hardware::radio::config::SlotPortMapping& slotPortMapping);
 
 aidl::android::hardware::radio::config::SimSlotStatus  //
 toAidl(const config::V1_0::SimSlotStatus& sst);
diff --git a/radio/aidl/compat/libradiocompat/data/RadioData.cpp b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
index fdb1273..d2f3687 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioData.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
@@ -31,12 +31,16 @@
 namespace aidlCommon = ::aidl::android::hardware::radio;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioDataResponse> RadioData::respond() {
+    return mCallbackManager->response().dataCb();
+}
+
 ScopedAStatus RadioData::allocatePduSessionId(int32_t serial) {
     LOG_CALL << serial;
     if (mHal1_6) {
         mHal1_6->allocatePduSessionId(serial);
     } else {
-        respond().allocatePduSessionIdResponse(notSupported(serial), 0);
+        respond()->allocatePduSessionIdResponse(notSupported(serial), 0);
     }
     return ok();
 }
@@ -46,7 +50,7 @@
     if (mHal1_6) {
         mHal1_6->cancelHandover(serial, callId);
     } else {
-        respond().cancelHandoverResponse(notSupported(serial));
+        respond()->cancelHandoverResponse(notSupported(serial));
     }
     return ok();
 }
@@ -60,7 +64,11 @@
 
 ScopedAStatus RadioData::getDataCallList(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getDataCallList(serial);
+    if (mHal1_6) {
+        mHal1_6->getDataCallList_1_6(serial);
+    } else {
+        mHal1_5->getDataCallList(serial);
+    }
     return ok();
 }
 
@@ -69,7 +77,7 @@
     if (mHal1_6) {
         mHal1_6->getSlicingConfig(serial);
     } else {
-        respond().getSlicingConfigResponse(notSupported(serial), {});
+        respond()->getSlicingConfigResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -79,7 +87,7 @@
     if (mHal1_6) {
         mHal1_6->releasePduSessionId(serial, id);
     } else {
-        respond().releasePduSessionIdResponse(notSupported(serial));
+        respond()->releasePduSessionIdResponse(notSupported(serial));
     }
     return ok();
 }
@@ -109,7 +117,7 @@
     if (mHal1_6) {
         mHal1_6->setDataThrottling(serial, V1_6::DataThrottlingAction(dta), completionDurationMs);
     } else {
-        respond().setDataThrottlingResponse(notSupported(serial));
+        respond()->setDataThrottlingResponse(notSupported(serial));
     }
     return ok();
 }
@@ -121,16 +129,10 @@
 }
 
 ScopedAStatus RadioData::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioDataResponse>& dataResponse,
-        const std::shared_ptr<aidl::IRadioDataIndication>& dataIndication) {
-    LOG_CALL << dataResponse << ' ' << dataIndication;
-
-    CHECK(dataResponse);
-    CHECK(dataIndication);
-
-    mRadioResponse->setResponseFunction(dataResponse);
-    mRadioIndication->setResponseFunction(dataIndication);
-
+        const std::shared_ptr<aidl::IRadioDataResponse>& response,
+        const std::shared_ptr<aidl::IRadioDataIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -139,14 +141,15 @@
         const aidl::DataProfileInfo& dataProfileInfo, bool roamingAllowed,
         aidl::DataRequestReason reason, const std::vector<aidl::LinkAddress>& addresses,
         const std::vector<std::string>& dnses, int32_t pduSessId,
-        const std::optional<aidl::SliceInfo>& sliceInfo,
-        const std::optional<aidl::TrafficDescriptor>& trDesc, bool matchAllRuleAllowed) {
+        const std::optional<aidl::SliceInfo>& sliceInfo, bool matchAllRuleAllowed) {
     if (mHal1_6) {
         mHal1_6->setupDataCall_1_6(  //
                 serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
                 V1_2::DataRequestReason(reason), toHidl(addresses), toHidl(dnses), pduSessId,
                 toHidl<V1_6::OptionalSliceInfo>(sliceInfo),
-                toHidl<V1_6::OptionalTrafficDescriptor>(trDesc), matchAllRuleAllowed);
+                toHidl<V1_6::OptionalTrafficDescriptor>(dataProfileInfo.trafficDescriptor),
+                matchAllRuleAllowed);
+        mContext->addDataProfile(dataProfileInfo);
     } else {
         mHal1_5->setupDataCall_1_5(  //
                 serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
@@ -160,7 +163,7 @@
     if (mHal1_6) {
         mHal1_6->startHandover(serial, callId);
     } else {
-        respond().startHandoverResponse(notSupported(serial));
+        respond()->startHandoverResponse(notSupported(serial));
     }
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
index f51d1a8..1d367d2 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
@@ -29,10 +29,13 @@
 namespace aidl = ::aidl::android::hardware::radio::data;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioDataIndication> dataCb) {
-    CHECK(dataCb);
     mDataCb = dataCb;
 }
 
+std::shared_ptr<aidl::IRadioDataIndication> RadioIndication::dataCb() {
+    return mDataCb.get();
+}
+
 Return<void> RadioIndication::dataCallListChanged(V1_0::RadioIndicationType type,
                                                   const hidl_vec<V1_0::SetupDataCallResult>&) {
     LOG_CALL << type;
@@ -50,40 +53,35 @@
 Return<void> RadioIndication::dataCallListChanged_1_5(
         V1_0::RadioIndicationType type, const hidl_vec<V1_5::SetupDataCallResult>& dcList) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->dataCallListChanged(toAidl(type), toAidl(dcList));
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
     return {};
 }
 
 Return<void> RadioIndication::dataCallListChanged_1_6(
         V1_0::RadioIndicationType type, const hidl_vec<V1_6::SetupDataCallResult>& dcList) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->dataCallListChanged(toAidl(type), toAidl(dcList));
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
     return {};
 }
 
 Return<void> RadioIndication::keepaliveStatus(V1_0::RadioIndicationType type,
                                               const V1_1::KeepaliveStatus& status) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->keepaliveStatus(toAidl(type), toAidl(status));
+    dataCb()->keepaliveStatus(toAidl(type), toAidl(status));
     return {};
 }
 
 Return<void> RadioIndication::pcoData(V1_0::RadioIndicationType type,
                                       const V1_0::PcoDataInfo& pco) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->pcoData(toAidl(type), toAidl(pco));
+    dataCb()->pcoData(toAidl(type), toAidl(pco));
     return {};
 }
 
 Return<void> RadioIndication::unthrottleApn(V1_0::RadioIndicationType type,
                                             const hidl_string& apn) {
     LOG_CALL << type;
-    CHECK_CB(mDataCb);
-    mDataCb->unthrottleApn(toAidl(type), apn);
+    dataCb()->unthrottleApn(toAidl(type), mContext->getDataProfile(apn));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
index 171f692..0bfa2df 100644
--- a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
+++ b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
@@ -29,29 +29,29 @@
 namespace aidl = ::aidl::android::hardware::radio::data;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioDataResponse> dataCb) {
-    CHECK(dataCb);
     mDataCb = dataCb;
 }
 
+std::shared_ptr<aidl::IRadioDataResponse> RadioResponse::dataCb() {
+    return mDataCb.get();
+}
+
 Return<void> RadioResponse::allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
                                                          int32_t id) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->allocatePduSessionIdResponse(toAidl(info), id);
+    dataCb()->allocatePduSessionIdResponse(toAidl(info), id);
     return {};
 }
 
 Return<void> RadioResponse::cancelHandoverResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->cancelHandoverResponse(toAidl(info));
+    dataCb()->cancelHandoverResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->deactivateDataCallResponse(toAidl(info));
+    dataCb()->deactivateDataCallResponse(toAidl(info));
     return {};
 }
 
@@ -73,8 +73,7 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
@@ -82,65 +81,56 @@
         const V1_6::RadioResponseInfo& info,
         const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
                                                      const V1_6::SlicingConfig& slicingConfig) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
+    dataCb()->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
     return {};
 }
 
 Return<void> RadioResponse::releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->releasePduSessionIdResponse(toAidl(info));
+    dataCb()->releasePduSessionIdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataAllowedResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataAllowedResponse(toAidl(info));
+    dataCb()->setDataAllowedResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataProfileResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataProfileResponse(toAidl(info));
+    dataCb()->setDataProfileResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataProfileResponse(toAidl(info));
+    dataCb()->setDataProfileResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setDataThrottlingResponse(toAidl(info));
+    dataCb()->setDataThrottlingResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setInitialAttachApnResponse(toAidl(info));
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setInitialAttachApnResponse(toAidl(info));
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
     return {};
 }
 
@@ -161,38 +151,33 @@
 Return<void> RadioResponse::setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                       const V1_5::SetupDataCallResult& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                       const V1_6::SetupDataCallResult& dcResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
     return {};
 }
 
 Return<void> RadioResponse::startHandoverResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->startHandoverResponse(toAidl(info));
+    dataCb()->startHandoverResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
                                                    const V1_1::KeepaliveStatus& status) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->startKeepaliveResponse(toAidl(info), toAidl(status));
+    dataCb()->startKeepaliveResponse(toAidl(info), toAidl(status));
     return {};
 }
 
 Return<void> RadioResponse::stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mDataCb);
-    mDataCb->stopKeepaliveResponse(toAidl(info));
+    dataCb()->stopKeepaliveResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/debug.h b/radio/aidl/compat/libradiocompat/debug.h
index 4158059..cb773bf 100644
--- a/radio/aidl/compat/libradiocompat/debug.h
+++ b/radio/aidl/compat/libradiocompat/debug.h
@@ -26,12 +26,6 @@
 #define LOG_CALL \
     if constexpr (debug::kSuperVerbose) LOG(VERBOSE) << (RADIO_MODULE ".") << __func__ << ' '
 
-#define CHECK_CB(field)                     \
-    if (!field) {                           \
-        LOG(WARNING) << "Callback not set"; \
-        return {};                          \
-    }
-
 }  // namespace debug
 
 inline std::ostream& operator<<(std::ostream& os, const V1_0::RadioIndicationType& type) {
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
new file mode 100644
index 0000000..f1a7b49
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
@@ -0,0 +1,62 @@
+/*
+ * 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 "DriverContext.h"
+#include "RadioIndication.h"
+#include "RadioResponse.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/radio/1.6/IRadio.h>
+
+#include <thread>
+
+namespace android::hardware::radio::compat {
+
+class CallbackManager {
+    sp<V1_5::IRadio> mHidlHal;
+    sp<RadioResponse> mRadioResponse;
+    sp<RadioIndication> mRadioIndication;
+
+    std::thread mDelayedSetterThread;
+    std::mutex mDelayedSetterGuard;
+    std::optional<std::chrono::time_point<std::chrono::steady_clock>> mDelayedSetterDeadline
+            GUARDED_BY(mDelayedSetterGuard);
+    std::condition_variable mDelayedSetterCv GUARDED_BY(mDelayedSetterGuard);
+    bool mDestroy GUARDED_BY(mDelayedSetterGuard) = false;
+
+    void setResponseFunctionsDelayed();
+    void delayedSetterThread();
+
+  public:
+    CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal);
+    ~CallbackManager();
+
+    RadioResponse& response() const;
+
+    template <typename ResponseType, typename IndicationType>
+    void setResponseFunctions(const std::shared_ptr<ResponseType>& response,
+                              const std::shared_ptr<IndicationType>& indication) {
+        CHECK(response);
+        CHECK(indication);
+
+        mRadioResponse->setResponseFunction(response);
+        mRadioIndication->setResponseFunction(indication);
+        setResponseFunctionsDelayed();
+    }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
new file mode 100644
index 0000000..6833aca
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
@@ -0,0 +1,32 @@
+/*
+ * 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/radio/data/DataProfileInfo.h>
+
+#include <map>
+
+namespace android::hardware::radio::compat {
+
+class DriverContext {
+    std::map<std::string, ::aidl::android::hardware::radio::data::DataProfileInfo> mDataProfiles;
+
+  public:
+    void addDataProfile(const ::aidl::android::hardware::radio::data::DataProfileInfo& profile);
+    ::aidl::android::hardware::radio::data::DataProfileInfo getDataProfile(const std::string& apn);
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
new file mode 100644
index 0000000..0b6ee11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
@@ -0,0 +1,50 @@
+/*
+ * 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 <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <utils/Mutex.h>
+
+namespace android::hardware::radio::compat {
+
+template <typename Interface, typename DefaultImplementation, bool isIndication = false>
+class GuaranteedCallback {
+    mutable std::mutex mCallbackGuard;
+    std::shared_ptr<Interface> mCallback GUARDED_BY(mCallbackGuard);
+
+  public:
+    GuaranteedCallback<Interface, DefaultImplementation, isIndication>& operator=(
+            const std::shared_ptr<Interface>& callback) {
+        CHECK(callback);
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        mCallback = callback;
+        return *this;
+    }
+
+    std::shared_ptr<Interface> get() {
+        if (mCallback) return mCallback;
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        if (mCallback) return mCallback;
+
+        LOG(isIndication ? WARNING : ERROR) << "Callback is not set";
+        return mCallback = ndk::SharedRefBase::make<DefaultImplementation>();
+    }
+
+    operator bool() const { return mCallback != nullptr; }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
index a412c34..eb22fff 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
@@ -15,8 +15,8 @@
  */
 #pragma once
 
-#include "RadioIndication.h"
-#include "RadioResponse.h"
+#include "CallbackManager.h"
+#include "DriverContext.h"
 
 #include <android/hardware/radio/1.6/IRadio.h>
 
@@ -24,17 +24,16 @@
 
 class RadioCompatBase {
   protected:
+    std::shared_ptr<DriverContext> mContext;
+
     sp<V1_5::IRadio> mHal1_5;
     sp<V1_6::IRadio> mHal1_6;
 
-    sp<RadioResponse> mRadioResponse;
-    sp<RadioIndication> mRadioIndication;
-
-    V1_6::IRadioResponse& respond();
+    std::shared_ptr<CallbackManager> mCallbackManager;
 
   public:
-    RadioCompatBase(sp<V1_5::IRadio> hidlHal, sp<RadioResponse> radioResponse,
-                    sp<RadioIndication> radioIndication);
+    RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+                    std::shared_ptr<CallbackManager> cbMgr);
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
index 31ad207..bbfff61 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include "RadioConfigIndication.h"
+#include "RadioConfigResponse.h"
+
 #include <aidl/android/hardware/radio/config/BnRadioConfig.h>
 #include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
 #include <android/hardware/radio/config/1.3/IRadioConfig.h>
@@ -30,11 +33,13 @@
  * fetch source implementation and publish resulting HAL instance.
  */
 class RadioConfig : public aidl::android::hardware::radio::config::BnRadioConfig {
-    sp<config::V1_1::IRadioConfig> mHal1_1;
-    sp<config::V1_3::IRadioConfig> mHal1_3;
+    const sp<config::V1_1::IRadioConfig> mHal1_1;
+    const sp<config::V1_3::IRadioConfig> mHal1_3;
 
-    sp<config::V1_3::IRadioConfigResponse> mRadioConfigResponse;
-    sp<config::V1_2::IRadioConfigIndication> mRadioConfigIndication;
+    const sp<RadioConfigResponse> mRadioConfigResponse;
+    const sp<RadioConfigIndication> mRadioConfigIndication;
+
+    std::shared_ptr<::aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
 
     ::ndk::ScopedAStatus getHalDeviceCapabilities(int32_t serial) override;
     ::ndk::ScopedAStatus getNumOfLiveModems(int32_t serial) override;
@@ -52,8 +57,6 @@
             const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap)
             override;
 
-    config::V1_3::IRadioConfigResponse& respond();
-
   public:
     /**
      * Constructs AIDL IRadioConfig instance wrapping existing HIDL IRadioConfig instance.
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
similarity index 82%
rename from radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h
rename to radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
index 3d8d971..d256a87 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
@@ -15,13 +15,17 @@
  */
 #pragma once
 
+#include "GuaranteedCallback.h"
+
 #include <aidl/android/hardware/radio/config/IRadioConfigIndication.h>
 #include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
 
 namespace android::hardware::radio::compat {
 
 class RadioConfigIndication : public config::V1_2::IRadioConfigIndication {
-    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> mCallback;
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigIndication,
+                       aidl::android::hardware::radio::config::IRadioConfigIndicationDefault, true>
+            mCallback;
 
     Return<void> simSlotsStatusChanged(
             V1_0::RadioIndicationType type,
@@ -31,8 +35,10 @@
             const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
 
   public:
-    RadioConfigIndication(
+    void setResponseFunction(
             std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> cb);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> indicate();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
similarity index 88%
rename from radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h
rename to radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
index 1461dd2..dc86da2 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
@@ -15,13 +15,17 @@
  */
 #pragma once
 
+#include "GuaranteedCallback.h"
+
 #include <aidl/android/hardware/radio/config/IRadioConfigResponse.h>
 #include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
 
 namespace android::hardware::radio::compat {
 
 class RadioConfigResponse : public config::V1_3::IRadioConfigResponse {
-    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> mCallback;
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigResponse,
+                       aidl::android::hardware::radio::config::IRadioConfigResponseDefault>
+            mCallback;
 
     Return<void> getSimSlotsStatusResponse(
             const V1_0::RadioResponseInfo& info,
@@ -41,8 +45,10 @@
                                                   bool modemReducedFeatureSet1) override;
 
   public:
-    RadioConfigResponse(
+    void setResponseFunction(
             std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> callback);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
index 900a669..c617ec2 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
@@ -22,6 +22,8 @@
 namespace android::hardware::radio::compat {
 
 class RadioData : public RadioCompatBase, public aidl::android::hardware::radio::data::BnRadioData {
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> respond();
+
     ::ndk::ScopedAStatus allocatePduSessionId(int32_t serial) override;
     ::ndk::ScopedAStatus cancelHandover(int32_t serial, int32_t callId) override;
     ::ndk::ScopedAStatus deactivateDataCall(
@@ -55,7 +57,6 @@
             const std::vector<::aidl::android::hardware::radio::data::LinkAddress>& addresses,
             const std::vector<std::string>& dnses, int32_t pduSessionId,
             const std::optional<::aidl::android::hardware::radio::data::SliceInfo>& sliceInfo,
-            const std::optional<::aidl::android::hardware::radio::data::TrafficDescriptor>& trDescr,
             bool matchAllRuleAllowed) override;
     ::ndk::ScopedAStatus startHandover(int32_t serial, int32_t callId) override;
     ::ndk::ScopedAStatus startKeepalive(
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
index 20e0973..c668af5 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include "DriverContext.h"
+#include "GuaranteedCallback.h"
+
 #include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
 #include <aidl/android/hardware/radio/modem/IRadioModemIndication.h>
@@ -26,13 +29,32 @@
 namespace android::hardware::radio::compat {
 
 class RadioIndication : public V1_6::IRadioIndication {
-    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> mDataCb;
-    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+    std::shared_ptr<DriverContext> mContext;
+
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::data::IRadioDataIndication,
+            ::aidl::android::hardware::radio::data::IRadioDataIndicationDefault, true>
+            mDataCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication,
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndicationDefault, true>
             mMessagingCb;
-    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> mModemCb;
-    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> mNetworkCb;
-    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> mSimCb;
-    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> mVoiceCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::modem::IRadioModemIndication,
+            ::aidl::android::hardware::radio::modem::IRadioModemIndicationDefault, true>
+            mModemCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndication,
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndicationDefault, true>
+            mNetworkCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::sim::IRadioSimIndication,
+            ::aidl::android::hardware::radio::sim::IRadioSimIndicationDefault, true>
+            mSimCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndication,
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndicationDefault, true>
+            mVoiceCb;
 
     // IRadioIndication @ 1.0
     Return<void> radioStateChanged(V1_0::RadioIndicationType type,
@@ -181,6 +203,8 @@
             const hidl_vec<V1_6::PhonebookRecordInfo>& records) override;
 
   public:
+    RadioIndication(std::shared_ptr<DriverContext> context);
+
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb);
     void setResponseFunction(
@@ -194,6 +218,14 @@
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voiceCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
index 0cd3381..419e9fb 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
@@ -23,6 +23,8 @@
 
 class RadioMessaging : public RadioCompatBase,
                        public aidl::android::hardware::radio::messaging::BnRadioMessaging {
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse> respond();
+
     ::ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
                                                           const std::string& ackPdu) override;
     ::ndk::ScopedAStatus acknowledgeLastIncomingCdmaSms(
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
index 666ff47..fdca124 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
@@ -23,6 +23,8 @@
 
 class RadioModem : public RadioCompatBase,
                    public aidl::android::hardware::radio::modem::BnRadioModem {
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> respond();
+
     ::ndk::ScopedAStatus enableModem(int32_t serial, bool on) override;
     ::ndk::ScopedAStatus getBasebandVersion(int32_t serial) override;
     ::ndk::ScopedAStatus getDeviceIdentity(int32_t serial) override;
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index c776fd1..ec76300 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -23,6 +23,8 @@
 
 class RadioNetwork : public RadioCompatBase,
                      public aidl::android::hardware::radio::network::BnRadioNetwork {
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
+
     ::ndk::ScopedAStatus getAllowedNetworkTypesBitmap(int32_t serial) override;
     ::ndk::ScopedAStatus getAvailableBandModes(int32_t serial) override;
     ::ndk::ScopedAStatus getAvailableNetworks(int32_t serial) override;
@@ -88,6 +90,10 @@
     ::ndk::ScopedAStatus stopNetworkScan(int32_t serial) override;
     ::ndk::ScopedAStatus supplyNetworkDepersonalization(int32_t serial,
                                                         const std::string& netPin) override;
+    ::ndk::ScopedAStatus setUsageSetting(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::UsageSetting usageSetting) override;
+    ::ndk::ScopedAStatus getUsageSetting(int32_t serial) override;
 
   public:
     using RadioCompatBase::RadioCompatBase;
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
index 5db963f..1f82dd1 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include "DriverContext.h"
+#include "GuaranteedCallback.h"
+
 #include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
 #include <aidl/android/hardware/radio/modem/IRadioModemResponse.h>
@@ -26,13 +29,26 @@
 namespace android::hardware::radio::compat {
 
 class RadioResponse : public V1_6::IRadioResponse {
-    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> mDataCb;
-    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+    std::shared_ptr<DriverContext> mContext;
+
+    GuaranteedCallback<::aidl::android::hardware::radio::data::IRadioDataResponse,
+                       ::aidl::android::hardware::radio::data::IRadioDataResponseDefault>
+            mDataCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse,
+                       ::aidl::android::hardware::radio::messaging::IRadioMessagingResponseDefault>
             mMessagingCb;
-    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> mModemCb;
-    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> mNetworkCb;
-    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> mSimCb;
-    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> mVoiceCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::modem::IRadioModemResponse,
+                       ::aidl::android::hardware::radio::modem::IRadioModemResponseDefault>
+            mModemCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::network::IRadioNetworkResponse,
+                       ::aidl::android::hardware::radio::network::IRadioNetworkResponseDefault>
+            mNetworkCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::sim::IRadioSimResponse,
+                       ::aidl::android::hardware::radio::sim::IRadioSimResponseDefault>
+            mSimCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::voice::IRadioVoiceResponse,
+                       ::aidl::android::hardware::radio::voice::IRadioVoiceResponseDefault>
+            mVoiceCb;
 
     // IRadioResponse @ 1.0
     Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
@@ -409,6 +425,8 @@
                                                    int32_t updatedRecordIndex) override;
 
   public:
+    RadioResponse(std::shared_ptr<DriverContext> context);
+
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb);
     void setResponseFunction(
@@ -422,6 +440,14 @@
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
index a6b77fd..84bb68b 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
@@ -22,6 +22,8 @@
 namespace android::hardware::radio::compat {
 
 class RadioSim : public RadioCompatBase, public aidl::android::hardware::radio::sim::BnRadioSim {
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> respond();
+
     ::ndk::ScopedAStatus areUiccApplicationsEnabled(int32_t serial) override;
     ::ndk::ScopedAStatus changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
                                              const std::string& newPin2,
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
index 5bf93e0..5839e3a 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
@@ -23,6 +23,8 @@
 
 class RadioVoice : public RadioCompatBase,
                    public aidl::android::hardware::radio::voice::BnRadioVoice {
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> respond();
+
     ::ndk::ScopedAStatus acceptCall(int32_t serial) override;
     ::ndk::ScopedAStatus conference(int32_t serial) override;
     ::ndk::ScopedAStatus dial(
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
index c7342b1..e5c33b3 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
@@ -27,67 +27,62 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingIndication> rmiCb) {
-    CHECK(rmiCb);
     mMessagingCb = rmiCb;
 }
 
+std::shared_ptr<aidl::IRadioMessagingIndication> RadioIndication::messagingCb() {
+    return mMessagingCb.get();
+}
+
 Return<void> RadioIndication::cdmaNewSms(V1_0::RadioIndicationType type,
                                          const V1_0::CdmaSmsMessage& msg) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cdmaNewSms(toAidl(type), toAidl(msg));
+    messagingCb()->cdmaNewSms(toAidl(type), toAidl(msg));
     return {};
 }
 
 Return<void> RadioIndication::cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cdmaRuimSmsStorageFull(toAidl(type));
+    messagingCb()->cdmaRuimSmsStorageFull(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::newBroadcastSms(V1_0::RadioIndicationType type,
                                               const hidl_vec<uint8_t>& data) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newBroadcastSms(toAidl(type), data);
+    messagingCb()->newBroadcastSms(toAidl(type), data);
     return {};
 }
 
 Return<void> RadioIndication::newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSms(toAidl(type), pdu);
+    messagingCb()->newSms(toAidl(type), pdu);
     return {};
 }
 
 Return<void> RadioIndication::newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSmsOnSim(toAidl(type), recordNumber);
+    messagingCb()->newSmsOnSim(toAidl(type), recordNumber);
     return {};
 }
 
 Return<void> RadioIndication::newSmsStatusReport(V1_0::RadioIndicationType type,
                                                  const hidl_vec<uint8_t>& pdu) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->newSmsStatusReport(toAidl(type), pdu);
+    messagingCb()->newSmsStatusReport(toAidl(type), pdu);
     return {};
 }
 
 Return<void> RadioIndication::onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
                                      const hidl_string& msg) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
+    messagingCb()->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
     return {};
 }
 
 Return<void> RadioIndication::simSmsStorageFull(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->simSmsStorageFull(toAidl(type));
+    messagingCb()->simSmsStorageFull(toAidl(type));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
index c1a82b5..4d94e17 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
@@ -29,6 +29,10 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioMessaging::respond() {
+    return mCallbackManager->response().messagingCb();
+}
+
 ScopedAStatus RadioMessaging::acknowledgeIncomingGsmSmsWithPdu(  //
         int32_t serial, bool success, const std::string& ackPdu) {
     LOG_CALL << serial << ' ' << success << ' ' << ackPdu;
@@ -100,13 +104,21 @@
 
 ScopedAStatus RadioMessaging::sendCdmaSms(int32_t serial, const aidl::CdmaSmsMessage& sms) {
     LOG_CALL << serial;
-    mHal1_5->sendCdmaSms(serial, toHidl(sms));
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSms_1_6(serial, toHidl(sms));
+    } else {
+        mHal1_5->sendCdmaSms(serial, toHidl(sms));
+    }
     return ok();
 }
 
 ScopedAStatus RadioMessaging::sendCdmaSmsExpectMore(int32_t serial, const aidl::CdmaSmsMessage& m) {
     LOG_CALL << serial;
-    mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSmsExpectMore_1_6(serial, toHidl(m));
+    } else {
+        mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+    }
     return ok();
 }
 
@@ -118,13 +130,21 @@
 
 ScopedAStatus RadioMessaging::sendSms(int32_t serial, const aidl::GsmSmsMessage& message) {
     LOG_CALL << serial;
-    mHal1_5->sendSms(serial, toHidl(message));
+    if (mHal1_6) {
+        mHal1_6->sendSms_1_6(serial, toHidl(message));
+    } else {
+        mHal1_5->sendSms(serial, toHidl(message));
+    }
     return ok();
 }
 
 ScopedAStatus RadioMessaging::sendSmsExpectMore(int32_t serial, const aidl::GsmSmsMessage& msg) {
     LOG_CALL << serial;
-    mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+    if (mHal1_6) {
+        mHal1_6->sendSmsExpectMore_1_6(serial, toHidl(msg));
+    } else {
+        mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+    }
     return ok();
 }
 
@@ -161,16 +181,10 @@
 }
 
 ScopedAStatus RadioMessaging::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioMessagingResponse>& messagingResponse,
-        const std::shared_ptr<aidl::IRadioMessagingIndication>& messagingIndication) {
-    LOG_CALL << messagingResponse << ' ' << messagingIndication;
-
-    CHECK(messagingResponse);
-    CHECK(messagingIndication);
-
-    mRadioResponse->setResponseFunction(messagingResponse);
-    mRadioIndication->setResponseFunction(messagingIndication);
-
+        const std::shared_ptr<aidl::IRadioMessagingResponse>& response,
+        const std::shared_ptr<aidl::IRadioMessagingIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
index 379e463..24ad3d7 100644
--- a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
@@ -29,52 +29,49 @@
 namespace aidl = ::aidl::android::hardware::radio::messaging;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingResponse> rmrCb) {
-    CHECK(rmrCb);
     mMessagingCb = rmrCb;
 }
 
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioResponse::messagingCb() {
+    return mMessagingCb.get();
+}
+
 Return<void> RadioResponse::acknowledgeIncomingGsmSmsWithPduResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
+    messagingCb()->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::acknowledgeLastIncomingCdmaSmsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
+    messagingCb()->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::acknowledgeLastIncomingGsmSmsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
+    messagingCb()->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->cancelPendingUssdResponse(toAidl(info));
+    messagingCb()->cancelPendingUssdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->deleteSmsOnRuimResponse(toAidl(info));
+    messagingCb()->deleteSmsOnRuimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->deleteSmsOnSimResponse(toAidl(info));
+    messagingCb()->deleteSmsOnSimResponse(toAidl(info));
     return {};
 }
 
@@ -82,162 +79,141 @@
         const V1_0::RadioResponseInfo& info,
         const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
+    messagingCb()->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
     return {};
 }
 
 Return<void> RadioResponse::getGsmBroadcastConfigResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& cfg) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
+    messagingCb()->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
     return {};
 }
 
 Return<void> RadioResponse::getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
                                                    const hidl_string& smsc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->getSmscAddressResponse(toAidl(info), smsc);
+    messagingCb()->getSmscAddressResponse(toAidl(info), smsc);
     return {};
 }
 
 Return<void> RadioResponse::reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->reportSmsMemoryStatusResponse(toAidl(info));
+    messagingCb()->reportSmsMemoryStatusResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
                                                           const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                               const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
                                                 const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                     const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
                                                const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendImsSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendImsSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
                                                       const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                           const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsResponse(const V1_0::RadioResponseInfo& info,
                                             const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                 const V1_0::SendSmsResult& sms) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendSmsResponse(toAidl(info), toAidl(sms));
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
     return {};
 }
 
 Return<void> RadioResponse::sendUssdResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->sendUssdResponse(toAidl(info));
+    messagingCb()->sendUssdResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaBroadcastActivationResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setCdmaBroadcastActivationResponse(toAidl(info));
+    messagingCb()->setCdmaBroadcastActivationResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setCdmaBroadcastConfigResponse(toAidl(info));
+    messagingCb()->setCdmaBroadcastConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setGsmBroadcastActivationResponse(toAidl(info));
+    messagingCb()->setGsmBroadcastActivationResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setGsmBroadcastConfigResponse(toAidl(info));
+    messagingCb()->setGsmBroadcastConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSmscAddressResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->setSmscAddressResponse(toAidl(info));
+    messagingCb()->setSmscAddressResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
                                                    uint32_t index) {
     LOG_CALL << info.serial << ' ' << index;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->writeSmsToRuimResponse(toAidl(info), index);
+    messagingCb()->writeSmsToRuimResponse(toAidl(info), index);
     return {};
 }
 
 Return<void> RadioResponse::writeSmsToSimResponse(const V1_0::RadioResponseInfo& info,
                                                   int32_t index) {
     LOG_CALL << info.serial << ' ' << index;
-    CHECK_CB(mMessagingCb);
-    mMessagingCb->writeSmsToSimResponse(toAidl(info), index);
+    messagingCb()->writeSmsToSimResponse(toAidl(info), index);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
index 8fc4da6..851c93b 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
@@ -29,44 +29,42 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioModemIndication> modemCb) {
-    CHECK(modemCb);
     mModemCb = modemCb;
 }
 
+std::shared_ptr<aidl::IRadioModemIndication> RadioIndication::modemCb() {
+    return mModemCb.get();
+}
+
 Return<void> RadioIndication::hardwareConfigChanged(V1_0::RadioIndicationType type,
                                                     const hidl_vec<V1_0::HardwareConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->hardwareConfigChanged(toAidl(type), toAidl(configs));
+    modemCb()->hardwareConfigChanged(toAidl(type), toAidl(configs));
     return {};
 }
 
 Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type, const hidl_string& reasn) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->modemReset(toAidl(type), reasn);
+    modemCb()->modemReset(toAidl(type), reasn);
     return {};
 }
 
 Return<void> RadioIndication::radioCapabilityIndication(V1_0::RadioIndicationType type,
                                                         const V1_0::RadioCapability& rc) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->radioCapabilityIndication(toAidl(type), toAidl(rc));
+    modemCb()->radioCapabilityIndication(toAidl(type), toAidl(rc));
     return {};
 }
 
 Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType t, V1_0::RadioState st) {
     LOG_CALL << t;
-    CHECK_CB(mModemCb);
-    mModemCb->radioStateChanged(toAidl(t), aidl::RadioState(st));
+    modemCb()->radioStateChanged(toAidl(t), aidl::RadioState(st));
     return {};
 }
 
 Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mModemCb);
-    mModemCb->rilConnected(toAidl(type));
+    modemCb()->rilConnected(toAidl(type));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
index 660ae9f..d28b940 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
@@ -27,6 +27,10 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioModemResponse> RadioModem::respond() {
+    return mCallbackManager->response().modemCb();
+}
+
 ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
     LOG_CALL << serial;
     mHal1_5->enableModem(serial, on);
@@ -129,16 +133,10 @@
 }
 
 ScopedAStatus RadioModem::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioModemResponse>& modemResponse,
-        const std::shared_ptr<aidl::IRadioModemIndication>& modemIndication) {
-    LOG_CALL << modemResponse << ' ' << modemIndication;
-
-    CHECK(modemResponse);
-    CHECK(modemIndication);
-
-    mRadioResponse->setResponseFunction(modemResponse);
-    mRadioIndication->setResponseFunction(modemIndication);
-
+        const std::shared_ptr<aidl::IRadioModemResponse>& response,
+        const std::shared_ptr<aidl::IRadioModemIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
index 300627c..6e1a962 100644
--- a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
@@ -29,22 +29,23 @@
 namespace aidl = ::aidl::android::hardware::radio::modem;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioModemResponse> modemCb) {
-    CHECK(modemCb);
     mModemCb = modemCb;
 }
 
+std::shared_ptr<aidl::IRadioModemResponse> RadioResponse::modemCb() {
+    return mModemCb.get();
+}
+
 Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->enableModemResponse(toAidl(info));
+    modemCb()->enableModemResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
                                                        const hidl_string& version) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getBasebandVersionResponse(toAidl(info), version);
+    modemCb()->getBasebandVersionResponse(toAidl(info), version);
     return {};
 }
 
@@ -52,112 +53,97 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
         const hidl_string& esn, const hidl_string& meid) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
+    modemCb()->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
     return {};
 }
 
 Return<void> RadioResponse::getHardwareConfigResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getHardwareConfigResponse(toAidl(info), toAidl(config));
+    modemCb()->getHardwareConfigResponse(toAidl(info), toAidl(config));
     return {};
 }
 
 Return<void> RadioResponse::getModemActivityInfoResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
+    modemCb()->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
     return {};
 }
 
 Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
                                                         bool isEnabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getModemStackStatusResponse(toAidl(info), isEnabled);
+    modemCb()->getModemStackStatusResponse(toAidl(info), isEnabled);
     return {};
 }
 
 Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
                                                        const V1_0::RadioCapability& rc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    modemCb()->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
     return {};
 }
 
 Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
                                                const hidl_string& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvReadItemResponse(toAidl(info), result);
+    modemCb()->nvReadItemResponse(toAidl(info), result);
     return {};
 }
 
 Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvResetConfigResponse(toAidl(info));
+    modemCb()->nvResetConfigResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvWriteCdmaPrlResponse(toAidl(info));
+    modemCb()->nvWriteCdmaPrlResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->nvWriteItemResponse(toAidl(info));
+    modemCb()->nvWriteItemResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->requestShutdownResponse(toAidl(info));
+    modemCb()->requestShutdownResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->sendDeviceStateResponse(toAidl(info));
+    modemCb()->sendDeviceStateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
                                                        const V1_0::RadioCapability& rc) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    modemCb()->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mModemCb);
-    mModemCb->setRadioPowerResponse(toAidl(info));
+    modemCb()->setRadioPowerResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
index 899b133..d4cbdbc 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
@@ -30,23 +30,24 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkIndication> netCb) {
-    CHECK(netCb);
     mNetworkCb = netCb;
 }
 
+std::shared_ptr<aidl::IRadioNetworkIndication> RadioIndication::networkCb() {
+    return mNetworkCb.get();
+}
+
 Return<void> RadioIndication::barringInfoChanged(V1_0::RadioIndicationType type,
                                                  const V1_5::CellIdentity& cellIdentity,
                                                  const hidl_vec<V1_5::BarringInfo>& barringInfos) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
+    networkCb()->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
     return {};
 }
 
 Return<void> RadioIndication::cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cdmaPrlChanged(toAidl(type), version);
+    networkCb()->cdmaPrlChanged(toAidl(type), version);
     return {};
 }
 
@@ -74,32 +75,28 @@
 Return<void> RadioIndication::cellInfoList_1_5(V1_0::RadioIndicationType type,
                                                const hidl_vec<V1_5::CellInfo>& records) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cellInfoList(toAidl(type), toAidl(records));
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
     return {};
 }
 
 Return<void> RadioIndication::cellInfoList_1_6(V1_0::RadioIndicationType type,
                                                const hidl_vec<V1_6::CellInfo>& records) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->cellInfoList(toAidl(type), toAidl(records));
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
     return {};
 }
 
 Return<void> RadioIndication::currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
                                                           const V1_2::LinkCapacityEstimate& lce) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
     return {};
 }
 
 Return<void> RadioIndication::currentLinkCapacityEstimate_1_6(
         V1_0::RadioIndicationType type, const V1_6::LinkCapacityEstimate& lce) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
     return {};
 }
 
@@ -113,16 +110,14 @@
 Return<void> RadioIndication::currentPhysicalChannelConfigs_1_4(
         V1_0::RadioIndicationType type, const hidl_vec<V1_4::PhysicalChannelConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
     return {};
 }
 
 Return<void> RadioIndication::currentPhysicalChannelConfigs_1_6(
         V1_0::RadioIndicationType type, const hidl_vec<V1_6::PhysicalChannelConfig>& configs) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
     return {};
 }
 
@@ -143,23 +138,20 @@
 Return<void> RadioIndication::currentSignalStrength_1_4(
         V1_0::RadioIndicationType type, const V1_4::SignalStrength& signalStrength) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioIndication::currentSignalStrength_1_6(
         V1_0::RadioIndicationType type, const V1_6::SignalStrength& signalStrength) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioIndication::imsNetworkStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->imsNetworkStateChanged(toAidl(type));
+    networkCb()->imsNetworkStateChanged(toAidl(type));
     return {};
 }
 
@@ -187,31 +179,27 @@
 Return<void> RadioIndication::networkScanResult_1_5(V1_0::RadioIndicationType type,
                                                     const V1_5::NetworkScanResult& result) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkScanResult(toAidl(type), toAidl(result));
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
     return {};
 }
 
 Return<void> RadioIndication::networkScanResult_1_6(V1_0::RadioIndicationType type,
                                                     const V1_6::NetworkScanResult& result) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkScanResult(toAidl(type), toAidl(result));
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
     return {};
 }
 
 Return<void> RadioIndication::networkStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->networkStateChanged(toAidl(type));
+    networkCb()->networkStateChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::nitzTimeReceived(V1_0::RadioIndicationType type,
                                                const hidl_string& nitzTime, uint64_t receivedTime) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
+    networkCb()->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
     return {};
 }
 
@@ -220,33 +208,29 @@
         const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
         int32_t additionalCauseCode) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn,
-                                   aidl::Domain(domain), causeCode, additionalCauseCode);
+    networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn,
+                                    aidl::Domain(domain), causeCode, additionalCauseCode);
     return {};
 }
 
 Return<void> RadioIndication::restrictedStateChanged(V1_0::RadioIndicationType type,
                                                      V1_0::PhoneRestrictedState state) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
+    networkCb()->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
     return {};
 }
 
 Return<void> RadioIndication::suppSvcNotify(V1_0::RadioIndicationType type,
                                             const V1_0::SuppSvcNotification& suppSvc) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->suppSvcNotify(toAidl(type), toAidl(suppSvc));
+    networkCb()->suppSvcNotify(toAidl(type), toAidl(suppSvc));
     return {};
 }
 
 Return<void> RadioIndication::voiceRadioTechChanged(V1_0::RadioIndicationType type,
                                                     V1_0::RadioTechnology rat) {
     LOG_CALL << type;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
+    networkCb()->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index af0bc46..156fdd2 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -33,6 +33,10 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioNetwork::respond() {
+    return mCallbackManager->response().networkCb();
+}
+
 ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(int32_t serial) {
     LOG_CALL << serial;
     if (mHal1_6) {
@@ -69,13 +73,21 @@
 
 ScopedAStatus RadioNetwork::getCellInfoList(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getCellInfoList(serial);
+    if (mHal1_6) {
+        mHal1_6->getCellInfoList_1_6(serial);
+    } else {
+        mHal1_5->getCellInfoList(serial);
+    }
     return ok();
 }
 
 ScopedAStatus RadioNetwork::getDataRegistrationState(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getDataRegistrationState(serial);
+    if (mHal1_6) {
+        mHal1_6->getDataRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getDataRegistrationState_1_5(serial);
+    }
     return ok();
 }
 
@@ -99,7 +111,11 @@
 
 ScopedAStatus RadioNetwork::getSignalStrength(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getSignalStrength(serial);
+    if (mHal1_6) {
+        mHal1_6->getSignalStrength_1_6(serial);
+    } else {
+        mHal1_5->getSignalStrength_1_4(serial);
+    }
     return ok();
 }
 
@@ -108,7 +124,7 @@
     if (mHal1_6) {
         mHal1_6->getSystemSelectionChannels(serial);
     } else {
-        respond().getSystemSelectionChannelsResponse(notSupported(serial), {});
+        respond()->getSystemSelectionChannelsResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -121,7 +137,11 @@
 
 ScopedAStatus RadioNetwork::getVoiceRegistrationState(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getVoiceRegistrationState(serial);
+    if (mHal1_6) {
+        mHal1_6->getVoiceRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getVoiceRegistrationState_1_5(serial);
+    }
     return ok();
 }
 
@@ -130,7 +150,7 @@
     if (mHal1_6) {
         mHal1_6->isNrDualConnectivityEnabled(serial);
     } else {
-        respond().isNrDualConnectivityEnabledResponse(notSupported(serial), false);
+        respond()->isNrDualConnectivityEnabledResponse(notSupported(serial), false);
     }
     return ok();
 }
@@ -179,7 +199,7 @@
 
 ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, aidl::IndicationFilter indFilter) {
     LOG_CALL << serial;
-    mHal1_5->setIndicationFilter(serial, toHidlBitfield<V1_0::IndicationFilter>(indFilter));
+    mHal1_5->setIndicationFilter_1_5(serial, toHidlBitfield<V1_5::IndicationFilter>(indFilter));
     return ok();
 }
 
@@ -188,9 +208,9 @@
         const std::vector<int32_t>& thrDownlinkKbps, const std::vector<int32_t>& thrUplinkKbps,
         AccessNetwork accessNetwork) {
     LOG_CALL << serial;
-    mHal1_5->setLinkCapacityReportingCriteria(  //
+    mHal1_5->setLinkCapacityReportingCriteria_1_5(  //
             serial, hysteresisMs, hysteresisDlKbps, hysteresisUlKbps, thrDownlinkKbps,
-            thrUplinkKbps, V1_2::AccessNetwork(accessNetwork));
+            thrUplinkKbps, V1_5::AccessNetwork(accessNetwork));
     return ok();
 }
 
@@ -219,29 +239,29 @@
     if (mHal1_6) {
         mHal1_6->setNrDualConnectivityState(serial, V1_6::NrDualConnectivityState(st));
     } else {
-        respond().setNrDualConnectivityStateResponse(notSupported(serial));
+        respond()->setNrDualConnectivityStateResponse(notSupported(serial));
     }
     return ok();
 }
 
 ScopedAStatus RadioNetwork::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioNetworkResponse>& networkResponse,
-        const std::shared_ptr<aidl::IRadioNetworkIndication>& networkIndication) {
-    LOG_CALL << networkResponse << ' ' << networkIndication;
-
-    CHECK(networkResponse);
-    CHECK(networkIndication);
-
-    mRadioResponse->setResponseFunction(networkResponse);
-    mRadioIndication->setResponseFunction(networkIndication);
-
+        const std::shared_ptr<aidl::IRadioNetworkResponse>& response,
+        const std::shared_ptr<aidl::IRadioNetworkIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
 ScopedAStatus RadioNetwork::setSignalStrengthReportingCriteria(
         int32_t serial, const std::vector<aidl::SignalThresholdInfo>& infos) {
     LOG_CALL << serial;
-    // TODO(b/203699028): how about other infos?
+    if (infos.size() == 0) {
+        LOG(ERROR) << "Threshold info array is empty - dropping setSignalStrengthReportingCriteria";
+        return ok();
+    }
+    if (infos.size() > 1) {
+        LOG(WARNING) << "Multi-element reporting criteria are not supported with HIDL HAL";
+    }
     mHal1_5->setSignalStrengthReportingCriteria_1_5(serial, toHidl(infos[0]),
                                                     V1_5::AccessNetwork(infos[0].ran));
     return ok();
@@ -278,4 +298,18 @@
     return ok();
 }
 
+ScopedAStatus RadioNetwork::setUsageSetting(int32_t serial, aidl::UsageSetting) {
+    LOG_CALL << serial;
+    LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+    respond()->setUsageSettingResponse(notSupported(serial));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+    respond()->getUsageSettingResponse(notSupported(serial), {});  // {} = neither voice nor data
+    return ok();
+}
+
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
index 81f7775..bab1d4a 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
@@ -33,25 +33,26 @@
 namespace aidl = ::aidl::android::hardware::radio::network;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkResponse> netCb) {
-    CHECK(netCb);
     mNetworkCb = netCb;
 }
 
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioResponse::networkCb() {
+    return mNetworkCb.get();
+}
+
 Return<void> RadioResponse::getAllowedNetworkTypesBitmapResponse(
         const V1_6::RadioResponseInfo& info,
         hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAllowedNetworkTypesBitmapResponse(toAidl(info),
-                                                     RadioAccessFamily(networkTypeBitmap));
+    networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info),
+                                                      RadioAccessFamily(networkTypeBitmap));
     return {};
 }
 
 Return<void> RadioResponse::getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
                                                             V1_0::PreferredNetworkType nwType) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAllowedNetworkTypesBitmapResponse(  //
+    networkCb()->getAllowedNetworkTypesBitmapResponse(  //
             toAidl(info), RadioAccessFamily(getRafFromNetworkType(nwType)));
     return {};
 }
@@ -66,16 +67,14 @@
 Return<void> RadioResponse::getAvailableBandModesResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::RadioBandMode>& bandModes) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
+    networkCb()->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
     return {};
 }
 
 Return<void> RadioResponse::getAvailableNetworksResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::OperatorInfo>& networkInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
+    networkCb()->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
     return {};
 }
 
@@ -83,16 +82,14 @@
         const V1_0::RadioResponseInfo& info, const V1_5::CellIdentity& cellIdentity,
         const hidl_vec<V1_5::BarringInfo>& barringInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
+    networkCb()->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
     return {};
 }
 
 Return<void> RadioResponse::getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
                                                              V1_0::CdmaRoamingType type) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
+    networkCb()->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
     return {};
 }
 
@@ -120,16 +117,14 @@
 Return<void> RadioResponse::getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                         const hidl_vec<V1_5::CellInfo>& cellInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
     return {};
 }
 
 Return<void> RadioResponse::getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                         const hidl_vec<V1_6::CellInfo>& cellInfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
     return {};
 }
 
@@ -157,25 +152,22 @@
 Return<void> RadioResponse::getDataRegistrationStateResponse_1_5(
         const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& dataRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getDataRegistrationStateResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& dataRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getImsRegistrationStateResponse(  //
         const V1_0::RadioResponseInfo& info, bool isRegd, V1_0::RadioTechnologyFamily ratFamily) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getImsRegistrationStateResponse(toAidl(info), isRegd,
-                                                RadioTechnologyFamily(ratFamily));
+    networkCb()->getImsRegistrationStateResponse(toAidl(info), isRegd,
+                                                 RadioTechnologyFamily(ratFamily));
     return {};
 }
 
@@ -189,8 +181,7 @@
 Return<void> RadioResponse::getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
                                                             bool manual) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getNetworkSelectionModeResponse(toAidl(info), manual);
+    networkCb()->getNetworkSelectionModeResponse(toAidl(info), manual);
     return {};
 }
 
@@ -198,8 +189,7 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& longName,
         const hidl_string& shortName, const hidl_string& numeric) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getOperatorResponse(toAidl(info), longName, shortName, numeric);
+    networkCb()->getOperatorResponse(toAidl(info), longName, shortName, numeric);
     return {};
 }
 
@@ -220,16 +210,14 @@
 Return<void> RadioResponse::getSignalStrengthResponse_1_4(
         const V1_0::RadioResponseInfo& info, const V1_4::SignalStrength& signalStrength) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
     return {};
 }
 
 Return<void> RadioResponse::getSignalStrengthResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::SignalStrength& signalStrength) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
     return {};
 }
 
@@ -237,16 +225,14 @@
         const V1_6::RadioResponseInfo& info,
         const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
+    networkCb()->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
     return {};
 }
 
 Return<void> RadioResponse::getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
                                                             V1_0::RadioTechnology rat) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
+    networkCb()->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
     return {};
 }
 
@@ -267,24 +253,21 @@
 Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_5(
         const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& voiceRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_6(
         const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& voiceRegResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
     return {};
 }
 
 Return<void> RadioResponse::isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
                                                                 bool isEnabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
+    networkCb()->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
     return {};
 }
 
@@ -297,15 +280,13 @@
 
 Return<void> RadioResponse::setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& i) {
     LOG_CALL << i.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setAllowedNetworkTypesBitmapResponse(toAidl(i));
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(i));
     return {};
 }
 
 Return<void> RadioResponse::setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setAllowedNetworkTypesBitmapResponse(toAidl(info));
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(info));
     return {};
 }
 
@@ -318,174 +299,151 @@
 
 Return<void> RadioResponse::setBandModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setBandModeResponse(toAidl(info));
+    networkCb()->setBandModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setBarringPasswordResponse(toAidl(info));
+    networkCb()->setBarringPasswordResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setCdmaRoamingPreferenceResponse(toAidl(info));
+    networkCb()->setCdmaRoamingPreferenceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setCellInfoListRateResponse(toAidl(info));
+    networkCb()->setCellInfoListRateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setIndicationFilterResponse(toAidl(info));
+    networkCb()->setIndicationFilterResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setIndicationFilterResponse(toAidl(info));
+    networkCb()->setIndicationFilterResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setLocationUpdatesResponse(toAidl(info));
+    networkCb()->setLocationUpdatesResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeAutomaticResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeAutomaticResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeAutomaticResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeManualResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeManualResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNetworkSelectionModeManualResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNetworkSelectionModeManualResponse(toAidl(info));
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setNrDualConnectivityStateResponse(
         const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setNrDualConnectivityStateResponse(toAidl(info));
+    networkCb()->setNrDualConnectivityStateResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSuppServiceNotificationsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSuppServiceNotificationsResponse(toAidl(info));
+    networkCb()->setSuppServiceNotificationsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSystemSelectionChannelsResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSystemSelectionChannelsResponse(toAidl(info));
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSystemSelectionChannelsResponse_1_5(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->setSystemSelectionChannelsResponse(toAidl(info));
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->startNetworkScanResponse(toAidl(info));
+    networkCb()->startNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->stopNetworkScanResponse(toAidl(info));
+    networkCb()->stopNetworkScanResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::supplyNetworkDepersonalizationResponse(
         const V1_0::RadioResponseInfo& info, int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mNetworkCb);
-    mNetworkCb->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
+    networkCb()->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
index 6b906c6..3938e00 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
@@ -29,29 +29,29 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioSimIndication> simCb) {
-    CHECK(simCb);
     mSimCb = simCb;
 }
 
+std::shared_ptr<aidl::IRadioSimIndication> RadioIndication::simCb() {
+    return mSimCb.get();
+}
+
 Return<void> RadioIndication::carrierInfoForImsiEncryption(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->carrierInfoForImsiEncryption(toAidl(type));
+    simCb()->carrierInfoForImsiEncryption(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::cdmaSubscriptionSourceChanged(
         V1_0::RadioIndicationType type, V1_0::CdmaSubscriptionSource cdmaSource) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
+    simCb()->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
     return {};
 }
 
 Return<void> RadioIndication::simPhonebookChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simPhonebookChanged(toAidl(type));
+    simCb()->simPhonebookChanged(toAidl(type));
     return {};
 }
 
@@ -59,62 +59,54 @@
         V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
         const hidl_vec<V1_6::PhonebookRecordInfo>& rec) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
+    simCb()->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
     return {};
 }
 
 Return<void> RadioIndication::simRefresh(V1_0::RadioIndicationType type,
                                          const V1_0::SimRefreshResult& refreshResult) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simRefresh(toAidl(type), toAidl(refreshResult));
+    simCb()->simRefresh(toAidl(type), toAidl(refreshResult));
     return {};
 }
 
 Return<void> RadioIndication::simStatusChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->simStatusChanged(toAidl(type));
+    simCb()->simStatusChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::stkEventNotify(V1_0::RadioIndicationType type,
                                              const hidl_string& cmd) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkEventNotify(toAidl(type), cmd);
+    simCb()->stkEventNotify(toAidl(type), cmd);
     return {};
 }
 
 Return<void> RadioIndication::stkProactiveCommand(V1_0::RadioIndicationType type,
                                                   const hidl_string& cmd) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkProactiveCommand(toAidl(type), cmd);
+    simCb()->stkProactiveCommand(toAidl(type), cmd);
     return {};
 }
 
 Return<void> RadioIndication::stkSessionEnd(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->stkSessionEnd(toAidl(type));
+    simCb()->stkSessionEnd(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::subscriptionStatusChanged(V1_0::RadioIndicationType type,
                                                         bool activate) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->subscriptionStatusChanged(toAidl(type), activate);
+    simCb()->subscriptionStatusChanged(toAidl(type), activate);
     return {};
 }
 
 Return<void> RadioIndication::uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
                                                                 bool enabled) {
     LOG_CALL << type;
-    CHECK_CB(mSimCb);
-    mSimCb->uiccApplicationsEnablementChanged(toAidl(type), enabled);
+    simCb()->uiccApplicationsEnablementChanged(toAidl(type), enabled);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
index 2dfbc50..3ad9130 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
@@ -29,48 +29,46 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioSimResponse> simCb) {
-    CHECK(simCb);
     mSimCb = simCb;
 }
 
+std::shared_ptr<aidl::IRadioSimResponse> RadioResponse::simCb() {
+    return mSimCb.get();
+}
+
 Return<void> RadioResponse::areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
                                                                bool enabled) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
+    simCb()->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
     return {};
 }
 
 Return<void> RadioResponse::changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->changeIccPinForAppResponse(toAidl(info), remainingRetries);
+    simCb()->changeIccPinForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->enableUiccApplicationsResponse(toAidl(info));
+    simCb()->enableUiccApplicationsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getAllowedCarriersResponse(  //
         const V1_0::RadioResponseInfo& info, bool allAllowed, const V1_0::CarrierRestrictions& cr) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
     aidl::CarrierRestrictions aidlCr = toAidl(cr);
     if (allAllowed) aidlCr = {};
-    mSimCb->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
+    simCb()->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
     return {};
 }
 
@@ -78,9 +76,8 @@
         const V1_0::RadioResponseInfo& info, const V1_4::CarrierRestrictionsWithPriority& carriers,
         V1_4::SimLockMultiSimPolicy multiSimPolicy) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
-                                       aidl::SimLockMultiSimPolicy(multiSimPolicy));
+    simCb()->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
+                                        aidl::SimLockMultiSimPolicy(multiSimPolicy));
     return {};
 }
 
@@ -88,133 +85,116 @@
         const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
         const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
+    simCb()->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
     return {};
 }
 
 Return<void> RadioResponse::getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
                                                               V1_0::CdmaSubscriptionSource s) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
+    simCb()->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
     return {};
 }
 
 Return<void> RadioResponse::getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
                                                           int32_t response) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getFacilityLockForAppResponse(toAidl(info), response);
+    simCb()->getFacilityLockForAppResponse(toAidl(info), response);
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
                                                      const V1_0::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
                                                          const V1_2::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
                                                          const V1_4::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
                                                          const V1_5::CardStatus& cardStatus) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
     return {};
 }
 
 Return<void> RadioResponse::getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
                                                   const hidl_string& imsi) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getImsiForAppResponse(toAidl(info), imsi);
+    simCb()->getImsiForAppResponse(toAidl(info), imsi);
     return {};
 }
 
 Return<void> RadioResponse::getSimPhonebookCapacityResponse(
         const V1_6::RadioResponseInfo& info, const V1_6::PhonebookCapacity& capacity) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
+    simCb()->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
     return {};
 }
 
 Return<void> RadioResponse::getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->getSimPhonebookRecordsResponse(toAidl(info));
+    simCb()->getSimPhonebookRecordsResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccCloseLogicalChannelResponse(toAidl(info));
+    simCb()->iccCloseLogicalChannelResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
                                                 const V1_0::IccIoResult& iccIo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
+    simCb()->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
     return {};
 }
 
 Return<void> RadioResponse::iccOpenLogicalChannelResponse(  //
         const V1_0::RadioResponseInfo& info, int32_t chanId, const hidl_vec<int8_t>& selectResp) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
+    simCb()->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
     return {};
 }
 
 Return<void> RadioResponse::iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
                                                                 const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
+    simCb()->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
     return {};
 }
 
 Return<void> RadioResponse::iccTransmitApduLogicalChannelResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
+    simCb()->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
     return {};
 }
 
 Return<void> RadioResponse::reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->reportStkServiceIsRunningResponse(toAidl(info));
+    simCb()->reportStkServiceIsRunningResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
                                                                 const V1_0::IccIoResult& result) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
+    simCb()->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
     return {};
 }
 
@@ -228,121 +208,105 @@
 Return<void> RadioResponse::sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
                                                  const hidl_string& commandResponse) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendEnvelopeResponse(toAidl(info), commandResponse);
+    simCb()->sendEnvelopeResponse(toAidl(info), commandResponse);
     return {};
 }
 
 Return<void> RadioResponse::sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
                                                            const V1_0::IccIoResult& iccIo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
+    simCb()->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
     return {};
 }
 
 Return<void> RadioResponse::sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->sendTerminalResponseToSimResponse(toAidl(info));
+    simCb()->sendTerminalResponseToSimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t numAllowed) {
     LOG_CALL << info.serial << ' ' << numAllowed;
-    CHECK_CB(mSimCb);
-    mSimCb->setAllowedCarriersResponse(toAidl(info));
+    simCb()->setAllowedCarriersResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setAllowedCarriersResponse(toAidl(info));
+    simCb()->setAllowedCarriersResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCarrierInfoForImsiEncryptionResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
+    simCb()->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setCdmaSubscriptionSourceResponse(toAidl(info));
+    simCb()->setCdmaSubscriptionSourceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
                                                           int32_t retry) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setFacilityLockForAppResponse(toAidl(info), retry);
+    simCb()->setFacilityLockForAppResponse(toAidl(info), retry);
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setSimCardPowerResponse(toAidl(info));
+    simCb()->setSimCardPowerResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->setUiccSubscriptionResponse(toAidl(info));
+    simCb()->setUiccSubscriptionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
                                                         int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
 Return<void> RadioResponse::supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
                                                        int32_t remainingRetries) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
+    simCb()->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
     return {};
 }
 
@@ -350,16 +314,14 @@
                                                                V1_5::PersoSubstate persoType,
                                                                int32_t rRet) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
+    simCb()->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
     return {};
 }
 
 Return<void> RadioResponse::updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
                                                               int32_t updatedRecordIndex) {
     LOG_CALL << info.serial;
-    CHECK_CB(mSimCb);
-    mSimCb->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
+    simCb()->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
index ca27918..b43f64f 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
@@ -30,6 +30,10 @@
 namespace aidl = ::aidl::android::hardware::radio::sim;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioSimResponse> RadioSim::respond() {
+    return mCallbackManager->response().simCb();
+}
+
 ScopedAStatus RadioSim::areUiccApplicationsEnabled(int32_t serial) {
     LOG_CALL << serial;
     mHal1_5->areUiccApplicationsEnabled(serial);
@@ -58,7 +62,7 @@
 
 ScopedAStatus RadioSim::getAllowedCarriers(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getAllowedCarriers(serial);
+    mHal1_5->getAllowedCarriers_1_4(serial);
     return ok();
 }
 
@@ -99,7 +103,7 @@
     if (mHal1_6) {
         mHal1_6->getSimPhonebookCapacity(serial);
     } else {
-        respond().getSimPhonebookCapacityResponse(notSupported(serial), {});
+        respond()->getSimPhonebookCapacityResponse(notSupported(serial), {});
     }
     return ok();
 }
@@ -109,7 +113,7 @@
     if (mHal1_6) {
         mHal1_6->getSimPhonebookRecords(serial);
     } else {
-        respond().getSimPhonebookRecordsResponse(notSupported(serial));
+        respond()->getSimPhonebookRecordsResponse(notSupported(serial));
     }
     return ok();
 }
@@ -217,16 +221,10 @@
 }
 
 ScopedAStatus RadioSim::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioSimResponse>& simResponse,
-        const std::shared_ptr<aidl::IRadioSimIndication>& simIndication) {
-    LOG_CALL << simResponse << ' ' << simIndication;
-
-    CHECK(simResponse);
-    CHECK(simIndication);
-
-    mRadioResponse->setResponseFunction(simResponse);
-    mRadioIndication->setResponseFunction(simIndication);
-
+        const std::shared_ptr<aidl::IRadioSimResponse>& response,
+        const std::shared_ptr<aidl::IRadioSimIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -287,7 +285,7 @@
     if (mHal1_6) {
         mHal1_6->updateSimPhonebookRecords(serial, toHidl(recordInfo));
     } else {
-        respond().updateSimPhonebookRecordsResponse(notSupported(serial), 0);
+        respond()->updateSimPhonebookRecordsResponse(notSupported(serial), 0);
     }
     return ok();
 }
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.cpp b/radio/aidl/compat/libradiocompat/sim/structs.cpp
index 97a21a1..bfbff02 100644
--- a/radio/aidl/compat/libradiocompat/sim/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/structs.cpp
@@ -173,7 +173,6 @@
             .atr = status.base.base.atr,
             .iccid = status.base.base.iccid,
             .eid = status.base.eid,
-            // TODO(b/203699028): we don't know portId here (but we can get it from RadioConfig)
             .slotMap = {static_cast<int32_t>(status.base.base.physicalSlotId), 0},
     };
 }
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
index 6d9bda8..359fce0 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
@@ -29,113 +29,102 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 
 void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceIndication> voiceCb) {
-    CHECK(voiceCb);
     mVoiceCb = voiceCb;
 }
 
+std::shared_ptr<aidl::IRadioVoiceIndication> RadioIndication::voiceCb() {
+    return mVoiceCb.get();
+}
+
 Return<void> RadioIndication::callRing(V1_0::RadioIndicationType type, bool isGsm,
                                        const V1_0::CdmaSignalInfoRecord& record) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->callRing(toAidl(type), isGsm, toAidl(record));
+    voiceCb()->callRing(toAidl(type), isGsm, toAidl(record));
     return {};
 }
 
 Return<void> RadioIndication::callStateChanged(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->callStateChanged(toAidl(type));
+    voiceCb()->callStateChanged(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::cdmaCallWaiting(V1_0::RadioIndicationType type,
                                               const V1_0::CdmaCallWaiting& callWaitingRecord) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
+    voiceCb()->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
     return {};
 }
 
 Return<void> RadioIndication::cdmaInfoRec(V1_0::RadioIndicationType type,
                                           const V1_0::CdmaInformationRecords& records) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
+    voiceCb()->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
     return {};
 }
 
 Return<void> RadioIndication::cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
                                                      V1_0::CdmaOtaProvisionStatus status) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
+    voiceCb()->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
     return {};
 }
 
 Return<void> RadioIndication::currentEmergencyNumberList(
         V1_0::RadioIndicationType type, const hidl_vec<V1_4::EmergencyNumber>& emergencyNumbers) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
+    voiceCb()->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
     return {};
 }
 
 Return<void> RadioIndication::enterEmergencyCallbackMode(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->enterEmergencyCallbackMode(toAidl(type));
+    voiceCb()->enterEmergencyCallbackMode(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::exitEmergencyCallbackMode(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->exitEmergencyCallbackMode(toAidl(type));
+    voiceCb()->exitEmergencyCallbackMode(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::indicateRingbackTone(V1_0::RadioIndicationType type, bool start) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->indicateRingbackTone(toAidl(type), start);
+    voiceCb()->indicateRingbackTone(toAidl(type), start);
     return {};
 }
 
 Return<void> RadioIndication::onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
                                                                const V1_0::StkCcUnsolSsResult& ss) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
+    voiceCb()->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
     return {};
 }
 
 Return<void> RadioIndication::resendIncallMute(V1_0::RadioIndicationType type) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->resendIncallMute(toAidl(type));
+    voiceCb()->resendIncallMute(toAidl(type));
     return {};
 }
 
 Return<void> RadioIndication::srvccStateNotify(V1_0::RadioIndicationType type,
                                                V1_0::SrvccState state) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
+    voiceCb()->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
     return {};
 }
 
 Return<void> RadioIndication::stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
                                                         const hidl_string& alpha) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stkCallControlAlphaNotify(toAidl(type), alpha);
+    voiceCb()->stkCallControlAlphaNotify(toAidl(type), alpha);
     return {};
 }
 
 Return<void> RadioIndication::stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) {
     LOG_CALL << type;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stkCallSetup(toAidl(type), timeout);
+    voiceCb()->stkCallSetup(toAidl(type), timeout);
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
index 0a64c56..d233548 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
@@ -29,265 +29,233 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 
 void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceResponse> voiceCb) {
-    CHECK(voiceCb);
     mVoiceCb = voiceCb;
 }
 
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioResponse::voiceCb() {
+    return mVoiceCb.get();
+}
+
 Return<void> RadioResponse::acceptCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->acceptCallResponse(toAidl(info));
+    voiceCb()->acceptCallResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::conferenceResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->conferenceResponse(toAidl(info));
+    voiceCb()->conferenceResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::dialResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->dialResponse(toAidl(info));
+    voiceCb()->dialResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::emergencyDialResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->emergencyDialResponse(toAidl(info));
+    voiceCb()->emergencyDialResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->exitEmergencyCallbackModeResponse(toAidl(info));
+    voiceCb()->exitEmergencyCallbackModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->explicitCallTransferResponse(toAidl(info));
+    voiceCb()->explicitCallTransferResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::getCallForwardStatusResponse(
         const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::CallForwardInfo>& callFwdInfos) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
+    voiceCb()->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
     return {};
 }
 
 Return<void> RadioResponse::getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
                                                    int32_t serviceClass) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCallWaitingResponse(toAidl(info), enable, serviceClass);
+    voiceCb()->getCallWaitingResponse(toAidl(info), enable, serviceClass);
     return {};
 }
 
 Return<void> RadioResponse::getClipResponse(const V1_0::RadioResponseInfo& info,
                                             V1_0::ClipStatus status) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getClipResponse(toAidl(info), aidl::ClipStatus(status));
+    voiceCb()->getClipResponse(toAidl(info), aidl::ClipStatus(status));
     return {};
 }
 
 Return<void> RadioResponse::getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
                                             int32_t m) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getClirResponse(toAidl(info), n, m);
+    voiceCb()->getClirResponse(toAidl(info), n, m);
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
                                                     const hidl_vec<V1_0::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
                                                         const hidl_vec<V1_2::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
                                                         const hidl_vec<V1_6::Call>& calls) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
     return {};
 }
 
 Return<void> RadioResponse::getLastCallFailCauseResponse(
         const V1_0::RadioResponseInfo& info, const V1_0::LastCallFailCauseInfo& failCauseinfo) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
+    voiceCb()->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
     return {};
 }
 
 Return<void> RadioResponse::getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getMuteResponse(toAidl(info), enable);
+    voiceCb()->getMuteResponse(toAidl(info), enable);
     return {};
 }
 
 Return<void> RadioResponse::getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
                                                              bool enable) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getPreferredVoicePrivacyResponse(toAidl(info), enable);
+    voiceCb()->getPreferredVoicePrivacyResponse(toAidl(info), enable);
     return {};
 }
 
 Return<void> RadioResponse::getTTYModeResponse(const V1_0::RadioResponseInfo& info,
                                                V1_0::TtyMode mode) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
+    voiceCb()->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
     return {};
 }
 
 Return<void> RadioResponse::handleStkCallSetupRequestFromSimResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->handleStkCallSetupRequestFromSimResponse(toAidl(info));
+    voiceCb()->handleStkCallSetupRequestFromSimResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupConnectionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupConnectionResponse(toAidl(info));
+    voiceCb()->hangupConnectionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupForegroundResumeBackgroundResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupForegroundResumeBackgroundResponse(toAidl(info));
+    voiceCb()->hangupForegroundResumeBackgroundResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->hangupWaitingOrBackgroundResponse(toAidl(info));
+    voiceCb()->hangupWaitingOrBackgroundResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::rejectCallResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->rejectCallResponse(toAidl(info));
+    voiceCb()->rejectCallResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendBurstDtmfResponse(toAidl(info));
+    voiceCb()->sendBurstDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendCdmaFeatureCodeResponse(toAidl(info));
+    voiceCb()->sendCdmaFeatureCodeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::sendDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->sendDtmfResponse(toAidl(info));
+    voiceCb()->sendDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::separateConnectionResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->separateConnectionResponse(toAidl(info));
+    voiceCb()->separateConnectionResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCallForwardResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setCallForwardResponse(toAidl(info));
+    voiceCb()->setCallForwardResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setCallWaitingResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setCallWaitingResponse(toAidl(info));
+    voiceCb()->setCallWaitingResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setClirResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setClirResponse(toAidl(info));
+    voiceCb()->setClirResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setMuteResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setMuteResponse(toAidl(info));
+    voiceCb()->setMuteResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setPreferredVoicePrivacyResponse(toAidl(info));
+    voiceCb()->setPreferredVoicePrivacyResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::setTTYModeResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->setTtyModeResponse(toAidl(info));
+    voiceCb()->setTtyModeResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::startDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->startDtmfResponse(toAidl(info));
+    voiceCb()->startDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::stopDtmfResponse(const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->stopDtmfResponse(toAidl(info));
+    voiceCb()->stopDtmfResponse(toAidl(info));
     return {};
 }
 
 Return<void> RadioResponse::switchWaitingOrHoldingAndActiveResponse(
         const V1_0::RadioResponseInfo& info) {
     LOG_CALL << info.serial;
-    CHECK_CB(mVoiceCb);
-    mVoiceCb->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
+    voiceCb()->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
index 16c6b14..7b1d1fa 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -30,6 +30,10 @@
 namespace aidl = ::aidl::android::hardware::radio::voice;
 constexpr auto ok = &ScopedAStatus::ok;
 
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioVoice::respond() {
+    return mCallbackManager->response().voiceCb();
+}
+
 ScopedAStatus RadioVoice::acceptCall(int32_t serial) {
     LOG_CALL << serial;
     mHal1_5->acceptCall(serial);
@@ -49,13 +53,19 @@
 }
 
 ScopedAStatus RadioVoice::emergencyDial(  //
-        int32_t serial, const aidl::Dial& dialInfo, aidl::EmergencyServiceCategory categories,
+        int32_t serial, const aidl::Dial& info, aidl::EmergencyServiceCategory categories,
         const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
-        bool hasKnownUserIntentEmerg, bool isTesting) {
+        bool knownUserIntentEmerg, bool isTesting) {
     LOG_CALL << serial;
-    mHal1_5->emergencyDial(serial, toHidl(dialInfo),
-                           toHidlBitfield<V1_4::EmergencyServiceCategory>(categories), toHidl(urns),
-                           V1_4::EmergencyCallRouting(routing), hasKnownUserIntentEmerg, isTesting);
+    if (mHal1_6) {
+        mHal1_6->emergencyDial_1_6(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    } else {
+        mHal1_5->emergencyDial(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    }
     return ok();
 }
 
@@ -98,7 +108,11 @@
 
 ScopedAStatus RadioVoice::getCurrentCalls(int32_t serial) {
     LOG_CALL << serial;
-    mHal1_5->getCurrentCalls(serial);
+    if (mHal1_6) {
+        mHal1_6->getCurrentCalls_1_6(serial);
+    } else {
+        mHal1_5->getCurrentCalls(serial);
+    }
     return ok();
 }
 
@@ -152,7 +166,7 @@
 
 ScopedAStatus RadioVoice::isVoNrEnabled(int32_t serial) {
     LOG_CALL << serial;
-    // TODO(b/203699028): can't call isVoNrEnabledResponse with 1.6 callback
+    respond()->isVoNrEnabledResponse(notSupported(serial), false);
     return ok();
 }
 
@@ -224,16 +238,10 @@
 }
 
 ScopedAStatus RadioVoice::setResponseFunctions(
-        const std::shared_ptr<aidl::IRadioVoiceResponse>& voiceResponse,
-        const std::shared_ptr<aidl::IRadioVoiceIndication>& voiceIndication) {
-    LOG_CALL << voiceResponse << ' ' << voiceIndication;
-
-    CHECK(voiceResponse);
-    CHECK(voiceIndication);
-
-    mRadioResponse->setResponseFunction(voiceResponse);
-    mRadioIndication->setResponseFunction(voiceIndication);
-
+        const std::shared_ptr<aidl::IRadioVoiceResponse>& response,
+        const std::shared_ptr<aidl::IRadioVoiceIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
     return ok();
 }
 
@@ -245,7 +253,8 @@
 
 ndk::ScopedAStatus RadioVoice::setVoNrEnabled(int32_t serial, [[maybe_unused]] bool enable) {
     LOG_CALL << serial;
-    // TODO(b/203699028): should set `persist.radio.is_vonr_enabled_` property instead
+    // Note: a workaround for older HALs could also be setting persist.radio.is_vonr_enabled_
+    respond()->setVoNrEnabledResponse(notSupported(serial));
     return ok();
 }
 
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
index 2a67569..8af05de 100644
--- a/radio/aidl/compat/service/service.cpp
+++ b/radio/aidl/compat/service/service.cpp
@@ -19,13 +19,12 @@
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
+#include <libradiocompat/CallbackManager.h>
 #include <libradiocompat/RadioConfig.h>
 #include <libradiocompat/RadioData.h>
-#include <libradiocompat/RadioIndication.h>
 #include <libradiocompat/RadioMessaging.h>
 #include <libradiocompat/RadioModem.h>
 #include <libradiocompat/RadioNetwork.h>
-#include <libradiocompat/RadioResponse.h>
 #include <libradiocompat/RadioSim.h>
 #include <libradiocompat/RadioVoice.h>
 
@@ -36,8 +35,8 @@
 static std::vector<std::shared_ptr<ndk::ICInterface>> gPublishedHals;
 
 template <typename T>
-static void publishRadioHal(sp<V1_5::IRadio> hidlHal, sp<compat::RadioResponse> responseCb,
-                            sp<compat::RadioIndication> indicationCb, const std::string& slot) {
+static void publishRadioHal(std::shared_ptr<compat::DriverContext> ctx, sp<V1_5::IRadio> hidlHal,
+                            std::shared_ptr<compat::CallbackManager> cm, const std::string& slot) {
     const auto instance = T::descriptor + "/"s + slot;
     if (!AServiceManager_isDeclared(instance.c_str())) {
         LOG(INFO) << instance << " is not declared in VINTF (this may be intentional)";
@@ -45,7 +44,7 @@
     }
     LOG(DEBUG) << "Publishing " << instance;
 
-    auto aidlHal = ndk::SharedRefBase::make<T>(hidlHal, responseCb, indicationCb);
+    auto aidlHal = ndk::SharedRefBase::make<T>(ctx, hidlHal, cm);
     gPublishedHals.push_back(aidlHal);
     const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
     CHECK_EQ(status, STATUS_OK);
@@ -57,16 +56,15 @@
 
     hidl_utils::linkDeathToDeath(radioHidl);
 
-    auto responseCb = sp<compat::RadioResponse>::make();
-    auto indicationCb = sp<compat::RadioIndication>::make();
-    radioHidl->setResponseFunctions(responseCb, indicationCb).assertOk();
+    auto context = std::make_shared<compat::DriverContext>();
+    auto callbackMgr = std::make_shared<compat::CallbackManager>(context, radioHidl);
 
-    publishRadioHal<compat::RadioData>(radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioMessaging>(radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioModem>(radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioNetwork>(radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioSim>(radioHidl, responseCb, indicationCb, slot);
-    publishRadioHal<compat::RadioVoice>(radioHidl, responseCb, indicationCb, slot);
+    publishRadioHal<compat::RadioData>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioMessaging>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioModem>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioNetwork>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioSim>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioVoice>(context, radioHidl, callbackMgr, slot);
 }
 
 static void publishRadioConfig() {
@@ -83,6 +81,7 @@
 }
 
 static void main() {
+    base::InitLogging(nullptr, base::LogdLogger(base::RADIO));
     base::SetDefaultTag("radiocompat");
     base::SetMinimumLogSeverity(base::VERBOSE);
     LOG(DEBUG) << "Radio HAL compat service starting...";