Merge "cuttlefish: suspend_blocker service"
diff --git a/OWNERS b/OWNERS
index ce92c4f..9594320 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,6 +2,7 @@
 ghartman@google.com
 jemoreira@google.com
 malchev@google.com
-schuffelen@google.com
 muntsinger@google.com
+natsu@google.com
 rammuthiah@google.com
+schuffelen@google.com
diff --git a/guest/hals/ril/cuttlefish_ril.cpp b/guest/hals/ril/cuttlefish_ril.cpp
index cf791b9..47cb5c5 100644
--- a/guest/hals/ril/cuttlefish_ril.cpp
+++ b/guest/hals/ril/cuttlefish_ril.cpp
@@ -102,6 +102,7 @@
 static int gSimPINAttempts = 0;
 static const int gSimPINAttemptsMax = 3;
 static SIM_Status gSimStatus = SIM_NOT_READY;
+static bool areUiccApplicationsEnabled = true;
 
 // SetUpNetworkInterface configures IP and Broadcast addresses on a RIL
 // controlled network interface.
@@ -1213,6 +1214,40 @@
                                  sizeof(gCdmaSubscriptionType));
 }
 
+static void request_enable_uicc_applications(int /*request*/, void* data,
+                                             size_t datalen,
+                                             RIL_Token t) {
+  ALOGV("Enable uicc applications.");
+
+  if (data == NULL || datalen != sizeof(int)) {
+    gce_ril_env->OnRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
+    return;
+  }
+
+  bool enable = *(int *)(data) != 0;
+
+  ALOGV("areUiccApplicationsEnabled change from %d to %d", areUiccApplicationsEnabled, enable);
+
+  areUiccApplicationsEnabled = enable;
+
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+static void request_are_uicc_applications_enabled(int /*request*/, void* /*data*/,
+                                                  size_t /*datalen*/,
+                                                  RIL_Token t) {
+  ALOGV("Getting whether uicc applications are enabled.");
+
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, &areUiccApplicationsEnabled, sizeof(bool));
+}
+
+static void request_can_toggle_uicc_applications_enablement(int /*request*/, void* /*data*/,
+                                                             size_t /*datalen*/, RIL_Token t) {
+  ALOGV("Getting can toggle uicc applications enablement.");
+
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
 static void request_cdma_set_subscription_source(int /*request*/, void* data,
                                                  size_t /*datalen*/,
                                                  RIL_Token t) {
@@ -2229,13 +2264,6 @@
   return;
 }
 
-static void request_set_signal_strength_reporting_criteria_1_5(int /*request*/, void* /*data*/,
-                                                               size_t /*datalen*/, RIL_Token t) {
-  ALOGV("request_set_signal_strength_reporting_criteria_1_5 - void");
-  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
-  return;
-}
-
 static void request_enable_modem(int /*request*/, RIL_Token t) {
   ALOGV("Enabling modem - void");
   gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
@@ -2248,6 +2276,26 @@
   return;
 }
 
+// New functions after Q
+static void request_set_signal_strength_reporting_criteria_1_5(int /*request*/, void* /*data*/,
+                                                               size_t /*datalen*/, RIL_Token t) {
+  ALOGV("request_set_signal_strength_reporting_criteria_1_5 - void");
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+  return;
+}
+
+static void request_set_system_selection_channels_1_5(int /*request*/, RIL_Token t) {
+  ALOGV("request_set_system_selection_channels_1_5 - void");
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+  return;
+}
+
+static void request_start_network_scan_1_5(RIL_Token t) {
+  ALOGV("request_start_network_scan_1_5");
+  gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+  return;
+}
+
 static void gce_ril_on_request(int request, void* data, size_t datalen,
                                RIL_Token t) {
   // Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
@@ -2467,7 +2515,6 @@
     case RIL_REQUEST_IMS_SEND_SMS:
       request_ims_send_SMS(data, datalen, t);
       break;
-
     case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
       ALOGW("INITIAL ATTACH APN");
       gce_ril_env->OnRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
@@ -2480,9 +2527,6 @@
     case RIL_REQUEST_START_NETWORK_SCAN4:
       request_start_network_scan4(t);
       break;
-    case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA_1_5:
-      request_set_signal_strength_reporting_criteria_1_5(request, data, datalen, t);
-      break;
     case RIL_REQUEST_GET_MODEM_STACK_STATUS:
       request_get_modem_stack_status(request, t);
       break;
@@ -2534,6 +2578,26 @@
     case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
       request_exit_emergency_mode(data, datalen, t);
       break;
+
+// New requests after Q.
+    case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA_1_5:
+      request_set_signal_strength_reporting_criteria_1_5(request, data, datalen, t);
+      break;
+    case RIL_REQUEST_ENABLE_UICC_APPLICATIONS:
+      request_enable_uicc_applications(request, data, datalen, t);
+      break;
+    case RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED:
+      request_are_uicc_applications_enabled(request, data, datalen, t);
+      break;
+    case RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT:
+      request_can_toggle_uicc_applications_enablement(request, data, datalen, t);
+      break;
+    case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS_1_5:
+      request_set_system_selection_channels_1_5(request, t);
+      break;
+    case RIL_REQUEST_START_NETWORK_SCAN_1_5:
+      request_start_network_scan_1_5(t);
+      break;
     default:
       ALOGE("Request %d not supported.", request);
       gce_ril_env->OnRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
diff --git a/guest/hals/ril/libril/ril.cpp b/guest/hals/ril/libril/ril.cpp
index ef77ed2..8d3497e 100644
--- a/guest/hals/ril/libril/ril.cpp
+++ b/guest/hals/ril/libril/ril.cpp
@@ -1072,8 +1072,11 @@
         case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK";
         case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";
         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: return "QUERY_NETWORK_SELECTION_MODE";
+        case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS: return "RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS";
+        case RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS_1_5: return "RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS5";
         case RIL_REQUEST_START_NETWORK_SCAN: return "RIL_REQUEST_START_NETWORK_SCAN";
         case RIL_REQUEST_START_NETWORK_SCAN4: return "RIL_REQUEST_START_NETWORK_SCAN4";
+        case RIL_REQUEST_START_NETWORK_SCAN_1_5: return "RIL_REQUEST_START_NETWORK_SCAN5";
         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: return "SET_NETWORK_SELECTION_AUTOMATIC";
         case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: return "SET_NETWORK_SELECTION_MANUAL";
         case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: return "QUERY_AVAILABLE_NETWORKS";
diff --git a/guest/hals/ril/libril/ril.h b/guest/hals/ril/libril/ril.h
index caf6939..80394ea 100644
--- a/guest/hals/ril/libril/ril.h
+++ b/guest/hals/ril/libril/ril.h
@@ -94,6 +94,9 @@
  *                    RIL_REQUEST_ENABLE_MODEM
  *                    RIL_REQUEST_EMERGENCY_DIAL
  *                    RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS
+ *                    RIL_REQUEST_ENABLE_UICC_APPLICATIONS
+ *                    RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED
+ *                    RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT
  */
 #define RIL_VERSION 12
 #define LAST_IMPRECISE_RIL_VERSION 12 // Better self-documented name
@@ -2098,6 +2101,7 @@
     GERAN = 0x01,   // GSM EDGE Radio Access Network
     UTRAN = 0x02,   // Universal Terrestrial Radio Access Network
     EUTRAN = 0x03,  // Evolved Universal Terrestrial Radio Access Network
+    NGRAN = 0x04,   // Next-Generation Radio Access Network
 } RIL_RadioAccessNetworks;
 
 typedef enum {
@@ -2191,6 +2195,45 @@
     EUTRAN_BAND_70 = 70,
 } RIL_EutranBands;
 
+typedef enum {
+    NGRAN_BAND_1 = 1,
+    NGRAN_BAND_2 = 2,
+    NGRAN_BAND_3 = 3,
+    NGRAN_BAND_5 = 5,
+    NGRAN_BAND_7 = 7,
+    NGRAN_BAND_8 = 8,
+    NGRAN_BAND_12 = 12,
+    NGRAN_BAND_20 = 20,
+    NGRAN_BAND_25 = 25,
+    NGRAN_BAND_28 = 28,
+    NGRAN_BAND_34 = 34,
+    NGRAN_BAND_38 = 38,
+    NGRAN_BAND_39 = 39,
+    NGRAN_BAND_40 = 40,
+    NGRAN_BAND_41 = 41,
+    NGRAN_BAND_50 = 50,
+    NGRAN_BAND_51 = 51,
+    NGRAN_BAND_66 = 66,
+    NGRAN_BAND_70 = 70,
+    NGRAN_BAND_71 = 71,
+    NGRAN_BAND_74 = 74,
+    NGRAN_BAND_75 = 75,
+    NGRAN_BAND_76 = 76,
+    NGRAN_BAND_77 = 77,
+    NGRAN_BAND_78 = 78,
+    NGRAN_BAND_79 = 79,
+    NGRAN_BAND_80 = 80,
+    NGRAN_BAND_81 = 81,
+    NGRAN_BAND_82 = 82,
+    NGRAN_BAND_83 = 83,
+    NGRAN_BAND_84 = 84,
+    NGRAN_BAND_86 = 86,
+    NGRAN_BAND_257 = 257,
+    NGRAN_BAND_258 = 258,
+    NGRAN_BAND_260 = 260,
+    NGRAN_BAND_261 = 261,
+} RIL_NgranBands;
+
 typedef struct {
     RIL_RadioAccessNetworks radio_access_network; // The type of network to scan.
     uint32_t bands_length;                        // Length of bands
@@ -2198,6 +2241,7 @@
         RIL_GeranBands geran_bands[MAX_BANDS];
         RIL_UtranBands utran_bands[MAX_BANDS];
         RIL_EutranBands eutran_bands[MAX_BANDS];
+        RIL_NgranBands ngran_bands[MAX_BANDS];
     } bands;
     uint32_t channels_length;                     // Length of channels
     uint32_t channels[MAX_CHANNELS];              // Frequency channels to scan
@@ -6596,6 +6640,89 @@
  */
 #define RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA_1_5 155
 
+/**
+ * RIL_REQUEST_ENABLE_UICC_APPLICATIONS
+ *
+ * Enable or disable uicc applications.
+ *
+ * Valid errors:
+ *  SUCCESS
+ *  RADIO_NOT_AVAILABLE
+ *  SIM_ABSENT
+ *  INTERNAL_ERR
+ *  REQUEST_NOT_SUPPORTED
+ */
+#define RIL_REQUEST_ENABLE_UICC_APPLICATIONS 156
+
+/**
+ * RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED
+ *
+ * Whether uicc applications are enabled.
+ *
+ * Response: a boolean of enable or not.
+ *
+ * Valid errors:
+ *  SUCCESS
+ *  RADIO_NOT_AVAILABLE
+ *  SIM_ABSENT
+ *  INTERNAL_ERR
+ *  REQUEST_NOT_SUPPORTED
+ */
+#define RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED 157
+
+/**
+ * RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT
+ *
+ * Whether disabling / enabling uicc applications is supported
+ *
+ * Response: a boolean of whether it's supported.
+ *
+ * Valid errors:
+ *  SUCCESS
+ *  RADIO_NOT_AVAILABLE
+ *  INTERNAL_ERR
+ */
+#define RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT 158
+
+/**
+ * Specify which bands modem's background scan must act on.
+ * If specifyChannels is true, it only scans bands specified in specifiers.
+ * If specifyChannels is false, it scans all bands.
+ *
+ * For example, CBRS is only on LTE band 48. By specifying this band,
+ * modem saves more power.
+ *
+ * Valid errors:
+ *  SUCCESS
+ *  RADIO_NOT_AVAILABLE
+ *  INTERNAL_ERR
+ *  INVALID_ARGUMENTS
+ *
+ */
+#define RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS_1_5 159
+
+/**
+ * RIL_REQUEST_START_NETWORK_SCAN5
+ *
+ * Starts a new network scan
+ *
+ * Request to start a network scan with specified radio access networks with frequency bands and/or
+ * channels.
+ *
+ * "data" is a const RIL_NetworkScanRequest *.
+ * "response" is NULL
+ *
+ * Valid errors:
+ *  SUCCESS
+ *  RADIO_NOT_AVAILABLE
+ *  DEVICE_IN_USE
+ *  INTERNAL_ERR
+ *  MODEM_ERR
+ *  INVALID_ARGUMENTS
+ *
+ */
+#define RIL_REQUEST_START_NETWORK_SCAN_1_5 160
+
 /***********************************************************************/
 
 /**
diff --git a/guest/hals/ril/libril/ril_commands.h b/guest/hals/ril/libril/ril_commands.h
index 3f45151..17cb594 100644
--- a/guest/hals/ril/libril/ril_commands.h
+++ b/guest/hals/ril/libril/ril_commands.h
@@ -170,3 +170,8 @@
     {RIL_REQUEST_SET_CARRIER_RESTRICTIONS_1_4, radio_1_5::setAllowedCarriersResponse4},
     {RIL_REQUEST_GET_CARRIER_RESTRICTIONS_1_4, radio_1_5::getAllowedCarriersResponse4},
     {RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA_1_5, radio_1_5::setSignalStrengthReportingCriteriaResponse_1_5},
+    {RIL_REQUEST_ENABLE_UICC_APPLICATIONS, radio_1_5::enableUiccApplicationsResponse},
+    {RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED, radio_1_5::areUiccApplicationsEnabledResponse},
+    {RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT, radio_1_5::canToggleUiccApplicationsEnablementResponse},
+    {RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS_1_5, radio_1_5::setSystemSelectionChannelsResponse_1_5},
+    {RIL_REQUEST_START_NETWORK_SCAN_1_5, radio_1_5::startNetworkScanResponse_1_5},
diff --git a/guest/hals/ril/libril/ril_service.cpp b/guest/hals/ril/libril/ril_service.cpp
index 9e009a5..b7b02a6 100755
--- a/guest/hals/ril/libril/ril_service.cpp
+++ b/guest/hals/ril/libril/ril_service.cpp
@@ -500,8 +500,7 @@
 
     // Methods from ::android::hardware::radio::V1_3::IRadio follow.
     Return<void> setSystemSelectionChannels(int32_t serial, bool specifyChannels,
-            const hidl_vec<::android::hardware::radio::V1_1::RadioAccessSpecifier>& specifiers)
-           ;
+            const hidl_vec<::android::hardware::radio::V1_1::RadioAccessSpecifier>& specifiers);
     Return<void> enableModem(int32_t serial, bool on);
     Return<void> getModemStackStatus(int32_t serial);
 
@@ -536,6 +535,13 @@
     Return<void> setSignalStrengthReportingCriteria_1_5(int32_t serial,
             const ::android::hardware::radio::V1_5::SignalThresholdInfo& signalThresholdInfo,
             const ::android::hardware::radio::V1_5::AccessNetwork accessNetwork);
+    Return<void> enableUiccApplications(int32_t serial, bool detach);
+    Return<void> areUiccApplicationsEnabled(int32_t serial);
+    Return<void> canToggleUiccApplicationsEnablement(int32_t serial);
+    Return<void> setSystemSelectionChannels_1_5(int32_t serial, bool specifyChannels,
+            const hidl_vec<::android::hardware::radio::V1_5::RadioAccessSpecifier>& specifiers);
+    Return<void> startNetworkScan_1_5(int32_t serial,
+            const ::android::hardware::radio::V1_5::NetworkScanRequest& request);
 };
 
 struct OemHookImpl : public IOemHook {
@@ -3164,6 +3170,98 @@
     return 0;
 }
 
+int prepareNetworkScanRequest_1_5(RIL_NetworkScanRequest &scan_request,
+    const ::android::hardware::radio::V1_5::NetworkScanRequest& request,
+    RequestInfo *pRI) {
+
+    scan_request.type = (RIL_ScanType) request.type;
+    scan_request.interval = request.interval;
+    scan_request.specifiers_length = request.specifiers.size();
+
+    int intervalLow = static_cast<int>(::android::hardware::radio::V1_2::ScanIntervalRange::MIN);
+    int intervalHigh = static_cast<int>(::android::hardware::radio::V1_2::ScanIntervalRange::MAX);
+    int maxSearchTimeLow =
+        static_cast<int>(::android::hardware::radio::V1_2::MaxSearchTimeRange::MIN);
+    int maxSearchTimeHigh =
+        static_cast<int>(::android::hardware::radio::V1_2::MaxSearchTimeRange::MAX);
+    int incrementalResultsPeriodicityRangeLow =
+        static_cast<int>(::android::hardware::radio::V1_2::IncrementalResultsPeriodicityRange::MIN);
+    int incrementalResultsPeriodicityRangeHigh =
+        static_cast<int>(::android::hardware::radio::V1_2::IncrementalResultsPeriodicityRange::MAX);
+    uint maxSpecifierSize =
+        static_cast<uint>(::android::hardware::radio::V1_2::RadioConst
+            ::RADIO_ACCESS_SPECIFIER_MAX_SIZE);
+
+    if (request.interval < intervalLow || request.interval > intervalHigh) {
+        sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+        return -1;
+    }
+    // If defined, must fall in correct range.
+    if (request.maxSearchTime != 0
+        && (request.maxSearchTime < maxSearchTimeLow
+            || request.maxSearchTime > maxSearchTimeHigh)) {
+        sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+        return -1;
+    }
+    if (request.maxSearchTime != 0
+        && (request.incrementalResultsPeriodicity < incrementalResultsPeriodicityRangeLow
+            || request.incrementalResultsPeriodicity > incrementalResultsPeriodicityRangeHigh
+            || request.incrementalResultsPeriodicity > request.maxSearchTime)) {
+        sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+        return -1;
+    }
+    if (request.specifiers.size() == 0 || request.specifiers.size() > maxSpecifierSize) {
+        sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+        return -1;
+    }
+
+    for (size_t i = 0; i < request.specifiers.size(); ++i) {
+        if (request.specifiers[i].bands.geranBands().size() > MAX_BANDS ||
+            request.specifiers[i].bands.utranBands().size() > MAX_BANDS ||
+            request.specifiers[i].bands.eutranBands().size() > MAX_BANDS ||
+            request.specifiers[i].bands.ngranBands().size() > MAX_BANDS ||
+            request.specifiers[i].channels.size() > MAX_CHANNELS) {
+            sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+            return -1;
+        }
+        const V1_5::RadioAccessSpecifier& ras_from = request.specifiers[i];
+        RIL_RadioAccessSpecifier& ras_to = scan_request.specifiers[i];
+
+        ras_to.radio_access_network = (RIL_RadioAccessNetworks) ras_from.radioAccessNetwork;
+        ras_to.channels_length = ras_from.channels.size();
+
+        std::copy(ras_from.channels.begin(), ras_from.channels.end(), ras_to.channels);
+        const std::vector<uint32_t> * bands = nullptr;
+        switch (request.specifiers[i].radioAccessNetwork) {
+            case V1_5::RadioAccessNetworks::GERAN:
+                ras_to.bands_length = ras_from.bands.geranBands().size();
+                bands = (std::vector<uint32_t> *) &ras_from.bands;
+                break;
+            case V1_5::RadioAccessNetworks::UTRAN:
+                ras_to.bands_length = ras_from.bands.utranBands().size();
+                bands = (std::vector<uint32_t> *) &ras_from.bands;
+                break;
+            case V1_5::RadioAccessNetworks::EUTRAN:
+                ras_to.bands_length = ras_from.bands.eutranBands().size();
+                bands = (std::vector<uint32_t> *) &ras_from.bands;
+                break;
+            case V1_5::RadioAccessNetworks::NGRAN:
+                ras_to.bands_length = ras_from.bands.ngranBands().size();
+                bands = (std::vector<uint32_t> *) &ras_from.bands;
+                break;
+            default:
+                sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
+                return -1;
+        }
+        // safe to copy to geran_bands because it's a union member
+        for (size_t idx = 0; idx < ras_to.bands_length; ++idx) {
+            ras_to.bands.geran_bands[idx] = (RIL_GeranBands) (*bands)[idx];
+        }
+    }
+
+    return 0;
+}
+
 // Methods from ::android::hardware::radio::V1_2::IRadio follow.
 Return<void> RadioImpl_1_5::startNetworkScan_1_2(int32_t serial,
         const ::android::hardware::radio::V1_2::NetworkScanRequest& request) {
@@ -3212,16 +3310,6 @@
     return Void();
 }
 
-Return<void> RadioImpl_1_5::setSignalStrengthReportingCriteria_1_5(int32_t /* serial */,
-        const ::android::hardware::radio::V1_5::SignalThresholdInfo& /* signalThresholdInfo */,
-        const ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */) {
-    // TODO implement
-#if VDBG
-    RLOGE("[%04d]< %s", serial, "Method is not implemented");
-#endif
-    return Void();
-}
-
 Return<void> RadioImpl_1_5::setLinkCapacityReportingCriteria(int32_t /* serial */,
         int32_t /* hysteresisMs */, int32_t /* hysteresisDlKbps */, int32_t /* hysteresisUlKbps */,
         const hidl_vec<int32_t>& /* thresholdsDownlinkKbps */,
@@ -3492,6 +3580,78 @@
     return Void();
 }
 
+// Methods from ::android::hardware::radio::IRadio::V1_5 follow.
+Return<void> RadioImpl_1_5::setSignalStrengthReportingCriteria_1_5(int32_t /* serial */,
+        const ::android::hardware::radio::V1_5::SignalThresholdInfo& /* signalThresholdInfo */,
+        const ::android::hardware::radio::V1_5::AccessNetwork /* accessNetwork */) {
+    // TODO implement
+#if VDBG
+    RLOGE("[%04d]< %s", serial, "Method is not implemented");
+#endif
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::enableUiccApplications(int32_t serial, bool enable) {
+#if VDBG
+    RLOGD("enableUiccApplications: serial %d enable %d", serial, enable);
+#endif
+    dispatchInts(serial, mSlotId, RIL_REQUEST_ENABLE_UICC_APPLICATIONS, 1, BOOL_TO_INT(enable));
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::areUiccApplicationsEnabled(int32_t serial) {
+#if VDBG
+    RLOGD("areUiccApplicationsEnabled: serial %d", serial);
+#endif
+    dispatchVoid(serial, mSlotId, RIL_REQUEST_ARE_UICC_APPLICATIONS_ENABLED);
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::canToggleUiccApplicationsEnablement(int32_t serial) {
+#if VDBG
+    RLOGD("canToggleUiccApplicationsEnablement: serial %d.", serial);
+#endif
+    dispatchVoid(serial, mSlotId, RIL_REQUEST_CAN_TOGGLE_UICC_APPLICATIONS_ENABLEMENT);
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::setSystemSelectionChannels_1_5(int32_t serial, bool /* specifyChannels */,
+        const hidl_vec<::android::hardware::radio::V1_5::RadioAccessSpecifier>& /* specifiers */) {
+#if VDBG
+    RLOGD("setSystemSelectionChannels_1_5: serial %d", serial);
+#endif
+    dispatchVoid(serial, mSlotId, RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS_1_5);
+    return Void();
+}
+
+Return<void> RadioImpl_1_5::startNetworkScan_1_5(int32_t serial,
+        const ::android::hardware::radio::V1_5::NetworkScanRequest& request) {
+#if VDBG
+    RLOGD("startNetworkScan_1_5: serial %d", serial);
+#endif
+
+    RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_START_NETWORK_SCAN_1_5);
+    if (pRI == NULL) {
+        return Void();
+    }
+
+    // TODO: implement checks for new fields.
+    // NetworkScanRequest added maxSearchTime, incrementalResults, incrementalResultsPeriodicity and
+    // mccMncs, could add more validations using request2 here.
+
+    RIL_NetworkScanRequest scan_request = {};
+
+    if (prepareNetworkScanRequest_1_5(scan_request, request, pRI) < 0) {
+        return Void();
+    }
+
+    CALL_ONREQUEST(RIL_REQUEST_START_NETWORK_SCAN_1_5, &scan_request, sizeof(scan_request), pRI,
+            mSlotId);
+
+    return Void();
+}
+
+// OEM hook methods:
 Return<void> OemHookImpl::setResponseFunctions(
         const ::android::sp<IOemHookResponse>& oemHookResponseParam,
         const ::android::sp<IOemHookIndication>& oemHookIndicationParam) {
@@ -7693,6 +7853,115 @@
     return 0;
 }
 
+int radio_1_5::enableUiccApplicationsResponse(int slotId, int responseType, int serial,
+                                    RIL_Errno e, void* /* response */, size_t responseLen) {
+#if VDBG
+    RLOGD("%s(): %d", __FUNCTION__, serial);
+#endif
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, responseType, e);
+
+    // If we don't have a radio service, there's nothing we can do
+    if (radioService[slotId]->mRadioResponseV1_5 == NULL) {
+        RLOGE("%s: radioService[%d]->mRadioResponseV1_5 == NULL", __FUNCTION__, slotId);
+        return 0;
+    }
+
+    Return<void> retStatus =
+            radioService[slotId]->mRadioResponseV1_5->enableUiccApplicationsResponse(
+            responseInfo);
+    radioService[slotId]->checkReturnStatus(retStatus);
+    return 0;
+}
+
+int radio_1_5::areUiccApplicationsEnabledResponse(int slotId, int responseType, int serial,
+                                        RIL_Errno e, void* response, size_t responseLen) {
+#if VDBG
+    RLOGD("%s(): %d", __FUNCTION__, serial);
+#endif
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, responseType, e);
+
+    // If we don't have a radio service, there's nothing we can do
+    if (radioService[slotId]->mRadioResponseV1_5 == NULL) {
+        RLOGE("%s: radioService[%d]->mRadioResponseV1_5 == NULL", __FUNCTION__, slotId);
+        return 0;
+    }
+
+    bool enable = false;
+    if (response == NULL || responseLen != sizeof(bool)) {
+        RLOGE("isSimDetachedFromNetwork Invalid response.");
+    } else {
+        enable = (*((bool *) response));
+    }
+
+    Return<void> retStatus =
+            radioService[slotId]->mRadioResponseV1_5->areUiccApplicationsEnabledResponse(
+            responseInfo, enable);
+    radioService[slotId]->checkReturnStatus(retStatus);
+    return 0;
+}
+
+int radio_1_5::canToggleUiccApplicationsEnablementResponse(int slotId, int responseType,
+                                                       int serial, RIL_Errno e,
+                                                       void *response, size_t responseLen) {
+#if VDBG
+    RLOGD("%s(): %d", __FUNCTION__, serial);
+#endif
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, responseType, e);
+
+    // If we don't have a radio service, there's nothing we can do
+    if (radioService[slotId]->mRadioResponseV1_5 == NULL) {
+        RLOGE("%s: radioService[%d]->mRadioResponseV1_5 == NULL", __FUNCTION__, slotId);
+        return 0;
+    }
+
+    Return<void> retStatus =
+            radioService[slotId]->mRadioResponseV1_5->canToggleUiccApplicationsEnablementResponse(
+            responseInfo, true);
+    radioService[slotId]->checkReturnStatus(retStatus);
+    return 0;
+}
+
+int radio_1_5::setSystemSelectionChannelsResponse_1_5(int slotId, int responseType, int serial,
+                                        RIL_Errno e, void* /* response */, size_t responseLen) {
+#if VDBG
+    RLOGD("%s(): %d", __FUNCTION__, serial);
+#endif
+    RadioResponseInfo responseInfo = {};
+    populateResponseInfo(responseInfo, serial, responseType, e);
+
+    // If we don't have a radio service, there's nothing we can do
+    if (radioService[slotId]->mRadioResponseV1_5 == NULL) {
+        RLOGE("%s: radioService[%d]->mRadioResponseV1_5 == NULL", __FUNCTION__, slotId);
+        return 0;
+    }
+
+    Return<void> retStatus =
+            radioService[slotId]->mRadioResponseV1_5->setSystemSelectionChannelsResponse_1_5(
+            responseInfo);
+    radioService[slotId]->checkReturnStatus(retStatus);
+    return 0;
+}
+
+int radio_1_5::startNetworkScanResponse_1_5(int slotId, int responseType, int serial, RIL_Errno e,
+                                    void *response, size_t responseLen) {
+#if VDBG
+    RLOGD("startNetworkScanResponse_1_5: serial %d", serial);
+#endif
+    if (radioService[slotId]->mRadioResponseV1_5 != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        Return<void> retStatus
+                = radioService[slotId]->mRadioResponseV1_5->startNetworkScanResponse_1_5(responseInfo);
+        radioService[slotId]->checkReturnStatus(retStatus);
+    } else {
+        RLOGE("startNetworkScanResponse: radioService[%d]->mRadioResponseV1_5 == NULL", slotId);
+    }
+    return 0;
+}
+
 /***************************************************************************************************
  * INDICATION FUNCTIONS
  * The below function handle unsolicited messages coming from the Radio
@@ -9483,7 +9752,7 @@
 
         radioService[i] = new RadioImpl_1_5;
         radioService[i]->mSlotId = i;
-        RLOGD("registerService: starting android::hardware::radio::V1_4::IRadio %s for slot %d",
+        RLOGD("registerService: starting android::hardware::radio::V1_5::IRadio %s for slot %d",
                 serviceNames[i], i);
         android::status_t status = radioService[i]->registerAsService(serviceNames[i]);
         assert(status == android::OK);
diff --git a/guest/hals/ril/libril/ril_service.h b/guest/hals/ril/libril/ril_service.h
index b6ba3e4..814768c 100644
--- a/guest/hals/ril/libril/ril_service.h
+++ b/guest/hals/ril/libril/ril_service.h
@@ -207,6 +207,10 @@
                              int responseType, int serial, RIL_Errno e, void *response,
                              size_t responselen);
 
+int startNetworkScanResponse_1_5(int slotId,
+                             int responseType, int serial, RIL_Errno e, void *response,
+                             size_t responselen);
+
 int stopNetworkScanResponse(int slotId,
                             int responseType, int serial, RIL_Errno e, void *response,
                             size_t responselen);
@@ -768,6 +772,10 @@
                                int responseType, int serial, RIL_Errno e,
                                void *response, size_t responseLen);
 
+int setSystemSelectionChannelsResponse_1_5(int slotId,
+                               int responseType, int serial, RIL_Errno e,
+                               void *response, size_t responseLen);
+
 int setAllowedCarriersResponse4(int slotId,
                                 int responseType, int serial, RIL_Errno e,
                                 void *response,
@@ -782,6 +790,18 @@
                           int responseType, int serial, RIL_Errno e,
                           void *response, size_t responselen);
 
+int enableUiccApplicationsResponse(int slotId,
+                                 int responseType, int serial, RIL_Errno e,
+                                 void *response, size_t responselen);
+
+int areUiccApplicationsEnabledResponse(int slotId,
+                                     int responseType, int serial, RIL_Errno e,
+                                     void *response, size_t responselen);
+
+int canToggleUiccApplicationsEnablementResponse(int slotId,
+                                            int responseType, int serial, RIL_Errno e,
+                                            void *response, size_t responselen);
+
 pthread_rwlock_t * getRadioServiceRwlock(int slotId);
 
 void setNitzTimeReceived(int slotId, long timeReceived);
diff --git a/guest/libs/remoter/Android.mk b/guest/libs/remoter/Android.mk
deleted file mode 100644
index bb0dba7..0000000
--- a/guest/libs/remoter/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    remoter_framework_pkt.cpp
-LOCAL_MODULE := libcuttlefish_remoter_framework
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    liblog \
-    libcuttlefish_fs
-LOCAL_C_INCLUDES := \
-    device/google/cuttlefish_common
-LOCAL_CFLAGS := $(VSOC_VERSION_CFLAGS)
-LOCAL_VENDOR_MODULE := true
-include $(BUILD_STATIC_LIBRARY)
-
-
diff --git a/guest/libs/remoter/remoter_framework_pkt.cpp b/guest/libs/remoter/remoter_framework_pkt.cpp
deleted file mode 100644
index 68564f1..0000000
--- a/guest/libs/remoter/remoter_framework_pkt.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "guest/libs/remoter/remoter_framework_pkt.h"
-
-void remoter_connect(cvd::SharedFD* dest) {
-  *dest = cvd::SharedFD::SocketLocalClient(
-      "remoter", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-  if ((*dest)->IsOpen()) {
-    ALOGE("Failed to connect to remoter (%s)", (*dest)->StrError());
-  } else {
-#ifdef DEBUG_CONNECTIONS
-    ALOGI("Connected to remoter (socket %d)", socket);
-#endif
-  }
-}
-
-int remoter_connect() {
-  int socket = socket_local_client(
-      "remoter", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-  if (socket < 0) {
-    ALOGE("Failed to connect to remoter (%s)", strerror(errno));
-    return -1;
-  } else {
-#ifdef DEBUG_CONNECTIONS
-    ALOGI("Connected to remoter (socket %d)", socket);
-#endif
-  }
-  return socket;
-}
-
diff --git a/guest/libs/remoter/remoter_framework_pkt.h b/guest/libs/remoter/remoter_framework_pkt.h
deleted file mode 100644
index f9e9db8..0000000
--- a/guest/libs/remoter/remoter_framework_pkt.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <stdlib.h>
-
-#include <cutils/sockets.h>
-#include <log/log.h>
-
-#include "common/libs/fs/shared_fd.h"
-
-// #define DEBUG_CONNECTIONS
-
-/*
- * Packet structures for commands sent to the remoter from the GCE HAL.
- * This is a private protocol between the HAL and the remoter.
- */
-
-static const size_t kSensorNameMaxLen = 64;
-// Don't use PATH_MAX here because it would increate the size of every
-// packet that we send to the remoter.
-static const size_t kScreenRecordFilePathMaxLen = 128;
-static const size_t kUnixSocketPathMaxLen = 128;
-
-struct remoter_request_packet {
-  /* Length of the packet in bytes. */
-  uint32_t length;
-
-  /* Operation to perform. */
-  uint8_t operation;
-
-  /* Set to '1' if a response packet is desired */
-  uint8_t send_response;
-
-  /* Operation arguments. */
-  union {
-    /* Arguments for the frame buffer 'post' operation. */
-    struct {
-      /* Y offset in the double-buffer where this frame starts. */
-      uint32_t y_offset;
-    } fb_post_params;
-    /* Arguments for the frame buffer 'update rect' operation. */
-    struct {
-      uint32_t left;
-      uint32_t top;
-      uint32_t width;
-      uint32_t height;
-    } fb_update_rect_params;
-    struct {
-      uint32_t type;
-      bool enabled;
-      int64_t delay_ns;
-      int handle;
-    } sensor_state_params;
-    struct {
-      char filepath[kScreenRecordFilePathMaxLen];
-    } screenrecord_params;
-    struct {
-      char unix_socket[kUnixSocketPathMaxLen];
-    } hal_ready_params;
-  } params;
-} __attribute__((packed));
-
-enum {
-  kRemoterHALReady = 1,
-  kRemoterSensorState
-};
-
-/*
- * If 'send_response' is set in a request then the remoter will respond
- * with the following structure.
- */
-struct remoter_response_packet {
-  uint32_t length;
-  uint8_t status;
-  union {
-    struct {
-      /* Number of 'struct sensor_list_element_packet's to follow */
-      uint8_t num_sensors;
-    } sensor_list_data;
-  } data;
-} __attribute__((packed));
-
-struct sensor_list_element_packet {
-  int handle;
-  int type;
-  char name[kSensorNameMaxLen];
-  char vendor[kSensorNameMaxLen];
-  int version;
-  float max_range;
-  float resolution;
-  float power;
-} __attribute__((packed));
-
-enum {
-  kResponseStatusOk = 1,
-  kResponseStatusFailed
-};
-
-static inline void remoter_request_packet_init(
-    struct remoter_request_packet* pkt, uint8_t operation,
-    uint8_t send_response) {
-  memset(pkt, 0, sizeof(*pkt));
-  pkt->length = sizeof(*pkt);
-  pkt->operation = operation;
-  pkt->send_response = send_response;
-}
-
-static inline void remoter_response_packet_init(
-    struct remoter_response_packet* pkt, uint8_t status) {
-  memset(pkt, 0, sizeof(*pkt));
-  pkt->length = sizeof(*pkt);
-  pkt->status = status;
-}
-
-void remoter_connect(cvd::SharedFD* dest);
-int remoter_connect();
-
-static inline int remoter_read_request(
-    const cvd::SharedFD& socket,
-    struct remoter_request_packet* request) {
-  int len;
-  int remaining_data;
-  /* Packets start with a 4 byte length (which includes the length). */
-
-  if ((len = socket->Read(request, sizeof(request->length))) < 0) {
-    ALOGE("%s: Failed to read remoter request (%s)",
-          __FUNCTION__, socket->StrError());
-    return -1;
-  } else if (len == 0) {
-    return 0;
-  } else if (len != sizeof(request->length)) {
-    ALOGE("%s: Failed to read remoter request (Short read)", __FUNCTION__);
-    return -1;
-  }
-
-  /* Extra paranoia. */
-  if (request->length != sizeof(*request)) {
-    ALOGE("%s: Malformed remoter request", __FUNCTION__);
-    return -1;
-  }
-  remaining_data = request->length - sizeof(request->length);
-  uint8_t* cursor = ((uint8_t*)request) + sizeof(request->length);
-  if ((len = socket->Read(cursor, remaining_data)) < 0) {
-    ALOGE("%s: Failed to read remoter request (%s)",
-          __FUNCTION__, socket->StrError());
-    return -1;
-  } else if (len == 0) {
-    return 0;
-  } else if (len != (int) remaining_data) {
-    ALOGE("%s: Failed to read remoter request (Short read)", __FUNCTION__);
-    return -1;
-  }
-  return 1;
-}
-
-static inline int remoter_read_response(
-    int socket, struct remoter_response_packet* response) {
-  int len;
-  int remaining_data;
-  /* Packets start with a 4 byte length (which includes the length). */
-
-#ifdef DEBUG_CONNECTIONS
-  ALOGI("remoter_read_response(): socket %d, length length = %d", socket,
-        sizeof(response->length));
-#endif
-  if ((len = TEMP_FAILURE_RETRY(
-      read(socket, response, sizeof(response->length)))) < 0) {
-    ALOGE("%s: Failed to read remoter response (%s)",
-          __FUNCTION__, strerror(errno));
-    return -1;
-  } else if (len == 0) {
-    return 0;
-  } else if (len != sizeof(response->length)) {
-    ALOGE("%s: Failed to read remoter response (Short read)", __FUNCTION__);
-    return -1;
-  }
-
-  /* Extra paranoia. */
-  if (response->length != sizeof(*response)) {
-    ALOGE("%s: Malformed remoter response", __FUNCTION__);
-    return -1;
-  }
-  remaining_data = response->length - sizeof(response->length);
-  uint8_t* cursor = ((uint8_t*)response) + sizeof(response->length);
-#ifdef DEBUG_CONNECTIONS
-  ALOGI("remoter_read_request(): socket %d, data length = %d",
-        socket, remaining_data);
-#endif
-  if ((len = TEMP_FAILURE_RETRY(read(socket, cursor, remaining_data))) < 0) {
-    ALOGE("%s: Failed to read remoter response (%s)",
-          __FUNCTION__, strerror(errno));
-    return -1;
-  } else if (len == 0) {
-    return 0;
-  } else if (len != (int) remaining_data) {
-    ALOGE("%s: Failed to read remoter response (Short read)", __FUNCTION__);
-    return -1;
-  }
-  return 1;
-}
-
-static inline int remoter_send_request(
-    int socket, struct remoter_request_packet* request) {
-#ifdef DEBUG_CONNECTIONS
-  ALOGI(
-      "remoter_send_request(): socket %d, length %u", socket, sizeof(*request));
-#endif
-  int len = TEMP_FAILURE_RETRY(write(socket, request, sizeof(*request)));
-  if (len <= 0) {
-    ALOGE("Failed to write request to remoter (%s)", strerror(errno));
-    return -1;
-  } else if (len != sizeof(*request)) {
-    ALOGE("Failed to write request to remoter (short write)");
-    return -1;
-  }
-  return 0;
-}
-
-static inline int remoter_send_response(
-    const cvd::SharedFD& socket,
-    struct remoter_response_packet* response) {
-  int len = socket->Write(response, sizeof(*response));
-  if (len <=0) {
-    ALOGE("%s: Failed to send response to remoter (%s)",
-          __FUNCTION__, strerror(errno));
-    return -1;
-  }
-  return 0;
-}
-
-static inline int remoter_do_single_request_with_socket(
-    int socket, struct remoter_request_packet* request,
-    struct remoter_response_packet* response) {
-
-  if (request->send_response && !response) {
-    ALOGE("%s: Request specifies a response but no response ptr set",
-          __FUNCTION__);
-    return -1;
-  } else if (!request->send_response && response) {
-    ALOGE("%s: Request specifies no response but has response ptr set",
-          __FUNCTION__);
-    return -1;
-  }
-
-  if (remoter_send_request(socket, request) < 0) {
-    return -1;
-  }
-
-  if (response && (remoter_read_response(socket, response) <= 0)) {
-    return -1;
-  }
-  return 0;
-}
-
-static inline int remoter_do_single_request(
-    struct remoter_request_packet* request,
-    struct remoter_response_packet* response) {
-  int socket;
-  if ((socket = remoter_connect()) < 0) {
-    return -1;
-  }
-
-  if (remoter_do_single_request_with_socket(socket, request, response) < 0) {
-    close(socket);
-    return -1;
-  }
-  close(socket);
-  return 0;
-}
-
diff --git a/guest/monitoring/tombstone_transmit/Android.bp b/guest/monitoring/tombstone_transmit/Android.bp
index 500a5f4..2e0af82 100644
--- a/guest/monitoring/tombstone_transmit/Android.bp
+++ b/guest/monitoring/tombstone_transmit/Android.bp
@@ -21,10 +21,12 @@
     static_libs: [
         "libcuttlefish_fs_product",
         "libgflags",
-        "liblog",
         "libbase",
         "libcutils",
     ],
