Merge cros/upstream to cros/master

Contains the following commits:
 17934810 iface-modem-3gpp-profile-manager: fix copy-paste error on tags for quarks (Maxim Anisimov)
 f00cb9f6 introspection: add Modem Simple (Dylan Van Assche)
 1e08f9ca mm-log: hiding personal info while logging (som)
 4207ee61 huawei: disable +CPOL based features in Huawei E226 (Aleksander Morgado)
 96fb4259 cinterion: add PLS63 port type hints (Konrad Zapałowicz)
 0645b70a plugins,telit: SWPKGV parsing needs more permissive regex (Carlo Lobrano)
 818b539d test,modem-helpers-telit: fix test inputs (Carlo Lobrano)
 ac243f94 sms: prevent crash if date is out of range (Carlo Lobrano)
 5c8c1136 modem-mbim: update default error when network error is out of range (som)
 e175ada2 plugins,telit: remove unnecessary after sim unlock 1s delay (Carlo Lobrano)
 7960b365 data: add example connection dispatcher (Aleksander Morgado)
 99232154 build: rename directory where fcc unlocks are kept (Aleksander Morgado)
 2dafb32d base-bearer: integrate connection status dispatcher scripts (Aleksander Morgado)
 e8612671 dispatcher-connection: new dispatcher for connection status scripts (Aleksander Morgado)
 e188a77e dispatcher-fcc-unlock: inherit from the base dispatcher object (Aleksander Morgado)
 01c8edf6 dispatcher: new generic object to handle script dispatchers (Aleksander Morgado)
 1fec1cd3 profile-manager: profile-id and apn-type check not required for user settings (som)
 19f38994 port-serial: ensure the port object is valid after BUFFER_FULL handling (Aleksander Morgado)
 210fa8bf qmi: Fall back to NAS SSP/NAS TP capabilities (Sven Schwermer)
 0fbab3c8 broadband-modem-mbim: Set InitialEPSBearer's authentication to CHAP when is UNKNOWN (Andrew Lassalle)
 97933788 bearer-properties: Match UNKNOWN auth to CHAP for loose comparison (Andrew Lassalle)
 d5805002 core: remove "all rights reserved" from copyright lines (Aleksander Morgado)
 cf7b58ce telit: reorganize common_parse_bnd_response for readability (Carlo Lobrano)
 c208d33e telit: fix AT#BND parsing for LE910C1-EUX (Carlo Lobrano)
 30a35e6d telit: detect modem model from revision (Carlo Lobrano)
 3df96a42 telit: override load revision (Carlo Lobrano)
 afd3ce86 mm-netlink: use unaligned netlink attribute length (Bjørn Mork)
 7bbf6c8a mm-netlink: only change IFF_UP flag (Bjørn Mork)
 b5a0a500 po add Dutch translation (Nathan Follens)
 ea247f7e foxconn: consolidate checks for T99W175 and T99W265 (Aleksander Morgado)
 cd2dd20b foxconn: consolidate logic deciding required update methods (Aleksander Morgado)
 b16b49f9 foxconn: consolidate logic deciding requested firmware version type (Aleksander Morgado)
 4efb5f61 foxconn: switch to use autoptr() in firmware info loading (Aleksander Morgado)
 b81680a3 foxconn: remove unneeded input bundle unref (Aleksander Morgado)
 a56f96f0 foxconn: use new qmi service(fox) to get firmware version (Freedom Liu)
 8d0d90a6 build: require libqmi 1.31.4 for FOX service support (Aleksander Morgado)
 0bc0831b build,meson: Fix udev rules and keyfiles tests (Iñigo Martínez)
 1fdc3ac7 linktop: new port type hints (Aleksander Morgado)
 e8bb90e0 cinterion: Add support for PLSx3w modems (Theodore A. Roth)
 8d95c82f shared-qmi: ignore slot status indications until initial status is known (Stephan Gerhold)
 8ab31cf0 broadband-modem-mbim: consolidate initialized SIM creation method (Aleksander Morgado)
 035879da broadband-modem-mbim: update sim-type and esim-status of inactive slot (som)
 c447785f telit: fix mode 'any' setting with AT commands (Daniele Palmas)
 598d99b5 test,modem-helpers: add test for the EM9191 COPS=? response (Aleksander Morgado)
 2c8cfb47 modem-helpers: improve and fix COPS=? numeric fields parsing (Aleksander Morgado)
 5ba67aff modem-helpers: act given in COPS=? may have more than one digit (Aleksander Morgado)

BUG=None
TEST=None

