Bug 801540 - Use setupDataCallByType to build data connection. r=dougt
authorPatrick Wang <kk1fff@patrickz.net>
Tue, 23 Oct 2012 15:18:11 +0800
changeset 111909 dffca1d334aea12f5ba2dd94286d6cc858b0f745
parent 111908 ff4f0988d15618fbd7a54d2d09a025b77cc69ccc
child 111910 e0cf397089ec879a15c170cbf1a100892d5727d6
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersdougt
bugs801540
milestone19.0a1
Bug 801540 - Use setupDataCallByType to build data connection. r=dougt
dom/system/gonk/GonkGPSGeolocationProvider.cpp
dom/system/gonk/GonkGPSGeolocationProvider.h
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -20,32 +20,37 @@
 #include "GonkGPSGeolocationProvider.h"
 #include "SystemWorkerManager.h"
 #include "mozilla/Preferences.h"
 #include "nsGeoPosition.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINetworkManager.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsIDOMMobileConnection.h"
+#include "nsJSUtils.h"
+#include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #ifdef AGPS_TYPE_INVALID
 #define AGPS_HAVE_DUAL_APN
 #endif
 
 #define DEBUG_GPS 0
 
 using namespace mozilla;
 
 static const int kDefaultPeriod = 1000; // ms
 
 // While most methods of GonkGPSGeolocationProvider should only be
 // called from main thread, we deliberately put the Init and ShutdownGPS
 // methods off main thread to avoid blocking.
-NS_IMPL_THREADSAFE_ISUPPORTS2(GonkGPSGeolocationProvider, nsIGeolocationProvider, nsIRILDataCallback)
+NS_IMPL_THREADSAFE_ISUPPORTS3(GonkGPSGeolocationProvider,
+                              nsIGeolocationProvider,
+                              nsIRILDataCallback,
+                              nsISettingsServiceCallback)
 
 GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton;
 GpsCallbacks GonkGPSGeolocationProvider::mCallbacks = {
   sizeof(GpsCallbacks),
   LocationCallback,
   StatusCallback,
   SvStatusCallback,
   NmeaCallback,
@@ -301,36 +306,82 @@ GonkGPSGeolocationProvider::GetGPSInterf
   const GpsInterface* result = gps_device->get_gps_interface(gps_device);
 
   if (result->size != sizeof(GpsInterface)) {
     return nullptr;
   }
   return result;
 }
 
+int32_t
+GonkGPSGeolocationProvider::GetDataConnectionState()
+{
+  if (!mRIL) {
+    return nsINetworkInterface::NETWORK_STATE_UNKNOWN;
+  }
+
+  int32_t state;
+  mRIL->GetDataCallStateByType(NS_LITERAL_STRING("supl"), &state);
+  return state;
+}
+
+void
+GonkGPSGeolocationProvider::SetAGpsDataConn(nsAString& aApn)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mAGpsInterface);
+
+  int32_t connectionState = GetDataConnectionState();
+  if (connectionState == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+    NS_ConvertUTF16toUTF8 apn(aApn);
+#ifdef AGPS_HAVE_DUAL_APN
+    mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
+                                   apn.get(),
+                                   AGPS_APN_BEARER_IPV4);
+#else
+    mAGpsInterface->data_conn_open(apn.get());
+#endif
+  } else if (connectionState == nsINetworkInterface::NETWORK_STATE_DISCONNECTED) {
+#ifdef AGPS_HAVE_DUAL_APN
+    mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
+#else
+    mAGpsInterface->data_conn_closed();
+#endif
+  }
+}
+
+void
+GonkGPSGeolocationProvider::RequestSettingValue(char* aKey)
+{
+  MOZ_ASSERT(aKey);
+  nsCOMPtr<nsISettingsService> ss = do_GetService("@mozilla.org/settingsService;1");
+  if (!ss) {
+    MOZ_ASSERT(ss);
+    return;
+  }
+  nsCOMPtr<nsISettingsServiceLock> lock;
+  ss->CreateLock(getter_AddRefs(lock));
+  lock->Get(aKey, this);
+}
+
 void
 GonkGPSGeolocationProvider::RequestDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRIL) {
     return;
   }
 