+    shared_libs: [
+        "liblog",
+    ],
     stl: "libc++_static",
     header_libs: [
         "cuttlefish_glog_product",
diff --git a/host/commands/assemble_cvd/data_image.cc b/host/commands/assemble_cvd/data_image.cc
index 70fe0ef..82dad14 100644
--- a/host/commands/assemble_cvd/data_image.cc
+++ b/host/commands/assemble_cvd/data_image.cc
@@ -15,9 +15,9 @@
 const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2;
 
 bool ForceFsckImage(const char* data_image) {
-  int fsck_status = cvd::execute({"/sbin/fsck.f2fs", "-y", "-f", data_image});
+  int fsck_status = cvd::execute({"/sbin/e2fsck", "-y", "-f", data_image});
   if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) {
-    LOG(ERROR) << "`fsck.f2fs -y -f " << data_image << "` failed with code "
+    LOG(ERROR) << "`e2fsck -y -f " << data_image << "` failed with code "
                << fsck_status;
     return false;
   }
@@ -46,9 +46,9 @@
     if (!fsck_success) {
       return false;
     }
-    int resize_status = cvd::execute({"/sbin/resize.f2fs", data_image});
+    int resize_status = cvd::execute({"/sbin/resize2fs", data_image});
     if (resize_status != 0) {
-      LOG(ERROR) << "`resize.f2fs " << data_image << "` failed with code "
+      LOG(ERROR) << "`resize2fs " << data_image << "` failed with code "
                  << resize_status;
       return false;
     }
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index be6c6d1..2d6007e 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -34,7 +34,7 @@
             "'always_create'.");
 DEFINE_int32(blank_data_image_mb, 0,
              "The size of the blank data image to generate, MB.");
