Ril hal gets interface parameters from shared memory

The parameters are obtained from the virtual network configuration.

Test: foo
Bug: 70724395
Change-Id: Ie578866c2adaaefe24513e190899e5105d3e8443
diff --git a/Android.bp b/Android.bp
index 6d58a46..44d97c5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,6 +97,8 @@
         "common/vsoc/lib/input_events_region_view.cpp",
         "common/vsoc/lib/lock_common.cpp",
         "common/vsoc/lib/region_view.cpp",
+        "common/vsoc/lib/ril_layout.cpp",
+        "common/vsoc/lib/ril_region_view.cpp",
         "common/vsoc/lib/wifi_exchange_layout.cpp",
         "common/vsoc/lib/wifi_exchange_view.cpp",
     ],
diff --git a/common/vsoc/lib/ril_layout.cpp b/common/vsoc/lib/ril_layout.cpp
new file mode 100644
index 0000000..89f45f1
--- /dev/null
+++ b/common/vsoc/lib/ril_layout.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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 "common/vsoc/shm/ril_layout.h"
+
+namespace vsoc {
+namespace layout {
+namespace ril {
+
+const char* RilLayout::region_name = "ril";
+}
+}  // namespace layout
+}  // namespace vsoc
diff --git a/common/vsoc/lib/ril_region_view.cpp b/common/vsoc/lib/ril_region_view.cpp
new file mode 100644
index 0000000..98c0625
--- /dev/null
+++ b/common/vsoc/lib/ril_region_view.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 <arpa/inet.h>
+
+#include <mutex>
+
+#include "common/vsoc/lib/ril_region_view.h"
+
+namespace vsoc {
+namespace ril {
+
+// TODO(jemoreira): use the general region singleton implementation when ready
+#if defined(CUTTLEFISH_HOST)
+RilRegionView* RilRegionView::GetInstance(const char* domain) {
+#else
+RilRegionView* RilRegionView::GetInstance() {
+#endif
+  static std::mutex m;
+  static RilRegionView* region;
+
+  std::lock_guard<std::mutex> lock(m);
+  if (!region) {
+    region = new RilRegionView();
+
+#if defined(CUTTLEFISH_HOST)
+    if (!region->Open(domain)) {
+#else
+    if (!region->Open()) {
+#endif
+      delete region;
+      region = nullptr;
+    }
+  }
+  return region;
+}
+
+const char* RilRegionView::address_and_prefix_length() const {
+  static char buffer[sizeof(data().ipaddr) + 3]{};  // <ipaddr>/dd
+  if (buffer[0] == '\0') {
+    snprintf(buffer, sizeof(buffer), "%s/%d", data().ipaddr, data().prefixlen);
+  }
+  return &buffer[0];
+}
+
+}  // namespace ril
+}  // namespace vsoc
diff --git a/common/vsoc/lib/ril_region_view.h b/common/vsoc/lib/ril_region_view.h
new file mode 100644
index 0000000..69c573f
--- /dev/null
+++ b/common/vsoc/lib/ril_region_view.h
@@ -0,0 +1,36 @@
+#pragma once
+/*
+ * 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 "common/vsoc/lib/typed_region_view.h"
+#include "common/vsoc/shm/ril_layout.h"
+
+namespace vsoc {
+namespace ril {
+class RilRegionView
+    : public vsoc::TypedRegionView<vsoc::layout::ril::RilLayout> {
+ public:
+#if defined(CUTTLEFISH_HOST)
+  static RilRegionView* GetInstance(const char* domain = nullptr);
+#else
+  static RilRegionView* GetInstance();
+#endif
+
+  // returns a string with '<ip>/<prefix_len>' like this: 192.168.99.2/30
+  const char* address_and_prefix_length() const;
+};
+}  // namespace ril
+}  // namespace vsoc
diff --git a/common/vsoc/shm/ril_layout.h b/common/vsoc/shm/ril_layout.h
new file mode 100644
index 0000000..c1c0745
--- /dev/null
+++ b/common/vsoc/shm/ril_layout.h
@@ -0,0 +1,41 @@
+#pragma once
+/*
+ * 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 <netinet/in.h>
+
+#include "common/vsoc/shm/base.h"
+#include "common/vsoc/shm/version.h"
+
+// Memory layout for the ril hal region
+
+namespace vsoc {
+namespace layout {
+namespace ril {
+
+struct RilLayout : public RegionLayout {
+  static const char* region_name;
+
+  char ipaddr[16]; // xxx.xxx.xxx.xxx\0 = 16 bytes
+  char gateway[16];
+  char dns[16];
+  char broadcast[16];
+  uint32_t prefixlen;
+};
+ASSERT_SHM_COMPATIBLE(RilLayout, ril);
+}  // namespace ril
+}  // namespace layout
+}  // namespace vsoc
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index 2c404d7..c1a82e2 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -136,6 +136,14 @@
     6;      // uint8_t[6] MAC address.
 }  // namespace wifi
 
+// Versioning information for ril_layout.h
+namespace ril {
+namespace {
+const uint32_t version = 1;
+}
+static const std::size_t RilLayout_size = 68;
+}  // namespace ril
+
 
 // Versioning information for e2e_test_region.h
 // Changes to these structures will affect only the e2e_test_region
diff --git a/guest/hals/ril/Android.mk b/guest/hals/ril/Android.mk
index e677b1d..56e9779 100644
--- a/guest/hals/ril/Android.mk
+++ b/guest/hals/ril/Android.mk
@@ -27,9 +27,12 @@
   libcuttlefish_fs \
   cuttlefish_net \
   cuttlefish_auto_resources \
-  libbase
+  libbase \
+  vsoc_lib
 
-LOCAL_C_INCLUDES := device/google/cuttlefish_common
+LOCAL_C_INCLUDES := \
+    device/google/cuttlefish_common \
+    device/google/cuttlefish_kernel
 
 LOCAL_CFLAGS += \
   -Wall \
@@ -40,5 +43,9 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_VENDOR_MODULE := true
 
-include $(BUILD_SHARED_LIBRARY)
+# See b/67109557
+ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
+LOCAL_MULTILIB := first
+endif
 
+include $(BUILD_SHARED_LIBRARY)
diff --git a/guest/hals/ril/vsoc_ril.cpp b/guest/hals/ril/vsoc_ril.cpp
index 60956eb..b60ad8d 100644
--- a/guest/hals/ril/vsoc_ril.cpp
+++ b/guest/hals/ril/vsoc_ril.cpp
@@ -29,6 +29,7 @@
 #include "common/libs/net/netlink_client.h"
 #include "common/libs/net/network_interface.h"
 #include "common/libs/net/network_interface_manager.h"
+#include "common/vsoc/lib/ril_region_view.h"
 #include "guest/libs/platform_support/api_level_fixes.h"
 
 #define VSOC_RIL_VERSION_STRING "Android VSoC RIL 1.0"
@@ -184,10 +185,13 @@
         break;
     }
 
+    auto ril_region_view = vsoc::ril::RilRegionView::GetInstance();
+
     responses[index].ifname = (char*)"rmnet0";
-    responses[index].addresses = (char*)"192.168.99.2/30";
-    responses[index].dnses = (char*)"8.8.8.8";
-    responses[index].gateways = (char*)"192.168.99.1";
+    responses[index].addresses =
+      const_cast<char*>(ril_region_view->address_and_prefix_length());
+    responses[index].dnses = (char*)ril_region_view->data()->dns;
+    responses[index].gateways = (char*)ril_region_view->data()->gateway;
 #if VSOC_PLATFORM_SDK_AFTER(N_MR1)
     responses[index].pcscf = (char*)"";
     responses[index].mtu = 1440;
@@ -309,7 +313,10 @@
   }
 
   if (gDataCalls.empty()) {
-    SetUpNetworkInterface("192.168.99.2", 30, "192.168.99.3");
+    auto ril_region_view = vsoc::ril::RilRegionView::GetInstance();
+    SetUpNetworkInterface(ril_region_view->data()->ipaddr,
+                          ril_region_view->data()->prefixlen,
+                          ril_region_view->data()->broadcast);
   }
 
   gDataCalls[gNextDataCallId] = call;
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index 2a3eb0d..a13c087 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -3,6 +3,7 @@
     srcs: [
         "main.cc",
         "fb_bcast_region_handler.cc",
+        "ril_region_handler.cc",
     ],
     header_libs: [
         "cuttlefish_glog",
diff --git a/host/commands/launch/pre_launch_initializers.h b/host/commands/launch/pre_launch_initializers.h
index 5d43bce..5cc53e5 100644
--- a/host/commands/launch/pre_launch_initializers.h
+++ b/host/commands/launch/pre_launch_initializers.h
@@ -21,10 +21,12 @@
 // To add initializers for more regions declare here, implement in its own
 // source file and call from PreLaunchInitializers::Initialize().
 void InitializeFBBroadcastRegion();
+void InitializeRilRegion();
 
 class PreLaunchInitializers {
  public:
   static void Initialize() {
     InitializeFBBroadcastRegion();
+    InitializeRilRegion();
   }
 };
diff --git a/host/commands/launch/ril_region_handler.cc b/host/commands/launch/ril_region_handler.cc
new file mode 100644
index 0000000..34f8c43
--- /dev/null
+++ b/host/commands/launch/ril_region_handler.cc
@@ -0,0 +1,187 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <memory>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include "common/vsoc/lib/ril_region_view.h"
+#include "host/commands/launch/pre_launch_initializers.h"
+#include "host/libs/config/host_config.h"
+
+DECLARE_string(hypervisor_uri);
+
+namespace {
+
+int number_of_ones(int val) {
+  LOG(INFO) << val;
+  int ret = 0;
+  while (val) {
+    ret += val % 2;
+    val >>= 1;
+  }
+  return ret;
+}
+
+class NetConfig {
+ public:
+  uint32_t ril_prefixlen = -1;
+  std::string ril_ipaddr;
+  std::string ril_gateway;
+  std::string ril_dns = "8.8.8.8";
+  std::string ril_broadcast;
+
+  bool ObtainConfig() {
+    bool ret = ParseLibvirtXml() && ParseIfconfig();
+    LOG(INFO) << "Network config:";
+    LOG(INFO) << "ipaddr = " << ril_ipaddr;
+    LOG(INFO) << "gateway = " << ril_gateway;
+    LOG(INFO) << "dns = " << ril_dns;
+    LOG(INFO) << "broadcast = " << ril_broadcast;
+    LOG(INFO) << "prefix length = " << ril_prefixlen;
+    return ret;
+  }
+
+ private:
+  bool ParseIfconfig() {
+    std::shared_ptr<FILE> broadcast(
+        popen("ifconfig cvd-mobile-01 | egrep -o 'broadcast "
+              "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+' | egrep -o "
+              "'[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+'",
+              "r"),
+        pclose);
+    if (!broadcast) {
+      LOG(ERROR) << "Unable to popen ifconfig...";
+      return false;
+    }
+    char buffer[16];
+    if (fgets(&buffer[0], sizeof(buffer), broadcast.get()) == NULL) {
+      LOG(ERROR) << "Unable to read broadcast address from subprocess output";
+      return false;
+    }
+    this->ril_broadcast = strtok(&buffer[0], "\n");
+    return true;
+  }
+
+  bool ParseLibvirtXml() {
+    std::string net_dump_command =
+        "virsh -c " + FLAGS_hypervisor_uri + " net-dumpxml cvd-mobile-01";
+    std::shared_ptr<FILE> net_xml_file(popen(net_dump_command.c_str(), "r"),
+                                       pclose);
+    if (!net_xml_file) {
+      LOG(ERROR) << "Unable to popen virsh...";
+      return false;
+    }
+    std::shared_ptr<xmlDoc> doc(
+        xmlReadFd(fileno(net_xml_file.get()), NULL, NULL, 0), xmlFreeDoc);
+    if (!doc) {
+      LOG(ERROR) << "Unable to parse network xml";
+      return false;
+    }
+
+    xmlNode* element = xmlDocGetRootElement(doc.get());
+    element = element->xmlChildrenNode;
+    while (element) {
+      if (strcmp((char*)element->name, "ip") == 0) {
+        return ProcessIpNode(element);
+      }
+      element = element->next;
+    }
+    LOG(ERROR) << "ip node not found in network xml spec";
+    return false;
+  }
+
+  bool ParseIpAttributes(xmlNode* ip_node) {
+    // The gateway is the host ip address
+    this->ril_gateway = (char*)xmlGetProp(ip_node, (xmlChar*)"address");
+
+    // The prefix length need to be obtained from the network mask
+    char* netmask = (char*)xmlGetProp(ip_node, (xmlChar*)"netmask");
+    int byte1, byte2, byte3, byte4;
+    sscanf(netmask, "%d.%d.%d.%d", &byte1, &byte2, &byte3, &byte4);
+    this->ril_prefixlen = 0;
+    this->ril_prefixlen += number_of_ones(byte1);
+    this->ril_prefixlen += number_of_ones(byte2);
+    this->ril_prefixlen += number_of_ones(byte3);
+    this->ril_prefixlen += number_of_ones(byte4);
+    return true;
+  }
+
+  bool ProcessDhcpNode(xmlNode* dhcp_node) {
+    xmlNode* child = dhcp_node->xmlChildrenNode;
+    while (child) {
+      if (strcmp((char*)child->name, "range") == 0) {
+        this->ril_ipaddr = (char*)xmlGetProp(child, (xmlChar*)"start");
+        return true;
+      }
+      child = child->next;
+    }
+    LOG(ERROR) << "range node not found in network xml spec";
+    return false;
+  }
+
+  bool ProcessIpNode(xmlNode* ip_node) {
+    ParseIpAttributes(ip_node);
+    xmlNode* child = ip_node->xmlChildrenNode;
+    while (child) {
+      if (strcmp((char*)child->name, "dhcp") == 0) {
+        return ProcessDhcpNode(child);
+      }
+      child = child->next;
+    }
+    LOG(ERROR) << "dhcp node not found in network xml spec";
+    return false;
+  }
+};
+}  // namespace
+
+void InitializeRilRegion() {
+  NetConfig netconfig;
+  if (!netconfig.ObtainConfig()) {
+    LOG(ERROR) << "Unable to obtain the network configuration";
+    return;
+  }
+
+  vsoc::ril::RilRegionView* region =
+      vsoc::ril::RilRegionView::GetInstance(vsoc::GetDomain().c_str());
+
+  if (!region) {
+    LOG(ERROR) << "Ril region was not found";
+    return;
+  }
+
+  auto dest = region->data();
+
+  snprintf(
+      dest->ipaddr, sizeof(dest->ipaddr), "%s", netconfig.ril_ipaddr.c_str());
+  snprintf(dest->gateway,
+           sizeof(dest->gateway),
+           "%s",
+           netconfig.ril_gateway.c_str());
+  snprintf(dest->dns, sizeof(dest->dns), "%s", netconfig.ril_dns.c_str());
+  snprintf(dest->broadcast,
+           sizeof(dest->broadcast),
+           "%s",
+           netconfig.ril_broadcast.c_str());
+  dest->prefixlen = netconfig.ril_prefixlen;
+}
diff --git a/host/config/vsoc_mem.json b/host/config/vsoc_mem.json
index 7a46f68..7cdb794 100644
--- a/host/config/vsoc_mem.json
+++ b/host/config/vsoc_mem.json
@@ -125,6 +125,25 @@
 
 
    {
+     "device_name" : "ril",
+     "__comment" : [
+       "Holds initialization values for the ril hal."
+     ],
+     "current_version" : 0,
+     "min_compatible_version" : 0,
+     "region_size" : 4096,
+
+     "guest_to_host_signal_table" : {
+       "num_nodes_lg2" : 2
+      },
+
+     "host_to_guest_signal_table" : {
+       "num_nodes_lg2" : 2
+      }
+   },
+
+
+   {
     "device_name" : "e2e_primary",
     "__comment" : "Sanity testing",
     "current_version" : 1,