Change-Id: I35bd0d5bbdda0ff3e270a93b3d5d652b11d7bb26
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..3f3efb9
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+ejcaruso@chromium.org
+pholla@chromium.org
+andrewlassalle@chromium.org
+madhavadas@google.com
+nmarupaka@google.com
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
new file mode 100644
index 0000000..51d8dd6
--- /dev/null
+++ b/PRESUBMIT.cfg
@@ -0,0 +1,9 @@
+# This sample config file disables all of the ChromiumOS source style checks.
+# Comment out the disable-flags for any checks you want to leave enabled.
+
+[Hook Overrides]
+stray_whitespace_check: false
+long_line_check: false
+cros_license_check: false
+tab_check: false
+
diff --git a/README.chromium b/README.chromium
new file mode 100644
index 0000000..10c881e
--- /dev/null
+++ b/README.chromium
@@ -0,0 +1,20 @@
+DESCRIPTION="Broadband modem support daemon (new API)"
+HOMEPAGE="http://projects.gnome.org/NetworkManager/"
+UPSTREAM_REPO="git://anongit.freedesktop.org/ModemManager/ModemManager"
+LOCAL_GIT_REPO="https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next.git"
+UPSTREAM_BUGSDB="https://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager"
+LOCAL_BUGSDB="http://crosbug.com"
+LICENSE="GPLv2"
+LICENSE_FILE="COPYING"
+
+Description:
+
+ModemManager provides a DBus interface to control broadband modem
+devices. The intended user is a network manager program, such as
+NetworkManager, flimflam, or shill.
+
+This repository mirrors the 0.6-api branch of the upstream repository
+while it is under active development as a branch.
+
+Local changes should be minimal, but support for particular modems may
+make it here before they make it upstream.
diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c
index 5483e56..0b74246 100644
--- a/cli/mmcli-output.c
+++ b/cli/mmcli-output.c
@@ -946,6 +946,9 @@
     if ((aux = mm_3gpp_profile_get_profile_name (profile)) != NULL)
         g_ptr_array_add (array, g_strdup_printf ("  profile name: %s", aux));
 
+    if ((aux = mm_3gpp_profile_get_profile_name (profile)) != NULL)
+        g_ptr_array_add (array, g_strdup_printf ("    profile name: %s", aux));
+
     if ((aux = mm_3gpp_profile_get_apn (profile)) != NULL)
         g_ptr_array_add (array, g_strdup_printf ("  apn: %s", aux));
 
diff --git a/plugins/fibocom/77-mm-fibocom-port-types.rules b/plugins/fibocom/77-mm-fibocom-port-types.rules
index 544dc25..3ab3ad1 100644
--- a/plugins/fibocom/77-mm-fibocom-port-types.rules
+++ b/plugins/fibocom/77-mm-fibocom-port-types.rules
@@ -81,4 +81,10 @@
 ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="07", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
 ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="08", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
 
+# ChromeOS specific configuration
+# The MBIM port alone is sufficient for 3GPP related functionalities.
+# The AT channels are used by modemfwd for firmware update related managed,
+# mark them as ignored by ModemManager to avoid perturbations.
+ACTION=="add|change|move", SUBSYSTEMS=="tty", ENV{ID_VENDOR_ID}=="2cb7", ENV{ID_MM_PORT_IGNORE}="1"
+
 LABEL="mm_fibocom_port_types_end"
diff --git a/plugins/qcom-soc/77-mm-qcom-soc.rules b/plugins/qcom-soc/77-mm-qcom-soc.rules
index 9719f96..8320a85 100644
--- a/plugins/qcom-soc/77-mm-qcom-soc.rules
+++ b/plugins/qcom-soc/77-mm-qcom-soc.rules
@@ -37,4 +37,7 @@
 # flag all rpmsg ports under this plugin as candidate
 KERNEL=="rpmsg*", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1"
 
+# TODO(b/175305412): flag rmnet_data0 port under this plugin as candidate.
+KERNEL=="rmnet_data0", SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1"
+
 LABEL="mm_qcom_soc_end"
diff --git a/plugins/tests/test-fixture.c b/plugins/tests/test-fixture.c
index 29eb8d5..ac2d3e6 100644
--- a/plugins/tests/test-fixture.c
+++ b/plugins/tests/test-fixture.c
@@ -142,7 +142,7 @@
             break;
 
         /* Blocking wait */
-        g_assert_cmpuint (wait_time, <=, 20);
+        g_assert_cmpuint (wait_time, <=, 120);
         wait_time++;
         sleep (1);
     }
diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c
index 4f5bba2..143345e 100644
--- a/src/mm-bearer-mbim.c
+++ b/src/mm-bearer-mbim.c
@@ -418,6 +418,9 @@
 
         /* Build IPv4 config */
         if (ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4 ||
+#if defined SUPPORT_MBIM_IPV6_WITH_IPV4_ROAMING //TODO(b/183029202): Remove hacks before merging to upstream
+            ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV6 ||
+#endif
             ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4V6 ||
             ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6) {
             gboolean address_set = FALSE;
@@ -556,11 +559,14 @@
              * otherwise use DHCP to indicate the missing ones should be
              * retrieved from SLAAC or DHCPv6.
              */
+#if defined SUPPORT_MBIM_IPV6_WITH_IPV4_ROAMING //TODO(b/183029202): Remove hacks before merging to upstream
+            mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
+#else
             if (address_set && gateway_set && dns_set)
                 mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
             else
                 mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
-
+#endif
             /* We requested IPv6, but it wasn't reported as activated. If there is no IPv6 address
              * provided by the modem, we assume the IPv6 bearer wasn't truly activated */
             if (!address_set &&
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index 22d774f..20c5d81 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -40,6 +40,9 @@
 
 #define GLOBAL_PACKET_DATA_HANDLE 0xFFFFFFFF
 
+/* TODO(b/175305412): Use rmnet_data0 as the only link. */
+#define CHROMEOS_USE_RMNET_DATA0_HACK 1
+
 struct _MMBearerQmiPrivate {
     /* Cancellables available during a connection attempt */
     GCancellable *ongoing_connect_user_cancellable;
@@ -581,7 +584,9 @@
     }
 
     if (ctx->link_name) {
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
         mm_port_qmi_cleanup_link (ctx->qmi, ctx->link_name, ctx->mux_id, NULL, NULL);
+#endif
         g_free (ctx->link_name);
     }
     g_clear_object (&ctx->link);
@@ -1733,12 +1738,26 @@
         /* if muxing has been enabled in the port, we need to create a new link
          * interface. */
         if (MM_PORT_QMI_DAP_IS_SUPPORTED_QMAP (ctx->dap)) {
+#ifdef CHROMEOS_USE_RMNET_DATA0_HACK
+            g_autoptr (MMBaseModem) modem = NULL;
+
+            g_object_get (ctx->self,
+                          MM_BASE_BEARER_MODEM, &modem,
+                          NULL);
+            g_assert (modem);
+
+            mm_obj_dbg (self, "Forcing rmnet_data0 link");
+            ctx->link_name = g_strdup ("rmnet_data0");
+            ctx->mux_id = 1;
+            ctx->link = mm_base_modem_peek_port (modem, ctx->link_name);
+#else
             mm_port_qmi_setup_link (ctx->qmi,
                                     ctx->data,
                                     ctx->link_prefix_hint,
                                     (GAsyncReadyCallback) setup_link_ready,
                                     task);
             return;
+#endif
         }
         ctx->step++;
         /* fall through */
@@ -2395,11 +2414,13 @@
             g_assert (self->priv->qmi);
             /* Link is disconnected; update the state */
             mm_port_set_connected (self->priv->link, FALSE);
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
             mm_port_qmi_cleanup_link (self->priv->qmi,
                                       mm_port_get_device (self->priv->link),
                                       self->priv->mux_id,
                                       NULL,
                                       NULL);
+#endif
             g_clear_object (&self->priv->link);
         }
         self->priv->mux_id = QMI_DEVICE_MUX_ID_UNBOUND;
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 3dc547e..25df8ab 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -1522,7 +1522,6 @@
         case MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED:
         case MBIM_SUBSCRIBER_READY_STATE_INITIALIZED:
         case MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED:
-        case MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE:
             /* Don't set error */
             break;
         case MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED:
@@ -1534,6 +1533,7 @@
             break;
         case MBIM_SUBSCRIBER_READY_STATE_FAILURE:
         case MBIM_SUBSCRIBER_READY_STATE_NOT_ACTIVATED:
+        case MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE:
         default:
             error = mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE, self);
             break;
@@ -1564,10 +1564,9 @@
         return;
     }
 
-    /* Initialized */
+    /* Initialized but locked? */
     if (ready_state == MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED ||
-        ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED ||
-        ready_state == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE) {
+        ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED) {
         MbimMessage *message;
 
         /* Query which lock is to unlock */
@@ -8193,7 +8192,11 @@
      * the backoff index set to the current index of modem
      */
     config_state = g_new (MbimSarConfigState, 1);
+#if defined MBIM_FIBOCOM_SAR_HACK //TODO(b/188002987): Remove hacks before merging to upstream
+    config_state->antenna_index = 0;
+#else
     config_state->antenna_index = 0xFFFFFFFF;
+#endif
     config_state->backoff_index = mm_iface_modem_sar_get_power_level (_self);
 
     message = mbim_message_ms_sar_config_set_new (MBIM_SAR_CONTROL_MODE_OS,
@@ -8267,7 +8270,11 @@
      * the backoff index set to the input power level
      */
     config_state = g_new (MbimSarConfigState, 1);
+#if defined MBIM_FIBOCOM_SAR_HACK //TODO(b/188002987): Remove hacks before merging to upstream
+    config_state->antenna_index = 0;
+#else
     config_state->antenna_index = 0xFFFFFFFF;
+#endif
     config_state->backoff_index = power_level;
 
     task = g_task_new (self, NULL, callback, user_data);
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 91d3a8f..d4341ca 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -40,6 +40,7 @@
 #include "mm-iface-modem-messaging.h"
 #include "mm-iface-modem-location.h"
 #include "mm-iface-modem-firmware.h"
+#include "mm-iface-modem-sar.h"
 #include "mm-iface-modem-signal.h"
 #include "mm-iface-modem-oma.h"
 #include "mm-shared-qmi.h"
@@ -62,6 +63,7 @@
 static void iface_modem_oma_init (MMIfaceModemOma *iface);
 static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
 static void iface_modem_signal_init (MMIfaceModemSignal *iface);
+static void iface_modem_sar_init (MMIfaceModemSar *iface);
 static void shared_qmi_init (MMSharedQmi *iface);
 
 static MMIfaceModemLocation  *iface_modem_location_parent;
@@ -78,10 +80,13 @@
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SAR, iface_modem_sar_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_OMA, iface_modem_oma_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QMI, shared_qmi_init))
 