-DEFINE_string(blank_data_image_fmt, "f2fs",
+DEFINE_string(blank_data_image_fmt, "ext4",
               "The fs format for the blank data image. Used with mkfs.");
 DEFINE_string(qemu_gdb, "",
               "Debug flag to pass to qemu. e.g. -qemu_gdb=tcp::1234");
@@ -55,16 +55,8 @@
 DEFINE_string(extra_kernel_cmdline, "",
               "Additional flags to put on the kernel command line");
 DEFINE_int32(loop_max_part, 7, "Maximum number of loop partitions");
-DEFINE_string(androidboot_console, "ttyS1",
-              "Console device for the Android framework");
-DEFINE_string(
-    hardware_name, "",
-    "The codename of the device's hardware, one of {cutf_ivsh, cutf_cvm}");
-DEFINE_string(guest_security, "selinux",
-              "The security module to use in the guest");
 DEFINE_bool(guest_enforce_security, true,
-            "Whether to run in enforcing mode (non permissive). Ignored if "
-            "-guest_security is empty.");
+            "Whether to run in enforcing mode (non permissive).");
 DEFINE_bool(guest_audit_security, true,
             "Whether to log security audits.");
 DEFINE_string(boot_image, "",
@@ -205,13 +197,6 @@
 const std::string kInitramfsImg = "initramfs.img";
 const std::string kRamdiskConcatExt = ".concat";
 
-template<typename S, typename T>
-static std::string concat(const S& s, const T& t) {
-  std::ostringstream os;
-  os << s << t;
-  return os.str();
-}
-
 bool ResolveInstanceFiles() {
   if (FLAGS_system_image_dir.empty()) {
     LOG(ERROR) << "--system_image_dir must be specified.";
@@ -277,7 +262,8 @@
   }
   tmp_config_obj.set_vm_manager(FLAGS_vm_manager);
   tmp_config_obj.set_gpu_mode(FLAGS_gpu_mode);
-  if (!vm_manager::VmManager::ConfigureGpuMode(&tmp_config_obj)) {
+  if (vm_manager::VmManager::ConfigureGpuMode(tmp_config_obj.vm_manager(),
+                                              tmp_config_obj.gpu_mode()).empty()) {
     LOG(ERROR) << "Invalid gpu_mode=" << FLAGS_gpu_mode <<
                " does not work with vm_manager=" << FLAGS_vm_manager;
     return false;
@@ -285,8 +271,6 @@
   tmp_config_obj.set_wayland_socket(FLAGS_wayland_socket);
   tmp_config_obj.set_x_display(FLAGS_x_display);
 
-  vm_manager::VmManager::ConfigureBootDevices(&tmp_config_obj);
-
   tmp_config_obj.set_serial_number(FLAGS_serial_number);
 
   tmp_config_obj.set_cpus(FLAGS_cpus);
@@ -323,89 +307,22 @@
 
   auto ramdisk_path = tmp_config_obj.PerInstancePath("ramdisk.img");
   auto vendor_ramdisk_path = tmp_config_obj.PerInstancePath("vendor_ramdisk.img");
-  bool use_ramdisk = boot_image_unpacker.HasRamdiskImage();
-  if (!use_ramdisk) {
-    LOG(INFO) << "No ramdisk present; assuming system-as-root build";
-    ramdisk_path = "";
-    vendor_ramdisk_path = "";
+  if (!boot_image_unpacker.HasRamdiskImage()) {
+    LOG(INFO) << "A ramdisk is required, but the boot image did not have one.";
+    return false;
   }
 
-  tmp_config_obj.add_kernel_cmdline(boot_image_unpacker.kernel_cmdline());
+  tmp_config_obj.set_boot_image_kernel_cmdline(boot_image_unpacker.kernel_cmdline());
+  tmp_config_obj.set_loop_max_part(FLAGS_loop_max_part);
+  tmp_config_obj.set_guest_enforce_security(FLAGS_guest_enforce_security);
+  tmp_config_obj.set_guest_audit_security(FLAGS_guest_audit_security);
+  tmp_config_obj.set_extra_kernel_cmdline(FLAGS_extra_kernel_cmdline);
 
-  if (use_ramdisk) {
-    if (FLAGS_composite_disk.empty()) {
-      tmp_config_obj.add_kernel_cmdline("androidboot.fstab_name=fstab");
-    } else {
-      tmp_config_obj.add_kernel_cmdline("androidboot.fstab_name=fstab.composite");
-    }
-  } else {
-    if (FLAGS_composite_disk.empty()) {
-      tmp_config_obj.add_kernel_cmdline("root=/dev/vda");
-      tmp_config_obj.add_kernel_cmdline("androidboot.fstab_name=fstab");
-    } else {
-      tmp_config_obj.add_kernel_cmdline("root=/dev/vda1");
-      tmp_config_obj.add_kernel_cmdline("androidboot.fstab_name=fstab.composite");
-    }
-  }
-
-  tmp_config_obj.add_kernel_cmdline("init=/init");
-  tmp_config_obj.add_kernel_cmdline(
-      concat("androidboot.serialno=", FLAGS_serial_number));
-  tmp_config_obj.add_kernel_cmdline("mac80211_hwsim.radios=0");
-  tmp_config_obj.add_kernel_cmdline(concat("androidboot.lcd_density=", FLAGS_dpi));
-  tmp_config_obj.add_kernel_cmdline(
-      concat("androidboot.setupwizard_mode=", FLAGS_setupwizard_mode));
-  tmp_config_obj.add_kernel_cmdline(concat("loop.max_part=", FLAGS_loop_max_part));
-  if (!FLAGS_androidboot_console.empty()) {
-    tmp_config_obj.add_kernel_cmdline(
-        concat("androidboot.console=", FLAGS_androidboot_console));
-  }
-  if (!FLAGS_hardware_name.empty()) {
-    tmp_config_obj.add_kernel_cmdline(
-        concat("androidboot.hardware=", FLAGS_hardware_name));
-  }
-  if (FLAGS_logcat_mode == cvd::kLogcatVsockMode) {
-    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_logcat_port=",
-                                             FLAGS_logcat_vsock_port));
-  }
-  tmp_config_obj.add_kernel_cmdline(concat("androidboot.cuttlefish_config_server_port=",
-                                           FLAGS_config_server_port));
-  tmp_config_obj.set_hardware_name(FLAGS_hardware_name);
-  if (!FLAGS_guest_security.empty()) {
-    tmp_config_obj.add_kernel_cmdline(concat("security=", FLAGS_guest_security));
-    if (FLAGS_guest_enforce_security) {
-      tmp_config_obj.add_kernel_cmdline("enforcing=1");
-    } else {
-      tmp_config_obj.add_kernel_cmdline("enforcing=0");
-      tmp_config_obj.add_kernel_cmdline("androidboot.selinux=permissive");
-    }
-    if (FLAGS_guest_audit_security) {
-      tmp_config_obj.add_kernel_cmdline("audit=1");
-    } else {
-      tmp_config_obj.add_kernel_cmdline("audit=0");
-    }
-  }
-  if (FLAGS_extra_kernel_cmdline.size()) {
-    tmp_config_obj.add_kernel_cmdline(FLAGS_extra_kernel_cmdline);
-  }
-
-  if (!FLAGS_composite_disk.empty()) {
-    tmp_config_obj.set_virtual_disk_paths({FLAGS_composite_disk});
-  } else {
-    tmp_config_obj.set_virtual_disk_paths({
-      FLAGS_super_image,
-      FLAGS_data_image,
-      FLAGS_cache_image,
-      FLAGS_metadata_image,
-    });
-  }
+  tmp_config_obj.set_virtual_disk_paths({FLAGS_composite_disk});
 
   tmp_config_obj.set_ramdisk_image_path(ramdisk_path);
   tmp_config_obj.set_vendor_ramdisk_image_path(vendor_ramdisk_path);
 
-  // Boot as recovery is set so normal boot needs to be forced every boot
-  tmp_config_obj.add_kernel_cmdline("androidboot.force_normal_boot=1");
-
   std::string discovered_ramdisk = fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
   std::string foreign_ramdisk = FLAGS_initramfs_path.size () ? FLAGS_initramfs_path : discovered_ramdisk;
   if (foreign_kernel.size() && !foreign_ramdisk.size()) {
@@ -484,32 +401,13 @@
   tmp_config_obj.set_logcat_vsock_port(FLAGS_logcat_vsock_port);
   tmp_config_obj.set_config_server_port(FLAGS_config_server_port);
   tmp_config_obj.set_frames_vsock_port(FLAGS_frames_vsock_port);
-  if (tmp_config_obj.enable_vnc_server()) {
-    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_frames_port=",
-                                             FLAGS_frames_vsock_port));
-  }
 
   tmp_config_obj.set_enable_tombstone_receiver(FLAGS_enable_tombstone_receiver);
   tmp_config_obj.set_tombstone_receiver_port(FLAGS_tombstone_receiver_port);
   tmp_config_obj.set_tombstone_receiver_binary(FLAGS_tombstone_receiver_binary);
-  if (FLAGS_enable_tombstone_receiver) {
-    tmp_config_obj.add_kernel_cmdline("androidboot.tombstone_transmit=1");
-    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_tombstone_port="
-      ,FLAGS_tombstone_receiver_port));
-    // TODO (b/128842613) populate a cid flag to read the host CID during
-    // runtime
-  } else {
-    tmp_config_obj.add_kernel_cmdline("androidboot.tombstone_transmit=0");
-  }
 
   tmp_config_obj.set_touch_socket_port(FLAGS_touch_server_port);
   tmp_config_obj.set_keyboard_socket_port(FLAGS_keyboard_server_port);