-  // TODO: Bug 772747 - We should ask NetworkManager or RIL to open
-  // SUPL type connection for us.
-  const nsAdoptingString& apnName = Preferences::GetString("geo.gps.apn.name");
-  const nsAdoptingString& apnUser = Preferences::GetString("geo.gps.apn.user");
-  const nsAdoptingString& apnPass = Preferences::GetString("geo.gps.apn.password");
-  if (apnName && apnUser && apnPass) {
-    mCid.Truncate();
-    mRIL->SetupDataCall(1 /* DATACALL_RADIOTECHNOLOGY_GSM */,
-                        apnName, apnUser, apnPass,
-                        3 /* DATACALL_AUTH_PAP_OR_CHAP */,
-                        NS_LITERAL_STRING("IP") /* pdptype */);
+  if (GetDataConnectionState() == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+    // Connection is already established, we don't need to setup again.
+    // We just get supl APN and make AGPS data connection state updated.
+    RequestSettingValue("ril.supl.apn");
+  } else {
+    mRIL->SetupDataCallByType(NS_LITERAL_STRING("supl"));
   }
 }
 
 void
 GonkGPSGeolocationProvider::ReleaseDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -583,55 +634,50 @@ GonkGPSGeolocationProvider::SetHighAccur
 
 /** nsIRILDataCallback interface **/
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::DataCallStateChanged(nsIRILDataCallInfo* aDataCall)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aDataCall);
-  MOZ_ASSERT(mAGpsInterface);
-  nsCOMPtr<nsIRILDataCallInfo> datacall = aDataCall;
 
-  uint32_t callState;
-  nsresult rv = datacall->GetState(&callState);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoString apn;
-  rv = datacall->GetApn(apn);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = datacall->GetCid(mCid);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ConvertUTF16toUTF8 currentApn(apn);
-  const nsAdoptingCString& agpsApn = Preferences::GetCString("geo.gps.apn.name");
-
-  // TODO: Bug 772748 - handle data call failed case.
-  if (currentApn == agpsApn) {
-    switch (callState) {
-      case nsINetworkInterface::NETWORK_STATE_CONNECTED:
-#ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
-                                       agpsApn.get(),
-                                       AGPS_APN_BEARER_IPV4);
-#else
-        mAGpsInterface->data_conn_open(agpsApn.get());
-#endif
-        break;
-      case nsINetworkInterface::NETWORK_STATE_DISCONNECTED:
-#ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
-#else
-        mAGpsInterface->data_conn_closed();
-#endif
-        break;
-    }
-  }
+  // We call Setting Service before we get the state of supl data connection
+  // since it is possible that state of supl data connection haven't been
+  // updated and will be updated after we finished this function (code that
+  // updates the state is in another dataCallStateChanged callback).
+  RequestSettingValue("ril.supl.apn");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::ReceiveDataCallList(nsIRILDataCallInfo** aDataCalls,
                                                 uint32_t aLength)
 {
   return NS_OK;
 }
+
+/** nsISettingsServiceCallback **/
+
+NS_IMETHODIMP
+GonkGPSGeolocationProvider::Handle(const nsAString& aName,
+                                   const JS::Value& aResult,
+                                   JSContext* cx)
+{
+  if (aName.EqualsLiteral("ril.supl.apn")) {
+    // When we get the APN, we attempt to call data_call_open of AGPS.
+    if (aResult.isString()) {
+      nsDependentJSString apn;
+      apn.init(cx, aResult.toString());
+      if (!apn.IsEmpty()) {
+        SetAGpsDataConn(apn);
+      }
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+GonkGPSGeolocationProvider::HandleError(const nsAString& aErrorMessage,
+                                        JSContext* cx)
+{
+  return NS_OK;
+}
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.h
@@ -17,32 +17,35 @@
 #ifndef GonkGPSGeolocationProvider_h
 #define GonkGPSGeolocationProvider_h
 
 #include <hardware/gps.h> // for GpsInterface
 #include "nsCOMPtr.h"
 #include "nsIGeolocationProvider.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsString.h"
+#include "nsISettingsService.h"
 
 class nsIThread;
 
 #define GONK_GPS_GEOLOCATION_PROVIDER_CID \
 { 0x48525ec5, 0x5a7f, 0x490a, { 0x92, 0x77, 0xba, 0x66, 0xe0, 0xd2, 0x2c, 0x8b } }
 
 #define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
 "@mozilla.org/gonk-gps-geolocation-provider;1"
 
 class GonkGPSGeolocationProvider : public nsIGeolocationProvider
                                  , public nsIRILDataCallback
+                                 , public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONPROVIDER
   NS_DECL_NSIRILDATACALLBACK
+  NS_DECL_NSISETTINGSSERVICECALLBACK
 
   static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
 
 private:
 
   /* Client should use GetSingleton() to get the provider instance. */
   GonkGPSGeolocationProvider();
   GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
@@ -61,16 +64,19 @@ private:
   static void AGPSStatusCallback(AGpsStatus* status);
   static void AGPSRILSetIDCallback(uint32_t flags);
   static void AGPSRILRefLocCallback(uint32_t flags);
 
   static GpsCallbacks mCallbacks;
   static AGpsCallbacks mAGPSCallbacks;
   static AGpsRilCallbacks mAGPSRILCallbacks;
 
+  int32_t GetDataConnectionState();
+  void SetAGpsDataConn(nsAString& aApn);
+  void RequestSettingValue(char* aKey);
   void Init();
   void SetupAGPS();
   void StartGPS();
   void ShutdownGPS();
   void RequestDataConnection();
   void ReleaseDataConnection();
   void RequestSetID(uint32_t flags);
   void SetReferenceLocation();