+/* TODO(b/175305412): Use rmnet_data0 as the only link. */
+#define CHROMEOS_USE_RMNET_DATA0_HACK 1
 struct _MMBroadbandModemQmiPrivate {
     /* Cached device IDs, retrieved by the modem interface when loading device
      * IDs, and used afterwards in the 3GPP and CDMA interfaces. */
@@ -109,6 +114,13 @@
     /* Index of the WDS profile used as initial EPS bearer */
     guint16 default_attach_pdn;
 
+    /* The WDS profile for the initial EPS bearer is owned by ModemManager
+     * and can be modified */
+    gboolean mm_owned_attach_pdn;
+
+    /* The current PDN list in the modem */
+    GArray *current_pdn_list;
+
     /* Support for the APN type mask in profiles */
     gboolean apn_type_not_supported;
 
@@ -169,6 +181,9 @@
     gboolean profile_manager_unsolicited_events_enabled;
     gboolean profile_manager_unsolicited_events_setup;
     guint refresh_indication_id;
+
+    /* SAR Operation */
+    gboolean is_sar_supported;
 };
 
 /*****************************************************************************/
@@ -7990,6 +8005,259 @@
     return mm_sms_qmi_new (MM_BASE_MODEM (self));
 }
 
+
+/*****************************************************************************/
+
+/* Check support (SAR interface) */
+
+static gboolean
+sar_check_support_finish (MMIfaceModemSar *self,
+                          GAsyncResult    *res,
+                          GError         **error)
+{
+    return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+sar_check_support (MMIfaceModemSar    *_self,
+                   GAsyncReadyCallback callback,
+                   gpointer            user_data)
+{
+    MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+    GTask               *task;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    /* If SAR service is available, assume sar state is OS */
+    if (!mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+                                    QMI_SERVICE_SAR,
+                                    MM_PORT_QMI_FLAG_DEFAULT,
+                                    NULL)) {
+        self->priv->is_sar_supported = FALSE;
+    } else
+        self->priv->is_sar_supported = TRUE;
+
+    mm_obj_dbg (self, "SAR capabilities %s", self->priv->is_sar_supported ? "supported" : "not supported");
+    g_task_return_boolean (task, self->priv->is_sar_supported);
+    g_object_unref (task);
+}
+
+static gboolean
+sar_load_state_finish (MMIfaceModemSar *self,
+                       GAsyncResult    *res,
+                       gboolean        *out_state,
+                       GError         **error)
+{
+    GError   *inner_error = NULL;
+    gboolean  result;
+
+    result = g_task_propagate_boolean (G_TASK (res), &inner_error);
+    if (inner_error) {
+        g_propagate_error (error, inner_error);
+        return FALSE;
+    }
+
+    if (out_state)
+        *out_state = result;
+    return TRUE;
+}
+
+static void
+sar_load_state (MMIfaceModemSar *_self,
+                GAsyncReadyCallback callback,
+                gpointer user_data)
+{
+    MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+    GTask               *task;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    mm_obj_dbg (self, "SAR enabled %s", self->priv->is_sar_supported ? "yes" : "no");
+    g_task_return_boolean (task, self->priv->is_sar_supported);
+    g_object_unref (task);
+}
+
+static gboolean
+sar_load_power_level_finish (MMIfaceModemSar *self,
+                             GAsyncResult    *res,
+                             guint           *out_power_level,
+                             GError          **error)
+{
+    gssize result;
+
+    result = g_task_propagate_int(G_TASK (res), error);
+    if (result < 0)
+        return FALSE;
+
+    *out_power_level = (guint) result;
+    return TRUE;
+}
+
+static void
+sar_load_power_level_ready (QmiClientSar *client,
+                            GAsyncResult *res,
+                            GTask        *task)
+{
+    g_autoptr(QmiMessageSarRfGetStateOutput) output = NULL;
+    GError                                  *error = NULL;
+    QmiSarRfState                            rf_state;
+
+    output = qmi_client_sar_rf_get_state_finish (client, res, &error);
+    if (output &&
+        qmi_message_sar_rf_get_state_output_get_result (output, &error) &&
+        qmi_message_sar_rf_get_state_output_get_state (output, &rf_state, &error)) {
+            g_task_return_int (task, rf_state);
+    } else
+        g_task_return_error (task, error);
+
+    g_object_unref (task);
+}
+
+static void
+sar_load_power_level (MMIfaceModemSar    *_self,
+                      GAsyncReadyCallback callback,
+                      gpointer            user_data)
+{
+    MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+    GTask               *task;
+    QmiClient           *client = NULL;
+
+    if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+                                      QMI_SERVICE_SAR, &client,
+                                      callback, user_data))
+        return;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    qmi_client_sar_rf_get_state (
+        QMI_CLIENT_SAR (client),
+        NULL,
+        5,
+        NULL,
+        (GAsyncReadyCallback)sar_load_power_level_ready,
+        task);
+}
+
+static gboolean
+sar_enable_finish (MMIfaceModemSar *self,
+                   GAsyncResult    *res,
+                   GError         **error)
+{
+     return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+sar_enable_ready (QmiClientSar *client,
+                  GAsyncResult *res,
+                  GTask        *task)
+{
+    g_autoptr(QmiMessageSarRfSetStateOutput) output = NULL;
+    GError                                  *error = NULL;
+
+    output = qmi_client_sar_rf_set_state_finish (client, res, &error);
+    if (output &&
+        qmi_message_sar_rf_set_state_output_get_result (output, &error)) {
+            g_task_return_boolean (task, TRUE);
+    } else
+        g_task_return_error (task, error);
+
+    g_object_unref (task);
+}
+
+
+static void
+sar_enable (MMIfaceModemSar    *_self,
+            gboolean            enable,
+            GAsyncReadyCallback callback,
+            gpointer            user_data)
+{
+    MMBroadbandModemQmi                    *self = MM_BROADBAND_MODEM_QMI (_self);
+    g_autoptr(QmiMessageSarRfSetStateInput) input = NULL;
+    GTask                                  *task;
+    QmiClient                              *client = NULL;
+    GError                                 *error = NULL;
+
+    if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+                                      QMI_SERVICE_SAR, &client,
+                                      callback, user_data))
+        return;
+
+    task = g_task_new (self, NULL, callback, user_data);
+    input = qmi_message_sar_rf_set_state_input_new ();
+    qmi_message_sar_rf_set_state_input_set_state (
+                input,
+                0,
+                &error);
+
+    qmi_client_sar_rf_set_state (
+        QMI_CLIENT_SAR (client),
+        input,
+        5,
+        NULL,
+        (GAsyncReadyCallback)sar_enable_ready,
+        task);
+}
+
+
+static gboolean
+sar_set_power_level_finish (MMIfaceModemSar *self,
+                            GAsyncResult    *res,
+                            GError         **error)
+{
+     return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+sar_set_power_level_ready (QmiClientSar *client,
+                           GAsyncResult *res,
+                           GTask        *task)
+{
+    g_autoptr(QmiMessageSarRfSetStateOutput) output = NULL;
+    GError                                  *error = NULL;
+
+    output = qmi_client_sar_rf_set_state_finish (client, res, &error);
+    if (output &&
+        qmi_message_sar_rf_set_state_output_get_result (output, &error)) {
+            g_task_return_boolean (task, TRUE);
+    } else
+        g_task_return_error (task, error);
+
+    g_object_unref (task);
+}
+
+
+static void
+sar_set_power_level (MMIfaceModemSar    *_self,
+                     guint               power_level,
+                     GAsyncReadyCallback callback,
+                     gpointer            user_data)
+{
+    MMBroadbandModemQmi                    *self = MM_BROADBAND_MODEM_QMI (_self);
+    g_autoptr(QmiMessageSarRfSetStateInput) input = NULL;
+    GTask                                  *task;
+    QmiClient                              *client = NULL;
+    GError                                 *error = NULL;
+
+    if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+                                      QMI_SERVICE_SAR, &client,
+                                      callback, user_data))
+        return;
+
+    task = g_task_new (self, NULL, callback, user_data);
+    input = qmi_message_sar_rf_set_state_input_new ();
+    qmi_message_sar_rf_set_state_input_set_state (
+                input,
+                power_level,
+                &error);
+    qmi_client_sar_rf_set_state (
+        QMI_CLIENT_SAR (client),
+        input,
+        5,
+        NULL,
+        (GAsyncReadyCallback)sar_set_power_level_ready,
+        task);
+}
+
 /*****************************************************************************/
 /* Location capabilities loading (Location interface) */
 