-  if (FLAGS_vm_manager == vm_manager::QemuManager::name()) {
-    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_touch_port=",
-                                             FLAGS_touch_server_port));
-    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_keyboard_port=",
-                                             FLAGS_keyboard_server_port));
-  }
 
   tmp_config_obj.set_use_bootloader(FLAGS_use_bootloader);
   tmp_config_obj.set_bootloader(FLAGS_bootloader);
@@ -518,16 +416,6 @@
       tmp_config_obj.set_boot_slot(FLAGS_boot_slot);
   }
 
-  if (!FLAGS_use_bootloader) {
-    std::string slot_suffix;
-    if (FLAGS_boot_slot.empty()) {
-      slot_suffix = "_a";
-    } else {
-      slot_suffix = "_" + FLAGS_boot_slot;
-    }
-    tmp_config_obj.add_kernel_cmdline("androidboot.slot_suffix=" + slot_suffix);
-  }
-
   tmp_config_obj.set_cuttlefish_env_path(GetCuttlefishEnvPath());
 
   auto config_file = GetConfigFilePath(tmp_config_obj);
@@ -553,9 +441,6 @@
   SetCommandLineOptionWithMode("instance_dir",
                                default_instance_dir.c_str(),
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
-  // TODO(b/144111429): Consolidate to one hardware name
-  SetCommandLineOptionWithMode("hardware_name", "cutf_cvm",
-                               google::FlagSettingMode::SET_FLAGS_DEFAULT);
   // TODO(b/144119457) Use the serial port.
   SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode,
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
@@ -573,9 +458,6 @@
   SetCommandLineOptionWithMode("x_display",
                                getenv("DISPLAY"),
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
-  // TODO(b/144111429): Consolidate to one hardware name
-  SetCommandLineOptionWithMode("hardware_name", "cutf_cvm",
-                               google::FlagSettingMode::SET_FLAGS_DEFAULT);
   SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode,
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
 }
@@ -682,9 +564,6 @@
 }
 
 bool ShouldCreateCompositeDisk() {
-  if (FLAGS_composite_disk.empty()) {
-    return false;
-  }
   if (FLAGS_vm_manager == vm_manager::CrosvmManager::name()) {
     // The crosvm implementation is very fast to rebuild but also more brittle due to being split
     // into multiple files. The QEMU implementation is slow to build, but completely self-contained
diff --git a/host/commands/run_cvd/main.cc b/host/commands/run_cvd/main.cc
index fdd909d..486a0db 100644
--- a/host/commands/run_cvd/main.cc
+++ b/host/commands/run_cvd/main.cc
@@ -277,6 +277,80 @@
   return config.PerInstancePath("cuttlefish_config.json");
 }
 
+template<typename T>
+void AppendVector(std::vector<T>* destination, const std::vector<T>& source) {
+  destination->insert(destination->end(), source.begin(), source.end());
+}
+
+template<typename S, typename T>
+static std::string concat(const S& s, const T& t) {
+  std::ostringstream os;
+  os << s << t;
+  return os.str();
+}
+
+std::vector<std::string> KernelCommandLineFromConfig(const vsoc::CuttlefishConfig& config) {
+  std::vector<std::string> kernel_cmdline;
+
+  AppendVector(&kernel_cmdline, config.boot_image_kernel_cmdline());
+  AppendVector(&kernel_cmdline,
+               vm_manager::VmManager::ConfigureGpuMode(config.vm_manager(), config.gpu_mode()));
+  AppendVector(&kernel_cmdline, vm_manager::VmManager::ConfigureBootDevices(config.vm_manager()));
+
+  kernel_cmdline.push_back(concat("androidboot.serialno=", config.serial_number()));
+  kernel_cmdline.push_back(concat("androidboot.lcd_density=", config.dpi()));
+  if (config.logcat_mode() == cvd::kLogcatVsockMode) {
+    kernel_cmdline.push_back(concat("androidboot.vsock_logcat_port=", config.logcat_vsock_port()));
+  }
+  if (config.enable_vnc_server()) {
+    kernel_cmdline.push_back(concat("androidboot.vsock_frames_port=", config.frames_vsock_port()));
+  }
+  if (config.enable_tombstone_receiver()) {
+    kernel_cmdline.push_back("androidboot.tombstone_transmit=1");
+    kernel_cmdline.push_back(concat(
+        "androidboot.vsock_tombstone_port=",
+        config.tombstone_receiver_port()));
+    // TODO (b/128842613) populate a cid flag to read the host CID during
+    // runtime
+  } else {
+    kernel_cmdline.push_back("androidboot.tombstone_transmit=0");
+  }
+  kernel_cmdline.push_back(concat(
+      "androidboot.cuttlefish_config_server_port=", config.config_server_port()));
+  kernel_cmdline.push_back(concat(
+      "androidboot.setupwizard_mode=", config.setupwizard_mode()));
+  if (!config.use_bootloader()) {
+    std::string slot_suffix;
+    if (config.boot_slot().empty()) {
+      slot_suffix = "_a";
+    } else {
+      slot_suffix = "_" + config.boot_slot();
+    }
+    kernel_cmdline.push_back(concat("androidboot.slot_suffix=", slot_suffix));
+  }
+  if (config.vm_manager() == vm_manager::QemuManager::name()) {
+    kernel_cmdline.push_back(concat("androidboot.vsock_touch_port=", config.touch_socket_port()));
+    kernel_cmdline.push_back(concat(
+        "androidboot.vsock_keyboard_port=", config.keyboard_socket_port()));
+  }
+  kernel_cmdline.push_back(concat("loop.max_part=", config.loop_max_part()));
+  if (config.guest_enforce_security()) {
+    kernel_cmdline.push_back("enforcing=1");
+  } else {
+    kernel_cmdline.push_back("enforcing=0");
+    kernel_cmdline.push_back("androidboot.selinux=permissive");
+  }
+  if (config.guest_audit_security()) {
+    kernel_cmdline.push_back("audit=1");
+  } else {
+    kernel_cmdline.push_back("audit=0");
+  }
+
+  AppendVector(&kernel_cmdline, config.extra_kernel_cmdline());
+
+  return kernel_cmdline;
+}
+
 }  // namespace
 
 int main(int argc, char** argv) {
@@ -416,7 +490,10 @@
       *config, &process_monitor, GetOnSubprocessExitCallback(*config));
 
   // Start the guest VM
