Merge "Add option to enable scrim SRC optimization" into lmp-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index e3cbef5..2e24785 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1970,9 +1970,9 @@
      * {@hide}
      */
     public void setProvisioningNotificationVisible(boolean visible, int networkType,
-            String extraInfo, String url) {
+            String action) {
         try {
-            mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url);
+            mService.setProvisioningNotificationVisible(visible, networkType, action);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 974c4cd..a983d88 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -139,8 +139,7 @@
 
     LinkQualityInfo[] getAllLinkQualityInfo();
 
-    void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo,
-            in String url);
+    void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
 
     void setAirplaneMode(boolean enable);
 
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b2ebc31..3ada9bb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -469,6 +469,7 @@
      * @param seInfo null-ok SELinux information for the new process.
      * @param abi non-null the ABI this app should be started with.
      * @param instructionSet null-ok the instruction set to use.
+     * @param appDataDir null-ok the data directory of the app.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return An object that describes the result of the attempt to start the process.
@@ -484,11 +485,12 @@
                                   String seInfo,
                                   String abi,
                                   String instructionSet,
+                                  String appDataDir,
                                   String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     debugFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, zygoteArgs);
+                    abi, instructionSet, appDataDir, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -592,6 +594,7 @@
      * @param seInfo null-ok SELinux information for the new process.
      * @param abi the ABI the process should use.
      * @param instructionSet null-ok the instruction set to use.
+     * @param appDataDir null-ok the data directory of the app.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -605,6 +608,7 @@
                                   String seInfo,
                                   String abi,
                                   String instructionSet,
+                                  String appDataDir,
                                   String[] extraArgs)
                                   throws ZygoteStartFailedEx {
         synchronized(Process.class) {
@@ -668,6 +672,10 @@
                 argsForZygote.add("--instruction-set=" + instructionSet);
             }
 
+            if (appDataDir != null) {
+                argsForZygote.add("--app-data-dir=" + appDataDir);
+            }
+
             argsForZygote.add(processClass);
 
             if (extraArgs != null) {
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index baa133d..1cadf69 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -1138,7 +1138,7 @@
             if (parentVirtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
                     || parentAccessibilityViewId == providerHost.getAccessibilityViewId()) {
                 final AccessibilityNodeInfo parent;
-                if (parentAccessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                if (parentVirtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
                     parent = provider.createAccessibilityNodeInfo(parentVirtualDescendantId);
                 } else {
                     parent = provider.createAccessibilityNodeInfo(
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index e4500eb..50c927a 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -19,6 +19,8 @@
 import android.graphics.Matrix;
 import android.widget.FrameLayout;
 
+import java.util.ArrayList;
+
 /**
  * This view draws another View in an Overlay without changing the parent. It will not be drawn
  * by its parent because its visibility is set to INVISIBLE, but will be drawn
@@ -30,6 +32,7 @@
 public class GhostView extends View {
     private final View mView;
     private int mReferences;
+    private boolean mBeingMoved;
 
     private GhostView(View view) {
         super(view.getContext());
@@ -75,12 +78,14 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        setGhostedVisibility(View.VISIBLE);
-        mView.mGhostView = null;
-        final ViewGroup parent = (ViewGroup) mView.getParent();
-        if (parent != null) {
-            parent.mRecreateDisplayList = true;
-            parent.getDisplayList();
+        if (!mBeingMoved) {
+            setGhostedVisibility(View.VISIBLE);
+            mView.mGhostView = null;
+            final ViewGroup parent = (ViewGroup) mView.getParent();
+            if (parent != null) {
+                parent.mRecreateDisplayList = true;
+                parent.getDisplayList();
+            }
         }
     }
 
@@ -121,7 +126,9 @@
             copySize(viewGroup, parent);
             copySize(viewGroup, ghostView);
             parent.addView(ghostView);
-            overlay.add(parent);
+            ArrayList<View> tempViews = new ArrayList<View>();
+            int firstGhost = moveGhostViewsToTop(overlay.mOverlayViewGroup, tempViews);
+            insertIntoOverlay(overlay.mOverlayViewGroup, parent, ghostView, tempViews, firstGhost);
             ghostView.mReferences = previousRefCount;
         } else if (matrix != null) {
             ghostView.setMatrix(matrix);
@@ -156,4 +163,180 @@
         to.setRight(from.getWidth());
         to.setBottom(from.getHeight());
     }
+
+    /**
+     * Move the GhostViews to the end so that they are on top of other views and it is easier
+     * to do binary search for the correct location for the GhostViews in insertIntoOverlay.
+     *
+     * @return The index of the first GhostView or -1 if no GhostView is in the ViewGroup
+     */
+    private static int moveGhostViewsToTop(ViewGroup viewGroup, ArrayList<View> tempViews) {
+        final int numChildren = viewGroup.getChildCount();
+        if (numChildren == 0) {
+            return -1;
+        } else if (isGhostWrapper(viewGroup.getChildAt(numChildren - 1))) {
+            // GhostViews are already at the end
+            int firstGhost = numChildren - 1;
+            for (int i = numChildren - 2; i >= 0; i--) {
+                if (!isGhostWrapper(viewGroup.getChildAt(i))) {
+                    break;
+                }
+                firstGhost = i;
+            }
+            return firstGhost;
+        }
+
+        // Remove all GhostViews from the middle
+        for (int i = numChildren - 2; i >= 0; i--) {
+            View child = viewGroup.getChildAt(i);
+            if (isGhostWrapper(child)) {
+                tempViews.add(child);
+                GhostView ghostView = (GhostView)((ViewGroup)child).getChildAt(0);
+                ghostView.mBeingMoved = true;
+                viewGroup.removeViewAt(i);
+                ghostView.mBeingMoved = false;
+            }
+        }
+
+        final int firstGhost;
+        if (tempViews.isEmpty()) {
+            firstGhost = -1;
+        } else {
+            firstGhost = viewGroup.getChildCount();
+            // Add the GhostViews to the end
+            for (int i = tempViews.size() - 1; i >= 0; i--) {
+                viewGroup.addView(tempViews.get(i));
+            }
+            tempViews.clear();
+        }
+        return firstGhost;
+    }
+
+    /**
+     * Inserts a GhostView into the overlay's ViewGroup in the order in which they
+     * should be displayed by the UI.
+     */
+    private static void insertIntoOverlay(ViewGroup viewGroup, ViewGroup wrapper,
+            GhostView ghostView, ArrayList<View> tempParents, int firstGhost) {
+        if (firstGhost == -1) {
+            viewGroup.addView(wrapper);
+        } else {
+            ArrayList<View> viewParents = new ArrayList<View>();
+            getParents(ghostView.mView, viewParents);
+
+            int index = getInsertIndex(viewGroup, viewParents, tempParents, firstGhost);
+            if (index < 0 || index >= viewGroup.getChildCount()) {
+                viewGroup.addView(wrapper);
+            } else {
+                viewGroup.addView(wrapper, index);
+            }
+        }
+    }
+
+    /**
+     * Find the index into the overlay to insert the GhostView based on the order that the
+     * views should be drawn. This keeps GhostViews layered in the same order
+     * that they are ordered in the UI.
+     */
+    private static int getInsertIndex(ViewGroup overlayViewGroup, ArrayList<View> viewParents,
+            ArrayList<View> tempParents, int firstGhost) {
+        int low = firstGhost;
+        int high = overlayViewGroup.getChildCount() - 1;
+
+        while (low <= high) {
+            int mid = (low + high) / 2;
+            ViewGroup wrapper = (ViewGroup) overlayViewGroup.getChildAt(mid);
+            GhostView midView = (GhostView) wrapper.getChildAt(0);
+            getParents(midView.mView, tempParents);
+            if (isOnTop(viewParents, tempParents)) {
+                low = mid + 1;
+            } else {
+                high = mid - 1;
+            }
+            tempParents.clear();
+        }
+
+        return low;
+    }
+
+    /**
+     * Returns true if view is a GhostView's FrameLayout wrapper.
+     */
+    private static boolean isGhostWrapper(View view) {
+        if (view instanceof FrameLayout) {
+            FrameLayout frameLayout = (FrameLayout) view;
+            if (frameLayout.getChildCount() == 1) {
+                View child = frameLayout.getChildAt(0);
+                return child instanceof GhostView;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if viewParents is from a View that is on top of the comparedWith's view.
+     * The ArrayLists contain the ancestors of views in order from top most grandparent, to
+     * the view itself, in order. The goal is to find the first matching parent and then
+     * compare the draw order of the siblings.
+     */
+    private static boolean isOnTop(ArrayList<View> viewParents, ArrayList<View> comparedWith) {
+        if (viewParents.isEmpty() || comparedWith.isEmpty() ||
+                viewParents.get(0) != comparedWith.get(0)) {
+            // Not the same decorView -- arbitrary ordering
+            return true;
+        }
+        int depth = Math.min(viewParents.size(), comparedWith.size());
+        for (int i = 1; i < depth; i++) {
+            View viewParent = viewParents.get(i);
+            View comparedWithParent = comparedWith.get(i);
+
+            if (viewParent != comparedWithParent) {
+                // i - 1 is the same parent, but these are different children.
+                return isOnTop(viewParent, comparedWithParent);
+            }
+        }
+
+        // one of these is the parent of the other
+        boolean isComparedWithTheParent = (comparedWith.size() == depth);
+        return isComparedWithTheParent;
+    }
+
+    /**
+     * Adds all the parents, grandparents, etc. of view to parents.
+     */
+    private static void getParents(View view, ArrayList<View> parents) {
+        ViewParent parent = view.getParent();
+        if (parent != null && parent instanceof ViewGroup) {
+            getParents((View) parent, parents);
+        }
+        parents.add(view);
+    }
+
+    /**
+     * Returns true if view would be drawn on top of comparedWith or false otherwise.
+     * view and comparedWith are siblings with the same parent. This uses the logic
+     * that dispatchDraw uses to determine which View should be drawn first.
+     */
+    private static boolean isOnTop(View view, View comparedWith) {
+        ViewGroup parent = (ViewGroup) view.getParent();
+
+        final int childrenCount = parent.getChildCount();
+        final ArrayList<View> preorderedList = parent.buildOrderedChildList();
+        final boolean customOrder = preorderedList == null
+                && parent.isChildrenDrawingOrderEnabled();
+        for (int i = 0; i < childrenCount; i++) {
+            int childIndex = customOrder ? parent.getChildDrawingOrder(childrenCount, i) : i;
+            final View child = (preorderedList == null)
+                    ? parent.getChildAt(childIndex) : preorderedList.get(childIndex);
+            if (child == view) {
+                return false;
+            } else if (child == comparedWith) {
+                return true;
+            }
+        }
+
+        // Shouldn't get here. Neither of the children is in the parent.
+        // Just return an arbitrary one.
+        return true;
+    }
 }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 6d3b419..b586caa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3298,7 +3298,7 @@
      * Uses a stable, insertion sort which is commonly O(n) for ViewGroups with very few elevated
      * children.
      */
-    private ArrayList<View> buildOrderedChildList() {
+    ArrayList<View> buildOrderedChildList() {
         final int count = mChildrenCount;
         if (count <= 1 || !hasChildWithZ()) return null;
 
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c579a15..cca340c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -79,19 +79,20 @@
      * (and replaced by /dev/null) after forking.  An integer value
      * of -1 in any entry in the array means "ignore this one".
      * @param instructionSet null-ok the instruction set to use.
+     * @param appDataDir null-ok the data directory of the app.
      *
      * @return 0 if this is the child, pid of the child
      * if this is the parent, or -1 on error.
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet) {
+          String instructionSet, String appDataDir) {
         long startTime = SystemClock.elapsedRealtime();
         VM_HOOKS.preFork();
         checkTime(startTime, "Zygote.preFork");
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  instructionSet);
+                  instructionSet, appDataDir);
         checkTime(startTime, "Zygote.nativeForkAndSpecialize");
         VM_HOOKS.postForkCommon();
         checkTime(startTime, "Zygote.postForkCommon");
@@ -100,7 +101,7 @@
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet);
+          String instructionSet, String appDataDir);
 
     /**
      * Temporary hack: check time since start time and log if over a fixed threshold.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index fb50b25..2ef8a20 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -93,7 +93,7 @@
                 new InputStreamReader(socket.getInputStream()), 256);
 
         mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
-                
+
         try {
             peer = mSocket.getPeerCredentials();
         } catch (IOException ex) {
@@ -245,7 +245,8 @@
             checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet);
+                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
+                    parsedArgs.appDataDir);
             checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
         } catch (IOException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
@@ -404,6 +405,12 @@
         String instructionSet;
 
         /**
+         * The app data directory. May be null, e.g., for the system server. Note that this might
+         * not be reliable in the case of process-sharing apps.
+         */
+        String appDataDir;
+
+        /**
          * Constructs instance and parses args
          * @param args zygote command-line args
          * @throws IllegalArgumentException
@@ -560,6 +567,8 @@
                     abiListQuery = true;
                 } else if (arg.startsWith("--instruction-set=")) {
                     instructionSet = arg.substring(arg.indexOf('=') + 1);
+                } else if (arg.startsWith("--app-data-dir=")) {
+                    appDataDir = arg.substring(arg.indexOf('=') + 1);
                 } else {
                     break;
                 }
@@ -611,7 +620,7 @@
         }
 
         // See bug 1092107: large argc can be used for a DOS attack
-        if (argc > MAX_ZYGOTE_ARGC) {   
+        if (argc > MAX_ZYGOTE_ARGC) {
             throw new IOException("max arg count exceeded");
         }
 
@@ -628,7 +637,7 @@
     }
 
     /**
-     * Applies zygote security policy per bugs #875058 and #1082165. 
+     * Applies zygote security policy per bugs #875058 and #1082165.
      * Based on the credentials of the process issuing a zygote command:
      * <ol>
      * <li> uid 0 (root) may specify any uid, gid, and setgroups() list
@@ -659,7 +668,7 @@
             /* In normal operation, SYSTEM_UID can only specify a restricted
              * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
              */
-            uidRestricted  
+            uidRestricted
                  = !(factoryTest.equals("1") || factoryTest.equals("2"));
 
             if (uidRestricted
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 451d97a..7ca9374 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -51,6 +51,8 @@
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
 
+#include "nativebridge/native_bridge.h"
+
 namespace {
 
 using android::String8;
@@ -249,20 +251,24 @@
 
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
-static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
-  if (mount_mode == MOUNT_EXTERNAL_NONE) {
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode, bool force_mount_namespace) {
+  if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
     return true;
   }
 
-  // See storage config details at http://source.android.com/tech/storage/
-  userid_t user_id = multiuser_get_user_id(uid);
-
   // Create a second private mount namespace for our process
   if (unshare(CLONE_NEWNS) == -1) {
       ALOGW("Failed to unshare(): %d", errno);
       return false;
   }
 
+  if (mount_mode == MOUNT_EXTERNAL_NONE) {
+    return true;
+  }
+
+  // See storage config details at http://source.android.com/tech/storage/
+  userid_t user_id = multiuser_get_user_id(uid);
+
   // Create bind mounts to expose external storage
   if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
     // These paths must already be created by init.rc
@@ -422,7 +428,7 @@
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose,
-                                     jstring instructionSet) {
+                                     jstring instructionSet, jstring dataDir) {
   uint64_t start = MsTime();
   SetSigChldHandler();
   ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
@@ -446,7 +452,13 @@
 
     DropCapabilitiesBoundingSet(env);
 
-    if (!MountEmulatedStorage(uid, mount_external)) {
+    bool need_native_bridge = false;
+    if (instructionSet != NULL) {
+      ScopedUtfChars isa_string(env, instructionSet);
+      need_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
+    }
+
+    if (!MountEmulatedStorage(uid, mount_external, need_native_bridge)) {
       ALOGW("Failed to mount emulated storage: %d", errno);
       if (errno == ENOTCONN || errno == EROFS) {
         // When device is actively encrypting, we get ENOTCONN here
@@ -475,6 +487,17 @@
 
     SetRLimits(env, javaRlimits);
 
+    if (!is_system_server && need_native_bridge) {
+      // Set the environment for the apps running with native bridge.
+      ScopedUtfChars isa_string(env, instructionSet);  // Known non-null because of need_native_...
+      if (dataDir == NULL) {
+        android::PreInitializeNativeBridge(NULL, isa_string.c_str());
+      } else {
+        ScopedUtfChars data_dir(env, dataDir);
+        android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
+      }
+    }
+
     int rc = setresgid(gid, gid, gid);
     if (rc == -1) {
       ALOGE("setresgid(%d) failed", gid);
@@ -563,7 +586,7 @@
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint debug_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose, jstring instructionSet) {
+        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
     jlong capabilities = 0;
     if (uid == AID_BLUETOOTH) {
@@ -572,7 +595,7 @@
 
     return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
             rlimits, capabilities, capabilities, mount_external, se_info,
-            se_name, false, fdsToClose, instructionSet);
+            se_name, false, fdsToClose, instructionSet, appDataDir);
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -582,7 +605,8 @@
   pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                       debug_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
-                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL);
+                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
+                                      NULL, NULL);
   if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -601,7 +625,7 @@
 
 static JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index aa42c75..84ada6f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -566,6 +566,9 @@
     }
 
     private void startCreateDocumentActivity() {
+        if (!isResumed()) {
+            return;
+        }
         PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
         if (info == null) {
             return;
@@ -724,10 +727,35 @@
             }
         }
 
+        // Handle selected page changes making sure they are in the doc.
         PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
         final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
         PageRange[] pageRanges = printJobInfo.getPages();
-        updateSelectedPages(pageRanges, pageCount);
+        if (pageRanges != null && pageCount > 0) {
+            pageRanges = PageRangeUtils.normalize(pageRanges);
+
+            List<PageRange> validatedList = new ArrayList<>();
+            final int rangeCount = pageRanges.length;
+            for (int i = 0; i < rangeCount; i++) {
+                PageRange pageRange = pageRanges[i];
+                if (pageRange.getEnd() >= pageCount) {
+                    final int rangeStart = pageRange.getStart();
+                    final int rangeEnd = pageCount - 1;
+                    if (rangeStart <= rangeEnd) {
+                        pageRange = new PageRange(rangeStart, rangeEnd);
+                        validatedList.add(pageRange);
+                    }
+                    break;
+                }
+                validatedList.add(pageRange);
+            }
+
+            if (!validatedList.isEmpty()) {
+                PageRange[] validatedArray = new PageRange[validatedList.size()];
+                validatedList.toArray(validatedArray);
+                updateSelectedPages(validatedArray, pageCount);
+            }
+        }
 
         // Update the content if needed.
         if (canUpdateDocument()) {
@@ -1347,7 +1375,8 @@
             mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
             mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
         }
-        if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
+        if (!mPrintedDocument.getDocumentInfo().laidout
+                ||(mRangeOptionsSpinner.getSelectedItemPosition() == 1
                 && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
                 || (mRangeOptionsSpinner.getSelectedItemPosition() == 0
                 && (mPrintedDocument.getDocumentInfo() == null || hasErrors()))) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index b842a6b..1186a33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -34,6 +34,7 @@
     private float mLastX;
     private float mLastY;
     private boolean mBlockFlinging;
+    private boolean mTouchCancelled;
 
     public ObservableScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -87,9 +88,20 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        boolean isEndGuesture = (ev.getAction() == MotionEvent.ACTION_UP
-                || ev.getAction() == MotionEvent.ACTION_CANCEL);
-        if (!mTouchEnabled && !isEndGuesture) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (!mTouchEnabled) {
+                mTouchCancelled = true;
+                return false;
+            }
+            mTouchCancelled = false;
+        } else if (mTouchCancelled) {
+            return false;
+        } else if (!mTouchEnabled) {
+            MotionEvent cancel = MotionEvent.obtain(ev);
+            cancel.setAction(MotionEvent.ACTION_CANCEL);
+            super.dispatchTouchEvent(ev);
+            cancel.recycle();
+            mTouchCancelled = true;
             return false;
         }
         return super.dispatchTouchEvent(ev);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a3c64d0..0b1a627 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -745,10 +745,6 @@
 
         mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
 
-        filter = new IntentFilter();
-        filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
-        mContext.registerReceiver(mProvisioningReceiver, filter);
-
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
 
@@ -1947,23 +1943,6 @@
                             state + "/" + info.getDetailedState());
                     }
 
-                    // Since mobile has the notion of a network/apn that can be used for
-                    // provisioning we need to check every time we're connected as
-                    // CaptiveProtalTracker won't detected it because DCT doesn't report it
-                    // as connected as ACTION_ANY_DATA_CONNECTION_STATE_CHANGED instead its
-                    // reported as ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN. Which
-                    // is received by MDST and sent here as EVENT_STATE_CHANGED.
-                    if (ConnectivityManager.isNetworkTypeMobile(info.getType())
-                            && (0 != Settings.Global.getInt(mContext.getContentResolver(),
-                                        Settings.Global.DEVICE_PROVISIONED, 0))
-                            && (((state == NetworkInfo.State.CONNECTED)
-                                    && (info.getType() == ConnectivityManager.TYPE_MOBILE))
-                                || info.isConnectedToProvisioningNetwork())) {
-                        log("ConnectivityChange checkMobileProvisioning for"
-                                + " TYPE_MOBILE or ProvisioningNetwork");
-                        checkMobileProvisioning(CheckMp.MAX_TIMEOUT_MS);
-                    }
-
                     EventLogTags.writeConnectivityStateChanged(
                             info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
 
@@ -2931,733 +2910,25 @@
                          enabled));
     }
 
-    private boolean isMobileDataStateTrackerReady() {
-        MobileDataStateTracker mdst =
-                (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
-        return (mdst != null) && (mdst.isReady());
-    }
-
-    /**
-     * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE)
-     */
-
-    /**
-     * No connection was possible to the network.
-     * This is NOT a warm sim.
-     */
-    private static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
-
-    /**
-     * A connection was made to the internet, all is well.
-     * This is NOT a warm sim.
-     */
-    private static final int CMP_RESULT_CODE_CONNECTABLE = 1;
-
-    /**
-     * A connection was made but no dns server was available to resolve a name to address.
-     * This is NOT a warm sim since provisioning network is supported.
-     */
-    private static final int CMP_RESULT_CODE_NO_DNS = 2;
-
-    /**
-     * A connection was made but could not open a TCP connection.
-     * This is NOT a warm sim since provisioning network is supported.
-     */
-    private static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 3;
-
-    /**
-     * A connection was made but there was a redirection, we appear to be in walled garden.
-     * This is an indication of a warm sim on a mobile network such as T-Mobile.
-     */
-    private static final int CMP_RESULT_CODE_REDIRECTED = 4;
-
-    /**
-     * The mobile network is a provisioning network.
-     * This is an indication of a warm sim on a mobile network such as AT&T.
-     */
-    private static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5;
-
-    /**
-     * The mobile network is provisioning
-     */
-    private static final int CMP_RESULT_CODE_IS_PROVISIONING = 6;
-
-    private AtomicBoolean mIsProvisioningNetwork = new AtomicBoolean(false);
-    private AtomicBoolean mIsStartingProvisioning = new AtomicBoolean(false);
-
-    private AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false);
-
     @Override
     public int checkMobileProvisioning(int suggestedTimeOutMs) {
-        int timeOutMs = -1;
-        if (DBG) log("checkMobileProvisioning: E suggestedTimeOutMs=" + suggestedTimeOutMs);
-        enforceConnectivityInternalPermission();
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            timeOutMs = suggestedTimeOutMs;
-            if (suggestedTimeOutMs > CheckMp.MAX_TIMEOUT_MS) {
-                timeOutMs = CheckMp.MAX_TIMEOUT_MS;
-            }
-
-            // Check that mobile networks are supported
-            if (!isNetworkSupported(ConnectivityManager.TYPE_MOBILE)
-                    || !isNetworkSupported(ConnectivityManager.TYPE_MOBILE_HIPRI)) {
-                if (DBG) log("checkMobileProvisioning: X no mobile network");
-                return timeOutMs;
-            }
-
-            // If we're already checking don't do it again
-            // TODO: Add a queue of results...
-            if (mIsCheckingMobileProvisioning.getAndSet(true)) {
-                if (DBG) log("checkMobileProvisioning: X already checking ignore for the moment");
-                return timeOutMs;
-            }
-
-            // Start off with mobile notification off
-            setProvNotificationVisible(false, ConnectivityManager.TYPE_MOBILE_HIPRI, null, null);
-
-            CheckMp checkMp = new CheckMp(mContext, this);
-            CheckMp.CallBack cb = new CheckMp.CallBack() {
-                @Override
-                void onComplete(Integer result) {
-                    if (DBG) log("CheckMp.onComplete: result=" + result);
-                    NetworkInfo ni =
-                            mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo();
-                    switch(result) {
-                        case CMP_RESULT_CODE_CONNECTABLE:
-                        case CMP_RESULT_CODE_NO_CONNECTION:
-                        case CMP_RESULT_CODE_NO_DNS:
-                        case CMP_RESULT_CODE_NO_TCP_CONNECTION: {
-                            if (DBG) log("CheckMp.onComplete: ignore, connected or no connection");
-                            break;
-                        }
-                        case CMP_RESULT_CODE_REDIRECTED: {
-                            if (DBG) log("CheckMp.onComplete: warm sim");
-                            String url = getMobileProvisioningUrl();
-                            if (TextUtils.isEmpty(url)) {
-                                url = getMobileRedirectedProvisioningUrl();
-                            }
-                            if (TextUtils.isEmpty(url) == false) {
-                                if (DBG) log("CheckMp.onComplete: warm (redirected), url=" + url);
-                                setProvNotificationVisible(true,
-                                        ConnectivityManager.TYPE_MOBILE_HIPRI, ni.getExtraInfo(),
-                                        url);
-                            } else {
-                                if (DBG) log("CheckMp.onComplete: warm (redirected), no url");
-                            }
-                            break;
-                        }
-                        case CMP_RESULT_CODE_PROVISIONING_NETWORK: {
-                            String url = getMobileProvisioningUrl();
-                            if (TextUtils.isEmpty(url) == false) {
-                                if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), url=" + url);
-                                setProvNotificationVisible(true,
-                                        ConnectivityManager.TYPE_MOBILE_HIPRI, ni.getExtraInfo(),
-                                        url);
-                                // Mark that we've got a provisioning network and
-                                // Disable Mobile Data until user actually starts provisioning.
-                                mIsProvisioningNetwork.set(true);
-                                MobileDataStateTracker mdst = (MobileDataStateTracker)
-                                        mNetTrackers[ConnectivityManager.TYPE_MOBILE];
-
-                                // Disable radio until user starts provisioning
-                                mdst.setRadio(false);
-                            } else {
-                                if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), no url");
-                            }
-                            break;
-                        }
-                        case CMP_RESULT_CODE_IS_PROVISIONING: {
-                            // FIXME: Need to know when provisioning is done. Probably we can
-                            // check the completion status if successful we're done if we
-                            // "timedout" or still connected to provisioning APN turn off data?
-                            if (DBG) log("CheckMp.onComplete: provisioning started");
-                            mIsStartingProvisioning.set(false);
-                            break;
-                        }
-                        default: {
-                            loge("CheckMp.onComplete: ignore unexpected result=" + result);
-                            break;
-                        }
-                    }
-                    mIsCheckingMobileProvisioning.set(false);
-                }
-            };
-            CheckMp.Params params =
-                    new CheckMp.Params(checkMp.getDefaultUrl(), timeOutMs, cb);
-            if (DBG) log("checkMobileProvisioning: params=" + params);
-            // TODO: Reenable when calls to the now defunct
-            //       MobileDataStateTracker.isProvisioningNetwork() are removed.
-            //       This code should be moved to the Telephony code.
-            // checkMp.execute(params);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-            if (DBG) log("checkMobileProvisioning: X");
-        }
-        return timeOutMs;
-    }
-
-    static class CheckMp extends
-            AsyncTask<CheckMp.Params, Void, Integer> {
-        private static final String CHECKMP_TAG = "CheckMp";
-
-        // adb shell setprop persist.checkmp.testfailures 1 to enable testing failures
-        private static boolean mTestingFailures;
-
-        // Choosing 4 loops as half of them will use HTTPS and the other half HTTP
-        private static final int MAX_LOOPS = 4;
-
-        // Number of milli-seconds to complete all of the retires
-        public static final int MAX_TIMEOUT_MS =  60000;
-
-        // The socket should retry only 5 seconds, the default is longer
-        private static final int SOCKET_TIMEOUT_MS = 5000;
-
-        // Sleep time for network errors
-        private static final int NET_ERROR_SLEEP_SEC = 3;
-
-        // Sleep time for network route establishment
-        private static final int NET_ROUTE_ESTABLISHMENT_SLEEP_SEC = 3;
-
-        // Short sleep time for polling :(
-        private static final int POLLING_SLEEP_SEC = 1;
-
-        private Context mContext;
-        private ConnectivityService mCs;
-        private TelephonyManager mTm;
-        private Params mParams;
-
-        /**
-         * Parameters for AsyncTask.execute
-         */
-        static class Params {
-            private String mUrl;
-            private long mTimeOutMs;
-            private CallBack mCb;
-
-            Params(String url, long timeOutMs, CallBack cb) {
-                mUrl = url;
-                mTimeOutMs = timeOutMs;
-                mCb = cb;
-            }
-
-            @Override
-            public String toString() {
-                return "{" + " url=" + mUrl + " mTimeOutMs=" + mTimeOutMs + " mCb=" + mCb + "}";
-            }
-        }
-
-        // As explained to me by Brian Carlstrom and Kenny Root, Certificates can be
-        // issued by name or ip address, for Google its by name so when we construct
-        // this HostnameVerifier we'll pass the original Uri and use it to verify
-        // the host. If the host name in the original uril fails we'll test the
-        // hostname parameter just incase things change.
-        static class CheckMpHostnameVerifier implements HostnameVerifier {
-            Uri mOrgUri;
-
-            CheckMpHostnameVerifier(Uri orgUri) {
-                mOrgUri = orgUri;
-            }
-
-            @Override
-            public boolean verify(String hostname, SSLSession session) {
-                HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
-                String orgUriHost = mOrgUri.getHost();
-                boolean retVal = hv.verify(orgUriHost, session) || hv.verify(hostname, session);
-                if (DBG) {
-                    log("isMobileOk: hostnameVerify retVal=" + retVal + " hostname=" + hostname
-                        + " orgUriHost=" + orgUriHost);
-                }
-                return retVal;
-            }
-        }
-
-        /**
-         * The call back object passed in Params. onComplete will be called
-         * on the main thread.
-         */
-        abstract static class CallBack {
-            // Called on the main thread.
-            abstract void onComplete(Integer result);
-        }
-
-        public CheckMp(Context context, ConnectivityService cs) {
-            if (Build.IS_DEBUGGABLE) {
-                mTestingFailures =
-                        SystemProperties.getInt("persist.checkmp.testfailures", 0) == 1;
-            } else {
-                mTestingFailures = false;
-            }
-
-            mContext = context;
-            mCs = cs;
-
-            // Setup access to TelephonyService we'll be using.
-            mTm = (TelephonyManager) mContext.getSystemService(
-                    Context.TELEPHONY_SERVICE);
-        }
-
-        /**
-         * Get the default url to use for the test.
-         */
-        public String getDefaultUrl() {
-            // See http://go/clientsdns for usage approval
-            String server = Settings.Global.getString(mContext.getContentResolver(),
-                    Settings.Global.CAPTIVE_PORTAL_SERVER);
-            if (server == null) {
-                server = "clients3.google.com";
-            }
-            return "http://" + server + "/generate_204";
-        }
-
-        /**
-         * Detect if its possible to connect to the http url. DNS based detection techniques
-         * do not work at all hotspots. The best way to check is to perform a request to
-         * a known address that fetches the data we expect.
-         */
-        private synchronized Integer isMobileOk(Params params) {
-            Integer result = CMP_RESULT_CODE_NO_CONNECTION;
-            Uri orgUri = Uri.parse(params.mUrl);
-            Random rand = new Random();
-            mParams = params;
-
-            if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
-                result = CMP_RESULT_CODE_NO_CONNECTION;
-                log("isMobileOk: X not mobile capable result=" + result);
-                return result;
-            }
-
-            if (mCs.mIsStartingProvisioning.get()) {
-                result = CMP_RESULT_CODE_IS_PROVISIONING;
-                log("isMobileOk: X is provisioning result=" + result);
-                return result;
-            }
-
-            // See if we've already determined we've got a provisioning connection,
-            // if so we don't need to do anything active.
-            MobileDataStateTracker mdstDefault = (MobileDataStateTracker)
-                    mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE];
-            boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork();
-            log("isMobileOk: isDefaultProvisioning=" + isDefaultProvisioning);
-
-            MobileDataStateTracker mdstHipri = (MobileDataStateTracker)
-                    mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
-            boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork();
-            log("isMobileOk: isHipriProvisioning=" + isHipriProvisioning);
-
-            if (isDefaultProvisioning || isHipriProvisioning) {
-                result = CMP_RESULT_CODE_PROVISIONING_NETWORK;
-                log("isMobileOk: X default || hipri is provisioning result=" + result);
-                return result;
-            }
-
-            try {
-                // Continue trying to connect until time has run out
-                long endTime = SystemClock.elapsedRealtime() + params.mTimeOutMs;
-
-                if (!mCs.isMobileDataStateTrackerReady()) {
-                    // Wait for MobileDataStateTracker to be ready.
-                    if (DBG) log("isMobileOk: mdst is not ready");
-                    while(SystemClock.elapsedRealtime() < endTime) {
-                        if (mCs.isMobileDataStateTrackerReady()) {
-                            // Enable fail fast as we'll do retries here and use a
-                            // hipri connection so the default connection stays active.
-                            if (DBG) log("isMobileOk: mdst ready, enable fail fast of mobile data");
-                            mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
-                            break;
-                        }
-                        sleep(POLLING_SLEEP_SEC);
-                    }
-                }
-
-                log("isMobileOk: start hipri url=" + params.mUrl);
-
-                // First wait until we can start using hipri
-                Binder binder = new Binder();
-/*
-                while(SystemClock.elapsedRealtime() < endTime) {
-                    int ret = mCs.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-                            Phone.FEATURE_ENABLE_HIPRI, binder);
-                    if ((ret == PhoneConstants.APN_ALREADY_ACTIVE)
-                        || (ret == PhoneConstants.APN_REQUEST_STARTED)) {
-                            log("isMobileOk: hipri started");
-                            break;
-                    }
-                    if (VDBG) log("isMobileOk: hipri not started yet");
-                    result = CMP_RESULT_CODE_NO_CONNECTION;
-                    sleep(POLLING_SLEEP_SEC);
-                }
-*/
-                // Continue trying to connect until time has run out
-                while(SystemClock.elapsedRealtime() < endTime) {
-                    try {
-                        // Wait for hipri to connect.
-                        // TODO: Don't poll and handle situation where hipri fails
-                        // because default is retrying. See b/9569540
-                        NetworkInfo.State state = mCs
-                                .getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
-                        if (state != NetworkInfo.State.CONNECTED) {
-                            if (true/*VDBG*/) {
-                                log("isMobileOk: not connected ni=" +
-                                    mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
-                            }
-                            sleep(POLLING_SLEEP_SEC);
-                            result = CMP_RESULT_CODE_NO_CONNECTION;
-                            continue;
-                        }
-
-                        // Hipri has started check if this is a provisioning url
-                        MobileDataStateTracker mdst = (MobileDataStateTracker)
-                                mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
-                        if (mdst.isProvisioningNetwork()) {
-                            result = CMP_RESULT_CODE_PROVISIONING_NETWORK;
-                            if (DBG) log("isMobileOk: X isProvisioningNetwork result=" + result);
-                            return result;
-                        } else {
-                            if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue");
-                        }
-
-                        // Get of the addresses associated with the url host. We need to use the
-                        // address otherwise HttpURLConnection object will use the name to get
-                        // the addresses and will try every address but that will bypass the
-                        // route to host we setup and the connection could succeed as the default
-                        // interface might be connected to the internet via wifi or other interface.
-                        InetAddress[] addresses;
-                        try {
-                            addresses = InetAddress.getAllByName(orgUri.getHost());
-                        } catch (UnknownHostException e) {
-                            result = CMP_RESULT_CODE_NO_DNS;
-                            log("isMobileOk: X UnknownHostException result=" + result);
-                            return result;
-                        }
-                        log("isMobileOk: addresses=" + inetAddressesToString(addresses));
-
-                        // Get the type of addresses supported by this link
-                        LinkProperties lp = mCs.getLinkPropertiesForTypeInternal(
-                                ConnectivityManager.TYPE_MOBILE_HIPRI);
-                        boolean linkHasIpv4 = lp.hasIPv4Address();
-                        boolean linkHasIpv6 = lp.hasGlobalIPv6Address();
-                        log("isMobileOk: linkHasIpv4=" + linkHasIpv4
-                                + " linkHasIpv6=" + linkHasIpv6);
-
-                        final ArrayList<InetAddress> validAddresses =
-                                new ArrayList<InetAddress>(addresses.length);
-
-                        for (InetAddress addr : addresses) {
-                            if (((addr instanceof Inet4Address) && linkHasIpv4) ||
-                                    ((addr instanceof Inet6Address) && linkHasIpv6)) {
-                                validAddresses.add(addr);
-                            }
-                        }
-
-                        if (validAddresses.size() == 0) {
-                            return CMP_RESULT_CODE_NO_CONNECTION;
-                        }
-
-                        int addrTried = 0;
-                        while (true) {
-                            // Loop through at most MAX_LOOPS valid addresses or until
-                            // we run out of time
-                            if (addrTried++ >= MAX_LOOPS) {
-                                log("isMobileOk: too many loops tried - giving up");
-                                break;
-                            }
-                            if (SystemClock.elapsedRealtime() >= endTime) {
-                                log("isMobileOk: spend too much time - giving up");
-                                break;
-                            }
-
-                            InetAddress hostAddr = validAddresses.get(rand.nextInt(
-                                    validAddresses.size()));
-
-                            // Make a route to host so we check the specific interface.
-                            if (mCs.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI,
-                                    hostAddr.getAddress())) {
-                                // Wait a short time to be sure the route is established ??
-                                log("isMobileOk:"
-                                        + " wait to establish route to hostAddr=" + hostAddr);
-                                sleep(NET_ROUTE_ESTABLISHMENT_SLEEP_SEC);
-                            } else {
-                                log("isMobileOk:"
-                                        + " could not establish route to hostAddr=" + hostAddr);
-                                // Wait a short time before the next attempt
-                                sleep(NET_ERROR_SLEEP_SEC);
-                                continue;
-                            }
-
-                            // Rewrite the url to have numeric address to use the specific route
-                            // using http for half the attempts and https for the other half.
-                            // Doing https first and http second as on a redirected walled garden
-                            // such as t-mobile uses we get a SocketTimeoutException: "SSL
-                            // handshake timed out" which we declare as
-                            // CMP_RESULT_CODE_NO_TCP_CONNECTION. We could change this, but by
-                            // having http second we will be using logic used for some time.
-                            URL newUrl;
-                            String scheme = (addrTried <= (MAX_LOOPS/2)) ? "https" : "http";
-                            newUrl = new URL(scheme, hostAddr.getHostAddress(),
-                                        orgUri.getPath());
-                            log("isMobileOk: newUrl=" + newUrl);
-
-                            HttpURLConnection urlConn = null;
-                            try {
-                                // Open the connection set the request headers and get the response
-                                urlConn = (HttpURLConnection)newUrl.openConnection(
-                                        java.net.Proxy.NO_PROXY);
-                                if (scheme.equals("https")) {
-                                    ((HttpsURLConnection)urlConn).setHostnameVerifier(
-                                            new CheckMpHostnameVerifier(orgUri));
-                                }
-                                urlConn.setInstanceFollowRedirects(false);
-                                urlConn.setConnectTimeout(SOCKET_TIMEOUT_MS);
-                                urlConn.setReadTimeout(SOCKET_TIMEOUT_MS);
-                                urlConn.setUseCaches(false);
-                                urlConn.setAllowUserInteraction(false);
-                                // Set the "Connection" to "Close" as by default "Keep-Alive"
-                                // is used which is useless in this case.
-                                urlConn.setRequestProperty("Connection", "close");
-                                int responseCode = urlConn.getResponseCode();
-
-                                // For debug display the headers
-                                Map<String, List<String>> headers = urlConn.getHeaderFields();
-                                log("isMobileOk: headers=" + headers);
-
-                                // Close the connection
-                                urlConn.disconnect();
-                                urlConn = null;
-
-                                if (mTestingFailures) {
-                                    // Pretend no connection, this tests using http and https
-                                    result = CMP_RESULT_CODE_NO_CONNECTION;
-                                    log("isMobileOk: TESTING_FAILURES, pretend no connction");
-                                    continue;
-                                }
-
-                                if (responseCode == 204) {
-                                    // Return
-                                    result = CMP_RESULT_CODE_CONNECTABLE;
-                                    log("isMobileOk: X got expected responseCode=" + responseCode
-                                            + " result=" + result);
-                                    return result;
-                                } else {
-                                    // Retry to be sure this was redirected, we've gotten
-                                    // occasions where a server returned 200 even though
-                                    // the device didn't have a "warm" sim.
-                                    log("isMobileOk: not expected responseCode=" + responseCode);
-                                    // TODO - it would be nice in the single-address case to do
-                                    // another DNS resolve here, but flushing the cache is a bit
-                                    // heavy-handed.
-                                    result = CMP_RESULT_CODE_REDIRECTED;
-                                }
-                            } catch (Exception e) {
-                                log("isMobileOk: HttpURLConnection Exception" + e);
-                                result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
-                                if (urlConn != null) {
-                                    urlConn.disconnect();
-                                    urlConn = null;
-                                }
-                                sleep(NET_ERROR_SLEEP_SEC);
-                                continue;
-                            }
-                        }
-                        log("isMobileOk: X loops|timed out result=" + result);
-                        return result;
-                    } catch (Exception e) {
-                        log("isMobileOk: Exception e=" + e);
-                        continue;
-                    }
-                }
-                log("isMobileOk: timed out");
-            } finally {
-                log("isMobileOk: F stop hipri");
-                mCs.setEnableFailFastMobileData(DctConstants.DISABLED);
-//                mCs.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-//                        Phone.FEATURE_ENABLE_HIPRI);
-
-                // Wait for hipri to disconnect.
-                long endTime = SystemClock.elapsedRealtime() + 5000;
-
-                while(SystemClock.elapsedRealtime() < endTime) {
-                    NetworkInfo.State state = mCs
-                            .getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
-                    if (state != NetworkInfo.State.DISCONNECTED) {
-                        if (VDBG) {
-                            log("isMobileOk: connected ni=" +
-                                mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
-                        }
-                        sleep(POLLING_SLEEP_SEC);
-                        continue;
-                    }
-                }
-
-                log("isMobileOk: X result=" + result);
-            }
-            return result;
-        }
-
-        @Override
-        protected Integer doInBackground(Params... params) {
-            return isMobileOk(params[0]);
-        }
-
-        @Override
-        protected void onPostExecute(Integer result) {
-            log("onPostExecute: result=" + result);
-            if ((mParams != null) && (mParams.mCb != null)) {
-                mParams.mCb.onComplete(result);
-            }
-        }
-
-        private String inetAddressesToString(InetAddress[] addresses) {
-            StringBuffer sb = new StringBuffer();
-            boolean firstTime = true;
-            for(InetAddress addr : addresses) {
-                if (firstTime) {
-                    firstTime = false;
-                } else {
-                    sb.append(",");
-                }
-                sb.append(addr);
-            }
-            return sb.toString();
-        }
-
-        private void printNetworkInfo() {
-            boolean hasIccCard = mTm.hasIccCard();
-            int simState = mTm.getSimState();
-            log("hasIccCard=" + hasIccCard
-                    + " simState=" + simState);
-            NetworkInfo[] ni = mCs.getAllNetworkInfo();
-            if (ni != null) {
-                log("ni.length=" + ni.length);
-                for (NetworkInfo netInfo: ni) {
-                    log("netInfo=" + netInfo.toString());
-                }
-            } else {
-                log("no network info ni=null");
-            }
-        }
-
-        /**
-         * Sleep for a few seconds then return.
-         * @param seconds
-         */
-        private static void sleep(int seconds) {
-            long stopTime = System.nanoTime() + (seconds * 1000000000);
-            long sleepTime;
-            while ((sleepTime = stopTime - System.nanoTime()) > 0) {
-                try {
-                    Thread.sleep(sleepTime / 1000000);
-                } catch (InterruptedException ignored) {
-                }
-            }
-        }
-
-        private static void log(String s) {
-            Slog.d(ConnectivityService.TAG, "[" + CHECKMP_TAG + "] " + s);
-        }
-    }
-
-    // TODO: Move to ConnectivityManager and make public?
-    private static final String CONNECTED_TO_PROVISIONING_NETWORK_ACTION =
-            "com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION";
-
-    private BroadcastReceiver mProvisioningReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(CONNECTED_TO_PROVISIONING_NETWORK_ACTION)) {
-                handleMobileProvisioningAction(intent.getStringExtra("EXTRA_URL"));
-            }
-        }
-    };
-
-    private void handleMobileProvisioningAction(String url) {
-        // Mark notification as not visible
-        setProvNotificationVisible(false, ConnectivityManager.TYPE_MOBILE_HIPRI, null, null);
-
-        // Check airplane mode
-        boolean isAirplaneModeOn = Settings.System.getInt(mContext.getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
-        // If provisioning network and not in airplane mode handle as a special case,
-        // otherwise launch browser with the intent directly.
-        if (mIsProvisioningNetwork.get() && !isAirplaneModeOn) {
-            if (DBG) log("handleMobileProvisioningAction: on prov network enable then launch");
-            mIsProvisioningNetwork.set(false);
-//            mIsStartingProvisioning.set(true);
-//            MobileDataStateTracker mdst = (MobileDataStateTracker)
-//                    mNetTrackers[ConnectivityManager.TYPE_MOBILE];
-            // Radio was disabled on CMP_RESULT_CODE_PROVISIONING_NETWORK, enable it here
-//            mdst.setRadio(true);
-//            mdst.setEnableFailFastMobileData(DctConstants.ENABLED);
-//            mdst.enableMobileProvisioning(url);
-        } else {
-            if (DBG) log("handleMobileProvisioningAction: not prov network");
-            mIsProvisioningNetwork.set(false);
-            // Check for  apps that can handle provisioning first
-            Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP);
-            List<String> carrierPackages =
-                    mTelephonyManager.getCarrierPackageNamesForIntent(provisioningIntent);
-            if (carrierPackages != null && !carrierPackages.isEmpty()) {
-                if (carrierPackages.size() != 1) {
-                    if (DBG) log("Multiple matching carrier apps found, launching the first.");
-                }
-                provisioningIntent.setPackage(carrierPackages.get(0));
-                provisioningIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                        Intent.FLAG_ACTIVITY_NEW_TASK);
-                mContext.startActivity(provisioningIntent);
-            } else {
-                // If no apps exist, use standard URL ACTION_VIEW method
-                Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
-                        Intent.CATEGORY_APP_BROWSER);
-                newIntent.setData(Uri.parse(url));
-                newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                        Intent.FLAG_ACTIVITY_NEW_TASK);
-                try {
-                    mContext.startActivity(newIntent);
-                } catch (ActivityNotFoundException e) {
-                    loge("handleMobileProvisioningAction: startActivity failed" + e);
-                }
-            }
-        }
+        // TODO: Remove?  Any reason to trigger a provisioning check?
+        return -1;
     }
 
     private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
     private volatile boolean mIsNotificationVisible = false;
 
-    private void setProvNotificationVisible(boolean visible, int networkType, String extraInfo,
-            String url) {
+    private void setProvNotificationVisible(boolean visible, int networkType, String action) {
         if (DBG) {
             log("setProvNotificationVisible: E visible=" + visible + " networkType=" + networkType
-                + " extraInfo=" + extraInfo + " url=" + url);
+                + " action=" + action);
         }
-        Intent intent = null;
-        PendingIntent pendingIntent = null;
-        if (visible) {
-            switch (networkType) {
-                case ConnectivityManager.TYPE_WIFI:
-                    intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-                    intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                            Intent.FLAG_ACTIVITY_NEW_TASK);
-                    pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
-                    break;
-                case ConnectivityManager.TYPE_MOBILE:
-                case ConnectivityManager.TYPE_MOBILE_HIPRI:
-                    intent = new Intent(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
-                    intent.putExtra("EXTRA_URL", url);
-                    intent.setFlags(0);
-                    pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
-                    break;
-                default:
-                    intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-                    intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                            Intent.FLAG_ACTIVITY_NEW_TASK);
-                    pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
-                    break;
-            }
-        }
+        Intent intent = new Intent(action);
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
         // Concatenate the range of types onto the range of NetIDs.
         int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
-        setProvNotificationVisibleIntent(visible, id, networkType, extraInfo, pendingIntent);
+        setProvNotificationVisibleIntent(visible, id, networkType, null, pendingIntent);
     }
 
     /**
@@ -3860,9 +3131,14 @@
 
     @Override
     public void setProvisioningNotificationVisible(boolean visible, int networkType,
-            String extraInfo, String url) {
+            String action) {
         enforceConnectivityInternalPermission();
-        setProvNotificationVisible(visible, networkType, extraInfo, url);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setProvNotificationVisible(visible, networkType, action);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d0463b7..12c98c1 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3176,7 +3176,7 @@
             Process.ProcessStartResult startResult = Process.start(entryPoint,
                     app.processName, uid, uid, gids, debugFlags, mountExternal,
                     app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
-                    entryPointArgs);
+                    app.info.dataDir, entryPointArgs);
             checkTime(startTime, "startProcess: returned from zygote!");
 
             if (app.isolated) {
@@ -6324,7 +6324,7 @@
                     startProcessLocked(procs.get(ip), "on-hold", null);
                 }
             }
-            
+
             if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 // Start looking for apps that are abusing wake locks.
                 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
@@ -6564,7 +6564,7 @@
                 throw new IllegalArgumentException("File descriptors passed in options");
             }
         }
-        
+
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
             int origUserId = userId;
@@ -6594,7 +6594,7 @@
 
                 return getIntentSenderLocked(type, packageName, callingUid, userId,
                         token, resultWho, requestCode, intents, resolvedTypes, flags, options);
-                
+
             } catch (RemoteException e) {
                 throw new SecurityException(e);
             }
@@ -6852,7 +6852,7 @@
                 "setProcessForeground()");
         synchronized(this) {
             boolean changed = false;
-            
+
             synchronized (mPidsSelfLocked) {
                 ProcessRecord pr = mPidsSelfLocked.get(pid);
                 if (pr == null && isForeground) {
@@ -6888,13 +6888,13 @@
                     }
                 }
             }
-            
+
             if (changed) {
                 updateOomAdjLocked();
             }
         }
     }
-    
+
     // =========================================================
     // PERMISSIONS
     // =========================================================
@@ -6956,7 +6956,7 @@
      * permission is automatically denied.  (Internally a null permission
      * string is used when calling {@link #checkComponentPermission} in cases
      * when only uid-based security is needed.)
-     * 
+     *
      * This can be called with or without the global lock held.
      */
     @Override
@@ -7213,12 +7213,12 @@
             if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                     "Checking grant " + targetPkg + " permission to " + grantUri);
         }
-        
+
         final IPackageManager pm = AppGlobals.getPackageManager();
 
         // If this is not a content: uri, we can't do anything with it.
         if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG, 
+            if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                     "Can't grant URI permission for non-content URI: " + grantUri);
             return -1;
         }
@@ -7346,7 +7346,7 @@
         // to the uri, and the target doesn't.  Let's now give this to
         // the target.
 
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG, 
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                 "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
 
         final String authority = grantUri.uri.getAuthority();
@@ -7548,7 +7548,7 @@
             final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
                     perm.targetUid);
             if (perms != null) {
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG, 
+                if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                         "Removing " + perm.targetUid + " permission to " + perm.uri);
 
                 perms.remove(perm.uri);
@@ -8117,7 +8117,7 @@
         outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
                 ProcessList.FOREGROUND_APP_ADJ);
     }
-    
+
     // =========================================================
     // TASK MANAGEMENT
     // =========================================================
@@ -8519,7 +8519,7 @@
             }
         }
     }
-    
+
     /**
      * TODO: Add mController hook
      */
@@ -8595,7 +8595,7 @@
     /**
      * Moves an activity, and all of the other activities within the same task, to the bottom
      * of the history stack.  The activity's order within the task is unchanged.
-     * 
+     *
      * @param token A reference to the activity we wish to move
      * @param nonRoot If false then this only works if the activity is the root
      *                of a task; if true it will work for any activity in a task.
@@ -9016,7 +9016,7 @@
                 == PackageManager.PERMISSION_GRANTED) {
             return null;
         }
-        
+
         PathPermission[] pps = cpi.pathPermissions;
         if (pps != null) {
             int i = pps.length;
@@ -9597,7 +9597,7 @@
             }
         }
     }
-    
+
     public final void publishContentProviders(IApplicationThread caller,
             List<ContentProviderHolder> providers) {
         if (providers == null) {
@@ -10075,7 +10075,7 @@
 
         return timedout;
     }
-    
+
     public final void activitySlept(IBinder token) {
         if (localLOGV) Slog.v(TAG, "Activity slept: token=" + token);
 
@@ -10150,7 +10150,7 @@
             throw new SecurityException("Requires permission "
                     + android.Manifest.permission.STOP_APP_SWITCHES);
         }
-        
+
         synchronized(this) {
             mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
                     + APP_SWITCH_DELAY_TIME;
@@ -10160,14 +10160,14 @@
             mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
         }
     }
-    
+
     public void resumeAppSwitches() {
         if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires permission "
                     + android.Manifest.permission.STOP_APP_SWITCHES);
         }
-        
+
         synchronized(this) {
             // Note that we don't execute any pending app switches... we will
             // let those wait until either the timeout, or the next start
@@ -10175,7 +10175,7 @@
             mAppSwitchesAllowedTime = 0;
         }
     }
-    
+
     boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
             int callingPid, int callingUid, String name) {
         if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
@@ -10203,7 +10203,7 @@
         Slog.w(TAG, name + " request from " + sourceUid + " stopped");
         return false;
     }
-    
+
     public void setDebugApp(String packageName, boolean waitForDebugger,
             boolean persistent) {
         enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
@@ -11177,7 +11177,7 @@
                 }
             }
         }
-        
+
         synchronized(this) {
             if (procsToKill != null) {
                 for (int i=procsToKill.size()-1; i>=0; i--) {
@@ -11186,20 +11186,20 @@
                     removeProcessLocked(proc, true, false, "system update done");
                 }
             }
-            
+
             // Now that we have cleaned up any update processes, we
             // are ready to start launching real processes and know that
             // we won't trample on them any more.
             mProcessesReady = true;
         }
-        
+
         Slog.i(TAG, "System now ready");
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
             SystemClock.uptimeMillis());
 
         synchronized(this) {
             // Make sure we have no pre-ready processes sitting around.
-            
+
             if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 ResolveInfo ri = mContext.getPackageManager()
                         .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
@@ -11272,7 +11272,7 @@
 
             // Start up initial activity.
             mBooting = true;
-            
+
             try {
                 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
                     Message msg = Message.obtain();
@@ -11333,12 +11333,12 @@
         startAppProblemLocked(app);
         app.stopFreezingAllLocked();
     }
-    
+
     /**
      * Generate a process error record, suitable for attachment to a ProcessRecord.
-     * 
+     *
      * @param app The ProcessRecord in which the error occurred.
-     * @param condition Crashing, Application Not Responding, etc.  Values are defined in 
+     * @param condition Crashing, Application Not Responding, etc.  Values are defined in
      *                      ActivityManager.AppErrorStateInfo
      * @param activity The activity associated with the crash, if known.
      * @param shortMsg Short message describing the crash.
@@ -11347,7 +11347,7 @@
      *
      * @return Returns a fully-formed AppErrorStateInfo record.
      */
-    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 
+    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
 
@@ -12104,14 +12104,14 @@
                     } else if (app.notResponding) {
                         report = app.notRespondingReport;
                     }
-                    
+
                     if (report != null) {
                         if (errList == null) {
                             errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
                         }
                         errList.add(report);
                     } else {
-                        Slog.w(TAG, "Missing app error report, app = " + app.processName + 
+                        Slog.w(TAG, "Missing app error report, app = " + app.processName +
                                 " crashing = " + app.crashing +
                                 " notResponding = " + app.notResponding);
                     }
@@ -12170,7 +12170,7 @@
                 }
                 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
                     // Generate process state info for running application
-                    ActivityManager.RunningAppProcessInfo currApp = 
+                    ActivityManager.RunningAppProcessInfo currApp =
                         new ActivityManager.RunningAppProcessInfo(app.processName,
                                 app.pid, app.getPackageList());
                     fillInProcMemInfo(app, currApp);
@@ -12252,7 +12252,7 @@
         boolean dumpAll = false;
         boolean dumpClient = false;
         String dumpPackage = null;
-        
+
         int opti = 0;
         while (opti < args.length) {
             String opt = args[opti];
@@ -12625,12 +12625,12 @@
                 }
             }
         }
-        
+
         if (mForegroundProcesses.size() > 0) {
             synchronized (mPidsSelfLocked) {
                 boolean printed = false;
                 for (int i=0; i<mForegroundProcesses.size(); i++) {
-                    ProcessRecord r = mPidsSelfLocked.get( 
+                    ProcessRecord r = mPidsSelfLocked.get(
                             mForegroundProcesses.valueAt(i).pid);
                     if (dumpPackage != null && (r == null
                             || !r.pkgList.containsKey(dumpPackage))) {
@@ -12648,7 +12648,7 @@
                 }
             }
         }
-        
+
         if (mPersistentStartingProcesses.size() > 0) {
             if (needSep) pw.println();
             needSep = true;
@@ -12666,7 +12666,7 @@
             dumpProcessList(pw, this, mRemovedProcesses, "    ",
                     "Removed Norm", "Removed PERS", dumpPackage);
         }
-        
+
         if (mProcessesOnHold.size() > 0) {
             if (needSep) pw.println();
             needSep = true;
@@ -12677,7 +12677,7 @@
         }
 
         needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
-        
+
         if (mProcessCrashTimes.getMap().size() > 0) {
             boolean printed = false;
             long now = SystemClock.uptimeMillis();
@@ -13047,7 +13047,7 @@
         ArrayList<String> strings;
         ArrayList<Integer> objects;
         boolean all;
-        
+
         ItemMatcher() {
             all = true;
         }
@@ -13132,7 +13132,7 @@
     protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
             int opti, boolean dumpAll) {
         ArrayList<ActivityRecord> activities;
-        
+
         synchronized (this) {
             activities = mStackSupervisor.getDumpActivitiesLocked(name);
         }
@@ -13255,7 +13255,7 @@
         }
 
         needSep = true;
-        
+
         if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) {
             for (int user=0; user<mStickyBroadcasts.size(); user++) {
                 if (needSep) {
@@ -13290,7 +13290,7 @@
                 }
             }
         }
-        
+
         if (!onlyHistory && dumpAll) {
             pw.println();
             for (BroadcastQueue queue : mBroadcastQueues) {
@@ -13302,7 +13302,7 @@
             needSep = true;
             printedAnything = true;
         }
-        
+
         if (!printedAnything) {
             pw.println("  (nothing)");
         }
@@ -13638,7 +13638,7 @@
         long realtime = SystemClock.elapsedRealtime();
         pw.println("Applications Graphics Acceleration Info:");
         pw.println("Uptime: " + uptime + " Realtime: " + realtime);
-        
+
         for (int i = procs.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = procs.get(i);
             if (r.thread != null) {
@@ -13832,7 +13832,7 @@
         boolean oomOnly = false;
         boolean isCompact = false;
         boolean localOnly = false;
-        
+
         int opti = 0;
         while (opti < args.length) {
             String opt = args[opti];
@@ -13866,7 +13866,7 @@
                 pw.println("Unknown argument: " + opt + "; use -h for help");
             }
         }
-        
+
         final boolean isCheckinRequest = scanArgs(args, "--checkin");
         long uptime = SystemClock.uptimeMillis();
         long realtime = SystemClock.elapsedRealtime();
@@ -14551,7 +14551,7 @@
         }
         return restart;
     }
-    
+
     // =========================================================
     // SERVICES
     // =========================================================
@@ -14633,7 +14633,7 @@
             return mServices.peekServiceLocked(service, resolvedType);
         }
     }
-    
+
     @Override
     public boolean stopServiceToken(ComponentName className, IBinder token,
             int startId) {
@@ -14855,11 +14855,11 @@
             mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
         }
     }
-    
+
     // =========================================================
     // BACKUP AND RESTORE
     // =========================================================
-    
+
     // Cause the target app to be launched if necessary and its backup agent
     // instantiated.  The backup agent will invoke backupAgentCreated() on the
     // activity manager to announce its creation.
@@ -14922,7 +14922,7 @@
             // mBackupAppName describe the app, so that when it binds back to the AM we
             // know that it's scheduled for a backup-agent operation.
         }
-        
+
         return true;
     }
 
@@ -15225,7 +15225,7 @@
             mReceiverResolver.removeFilter(rl.get(i));
         }
     }
-    
+
     private final void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
         for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = mLruProcesses.get(i);
@@ -15631,10 +15631,10 @@
 
         final boolean replacePending =
                 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
-        
+
         if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
                 + " replacePending=" + replacePending);
-        
+
         int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
         if (!ordered && NR > 0) {
             // If we are not serializing this broadcast, then send the
@@ -15742,7 +15742,7 @@
                 int seq = r.intent.getIntExtra("seq", -1);
                 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
             }
-            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); 
+            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
             if (!replaced) {
                 queue.enqueueOrderedBroadcastLocked(r);
                 queue.scheduleBroadcastsLocked();
@@ -15908,7 +15908,7 @@
             Binder.restoreCallingIdentity(origId);
         }
     }
-    
+
     // =========================================================
     // INSTRUMENTATION
     // =========================================================
@@ -15978,17 +15978,17 @@
 
         return true;
     }
-    
+
     /**
-     * Report errors that occur while attempting to start Instrumentation.  Always writes the 
+     * Report errors that occur while attempting to start Instrumentation.  Always writes the
      * error to the logs, but if somebody is watching, send the report there too.  This enables
      * the "am" command to report errors with more information.
-     * 
+     *
      * @param watcher The IInstrumentationWatcher.  Null if there isn't one.
      * @param cn The component name of the instrumentation.
      * @param report The error report.
      */
-    private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher, 
+    private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
             ComponentName cn, String report) {
         Slog.w(TAG, report);
         try {
@@ -16058,7 +16058,7 @@
     // =========================================================
     // CONFIGURATION
     // =========================================================
-    
+
     public ConfigurationInfo getDeviceConfigurationInfo() {
         ConfigurationInfo config = new ConfigurationInfo();
         synchronized (this) {
@@ -16148,11 +16148,11 @@
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
                     Slog.i(TAG, "Updating configuration to: " + values);
                 }
-                
+
                 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
 
                 if (values.locale != null && !initLocale) {
-                    saveLocaleLocked(values.locale, 
+                    saveLocaleLocked(values.locale,
                                      !values.locale.equals(mConfiguration.locale),
                                      values.userSetLocale);
                 }
@@ -16168,7 +16168,7 @@
                 //mUsageStatsService.noteStartConfig(newConfig);
 
                 final Configuration configCopy = new Configuration(mConfiguration);
-                
+
                 // TODO: If our config changes, should we auto dismiss any currently
                 // showing dialogs?
                 mShowDialogs = shouldShowDialogs(newConfig);
@@ -16267,7 +16267,7 @@
         if(isDiff) {
             SystemProperties.set("user.language", l.getLanguage());
             SystemProperties.set("user.region", l.getCountry());
-        } 
+        }
 
         if(isPersist) {
             SystemProperties.set("persist.sys.language", l.getLanguage());
@@ -16955,7 +16955,7 @@
         }
 
         app.curRawAdj = adj;
-        
+
         //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
         //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
         if (adj > app.maxAdj) {
@@ -17038,7 +17038,7 @@
             // whatever.
         }
     }
-    
+
     /**
      * Returns true if things are idle enough to perform GCs.
      */
@@ -17052,7 +17052,7 @@
         return !processingBroadcasts
                 && (isSleeping() || mStackSupervisor.allResumedActivitiesIdle());
     }
-    
+
     /**
      * Perform GCs on all processes that are waiting for it, but only
      * if things are idle.
@@ -17081,11 +17081,11 @@
                     }
                 }
             }
-            
+
             scheduleAppGcsLocked();
         }
     }
-    
+
     /**
      * If all looks good, perform GCs on all processes waiting for them.
      */
@@ -17103,12 +17103,12 @@
      */
     final void scheduleAppGcsLocked() {
         mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
-        
+
         if (mProcessesToGc.size() > 0) {
             // Schedule a GC for the time to the next process.
             ProcessRecord proc = mProcessesToGc.get(0);
             Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
-            
+
             long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
             long now = SystemClock.uptimeMillis();
             if (when < (now+GC_TIMEOUT)) {
@@ -17117,7 +17117,7 @@
             mHandler.sendMessageAtTime(msg, when);
         }
     }
-    
+
     /**
      * Add a process to the array of processes waiting to be GCed.  Keeps the
      * list in sorted order by the last GC time.  The process can't already be
@@ -17137,7 +17137,7 @@
             mProcessesToGc.add(0, proc);
         }
     }
-    
+
     /**
      * Set up to ask a process to GC itself.  This will either do it
      * immediately, or put it on the list of processes to gc the next