@@ -10478,20 +10746,26 @@
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FIRST,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LOAD_POWER_STATE,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_DOWN,
+    SET_INITIAL_EPS_BEARER_SETTINGS_STEP_HANDLE_APP_PROFILE,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE,
+    SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LAST_SETTING,
 } SetInitialEpsBearerSettingsStep;
 
 typedef struct {
     SetInitialEpsBearerSettingsStep  step;
+    QmiClientWds                    *client;
     MM3gppProfile                   *profile;
     MMModemPowerState                power_state;
+    gboolean                         setting_mm_owned_pdn;
+    gboolean                         update_lte_attach_pdn;
 } SetInitialEpsBearerSettingsContext;
 
 static void
 set_initial_eps_bearer_settings_context_free (SetInitialEpsBearerSettingsContext *ctx)
 {
+    g_clear_object (&ctx->client);
     g_clear_object (&ctx->profile);
     g_slice_free (SetInitialEpsBearerSettingsContext, ctx);
 }
@@ -10528,6 +10802,67 @@
 }
 
 static void
+set_initial_eps_bearer_set_lte_attach_pdn_ready (QmiClientWds *client,
+                                                 GAsyncResult *res,
+                                                 GTask        *task)
+{
+    g_autoptr(QmiMessageWdsSetLteAttachPdnListOutput)  output = NULL;
+    GError                                            *error = NULL;
+    MMBroadbandModemQmi                               *self;
+    SetInitialEpsBearerSettingsContext                *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_wds_set_lte_attach_pdn_list_finish (client, res, &error);
+    if (!output) {
+        g_prefix_error (&error, "QMI operation failed: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    if (!qmi_message_wds_set_lte_attach_pdn_list_output_get_result (output, &error)) {
+        g_prefix_error (&error, "Couldn't set the LTE attach PDN list: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    self->priv->mm_owned_attach_pdn = ctx->setting_mm_owned_pdn;
+
+    ctx->step++;
+    set_initial_eps_bearer_settings_step (task);
+}
+
+static void
+set_initial_eps_bearer_set_lte_attach_pdn (GTask *task)
+{
+    g_autoptr(QmiMessageWdsSetLteAttachPdnListInput)  input = NULL;
+    MMBroadbandModemQmi                *self;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx  = g_task_get_task_data (task);
+
+    input = qmi_message_wds_set_lte_attach_pdn_list_input_new ();
+    qmi_message_wds_set_lte_attach_pdn_list_input_set_list (input,
+                                                            self->priv->current_pdn_list,
+                                                            NULL);
+
+    qmi_message_wds_set_lte_attach_pdn_list_input_set_action (input,
+                                                              QMI_WDS_ATTACH_PDN_LIST_ACTION_DETACH_OR_PDN_DISCONNECT,
+                                                              NULL);
+
+    qmi_client_wds_set_lte_attach_pdn_list (ctx->client,
+                                            input,
+                                            10,
+                                            NULL,
+                                            (GAsyncReadyCallback)set_initial_eps_bearer_set_lte_attach_pdn_ready,
+                                            task);
+}
+
+static void
 set_initial_eps_bearer_modify_profile_ready (MMIfaceModem3gppProfileManager *self,
                                              GAsyncResult                   *res,
                                              GTask                          *task)
@@ -10545,6 +10880,13 @@
         return;
     }
 
+    if (mm_3gpp_profile_get_profile_id(ctx->profile) == MM_3GPP_PROFILE_ID_UNKNOWN) {
+        // The profile was just created.
+        ctx->update_lte_attach_pdn = TRUE;
+        /* Update |default_attach_pdn| now so it can be modified in the next step. */
+        MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn = (guint16) mm_3gpp_profile_get_profile_id (stored);
+        g_array_prepend_val (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn);
+    }
     ctx->step++;
     set_initial_eps_bearer_settings_step (task);
 }
@@ -10567,6 +10909,47 @@
 }
 
 static void