-  auto vmm_commands = vm_manager->StartCommands(frontend_enabled);
+  vm_manager->WithFrontend(frontend_enabled);
+  auto kernel_args = KernelCommandLineFromConfig(*config);
+  vm_manager->WithKernelCommandLine(android::base::Join(kernel_args, " "));
+  auto vmm_commands = vm_manager->StartCommands();
   for (auto& vmm_cmd: vmm_commands) {
       process_monitor.StartSubprocess(std::move(vmm_cmd),
                                       GetOnSubprocessExitCallback(*config));
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 7a65525..3b223d9 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -26,6 +26,7 @@
 #include <sstream>
 #include <string>
 
+#include <android-base/strings.h>
 #include <glog/logging.h>
 #include <json/json.h>
 
@@ -72,7 +73,6 @@
 const char* const kGpuMode = "gpu_mode";
 const char* const kWaylandSocket = "wayland_socket";
 const char* const kXDisplay = "x_display";
-const char* kHardwareName = "hardware_name";
 const char* kDeviceTitle = "device_title";
 
 const char* kCpus = "cpus";
@@ -88,7 +88,6 @@
 const char* kDecompressedKernelImagePath = "decompressed_kernel_image_path";
 const char* kDecompressKernel = "decompress_kernel";
 const char* kGdbFlag = "gdb_flag";
-const char* kKernelCmdline = "kernel_cmdline";
 const char* kRamdiskImagePath = "ramdisk_image_path";
 const char* kInitramfsPath = "initramfs_path";
 const char* kFinalRamdiskPath = "final_ramdisk_path";
@@ -160,6 +159,12 @@
 const char* kTouchSocketPort = "touch_socket_port";
 const char* kKeyboardSocketPort = "keyboard_socket_port";
 
+const char* kLoopMaxPart = "loop_max_part";
+const char* kGuestEnforceSecurity = "guest_enforce_security";
+const char* kGuestAuditSecurity = "guest_audit_security";
+const char* kBootImageKernelCmdline = "boot_image_kernel_cmdline";
+const char* kExtraKernelCmdline = "extra_kernel_cmdline";
+
 }  // namespace
 
 namespace vsoc {
@@ -213,13 +218,6 @@
   (*dictionary_)[kXDisplay] = address;
 }
 
-std::string CuttlefishConfig::hardware_name() const {
-  return (*dictionary_)[kHardwareName].asString();
-}
-void CuttlefishConfig::set_hardware_name(const std::string& name) {
-  (*dictionary_)[kHardwareName] = name;
-}
-
 std::string CuttlefishConfig::serial_number() const {
   return (*dictionary_)[kSerialNumber].asString();
 }
@@ -307,49 +305,6 @@
   (*dictionary_)[kGdbFlag] = device;
 }
 
