Add provisioning apn timeout.
Wink Saville [Wed, 4 Sep 2013 23:00:44 +0000 (16:00 -0700)]
Bug: 10609993
Change-Id: I2dd4fe23fa2b22ef8f4849c161c630d1a85cdb4b

src/java/com/android/internal/telephony/dataconnection/ApnContext.java
src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java

index ce085c9..e262249 100644 (file)
@@ -194,6 +194,13 @@ public class ApnContext {
                                 || (mState == DctConstants.State.FAILED));
     }
 
+    public boolean isConnectedOrConnecting() {
+        return isReady() && ((mState == DctConstants.State.CONNECTED)
+                                || (mState == DctConstants.State.CONNECTING)
+                                || (mState == DctConstants.State.SCANNING)
+                                || (mState == DctConstants.State.RETRYING));
+    }
+
     public void setEnabled(boolean enabled) {
         if (DBG) {
             log("set enabled as " + enabled + ", current state is " + mDataEnabled.get());
index 518e82c..3318768 100644 (file)
@@ -273,9 +273,29 @@ public abstract class DcTrackerBase extends Handler {
     /* Set to true with CMD_ENABLE_MOBILE_PROVISIONING */
     protected boolean mIsProvisioning = false;
 
-    /* Object parameter in CMD_ENABLE_MOBILE_PROVISIONING */
+    /* The Url passed as object parameter in CMD_ENABLE_MOBILE_PROVISIONING */
     protected String mProvisioningUrl = null;
 
+    /* Intent for the provisioning apn alarm */
+    protected static final String INTENT_PROVISIONING_APN_ALARM =
+            "com.android.internal.telephony.provisioning_apn_alarm";
+
+    /* Tag for tracking stale alarms */
+    protected static final String PROVISIONING_APN_ALARM_TAG_EXTRA = "provisioning.apn.alarm.tag";
+
+    /* Debug property for overriding the PROVISIONING_APN_ALARM_DELAY_IN_MS */
+    protected static final String DEBUG_PROV_APN_ALARM =
+            "persist.debug.prov_apn_alarm";
+
+    /* Default for the provisioning apn alarm timeout */
+    protected static final int PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 15;
+
+    /* The provision apn alarm intent used to disable the provisioning apn */
+    protected PendingIntent mProvisioningApnAlarmIntent = null;
+
+    /* Used to track stale provisioning apn alarms */
+    protected int mProvisioningApnAlarmTag = (int) SystemClock.elapsedRealtime();
+
     protected AsyncChannel mReplyAc = new AsyncChannel();
 
     protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
@@ -303,6 +323,8 @@ public abstract class DcTrackerBase extends Handler {
                 onActionIntentRestartTrySetupAlarm(intent);
             } else if (action.equals(INTENT_DATA_STALL_ALARM)) {
                 onActionIntentDataStallAlarm(intent);
+            } else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
+                onActionIntentProvisioningApnAlarm(intent);
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -512,6 +534,7 @@ public abstract class DcTrackerBase extends Handler {
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         filter.addAction(INTENT_DATA_STALL_ALARM);
+        filter.addAction(INTENT_PROVISIONING_APN_ALARM);
 
         mUserDataEnabled = Settings.Global.getInt(
                 mPhone.getContext().getContentResolver(), Settings.Global.MOBILE_DATA, 1) == 1;
@@ -832,7 +855,8 @@ public abstract class DcTrackerBase extends Handler {
                         log("CMD_ENABLE_MOBILE_PROVISIONING: mIsProvisioning=true url="
                                 + mProvisioningUrl);
                         mIsProvisioning = true;
-                        completeConnection(mApnContexts.get(PhoneConstants.APN_TYPE_DEFAULT));                        
+                        startProvisioningApnAlarm();
+                        completeConnection(mApnContexts.get(PhoneConstants.APN_TYPE_DEFAULT));
                     } else {
                         log("CMD_ENABLE_MOBILE_PROVISIONING: No longer connected");
                         mIsProvisioning = false;
@@ -841,6 +865,28 @@ public abstract class DcTrackerBase extends Handler {
                 }
                 break;
             }
+            case DctConstants.EVENT_PROVISIONING_APN_ALARM: {
+                if (DBG) log("EVENT_PROVISIONING_APN_ALARM");
+                ApnContext apnCtx = mApnContexts.get("default");
+                if (apnCtx.isProvisioningApn() && apnCtx.isConnectedOrConnecting()) {
+                    if (mProvisioningApnAlarmTag == msg.arg1) {
+                        if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Disconnecting");
+                        mIsProvisioning = false;
+                        mProvisioningUrl = null;
+                        stopProvisioningApnAlarm();
+                        sendCleanUpConnection(true, apnCtx);
+                    } else {
+                        if (DBG) {
+                            log("EVENT_PROVISIONING_APN_ALARM: ignore stale tag,"
+                                    + " mProvisioningApnAlarmTag:" + mProvisioningApnAlarmTag
+                                    + " != arg1:" + msg.arg1);
+                        }
+                    }
+                } else {
+                    if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Not connected ignore");
+                }
+                break;
+            }
             case DctConstants.CMD_IS_PROVISIONING_APN: {
                 if (DBG) log("CMD_IS_PROVISIONING_APN");
                 boolean isProvApn;
@@ -1591,6 +1637,53 @@ public abstract class DcTrackerBase extends Handler {
         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
     }
 
+    protected void onActionIntentProvisioningApnAlarm(Intent intent) {
+        if (DBG) log("onActionIntentProvisioningApnAlarm: action=" + intent.getAction());
+        Message msg = obtainMessage(DctConstants.EVENT_PROVISIONING_APN_ALARM,
+                intent.getAction());
+        msg.arg1 = intent.getIntExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, 0);
+        sendMessage(msg);
+    }
+
+    protected void startProvisioningApnAlarm() {
+        int delayInMs = Settings.Global.getInt(mResolver,
+                                Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
+                                PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT);
+        if (Build.IS_DEBUGGABLE) {
+            // Allow debug code to use a system property to provide another value
+            String delayInMsStrg = Integer.toString(delayInMs);
+            delayInMsStrg = System.getProperty(DEBUG_PROV_APN_ALARM, delayInMsStrg);
+            try {
+                delayInMs = Integer.parseInt(delayInMsStrg);
+            } catch (NumberFormatException e) {
+                loge("startProvisioningApnAlarm: e=" + e);
+            }
+        }
+        mProvisioningApnAlarmTag += 1;
+        if (DBG) {
+            log("startProvisioningApnAlarm: tag=" + mProvisioningApnAlarmTag +
+                    " delay=" + (delayInMs / 1000) + "s");
+        }
+        Intent intent = new Intent(INTENT_PROVISIONING_APN_ALARM);
+        intent.putExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, mProvisioningApnAlarmTag);
+        mProvisioningApnAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                SystemClock.elapsedRealtime() + delayInMs, mProvisioningApnAlarmIntent);
+    }
+
+    protected void stopProvisioningApnAlarm() {
+        if (DBG) {
+            log("stopProvisioningApnAlarm: current tag=" + mProvisioningApnAlarmTag +
+                    " mProvsioningApnAlarmIntent=" + mProvisioningApnAlarmIntent);
+        }
+        mProvisioningApnAlarmTag += 1;
+        if (mProvisioningApnAlarmIntent != null) {
+            mAlarmManager.cancel(mProvisioningApnAlarmIntent);
+            mProvisioningApnAlarmIntent = null;
+        }
+    }
+
     void sendCleanUpConnection(boolean tearDown, ApnContext apnContext) {
         if (DBG)log("sendCleanUpConnection: tearDown=" + tearDown + " apnContext=" + apnContext);
         Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION);