shill: Lookup the mobile provider database to obtain GSM network info.

Load the provider database in ModemInfo. Use the database to lookup operator
name and country when the GSM registration state changes.

This also adds a small mobile provider database used for unit test purposes.

BUG=chromium-os:19699
TEST=unit tests

Change-Id: I5cf0b6d0682d1e0f47fe4b92a45ec6c48837b650
Reviewed-on: https://gerrit.chromium.org/gerrit/10718
Commit-Ready: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/modem_info.cc b/modem_info.cc
index 230e927..0a29c5b 100644
--- a/modem_info.cc
+++ b/modem_info.cc
@@ -4,7 +4,9 @@
 
 #include "shill/modem_info.h"
 
+#include <base/logging.h>
 #include <mm/mm-modem.h>
+#include <mobile_provider.h>
 
 #include "shill/modem_manager.h"
 
@@ -14,6 +16,8 @@
 
 const char ModemInfo::kCromoService[] = "org.chromium.ModemManager";
 const char ModemInfo::kCromoPath[] = "/org/chromium/ModemManager";
+const char ModemInfo::kMobileProviderDBPath[] =
+    "/usr/share/mobile-broadband-provider-info/serviceproviders.bfd";
 
 ModemInfo::ModemInfo(ControlInterface *control_interface,
                      EventDispatcher *dispatcher,
@@ -22,18 +26,27 @@
     : control_interface_(control_interface),
       dispatcher_(dispatcher),
       manager_(manager),
-      glib_(glib) {}
+      glib_(glib),
+      provider_db_path_(kMobileProviderDBPath),
+      provider_db_(NULL) {}
 
 ModemInfo::~ModemInfo() {
   Stop();
 }
 
 void ModemInfo::Start() {
+  // TODO(petkov): Consider initializing the mobile provider database lazily
+  // only if a GSM modem needs to be registered.
+  provider_db_ = mobile_provider_open_db(provider_db_path_.c_str());
+  PLOG_IF(WARNING, !provider_db_)
+      << "Unable to load mobile provider database: ";
   RegisterModemManager(MM_MODEMMANAGER_SERVICE, MM_MODEMMANAGER_PATH);
   RegisterModemManager(kCromoService, kCromoPath);
 }
 
 void ModemInfo::Stop() {
+  mobile_provider_close_db(provider_db_);
+  provider_db_ = NULL;
   modem_managers_.reset();
 }
 
@@ -44,7 +57,8 @@
                                            control_interface_,
                                            dispatcher_,
                                            manager_,
-                                           glib_);
+                                           glib_,
+                                           provider_db_);
   modem_managers_.push_back(manager);  // Passes ownership.
   manager->Start();
 }