-std::set<std::string> CuttlefishConfig::kernel_cmdline() const {
-  std::set<std::string> args_set;
-  auto args_json_obj = (*dictionary_)[kKernelCmdline];
-  std::transform(args_json_obj.begin(), args_json_obj.end(),
-                 std::inserter(args_set, args_set.begin()),
-                 [](const Json::Value& it) { return it.asString(); });
-  return args_set;
-}
-void CuttlefishConfig::set_kernel_cmdline(
-    const std::set<std::string>& kernel_cmdline) {
-  Json::Value args_json_obj(Json::arrayValue);
-  for (const auto& arg : kernel_cmdline) {
-    args_json_obj.append(arg);
-  }
-  (*dictionary_)[kKernelCmdline] = args_json_obj;
-}
-void CuttlefishConfig::add_kernel_cmdline(
-    const std::set<std::string>& extra_args) {
-  std::set<std::string> cmdline = kernel_cmdline();
-  for (const auto& arg : extra_args) {
-    if (cmdline.count(arg)) {
-      LOG(ERROR) << "Kernel argument " << arg << " is duplicated";
-    }
-    cmdline.insert(arg);
-  }
-  set_kernel_cmdline(cmdline);
-}
-void CuttlefishConfig::add_kernel_cmdline(const std::string& kernel_cmdline) {
-  std::stringstream args_stream(kernel_cmdline);
-  std::set<std::string> kernel_cmdline_set;
-  using is_iter = std::istream_iterator<std::string>;
-  std::copy(is_iter(args_stream), is_iter(),
-            std::inserter(kernel_cmdline_set, kernel_cmdline_set.begin()));
-  add_kernel_cmdline(kernel_cmdline_set);
-}
-std::string CuttlefishConfig::kernel_cmdline_as_string() const {
-  auto args_set = kernel_cmdline();
-  std::stringstream output;
-  std::copy(args_set.begin(), args_set.end(),
-            std::ostream_iterator<std::string>(output, " "));
-  return output.str();
-}
-
 std::string CuttlefishConfig::ramdisk_image_path() const {
   return (*dictionary_)[kRamdiskImagePath].asString();
 }
@@ -859,6 +814,57 @@
   return (*dictionary_)[kKeyboardSocketPort].asInt();
 }
 
+void CuttlefishConfig::set_loop_max_part(int loop_max_part) {
+  (*dictionary_)[kLoopMaxPart] = loop_max_part;
+}
+int CuttlefishConfig::loop_max_part() const {
+  return (*dictionary_)[kLoopMaxPart].asInt();
+}
+
+void CuttlefishConfig::set_guest_enforce_security(bool guest_enforce_security) {
+  (*dictionary_)[kGuestEnforceSecurity] = guest_enforce_security;
+}
+bool CuttlefishConfig::guest_enforce_security() const {
+  return (*dictionary_)[kGuestEnforceSecurity].asBool();
+}
+
+void CuttlefishConfig::set_guest_audit_security(bool guest_audit_security) {
+  (*dictionary_)[kGuestAuditSecurity] = guest_audit_security;
+}
+bool CuttlefishConfig::guest_audit_security() const {
+  return (*dictionary_)[kGuestAuditSecurity].asBool();
+}
+
+void CuttlefishConfig::set_boot_image_kernel_cmdline(std::string boot_image_kernel_cmdline) {
+  Json::Value args_json_obj(Json::arrayValue);
+  for (const auto& arg : android::base::Split(boot_image_kernel_cmdline, " ")) {
+    args_json_obj.append(arg);
+  }
+  (*dictionary_)[kBootImageKernelCmdline] = args_json_obj;
+}
+std::vector<std::string> CuttlefishConfig::boot_image_kernel_cmdline() const {
+  std::vector<std::string> cmdline;
+  for (const Json::Value& arg : (*dictionary_)[kBootImageKernelCmdline]) {
+    cmdline.push_back(arg.asString());
+  }
+  return cmdline;
+}
+
+void CuttlefishConfig::set_extra_kernel_cmdline(std::string extra_cmdline) {
+  Json::Value args_json_obj(Json::arrayValue);
+  for (const auto& arg : android::base::Split(extra_cmdline, " ")) {
+    args_json_obj.append(arg);
+  }
+  (*dictionary_)[kExtraKernelCmdline] = extra_cmdline;
+}
+std::vector<std::string> CuttlefishConfig::extra_kernel_cmdline() const {
+  std::vector<std::string> cmdline;
+  for (const Json::Value& arg : (*dictionary_)[kExtraKernelCmdline]) {
+    cmdline.push_back(arg.asString());
+  }
+  return cmdline;
+}
+
 // Creates the (initially empty) config object and populates it with values from
 // the config file if the CUTTLEFISH_CONFIG_FILE env variable is present.
 // Returns nullptr if there was an error loading from file
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index a920e76..bf3d231 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -86,9 +86,6 @@
   std::string x_display() const;
   void set_x_display(const std::string& address);
 
-  std::string hardware_name() const;
-  void set_hardware_name(const std::string& name);
-
   std::string serial_number() const;
   void set_serial_number(const std::string& serial_number);
 
@@ -137,12 +134,6 @@
   bool use_unpacked_kernel() const;
   void set_use_unpacked_kernel(bool use_unpacked_kernel);
 
-  std::set<std::string> kernel_cmdline() const;
-  void set_kernel_cmdline(const std::set<std::string>& kernel_cmdline);
-  void add_kernel_cmdline(const std::string& arg);
-  void add_kernel_cmdline(const std::set<std::string>& kernel_cmdline);
-  std::string kernel_cmdline_as_string() const;
-
   std::string gdb_flag() const;
   void set_gdb_flag(const std::string& gdb);
 
@@ -327,6 +318,21 @@
   void set_keyboard_socket_port(int keyboard_socket_port);
   int keyboard_socket_port() const;
 
+  void set_loop_max_part(int loop_max_part);
+  int loop_max_part() const;
+
+  void set_guest_enforce_security(bool guest_enforce_security);
+  bool guest_enforce_security() const;
+
+  void set_guest_audit_security(bool guest_audit_security);
+  bool guest_audit_security() const;
+
+  void set_boot_image_kernel_cmdline(std::string boot_image_kernel_cmdline);
+  std::vector<std::string> boot_image_kernel_cmdline() const;
+
+  void set_extra_kernel_cmdline(std::string extra_cmdline);
+  std::vector<std::string> extra_kernel_cmdline() const;
+
  private:
   std::unique_ptr<Json::Value> dictionary_;
 
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index f132bac..6ed43c2 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -22,6 +22,7 @@
 #include <string>
 #include <vector>
 
+#include <android-base/strings.h>
 #include <glog/logging.h>
 
 #include "common/libs/utils/network.h"
@@ -62,39 +63,39 @@
 
 const std::string CrosvmManager::name() { return "crosvm"; }
 
