Merge "Return NetworkStats bundle from NM service."
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 984102a..2b79a76 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -261,6 +261,13 @@
     private static native boolean nDrawDisplayList(int renderer, int displayList,
             int width, int height, Rect dirty);
 
+    @Override
+    void outputDisplayList(DisplayList displayList) {
+        nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+    }
+
+    private static native void nOutputDisplayList(int renderer, int displayList);
+
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layer
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index caa7b74..23b3abc 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -64,6 +64,14 @@
     abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty);
 
     /**
+     * Outputs the specified display list to the log. This method exists for use by
+     * tools to output display lists for selected nodes to the log.
+     *
+     * @param displayList The display list to be logged.
+     */
+    abstract void outputDisplayList(DisplayList displayList);
+
+    /**
      * Draws the specified layer onto this canvas.
      *
      * @param layer The layer to composite on this canvas
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 3f05b29..d751d29 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -375,6 +375,7 @@
     private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
     private static final String REMOTE_PROFILE = "PROFILE";
     private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS";
+    private static final String REMOTE_COMMAND_OUTPUT_DISPLAYLIST = "OUTPUT_DISPLAYLIST";
 
     private static HashMap<Class<?>, Field[]> sFieldsForClasses;
     private static HashMap<Class<?>, Method[]> sMethodsForClasses;
@@ -885,6 +886,8 @@
             final String[] params = parameters.split(" ");
             if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) {
                 capture(view, clientStream, params[0]);
+            } else if (REMOTE_COMMAND_OUTPUT_DISPLAYLIST.equalsIgnoreCase(command)) {
+                outputDisplayList(view, params[0]);
             } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) {
                 invalidate(view, params[0]);
             } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) {
@@ -1156,6 +1159,11 @@
         }
     }
 
+    private static void outputDisplayList(View root, String parameter) throws IOException {
+        final View view = findView(root, parameter);
+        view.getViewRoot().outputDisplayList(view);
+    }
+
     private static void capture(View root, final OutputStream clientStream, String parameter)
             throws IOException {
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index f929a0e..d43a27f 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -519,6 +519,11 @@
     return redraw;
 }
 
+static void android_view_GLES20Canvas_outputDisplayList(JNIEnv* env,
+        jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
+    renderer->outputDisplayList(displayList);
+}
+
 // ----------------------------------------------------------------------------
 // Layers
 // ----------------------------------------------------------------------------
@@ -714,7 +719,7 @@
     { "nGetDisplayListRenderer", "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListRenderer },
     { "nDrawDisplayList",        "(IIIILandroid/graphics/Rect;)Z",
                                                (void*) android_view_GLES20Canvas_drawDisplayList },
-
+    { "nOutputDisplayList",      "(II)V",      (void*) android_view_GLES20Canvas_outputDisplayList },
     { "nInterrupt",              "(I)V",       (void*) android_view_GLES20Canvas_interrupt },
     { "nResume",                 "(I)V",       (void*) android_view_GLES20Canvas_resume },
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 565f183..620d293 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -150,8 +150,8 @@
          does not require auto-restore. -->
     <!-- the 6th element indicates boot-time dependency-met value. -->
     <string-array translatable="false" name="networkAttributes">
-        <item>"wifi,1,1,1,true"</item>
-        <item>"mobile,0,0,0,true"</item>
+        <item>"wifi,1,1,1,-1,true"</item>
+        <item>"mobile,0,0,0,-1,true"</item>
         <item>"mobile_mms,2,0,2,60000,true"</item>
         <item>"mobile_supl,3,0,2,60000,true"</item>
         <item>"mobile_hipri,5,0,3,60000,true"</item>
diff --git a/docs/html/guide/topics/usb/accessory.jd b/docs/html/guide/topics/usb/accessory.jd
index 7638e30..b0f4881 100644
--- a/docs/html/guide/topics/usb/accessory.jd
+++ b/docs/html/guide/topics/usb/accessory.jd
@@ -50,9 +50,9 @@
     </div>
   </div>
 
-  <p><a href="http://accessories.android.com/demokit">USB accessory mode allows users to connect
+  <p>USB accessory mode allows users to connect
   USB host hardware specifically designed for Android-powered devices. The accessories must adhere
-  to the Android accessory protocol outlined in</a> <a href=
+  to the Android accessory protocol outlined in the <a href=
   "http://accessories.android.com/demokit">Android Accessory Development Kit</a> documentation.
   This allows Android-powered devices that cannot act as a USB host to still interact with USB
   hardware. When an Android-powered device is in USB accessory mode, the attached Android USB
@@ -445,7 +445,7 @@
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction(); 
 
-      if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
+        if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
             UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
             if (accessory != null) {
                 // call your method that cleans up and closes communication with the accessory
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 34dda9a..f8582d8 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -177,6 +177,331 @@
 void DisplayList::init() {
 }
 
+/**
+ * This function is a simplified version of replay(), where we simply retrieve and log the
+ * display list. This function should remain in sync with the replay() function.
+ */
+void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
+    TextContainer text;
+
+    uint32_t count = (level + 1) * 2;
+    char indent[count + 1];
+    for (uint32_t i = 0; i < count; i++) {
+        indent[i] = ' ';
+    }
+    indent[count] = '\0';
+    LOGD("%sStart display list (%p)", (char*) indent + 2, this);
+
+    int saveCount = renderer.getSaveCount() - 1;
+
+    mReader.rewind();
+
+    while (!mReader.eof()) {
+        int op = mReader.readInt();
+
+        switch (op) {
+            case DrawGLFunction: {
+                Functor *functor = (Functor *) getInt();
+                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
+            }
+            break;
+            case Save: {
+                int rendererNum = getInt();
+                LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
+            }
+            break;
+            case Restore: {
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case RestoreToCount: {
+                int restoreCount = saveCount + getInt();
+                LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
+            }
+            break;
+            case SaveLayer: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                SkPaint* paint = getPaint();
+                int flags = getInt();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
+                    OP_NAMES[op], f1, f2, f3, f4, paint, flags);
+            }
+            break;
+            case SaveLayerAlpha: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                int alpha = getInt();
+                int flags = getInt();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
+                    OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
+            }
+            break;
+            case Translate: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
+            }
+            break;
+            case Rotate: {
+                float rotation = getFloat();
+                LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
+            }
+            break;
+            case Scale: {
+                float sx = getFloat();
+                float sy = getFloat();
+                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+            }
+            break;
+            case Skew: {
+                float sx = getFloat();
+                float sy = getFloat();
+                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+            }
+            break;
+            case SetMatrix: {
+                SkMatrix* matrix = getMatrix();
+                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+            }
+            break;
+            case ConcatMatrix: {
+                SkMatrix* matrix = getMatrix();
+                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+            }
+            break;
+            case ClipRect: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                int regionOp = getInt();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
+                    f1, f2, f3, f4, regionOp);
+            }
+            break;
+            case DrawDisplayList: {
+                DisplayList* displayList = getDisplayList();
+                uint32_t width = getUInt();
+                uint32_t height = getUInt();
+                LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
+                    displayList, width, height, level + 1);
+                renderer.outputDisplayList(displayList, level + 1);
+            }
+            break;
+            case DrawLayer: {
+                Layer* layer = (Layer*) getInt();
+                float x = getFloat();
+                float y = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+                    layer, x, y, paint);
+            }
+            break;
+            case DrawBitmap: {
+                SkBitmap* bitmap = getBitmap();
+                float x = getFloat();
+                float y = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+                    bitmap, x, y, paint);
+            }
+            break;
+            case DrawBitmapMatrix: {
+                SkBitmap* bitmap = getBitmap();
+                SkMatrix* matrix = getMatrix();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
+                    bitmap, matrix, paint);
+            }
+            break;
+            case DrawBitmapRect: {
+                SkBitmap* bitmap = getBitmap();
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                float f5 = getFloat();
+                float f6 = getFloat();
+                float f7 = getFloat();
+                float f8 = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+                    (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
+            }
+            break;
+            case DrawBitmapMesh: {
+                int verticesCount = 0;
+                uint32_t colorsCount = 0;
+                SkBitmap* bitmap = getBitmap();
+                uint32_t meshWidth = getInt();
+                uint32_t meshHeight = getInt();
+                float* vertices = getFloats(verticesCount);
+                bool hasColors = getInt();
+                int* colors = hasColors ? getInts(colorsCount) : NULL;
+                SkPaint* paint = getPaint();
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case DrawPatch: {
+                int32_t* xDivs = NULL;
+                int32_t* yDivs = NULL;
+                uint32_t* colors = NULL;
+                uint32_t xDivsCount = 0;
+                uint32_t yDivsCount = 0;
+                int8_t numColors = 0;
+                SkBitmap* bitmap = getBitmap();
+                xDivs = getInts(xDivsCount);
+                yDivs = getInts(yDivsCount);
+                colors = getUInts(numColors);
+                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+                getFloat();
+                getFloat();
+                getFloat();
+                getFloat();
+                getPaint();
+            }
+            break;
+            case DrawColor: {
+                int color = getInt();
+                int xferMode = getInt();
+                LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
+            }
+            break;
+            case DrawRect: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+                    f1, f2, f3, f4, paint);
+            }
+            break;
+            case DrawRoundRect: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                float f5 = getFloat();
+                float f6 = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
+            }
+            break;
+            case DrawCircle: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %.2f, %.2f, %.2f, %p",
+                    (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
+            }
+            break;
+            case DrawOval: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
+                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
+            }
+            break;
+            case DrawArc: {
+                float f1 = getFloat();
+                float f2 = getFloat();
+                float f3 = getFloat();
+                float f4 = getFloat();
+                float f5 = getFloat();
+                float f6 = getFloat();
+                int i1 = getInt();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
+                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
+            }
+            break;
+            case DrawPath: {
+                SkPath* path = getPath();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
+            }
+            break;
+            case DrawLines: {
+                int count = 0;
+                float* points = getFloats(count);
+                SkPaint* paint = getPaint();
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case DrawPoints: {
+                int count = 0;
+                float* points = getFloats(count);
+                SkPaint* paint = getPaint();
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case DrawText: {
+                getText(&text);
+                int count = getInt();
+                float x = getFloat();
+                float y = getFloat();
+                SkPaint* paint = getPaint();
+                LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+                    text.text(), text.length(), count, x, y, paint);
+            }
+            break;
+            case ResetShader: {
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case SetupShader: {
+                SkiaShader* shader = getShader();
+                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
+            }
+            break;
+            case ResetColorFilter: {
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case SetupColorFilter: {
+                SkiaColorFilter *colorFilter = getColorFilter();
+                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
+            }
+            break;
+            case ResetShadow: {
+                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+            }
+            break;
+            case SetupShadow: {
+                float radius = getFloat();
+                float dx = getFloat();
+                float dy = getFloat();
+                int color = getInt();
+                LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
+                    radius, dx, dy, color);
+            }
+            break;
+            default:
+                LOGD("Display List error: op not handled: %s%s",
+                    (char*) indent, OP_NAMES[op]);
+                break;
+        }
+    }
+
+    LOGD("%sDone", (char*) indent + 2);
+}
+
+/**
+ * Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked
+ * in the output() function, since that function processes the same list of opcodes for the
+ * purposes of logging display list info for a given view.
+ */
 bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
     bool needsInvalidate = false;
     TextContainer text;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b782103..dcf2cf2 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -107,6 +107,8 @@
 
     bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
 
+    void output(OpenGLRenderer& renderer, uint32_t level = 0);
+
     static void outputLogBuffer(int fd);
 
 private:
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6f751e8..f6a21d4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1185,6 +1185,12 @@
     return false;
 }
 
+void OpenGLRenderer::outputDisplayList(DisplayList* displayList, uint32_t level) {
+    if (displayList) {
+        displayList->output(*this, level);
+    }
+}
+
 void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) {
     int alpha;
     SkXfermode::Mode mode;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b5c37c2..271e4b1 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -98,6 +98,7 @@
 
     virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
             Rect& dirty, uint32_t level = 0);
+    virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0);
     virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/services/java/com/android/server/wm/ViewServer.java b/services/java/com/android/server/wm/ViewServer.java
index cebd5e7..9fb35b9 100644
--- a/services/java/com/android/server/wm/ViewServer.java
+++ b/services/java/com/android/server/wm/ViewServer.java
@@ -49,7 +49,7 @@
     // Debug facility
     private static final String LOG_TAG = "ViewServer";
 
-    private static final String VALUE_PROTOCOL_VERSION = "3";
+    private static final String VALUE_PROTOCOL_VERSION = "4";
     private static final String VALUE_SERVER_VERSION = "4";
 
     // Protocol commands
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index ad4e796..ad39b27 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 
 import com.android.internal.R;
+import com.android.internal.telephony.DataConnection.FailCause;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
@@ -202,6 +203,19 @@
     //       getActionIntentReconnectAlarm.
     protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
+    // Used for debugging. Send the INTENT with an optional counter value with the number
+    // of times the setup is to fail before succeeding. If the counter isn't passed the
+    // setup will fail once. Example fail two times with FailCause.SIGNAL_LOST(-3)
+    // adb shell am broadcast \
+    //  -a com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter \
+    //  --ei fail_data_setup_counter 3 --ei fail_data_setup_fail_cause -3
+    protected static final String INTENT_SET_FAIL_DATA_SETUP_COUNTER =
+        "com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter";
+    protected static final String FAIL_DATA_SETUP_COUNTER = "fail_data_setup_counter";
+    protected int mFailDataSetupCounter = 0;
+    protected static final String FAIL_DATA_SETUP_FAIL_CAUSE = "fail_data_setup_fail_cause";
+    protected FailCause mFailDataSetupFailCause = FailCause.ERROR_UNSPECIFIED;
+
     // member variables
     protected PhoneBase mPhone;
     protected Activity mActivity = Activity.NONE;
@@ -275,6 +289,7 @@
         public void onReceive(Context context, Intent intent)
         {
             String action = intent.getAction();
+            if (DBG) log("onReceive: action=" + action);
             if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 mIsScreenOn = true;
                 stopNetStatPoll();
@@ -300,10 +315,36 @@
                     // quit and won't report disconnected until next enabling.
                     mIsWifiConnected = false;
                 }
+            } else if (action.equals(INTENT_SET_FAIL_DATA_SETUP_COUNTER)) {
+                mFailDataSetupCounter = intent.getIntExtra(FAIL_DATA_SETUP_COUNTER, 1);
+                mFailDataSetupFailCause = FailCause.fromInt(
+                        intent.getIntExtra(FAIL_DATA_SETUP_FAIL_CAUSE,
+                                                    FailCause.ERROR_UNSPECIFIED.getErrorCode()));
+                if (DBG) log("set mFailDataSetupCounter=" + mFailDataSetupCounter +
+                        " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
             }
         }
     };
 
+    protected boolean isDataSetupCompleteOk(AsyncResult ar) {
+        if (ar.exception != null) {
+            if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
+            return false;
+        }
+        if (mFailDataSetupCounter <= 0) {
+            if (DBG) log("isDataSetupCompleteOk return true");
+            return true;
+        }
+        ar.result = mFailDataSetupFailCause;
+        if (DBG) {
+            log("isDataSetupCompleteOk return false" +
+                    " mFailDataSetupCounter=" + mFailDataSetupCounter +
+                    " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
+        }
+        mFailDataSetupCounter -= 1;
+        return false;
+    }
+
     protected void onActionIntentReconnectAlarm(Intent intent) {
         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
         if (mState == State.FAILED) {
@@ -329,6 +370,7 @@
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
 
         mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
                 Settings.Secure.MOBILE_DATA, 1) == 1;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 4b185a0..2f783e8 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -54,9 +54,6 @@
 
     private CDMAPhone mCdmaPhone;
 
-    //useful for debugging
-    boolean mFailNextConnect = false;
-
     /** The DataConnection being setup */
     private CdmaDataConnection mPendingDataConnection;
 
@@ -660,7 +657,7 @@
             reason = (String) ar.userObj;
         }
 
-        if (ar.exception == null) {
+        if (isDataSetupCompleteOk(ar)) {
             // Everything is setup
             notifyDefaultData(reason);
         } else {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index a1b4376..69a8153 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -104,9 +104,6 @@
     /** Delay between APN attempts */
     protected static final int APN_DELAY_MILLIS = 5000;
 
-    //useful for debugging
-    boolean mFailNextConnect = false;
-
     //***** Constants
 
     private static final int POLL_PDP_MILLIS = 5 * 1000;
@@ -1574,13 +1571,14 @@
         } else {
             throw new RuntimeException("onDataSetupComplete: No apnContext");
         }
-        DataConnectionAc dcac = apnContext.getDataConnectionAc();
-        if (dcac == null) {
-            throw new RuntimeException("onDataSetupCompete: No dcac");
-        }
-        DataConnection dc = apnContext.getDataConnection();
 
-        if (ar.exception == null) {
+        if (isDataSetupCompleteOk(ar)) {
+            DataConnectionAc dcac = apnContext.getDataConnectionAc();
+            if (dcac == null) {
+                throw new RuntimeException("onDataSetupCompete: No dcac");
+            }
+            DataConnection dc = apnContext.getDataConnection();
+
             if (DBG) {
                 log(String.format("onDataSetupComplete: success apn=%s",
                     apnContext.getWaitingApns().get(0).apn) + " refCount=" + dc.getRefCount());
@@ -1612,16 +1610,11 @@
             }
             notifyDefaultData(apnContext);
         } else {
-            int refCount = releaseApnContext(apnContext, false);
-            if (DBG) {
-                log(String.format("onDataSetupComplete: error apn=%s",
-                    apnContext.getWaitingApns().get(0).apn) + " refCount=" + refCount);
-            }
+            String apnString;
+            DataConnection.FailCause cause;
 
-            GsmDataConnection.FailCause cause;
-            cause = (GsmDataConnection.FailCause) (ar.result);
+            cause = (DataConnection.FailCause) (ar.result);
             if (DBG) {
-                String apnString;
                 try {
                     apnString = apnContext.getWaitingApns().get(0).apn;
                 } catch (Exception e) {
@@ -1667,6 +1660,11 @@
                 sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext),
                         APN_DELAY_MILLIS);
             }
+
+            int refCount = releaseApnContext(apnContext, false);
+            if (DBG) {
+                log("onDataSetupComplete: error apn=%s" + apnString + " refCount=" + refCount);
+            }
         }
     }