+set_initial_eps_bearer_delete_mm_profile_ready (MMIfaceModem3gppProfileManager *self,
+                                                GAsyncResult                   *res,
+                                                GTask                          *task)
+{
+    GError                             *error = NULL;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!modem_3gpp_profile_manager_delete_profile_finish (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER(self), res, &error)) {
+        g_prefix_error (&error, "Couldn't delete the profile: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN;
+    ctx->update_lte_attach_pdn = TRUE;
+    MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list = g_array_remove_index (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, 0);
+    if (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list->len > 0)
+        MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn = g_array_index (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, guint16, 0);
+    set_initial_eps_bearer_settings_step (task);
+}
+
+static void
+set_initial_eps_bearer_delete_mm_profile (GTask *task)
+{
+    MMBroadbandModemQmi                *self;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx  = g_task_get_task_data (task);
+
+    modem_3gpp_profile_manager_delete_profile (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self),
+                                               ctx->profile,
+                                               "profile-id",
+                                               (GAsyncReadyCallback)set_initial_eps_bearer_delete_mm_profile_ready,
+                                               task);
+}
+
+static void
 set_initial_eps_bearer_power_down_ready (MMIfaceModem *self,
                                          GAsyncResult *res,
                                          GTask        *task)
@@ -10614,6 +10997,7 @@
 {
     SetInitialEpsBearerSettingsContext *ctx;
     MMBroadbandModemQmi                *self;
+    const gchar*                        apn_name;
 
     self = g_task_get_source_object (task);
     ctx  = g_task_get_task_data (task);
@@ -10641,11 +11025,55 @@
             ctx->step++;
             /* fall through */
 
+        case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_HANDLE_APP_PROFILE:
+            apn_name = mm_3gpp_profile_get_apn(ctx->profile);
+            ctx->update_lte_attach_pdn = FALSE;
+            mm_obj_info (self, "Set Initial eps settings: apn_name: %s", apn_name);
+            if (apn_name && g_strcmp0 (apn_name, "") != 0) {
+                ctx->setting_mm_owned_pdn = TRUE;
+                mm_3gpp_profile_set_profile_name(ctx->profile, MM_BROADBAND_MODEM_QMI_PROFILE_NAME);
+                if (self->priv->mm_owned_attach_pdn) {
+                    mm_obj_info (self, "Overriding MM owned profile %d with APN: %s.",
+                        self->priv->default_attach_pdn, apn_name);
+                    ctx->step++;
+                    /* fall through */
+                } else {
+                    mm_obj_info (self, "creating a profile for initial EPS bearer settings...");
+                    mm_3gpp_profile_set_profile_id(ctx->profile, MM_3GPP_PROFILE_ID_UNKNOWN);
+                    ctx->update_lte_attach_pdn = FALSE;
+                    ctx->step++;
+                    /* fall through */
+                }
+            } else {
+                /* Note: Never store an empty APN on the mm_owned_profile_index, since the logic in iface-modem-3gpp
+                   will skip the reattach if the new settings are also empty, and we might get stuck with empty APN
+                   settings which have the wrong |ip_type|. */
+                mm_obj_info (self, "Empty APN name provided. Falling back to modem profile for Attach APN.");
+                ctx->setting_mm_owned_pdn = FALSE;
+                if (self->priv->mm_owned_attach_pdn) {
+                    mm_obj_info (self, "Deleting MM owned profile for initial EPS bearer settings...");
+                    set_initial_eps_bearer_delete_mm_profile (task);
+                } else {
+                    ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP;
+                    set_initial_eps_bearer_settings_step (task);
+                }
+                return;
+            }
+
         case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE:
             mm_obj_dbg (self, "modifying initial EPS bearer settings profile...");
             set_initial_eps_bearer_modify_profile (task);
             return;
 
+        case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN:
+            if (ctx->update_lte_attach_pdn) {
+                mm_obj_info (self, "updating lte attach pdn after changing initial EPS bearer settings...");
+                set_initial_eps_bearer_set_lte_attach_pdn (task);
+                return;
+            }
+            ctx->step++;
+            /* fall through */
+
         case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP:
             if (ctx->power_state == MM_MODEM_POWER_STATE_ON) {
                 mm_obj_dbg (self, "powering up after changing initial EPS bearer settings...");
@@ -10676,6 +11104,13 @@
     SetInitialEpsBearerSettingsContext *ctx;
     GTask                              *task;
     MM3gppProfile                      *profile;
+    QmiClient                          *client;
+
+
+    if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+                                      QMI_SERVICE_WDS, &client,
+                                      callback, user_data))
+        return;
 
     task = g_task_new (self, NULL, callback, user_data);
 
@@ -10691,6 +11126,7 @@
 
     ctx = g_slice_new0 (SetInitialEpsBearerSettingsContext);
     ctx->profile = g_object_ref (profile);
+    ctx->client = QMI_CLIENT_WDS (g_object_ref (client));
     ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FIRST;
     g_task_set_task_data (task, ctx, (GDestroyNotify) set_initial_eps_bearer_settings_context_free);
 
@@ -10716,6 +11152,9 @@
     GError                   *error = NULL;
     g_autoptr(MM3gppProfile)  profile = NULL;
     MMBearerProperties       *properties;
+    MMBroadbandModemQmi      *self;
+
+    self = g_task_get_source_object (task);
 
     profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (_self, res, &error);
     if (!profile) {
@@ -10724,6 +11163,10 @@
         return;
     }
 
+    self->priv->mm_owned_attach_pdn = FALSE;
+    if (g_strcmp0(mm_3gpp_profile_get_profile_name (profile), MM_BROADBAND_MODEM_QMI_PROFILE_NAME) == 0)
+            self->priv->mm_owned_attach_pdn = TRUE;
+
     properties = mm_bearer_properties_new_from_profile (profile, &error);
     if (!properties)
         g_task_return_error (task, error);
@@ -10782,8 +11225,12 @@
         return;
     }
 
+    /* Resize array to match |current_list| */
+    g_array_set_size (self->priv->current_pdn_list, current_list->len);
+
     mm_obj_dbg (self, "Found %u LTE attach PDNs defined", current_list->len);
     for (i = 0; i < current_list->len; i++) {
+        g_array_index (self->priv->current_pdn_list, guint16, i) = g_array_index (current_list, guint16, i);
         if (i == 0) {
             self->priv->default_attach_pdn = g_array_index (current_list, guint16, i);
             mm_obj_dbg (self, "Default LTE attach PDN profile: %u", self->priv->default_attach_pdn);
@@ -12367,6 +12814,7 @@
     QMI_SERVICE_LOC,
     QMI_SERVICE_PDC,
     QMI_SERVICE_VOICE,
+    QMI_SERVICE_SAR,
 };
 
 typedef struct {
@@ -12670,7 +13118,16 @@
         return;
     }
 
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
     initialization_reset_ports (task);
+#else
+    mm_port_qmi_open (ctx->qmi,
+                      TRUE,
+                      NULL,
+                      (GAsyncReadyCallback)qmi_port_open_ready,
+                      task);
+#endif
+
 }
 
 /*****************************************************************************/
@@ -12703,6 +13160,7 @@
     self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
                                               MM_TYPE_BROADBAND_MODEM_QMI,
                                               MMBroadbandModemQmiPrivate);
+    self->priv->current_pdn_list = g_array_new (FALSE, FALSE, sizeof (guint16));
 }
 
 static void
@@ -12718,6 +13176,9 @@
     if (self->priv->supported_bands)
         g_array_unref (self->priv->supported_bands);
 
+    if (self->priv->current_pdn_list)
+        g_array_free (self->priv->current_pdn_list, TRUE);
+
     G_OBJECT_CLASS (mm_broadband_modem_qmi_parent_class)->finalize (object);
 }
 
@@ -13074,6 +13535,21 @@
 }
 
 static void
+iface_modem_sar_init (MMIfaceModemSar *iface)
+{
+    iface->check_support = sar_check_support;
+    iface->check_support_finish  = sar_check_support_finish;
+    iface->load_state = sar_load_state;
+    iface->load_state_finish = sar_load_state_finish;
+    iface->load_power_level = sar_load_power_level;
+    iface->load_power_level_finish = sar_load_power_level_finish;
+    iface->enable = sar_enable;
+    iface->enable_finish = sar_enable_finish;
+    iface->set_power_level = sar_set_power_level;
+    iface->set_power_level_finish = sar_set_power_level_finish;
+}
+
+static void
 iface_modem_oma_init (MMIfaceModemOma *iface)
 {
     iface->check_support = oma_check_support;
diff --git a/src/mm-broadband-modem-qmi.h b/src/mm-broadband-modem-qmi.h
index 9b71210..da794b6 100644
--- a/src/mm-broadband-modem-qmi.h
+++ b/src/mm-broadband-modem-qmi.h
@@ -25,6 +25,9 @@
 #define MM_IS_BROADBAND_MODEM_QMI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  MM_TYPE_BROADBAND_MODEM_QMI))
 #define MM_BROADBAND_MODEM_QMI_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  MM_TYPE_BROADBAND_MODEM_QMI, MMBroadbandModemQmiClass))
 
+/* Chromium OS specific profile */
+#define MM_BROADBAND_MODEM_QMI_PROFILE_NAME    "CrOS_attach_PDN"
+
 typedef struct _MMBroadbandModemQmi MMBroadbandModemQmi;
 typedef struct _MMBroadbandModemQmiClass MMBroadbandModemQmiClass;
 typedef struct _MMBroadbandModemQmiPrivate MMBroadbandModemQmiPrivate;
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 5153661..c1fa0e8 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -1069,7 +1069,11 @@
     mm_obj_dbg (self, "Updated initial EPS bearer settings:");
     log_initial_eps_bearer_settings (self, new_config);
 
-    if (!mm_bearer_properties_cmp (new_config, ctx->config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
+    /* When we request to set an empty/NULL APN, we instead select the default initial attach APN used by the modem,
+       which will probably not be an empty APN. If that's the case, we won't check for equality between the requested
+       APN and the APN which is now set. */
+    if (mm_bearer_properties_get_apn (ctx->config) && g_strcmp0 (mm_bearer_properties_get_apn (ctx->config), "") != 0 &&
+        !mm_bearer_properties_cmp (new_config, ctx->config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
         mm_obj_dbg (self, "Requested initial EPS bearer settings:");
         log_initial_eps_bearer_settings (self, ctx->config);
         g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
diff --git a/src/tests/test-qcdm-serial-port.c b/src/tests/test-qcdm-serial-port.c
index fff345d..bf8ff4b 100644
--- a/src/tests/test-qcdm-serial-port.c
+++ b/src/tests/test-qcdm-serial-port.c
@@ -444,10 +444,13 @@
 {
     g_test_init (&argc, &argv, NULL);
 
-    TESTCASE_PTY ("/MM/QCDM/Verinfo", test_verinfo);
-    TESTCASE_PTY ("/MM/QCDM/Sierra-Cns-Rejected", test_sierra_cns_rejected);
-    TESTCASE_PTY ("/MM/QCDM/Random-Data-Rejected", test_random_data_rejected);
-    TESTCASE_PTY ("/MM/QCDM/Leading-Frame-Markers", test_leading_frame_markers);
+    // Disabled in ChromiumOS because of flakiness.
+    // TODO(b/172214192); Re-enabled them once
+    // https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/184 is resolved
+    // TESTCASE_PTY ("/MM/QCDM/Verinfo", test_verinfo);
+    // TESTCASE_PTY ("/MM/QCDM/Sierra-Cns-Rejected", test_sierra_cns_rejected);
+    // TESTCASE_PTY ("/MM/QCDM/Random-Data-Rejected", test_random_data_rejected);
+    // TESTCASE_PTY ("/MM/QCDM/Leading-Frame-Markers", test_leading_frame_markers);
 
     return g_test_run ();
 }
diff --git a/unblocked_terms.txt b/unblocked_terms.txt
new file mode 100644
index 0000000..cc0e0cd
--- /dev/null
+++ b/unblocked_terms.txt
@@ -0,0 +1,12 @@
+# Don't delete this file if you want to keep keyword_check enabled even if it's
+# empty.
+# See repohooks/README.md for more details.
+black.?list
+dummy
+gr[ae]y.?list
+\bhe\b
+\bshe\b
+master
+\bnative
+slave
+white.?list