-bool CrosvmManager::ConfigureGpu(vsoc::CuttlefishConfig* config) {
+std::vector<std::string> CrosvmManager::ConfigureGpu(const std::string& gpu_mode) {
   // Override the default HAL search paths in all cases. We do this because
   // the HAL search path allows for fallbacks, and fallbacks in conjunction
   // with properities lead to non-deterministic behavior while loading the
   // HALs.
-  if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl) {
-    config->add_kernel_cmdline("androidboot.hardware.gralloc=minigbm");
-    config->add_kernel_cmdline("androidboot.hardware.hwcomposer=drm_minigbm");
-    config->add_kernel_cmdline("androidboot.hardware.egl=mesa");
-    return true;
+  if (gpu_mode == vsoc::kGpuModeDrmVirgl) {
+    return {
+      "androidboot.hardware.gralloc=minigbm",
+      "androidboot.hardware.hwcomposer=drm_minigbm",
+      "androidboot.hardware.egl=mesa",
+    };
   }
-  if (config->gpu_mode() == vsoc::kGpuModeGuestSwiftshader) {
-    config->add_kernel_cmdline("androidboot.hardware.gralloc=cutf_ashmem");
-    config->add_kernel_cmdline(
-        "androidboot.hardware.hwcomposer=cutf_cvm_ashmem");
-    config->add_kernel_cmdline("androidboot.hardware.egl=swiftshader");
-    config->add_kernel_cmdline("androidboot.hardware.vulkan=pastel");
-    return true;
+  if (gpu_mode == vsoc::kGpuModeGuestSwiftshader) {
+    return {
+        "androidboot.hardware.gralloc=cutf_ashmem",
+        "androidboot.hardware.hwcomposer=cutf_cvm_ashmem",
+        "androidboot.hardware.egl=swiftshader",
+        "androidboot.hardware.vulkan=pastel",
+    };
   }
-  return false;
+  return {};
 }
 
-void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
+std::vector<std::string> CrosvmManager::ConfigureBootDevices() {
   // PCI domain 0, bus 0, device 1, function 0
   // TODO There is no way to control this assignment with crosvm (yet)
-  config->add_kernel_cmdline(
-      "androidboot.boot_devices=pci0000:00/0000:00:01.0");
+  return { "androidboot.boot_devices=pci0000:00/0000:00:01.0" };
 }
 
 CrosvmManager::CrosvmManager(const vsoc::CuttlefishConfig* config)
     : VmManager(config) {}
 
-std::vector<cvd::Command> CrosvmManager::StartCommands(bool with_frontend) {
+std::vector<cvd::Command> CrosvmManager::StartCommands() {
   cvd::Command crosvm_cmd(config_->crosvm_binary(), [](cvd::Subprocess* proc) {
     auto stopped = Stop();
     if (stopped) {
@@ -120,13 +121,13 @@
   crosvm_cmd.AddParameter("--null-audio");
   crosvm_cmd.AddParameter("--mem=", config_->memory_mb());
   crosvm_cmd.AddParameter("--cpus=", config_->cpus());
-  crosvm_cmd.AddParameter("--params=", config_->kernel_cmdline_as_string());
+  crosvm_cmd.AddParameter("--params=", kernel_cmdline_);
   for (const auto& disk : config_->virtual_disk_paths()) {
     crosvm_cmd.AddParameter("--rwdisk=", disk);
   }
   crosvm_cmd.AddParameter("--socket=", GetControlSocketPath(config_));
 
-  if (with_frontend) {
+  if (frontend_enabled_) {
     crosvm_cmd.AddParameter("--single-touch=", config_->touch_socket_path(),
                             ":", config_->x_res(), ":", config_->y_res());
     crosvm_cmd.AddParameter("--keyboard=", config_->keyboard_socket_path());
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index 74ed8c5..848f2ae 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include <string>
+#include <vector>
+
 #include "host/libs/vm_manager/vm_manager.h"
 
 #include "common/libs/fs/shared_fd.h"
@@ -28,13 +31,13 @@
  public:
   static const std::string name();
   static bool EnsureInstanceDirExists(const std::string& instance_dir);
-  static bool ConfigureGpu(vsoc::CuttlefishConfig* config);
-  static void ConfigureBootDevices(vsoc::CuttlefishConfig* config);
+  static std::vector<std::string> ConfigureGpu(const std::string& gpu_mode);
+  static std::vector<std::string> ConfigureBootDevices();
 
   CrosvmManager(const vsoc::CuttlefishConfig* config);
   virtual ~CrosvmManager() = default;
 
-  std::vector<cvd::Command> StartCommands(bool with_frontend) override;
+  std::vector<cvd::Command> StartCommands() override;
 };
 
 }  // namespace vm_manager
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index b40be87..45e3003 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -30,6 +30,7 @@
 #include <thread>
 #include <vector>
 
+#include <android-base/strings.h>
 #include <glog/logging.h>
 
 #include "common/libs/fs/shared_select.h"
@@ -100,33 +101,32 @@
 
 const std::string QemuManager::name() { return "qemu_cli"; }
 
-bool QemuManager::ConfigureGpu(vsoc::CuttlefishConfig *config) {
-  if (config->gpu_mode() != vsoc::kGpuModeGuestSwiftshader) {
-    return false;
+std::vector<std::string> QemuManager::ConfigureGpu(const std::string& gpu_mode) {
+  if (gpu_mode != vsoc::kGpuModeGuestSwiftshader) {
+    return {};
   }
   // Override the default HAL search paths in all cases. We do this because
   // the HAL search path allows for fallbacks, and fallbacks in conjunction
   // with properities lead to non-deterministic behavior while loading the
   // HALs.
-  config->add_kernel_cmdline("androidboot.hardware.gralloc=cutf_ashmem");
-  config->add_kernel_cmdline(
-      "androidboot.hardware.hwcomposer=cutf_cvm_ashmem");
-  config->add_kernel_cmdline("androidboot.hardware.egl=swiftshader");
-  config->add_kernel_cmdline("androidboot.hardware.vulkan=pastel");
-  return true;
+  return {
+      "androidboot.hardware.gralloc=cutf_ashmem",
+      "androidboot.hardware.hwcomposer=cutf_cvm_ashmem",
+      "androidboot.hardware.egl=swiftshader",
+      "androidboot.hardware.vulkan=pastel",
+  };
 }
 
-void QemuManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
+std::vector<std::string> QemuManager::ConfigureBootDevices() {
   // PCI domain 0, bus 0, device 3, function 0
   // This is controlled with 'addr=0x3' in cf_qemu.sh
-  config->add_kernel_cmdline(
-    "androidboot.boot_devices=pci0000:00/0000:00:03.0");
+  return { "androidboot.boot_devices=pci0000:00/0000:00:03.0" };
 }
 
 QemuManager::QemuManager(const vsoc::CuttlefishConfig* config)
   : VmManager(config) {}
 
-std::vector<cvd::Command> QemuManager::StartCommands(bool /*with_frontend*/) {
+std::vector<cvd::Command> QemuManager::StartCommands() {
   // Set the config values in the environment
   LogAndSetEnv("qemu_binary", config_->qemu_binary());
   LogAndSetEnv("instance_name", config_->instance_name());
@@ -137,7 +137,7 @@
   LogAndSetEnv("kernel_image_path", config_->GetKernelImageToUse());
   LogAndSetEnv("gdb_flag", config_->gdb_flag());
   LogAndSetEnv("ramdisk_image_path", config_->final_ramdisk_path());
-  LogAndSetEnv("kernel_cmdline", config_->kernel_cmdline_as_string());
+  LogAndSetEnv("kernel_cmdline", kernel_cmdline_);
   LogAndSetEnv("virtual_disk_paths", JoinString(config_->virtual_disk_paths(),
                                                 ";"));
   LogAndSetEnv("wifi_tap_name", config_->wifi_tap_name());
diff --git a/host/libs/vm_manager/qemu_manager.h b/host/libs/vm_manager/qemu_manager.h
index 9b0df49..4b04876 100644
--- a/host/libs/vm_manager/qemu_manager.h
+++ b/host/libs/vm_manager/qemu_manager.h
@@ -15,6 +15,9 @@
  */
 #pragma once
 
+#include <string>
+#include <vector>
+
 #include "host/libs/vm_manager/vm_manager.h"
 
 #include "common/libs/fs/shared_fd.h"
@@ -26,13 +29,13 @@
 class QemuManager : public VmManager {
  public:
   static const std::string name();
-  static bool ConfigureGpu(vsoc::CuttlefishConfig* config);
-  static void ConfigureBootDevices(vsoc::CuttlefishConfig* config);
+  static std::vector<std::string> ConfigureGpu(const std::string& gpu_mode);
+  static std::vector<std::string> ConfigureBootDevices();
 
   QemuManager(const vsoc::CuttlefishConfig* config);
   virtual ~QemuManager() = default;
 
-  std::vector<cvd::Command> StartCommands(bool with_frontend) override;
+  std::vector<cvd::Command> StartCommands() override;
 };
 
 }  // namespace vm_manager
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index ac5531a..2ab4157 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -48,11 +48,11 @@
               return GetManagerSingleton<QemuManager>(config);
             },
             []() { return vsoc::HostSupportsQemuCli(); },
-            [](vsoc::CuttlefishConfig* c) {
-              return QemuManager::ConfigureGpu(c);
+            [](const std::string& gpu_mode) {
+              return QemuManager::ConfigureGpu(gpu_mode);
             },
-            [](vsoc::CuttlefishConfig* c) {
-              return QemuManager::ConfigureBootDevices(c);
+            []() {
+              return QemuManager::ConfigureBootDevices();
             }
           },
         },
@@ -64,11 +64,11 @@
             },
             // Same as Qemu for the time being
             []() { return vsoc::HostSupportsQemuCli(); },
-            [](vsoc::CuttlefishConfig* c) {
-              return CrosvmManager::ConfigureGpu(c);
+            [](const std::string& gpu_mode) {
+              return CrosvmManager::ConfigureGpu(gpu_mode);
             },
-            [](vsoc::CuttlefishConfig* c) {
-              return CrosvmManager::ConfigureBootDevices(c);
+            []() {
+              return CrosvmManager::ConfigureBootDevices();
             }
           }
         }
@@ -92,20 +92,22 @@
          vm_manager_helpers_[name].support_checker();
 }
 
-bool VmManager::ConfigureGpuMode(vsoc::CuttlefishConfig* config) {
-  auto it = vm_manager_helpers_.find(config->vm_manager());
+std::vector<std::string> VmManager::ConfigureGpuMode(
+    const std::string& vmm_name, const std::string& gpu_mode) {
+  auto it = vm_manager_helpers_.find(vmm_name);
   if (it == vm_manager_helpers_.end()) {
-    return false;
+    return {};
   }
-  return it->second.configure_gpu_mode(config);
+  return it->second.configure_gpu_mode(gpu_mode);
 }
 
-void VmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
-  auto it = vm_manager_helpers_.find(config->vm_manager());
+std::vector<std::string> VmManager::ConfigureBootDevices(
+    const std::string& vmm_name) {
+  auto it = vm_manager_helpers_.find(vmm_name);
   if (it == vm_manager_helpers_.end()) {
-    return;
+    return {};
   }
-  it->second.configure_boot_devices(config);
+  return it->second.configure_boot_devices();
 }
 
 std::vector<std::string> VmManager::GetValidNames() {
@@ -154,4 +156,13 @@
   auto linux_ver_4_8 = VmManager::LinuxVersionAtLeast4_8(config_commands);
   return in_kvm && in_cvdnetwork && linux_ver_4_8;
 }
+
+void VmManager::WithFrontend(bool enabled) {
+  frontend_enabled_ = enabled;
+}
+
+void VmManager::WithKernelCommandLine(const std::string& kernel_cmdline) {
+  kernel_cmdline_ = kernel_cmdline;
+}
+
 }  // namespace vm_manager
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index 62adbf8..a14ad05 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <map>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -35,18 +36,23 @@
   static VmManager* Get(const std::string& vm_manager_name,
                         const vsoc::CuttlefishConfig* config);
   static bool IsValidName(const std::string& name);
-  static bool ConfigureGpuMode(vsoc::CuttlefishConfig* config);
-  static void ConfigureBootDevices(vsoc::CuttlefishConfig* config);
+  static std::vector<std::string> ConfigureGpuMode(
+      const std::string& vmm_name, const std::string& gpu_mode);
+  static std::vector<std::string> ConfigureBootDevices(
+      const std::string& vmm_name);
   static bool IsVmManagerSupported(const std::string& name);
   static std::vector<std::string> GetValidNames();
 
   virtual ~VmManager() = default;
 
+  virtual void WithFrontend(bool);
+  virtual void WithKernelCommandLine(const std::string&);
+
   // Starts the VMM. It will usually build a command and pass it to the
   // command_starter function, although it may start more than one. The
   // command_starter function allows to customize the way vmm commands are
   // started/tracked/etc.
-  virtual std::vector<cvd::Command> StartCommands(bool with_frontend) = 0;
+  virtual std::vector<cvd::Command> StartCommands() = 0;
 
   virtual bool ValidateHostConfiguration(
       std::vector<std::string>* config_commands) const;
@@ -59,14 +65,17 @@
   const vsoc::CuttlefishConfig* config_;
   VmManager(const vsoc::CuttlefishConfig* config);
 
+  bool frontend_enabled_;
+  std::string kernel_cmdline_;
+
  private:
   struct VmManagerHelper {
     // The singleton implementation
     std::function<VmManager*(const vsoc::CuttlefishConfig*)> builder;
     // Whether the host packages support this vm manager
     std::function<bool()> support_checker;
-    std::function<bool(vsoc::CuttlefishConfig*)> configure_gpu_mode;
-    std::function<void(vsoc::CuttlefishConfig*)> configure_boot_devices;
+    std::function<std::vector<std::string>(const std::string&)> configure_gpu_mode;
+    std::function<std::vector<std::string>()> configure_boot_devices;
   };
   // Asociates a vm manager helper to every valid vm manager name
   static std::map<std::string, VmManagerHelper> vm_manager_helpers_;