Clean up some temporary allocations.

Yay to ArrayMap, letting me get rid of a bunch of temporary
iterators in core code paths like updateOomAdj.  (Now I definitely
need an ArraySet to finish that up.)

Also clean up various other things that are doing unnecessary
allocations, clean up some debug output, make more of the debug
output respect package filtering.

Change-Id: Ib4979faf4de8c7912739bc0937c3fa9e7bfcde67
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d02a320..c1d4ae9 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.util.ArrayMap;
+
 import java.util.HashMap;
 
 /**
@@ -47,8 +49,8 @@
  * implements the {@link #onCallbackDied} method.
  */
 public class RemoteCallbackList<E extends IInterface> {
-    /*package*/ HashMap<IBinder, Callback> mCallbacks
-            = new HashMap<IBinder, Callback>();
+    /*package*/ ArrayMap<IBinder, Callback> mCallbacks
+            = new ArrayMap<IBinder, Callback>();
     private Object[] mActiveBroadcast;
     private int mBroadcastCount = -1;
     private boolean mKilled = false;
@@ -159,7 +161,8 @@
      */
     public void kill() {
         synchronized (mCallbacks) {
-            for (Callback cb : mCallbacks.values()) {
+            for (int cbi=mCallbacks.size()-1; cbi>=0; cbi--) {
+                Callback cb = mCallbacks.valueAt(cbi);
                 cb.mCallback.asBinder().unlinkToDeath(cb, 0);
             }
             mCallbacks.clear();
@@ -238,11 +241,10 @@
             if (active == null || active.length < N) {
                 mActiveBroadcast = active = new Object[N];
             }
-            int i=0;
-            for (Callback cb : mCallbacks.values()) {
-                active[i++] = cb;
+            for (int i=0; i<N; i++) {
+                active[i] = mCallbacks.valueAt(i);
             }
-            return i;
+            return N;
         }
     }
 
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3267939..31da091 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Printer;
 import android.util.Singleton;
@@ -1069,7 +1070,7 @@
         // Map from violation stacktrace hashcode -> uptimeMillis of
         // last violation.  No locking needed, as this is only
         // accessed by the same thread.
-        private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
+        private ArrayMap<Integer, Long> mLastViolationTime;
 
         public AndroidBlockGuardPolicy(final int policyMask) {
             mPolicyMask = policyMask;
@@ -1279,8 +1280,13 @@
             // Not perfect, but fast and good enough for dup suppression.
             Integer crashFingerprint = info.hashCode();
             long lastViolationTime = 0;
-            if (mLastViolationTime.containsKey(crashFingerprint)) {
-                lastViolationTime = mLastViolationTime.get(crashFingerprint);
+            if (mLastViolationTime != null) {
+                Long vtime = mLastViolationTime.get(crashFingerprint);
+                if (vtime != null) {
+                    lastViolationTime = vtime;
+                }
+            } else {
+                mLastViolationTime = new ArrayMap<Integer, Long>(1);
             }
             long now = SystemClock.uptimeMillis();
             mLastViolationTime.put(crashFingerprint, now);
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 70f7d2e..6da7546 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -212,10 +212,12 @@
      */
     @Override
     public void clear() {
-        freeArrays(mHashes, mArray, mSize);
-        mHashes = SparseArray.EMPTY_INTS;
-        mArray = SparseArray.EMPTY_OBJECTS;
-        mSize = 0;
+        if (mSize != 0) {
+            freeArrays(mHashes, mArray, mSize);
+            mHashes = SparseArray.EMPTY_INTS;
+            mArray = SparseArray.EMPTY_OBJECTS;
+            mSize = 0;
+        }
     }
 
     /**
@@ -227,9 +229,9 @@
             int[] ohashes = mHashes;
             Object[] oarray = mArray;
             allocArrays(minimumCapacity);
-            if (mHashes.length > 0) {
-                System.arraycopy(ohashes, 0, mHashes, 0, mHashes.length);
-                System.arraycopy(oarray, 0, mArray, 0, mArray.length);
+            if (mSize > 0) {
+                System.arraycopy(ohashes, 0, mHashes, 0, mSize);
+                System.arraycopy(oarray, 0, mArray, 0, mSize<<1);
             }
             freeArrays(ohashes, oarray, mSize);
         }
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index fa758a8..bc06561 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -351,12 +351,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-        
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (alarm.operation.equals(operation)) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -375,12 +374,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-        
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (alarm.operation.getTargetPackage().equals(packageName)) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -398,12 +396,11 @@
         }
 
         // iterator over the list removing any it where the intent match
-        Iterator<Alarm> it = alarmList.iterator();
-
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
             if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
-                it.remove();
+                alarmList.remove(i);
+                i--;
             }
         }
     }
@@ -666,12 +663,10 @@
                                      ArrayList<Alarm> triggerList,
                                      long now)
     {
-        Iterator<Alarm> it = alarmList.iterator();
-        ArrayList<Alarm> repeats = new ArrayList<Alarm>();
-        
-        while (it.hasNext())
-        {
-            Alarm alarm = it.next();
+        ArrayList<Alarm> repeats = null;
+
+        for (int i=0; i<alarmList.size(); i++) {
+            Alarm alarm = alarmList.get(i);
 
             if (localLOGV) Slog.v(TAG, "Checking active alarm when=" + alarm.when + " " + alarm);
 
@@ -702,20 +697,25 @@
             triggerList.add(alarm);
             
             // remove the alarm from the list
-            it.remove();
-            
+            alarmList.remove(i);
+            i--;
+
             // if it repeats queue it up to be read-added to the list
             if (alarm.repeatInterval > 0) {
+                if (repeats == null) {
+                    repeats = new ArrayList<Alarm>();
+                }
                 repeats.add(alarm);
             }
         }
 
         // reset any repeating alarms.
-        it = repeats.iterator();
-        while (it.hasNext()) {
-            Alarm alarm = it.next();
-            alarm.when += alarm.count * alarm.repeatInterval;
-            addAlarmLocked(alarm);
+        if (repeats != null) {
+            for (int i=0; i<repeats.size(); i++) {
+                Alarm alarm = repeats.get(i);
+                alarm.when += alarm.count * alarm.repeatInterval;
+                addAlarmLocked(alarm);
+            }
         }
         
         if (alarmList.size() > 0) {
@@ -785,12 +785,14 @@
         
         public void run()
         {
+            ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
+
             while (true)
             {
                 int result = waitForAlarm(mDescriptor);
-                
-                ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
-                
+
+                triggerList.clear();
+
                 if ((result & TIME_CHANGED_MASK) != 0) {
                     remove(mTimeTickSender);
                     mClockReceiver.scheduleTimeTickEvent();
@@ -820,9 +822,8 @@
                         triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowELAPSED);
                     
                     // now trigger the alarms
-                    Iterator<Alarm> it = triggerList.iterator();
-                    while (it.hasNext()) {
-                        Alarm alarm = it.next();
+                    for (int i=0; i<triggerList.size(); i++) {
+                        Alarm alarm = triggerList.get(i);
                         try {
                             if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
                             alarm.operation.send(mContext, 0,
@@ -913,10 +914,8 @@
                 }
                 
                 // now trigger the alarms without the lock held
-                Iterator<Alarm> it = triggerList.iterator();
-                while (it.hasNext())
-                {
-                    Alarm alarm = it.next();
+                for (int i=0; i<triggerList.size(); i++) {
+                    Alarm alarm = triggerList.get(i);
                     try {
                         alarm.operation.send();
                     } catch (PendingIntent.CanceledException e) {
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 10db70f..84e44bd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -574,30 +574,26 @@
                     b.binder = service;
                     b.requested = true;
                     b.received = true;
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> it
-                                = r.connections.values().iterator();
-                        while (it.hasNext()) {
-                            ArrayList<ConnectionRecord> clist = it.next();
-                            for (int i=0; i<clist.size(); i++) {
-                                ConnectionRecord c = clist.get(i);
-                                if (!filter.equals(c.binding.intent.intent)) {
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Not publishing to: " + c);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Bound intent: " + c.binding.intent.intent);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Published intent: " + intent);
-                                    continue;
-                                }
-                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
-                                try {
-                                    c.conn.connected(r.name, service);
-                                } catch (Exception e) {
-                                    Slog.w(TAG, "Failure sending service " + r.name +
-                                          " to connection " + c.conn.asBinder() +
-                                          " (in " + c.binding.client.processName + ")", e);
-                                }
+                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
+                        for (int i=0; i<clist.size(); i++) {
+                            ConnectionRecord c = clist.get(i);
+                            if (!filter.equals(c.binding.intent.intent)) {
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Not publishing to: " + c);
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Bound intent: " + c.binding.intent.intent);
+                                if (DEBUG_SERVICE) Slog.v(
+                                        TAG, "Published intent: " + intent);
+                                continue;
+                            }
+                            if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+                            try {
+                                c.conn.connected(r.name, service);
+                            } catch (Exception e) {
+                                Slog.w(TAG, "Failure sending service " + r.name +
+                                      " to connection " + c.conn.asBinder() +
+                                      " (in " + c.binding.client.processName + ")", e);
                             }
                         }
                     }
@@ -1064,10 +1060,9 @@
     }
 
     private final void requestServiceBindingsLocked(ServiceRecord r) {
-        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
-        while (bindings.hasNext()) {
-            IntentBindRecord i = bindings.next();
-            if (!requestServiceBindingLocked(r, i, false)) {
+        for (int i=r.bindings.size()-1; i>=0; i--) {
+            IntentBindRecord ibr = r.bindings.valueAt(i);
+            if (!requestServiceBindingLocked(r, ibr, false)) {
                 break;
             }
         }
@@ -1179,50 +1174,45 @@
         if (!force && r.startRequested) {
             return;
         }
-        if (r.connections.size() > 0) {
-            if (!force) {
-                // XXX should probably keep a count of the number of auto-create
-                // connections directly in the service.
-                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-                while (it.hasNext()) {
-                    ArrayList<ConnectionRecord> cr = it.next();
-                    for (int i=0; i<cr.size(); i++) {
-                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
-                            return;
-                        }
-                    }
-                }
-            }
-
-            // Report to all of the connections that the service is no longer
-            // available.
-            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-            while (it.hasNext()) {
-                ArrayList<ConnectionRecord> c = it.next();
-                for (int i=0; i<c.size(); i++) {
-                    ConnectionRecord cr = c.get(i);
-                    // There is still a connection to the service that is
-                    // being brought down.  Mark it as dead.
-                    cr.serviceDead = true;
-                    try {
-                        cr.conn.connected(r.name, null);
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Failure disconnecting service " + r.name +
-                              " to connection " + c.get(i).conn.asBinder() +
-                              " (in " + c.get(i).binding.client.processName + ")", e);
+        if (!force) {
+            // XXX should probably keep a count of the number of auto-create
+            // connections directly in the service.
+            for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                ArrayList<ConnectionRecord> cr = r.connections.valueAt(conni);
+                for (int i=0; i<cr.size(); i++) {
+                    if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                        return;
                     }
                 }
             }
         }
 
+        // Report to all of the connections that the service is no longer
+        // available.
+        for (int conni=r.connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
+            for (int i=0; i<c.size(); i++) {
+                ConnectionRecord cr = c.get(i);
+                // There is still a connection to the service that is
+                // being brought down.  Mark it as dead.
+                cr.serviceDead = true;
+                try {
+                    cr.conn.connected(r.name, null);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Failure disconnecting service " + r.name +
+                          " to connection " + c.get(i).conn.asBinder() +
+                          " (in " + c.get(i).binding.client.processName + ")", e);
+                }
+            }
+        }
+
         // Tell the service that it has been unbound.
-        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
-            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
-            while (it.hasNext()) {
-                IntentBindRecord ibr = it.next();
+        if (r.app != null && r.app.thread != null) {
+            for (int i=r.bindings.size()-1; i>=0; i--) {
+                IntentBindRecord ibr = r.bindings.valueAt(i);
                 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
                         + ": hasBound=" + ibr.hasBound);
-                if (r.app != null && r.app.thread != null && ibr.hasBound) {
+                if (ibr.hasBound) {
                     try {
                         bumpServiceExecutingLocked(r, "bring down unbind");
                         mAm.updateOomAdjLocked(r.app);
@@ -1595,22 +1585,18 @@
                 Iterator<ServiceRecord> it = app.services.iterator();
                 while (it.hasNext()) {
                     ServiceRecord r = it.next();
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> jt
-                                = r.connections.values().iterator();
-                        while (jt.hasNext()) {
-                            ArrayList<ConnectionRecord> cl = jt.next();
-                            for (int i=0; i<cl.size(); i++) {
-                                ConnectionRecord c = cl.get(i);
-                                if (c.binding.client != app) {
-                                    try {
-                                        //c.conn.connected(r.className, null);
-                                    } catch (Exception e) {
-                                        // todo: this should be asynchronous!
-                                        Slog.w(TAG, "Exception thrown disconnected servce "
-                                              + r.shortName
-                                              + " from app " + app.processName, e);
-                                    }
+                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                        ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
+                        for (int i=0; i<cl.size(); i++) {
+                            ConnectionRecord c = cl.get(i);
+                            if (c.binding.client != app) {
+                                try {
+                                    //c.conn.connected(r.className, null);
+                                } catch (Exception e) {
+                                    // todo: this should be asynchronous!
+                                    Slog.w(TAG, "Exception thrown disconnected servce "
+                                          + r.shortName
+                                          + " from app " + app.processName, e);
                                 }
                             }
                         }
@@ -1645,17 +1631,13 @@
                     if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
                 }
 
-                boolean hasClients = sr.bindings.size() > 0;
-                if (hasClients) {
-                    Iterator<IntentBindRecord> bindings
-                            = sr.bindings.values().iterator();
-                    while (bindings.hasNext()) {
-                        IntentBindRecord b = bindings.next();
-                        if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
-                                + ": shouldUnbind=" + b.hasBound);
-                        b.binder = null;
-                        b.requested = b.received = b.hasBound = false;
-                    }
+                final int numClients = sr.bindings.size();
+                for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
+                    IntentBindRecord b = sr.bindings.valueAt(bindingi);
+                    if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
+                            + ": shouldUnbind=" + b.hasBound);
+                    b.binder = null;
+                    b.requested = b.received = b.hasBound = false;
                 }
 
                 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
@@ -1676,7 +1658,7 @@
                     if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                         if (sr.pendingStarts.size() == 0) {
                             sr.startRequested = false;
-                            if (!hasClients) {
+                            if (numClients > 0) {
                                 // Whoops, no reason to restart!
                                 bringDownServiceLocked(sr, true);
                             }
@@ -1732,7 +1714,8 @@
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
 
-        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+        for (int conni=r.connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> connl = r.connections.valueAt(conni);
             for (int i=0; i<connl.size(); i++) {
                 ConnectionRecord conn = connl.get(i);
                 if (conn.clientLabel != 0) {
@@ -1805,7 +1788,8 @@
         int userId = UserHandle.getUserId(Binder.getCallingUid());
         ServiceRecord r = mServiceMap.getServiceByName(name, userId);
         if (r != null) {
-            for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+            for (int conni=r.connections.size()-1; conni>=0; conni--) {
+                ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
                 for (int i=0; i<conn.size(); i++) {
                     if (conn.get(i).clientIntent != null) {
                         return conn.get(i).clientIntent;
@@ -1859,6 +1843,7 @@
     boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
         boolean needSep = false;
+        boolean needSepResult = false;
 
         ItemMatcher matcher = new ItemMatcher();
         matcher.build(args, opti);
@@ -1881,6 +1866,7 @@
                         if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                             continue;
                         }
+                        needSepResult = true;
                         if (!printed) {
                             if (user != 0) {
                                 pw.println();
@@ -1907,7 +1893,8 @@
                             pw.println(r.connections.size());
                             if (r.connections.size() > 0) {
                                 pw.println("    Connections:");
-                                for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+                                for (int conni=0; conni<=r.connections.size(); conni++) {
+                                    ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                                     for (int i = 0; i < clist.size(); i++) {
                                         ConnectionRecord conn = clist.get(i);
                                         pw.print("      ");
@@ -1960,6 +1947,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -1982,6 +1970,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -2004,6 +1993,7 @@
                 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
                     continue;
                 }
+                needSepResult = true;
                 if (!printed) {
                     if (needSep) pw.println(" ");
                     needSep = true;
@@ -2032,6 +2022,7 @@
                                 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
                             continue;
                         }
+                        needSepResult = true;
                         if (!printed) {
                             if (needSep) pw.println(" ");
                             needSep = true;
@@ -2042,11 +2033,10 @@
                         cr.dump(pw, "    ");
                     }
                 }
-                needSep = true;
             }
         }
 
-        return needSep;
+        return needSepResult;
     }
 
     /**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 86a6bca..8d71cf9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6515,6 +6515,7 @@
         int userId = app.userId;
         if (providers != null) {
             int N = providers.size();
+            app.pubProviders.ensureCapacity(N + app.pubProviders.size());
             for (int i=0; i<N; i++) {
                 ProviderInfo cpi =
                     (ProviderInfo)providers.get(i);
@@ -10099,6 +10100,7 @@
 
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
+        boolean dumpedHeader = false;
         boolean needSep = false;
         boolean onlyHistory = false;
 
@@ -10194,14 +10196,14 @@
 
     boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
-        boolean needSep = true;
+        boolean needSep;
 
         ItemMatcher matcher = new ItemMatcher();
         matcher.build(args, opti);
 
         pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
 
-        mProviderMap.dumpProvidersLocked(pw, dumpAll);
+        needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
 
         if (mLaunchingProviders.size() > 0) {
             boolean printed = false;
@@ -10222,13 +10224,28 @@
         }
 
         if (mGrantedUriPermissions.size() > 0) {
-            if (needSep) pw.println();
-            needSep = true;
-            pw.println("Granted Uri Permissions:");
+            boolean printed = false;
+            int dumpUid = -1;
+            if (dumpPackage != null) {
+                try {
+                    dumpUid = mContext.getPackageManager().getPackageUid(dumpPackage, 0);
+                } catch (NameNotFoundException e) {
+                    dumpUid = -1;
+                }
+            }
             for (int i=0; i<mGrantedUriPermissions.size(); i++) {
                 int uid = mGrantedUriPermissions.keyAt(i);
+                if (dumpUid >= 0 && UserHandle.getAppId(uid) != dumpUid) {
+                    continue;
+                }
                 HashMap<Uri, UriPermission> perms
                         = mGrantedUriPermissions.valueAt(i);
+                if (!printed) {
+                    if (needSep) pw.println();
+                    needSep = true;
+                    pw.println("  Granted Uri Permissions:");
+                    printed = true;
+                }
                 pw.print("  * UID "); pw.print(uid);
                         pw.println(" holds:");
                 for (UriPermission perm : perms.values()) {
@@ -10238,7 +10255,6 @@
                     }
                 }
             }
-            needSep = true;
         }
         
         return needSep;
@@ -11025,24 +11041,20 @@
         boolean restart = false;
 
         // Remove published content providers.
-        if (!app.pubProviders.isEmpty()) {
-            Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
-            while (it.hasNext()) {
-                ContentProviderRecord cpr = it.next();
-
-                final boolean always = app.bad || !allowRestart;
-                if (removeDyingProviderLocked(app, cpr, always) || always) {
-                    // We left the provider in the launching list, need to
-                    // restart it.
-                    restart = true;
-                }
-
-                cpr.provider = null;
-                cpr.proc = null;
+        for (int i=app.pubProviders.size()-1; i>=0; i--) {
+            ContentProviderRecord cpr = app.pubProviders.valueAt(i);
+            final boolean always = app.bad || !allowRestart;
+            if (removeDyingProviderLocked(app, cpr, always) || always) {
+                // We left the provider in the launching list, need to
+                // restart it.
+                restart = true;
             }
-            app.pubProviders.clear();
+
+            cpr.provider = null;
+            cpr.proc = null;
         }
-        
+        app.pubProviders.clear();
+
         // Take care of any launching providers waiting for this process.
         if (checkAppInLaunchingProvidersLocked(app, false)) {
             restart = true;
@@ -13119,158 +13131,159 @@
                     // has said it is doing work.
                     app.keeping = true;
                 }
-                if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                    Iterator<ArrayList<ConnectionRecord>> kt
-                            = s.connections.values().iterator();
-                    while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
-                        ArrayList<ConnectionRecord> clist = kt.next();
-                        for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
-                            // XXX should compute this based on the max of
-                            // all connected clients.
-                            ConnectionRecord cr = clist.get(i);
-                            if (cr.binding.client == app) {
-                                // Binding to ourself is not interesting.
-                                continue;
+                for (int conni = s.connections.size()-1;
+                        conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                        conni--) {
+                    ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
+                    for (int i = 0;
+                            i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
+                                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                            i++) {
+                        // XXX should compute this based on the max of
+                        // all connected clients.
+                        ConnectionRecord cr = clist.get(i);
+                        if (cr.binding.client == app) {
+                            // Binding to ourself is not interesting.
+                            continue;
+                        }
+                        if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
+                            ProcessRecord client = cr.binding.client;
+                            int clientAdj = adj;
+                            int myHiddenAdj = hiddenAdj;
+                            if (myHiddenAdj > client.hiddenAdj) {
+                                if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myHiddenAdj = client.hiddenAdj;
+                                } else {
+                                    myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+                                }
                             }
-                            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
-                                ProcessRecord client = cr.binding.client;
-                                int clientAdj = adj;
-                                int myHiddenAdj = hiddenAdj;
-                                if (myHiddenAdj > client.hiddenAdj) {
-                                    if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myHiddenAdj = client.hiddenAdj;
-                                    } else {
-                                        myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
+                            int myClientHiddenAdj = clientHiddenAdj;
+                            if (myClientHiddenAdj > client.clientHiddenAdj) {
+                                if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myClientHiddenAdj = client.clientHiddenAdj;
+                                } else {
+                                    myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
                                 }
-                                int myClientHiddenAdj = clientHiddenAdj;
-                                if (myClientHiddenAdj > client.clientHiddenAdj) {
-                                    if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myClientHiddenAdj = client.clientHiddenAdj;
-                                    } else {
-                                        myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
+                            }
+                            int myEmptyAdj = emptyAdj;
+                            if (myEmptyAdj > client.emptyAdj) {
+                                if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                    myEmptyAdj = client.emptyAdj;
+                                } else {
+                                    myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
                                 }
-                                int myEmptyAdj = emptyAdj;
-                                if (myEmptyAdj > client.emptyAdj) {
-                                    if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
-                                        myEmptyAdj = client.emptyAdj;
-                                    } else {
-                                        myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
-                                    }
-                                }
-                                clientAdj = computeOomAdjLocked(client, myHiddenAdj,
-                                        myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
-                                String adjType = null;
-                                if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
-                                    // Not doing bind OOM management, so treat
-                                    // this guy more like a started service.
-                                    if (app.hasShownUi && app != mHomeProcess) {
-                                        // If this process has shown some UI, let it immediately
-                                        // go to the LRU list because it may be pretty heavy with
-                                        // UI stuff.  We'll tag it with a label just to help
-                                        // debug and understand what is going on.
-                                        if (adj > clientAdj) {
-                                            adjType = "bound-bg-ui-services";
-                                        }
-                                        app.hidden = false;
-                                        clientAdj = adj;
-                                    } else {
-                                        if (now >= (s.lastActivity
-                                                + ActiveServices.MAX_SERVICE_INACTIVITY)) {
-                                            // This service has not seen activity within
-                                            // recent memory, so allow it to drop to the
-                                            // LRU list if there is no other reason to keep
-                                            // it around.  We'll also tag it with a label just
-                                            // to help debug and undertand what is going on.
-                                            if (adj > clientAdj) {
-                                                adjType = "bound-bg-services";
-                                            }
-                                            clientAdj = adj;
-                                        }
-                                    }
-                                } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                                    if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
-                                        // If this connection is keeping the service
-                                        // created, then we want to try to better follow
-                                        // its memory management semantics for activities.
-                                        // That is, if it is sitting in the background
-                                        // LRU list as a hidden process (with activities),
-                                        // we don't want the service it is connected to
-                                        // to go into the empty LRU and quickly get killed,
-                                        // because I'll we'll do is just end up restarting
-                                        // the service.
-                                        app.hasClientActivities |= client.hasActivities;
-                                    }
-                                }
-                                if (adj > clientAdj) {
-                                    // If this process has recently shown UI, and
-                                    // the process that is binding to it is less
-                                    // important than being visible, then we don't
-                                    // care about the binding as much as we care
-                                    // about letting this process get into the LRU
-                                    // list to be killed and restarted if needed for
-                                    // memory.
-                                    if (app.hasShownUi && app != mHomeProcess
-                                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                            }
+                            clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                                    myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+                            String adjType = null;
+                            if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+                                // Not doing bind OOM management, so treat
+                                // this guy more like a started service.
+                                if (app.hasShownUi && app != mHomeProcess) {
+                                    // If this process has shown some UI, let it immediately
+                                    // go to the LRU list because it may be pretty heavy with
+                                    // UI stuff.  We'll tag it with a label just to help
+                                    // debug and understand what is going on.
+                                    if (adj > clientAdj) {
                                         adjType = "bound-bg-ui-services";
-                                    } else {
-                                        if ((cr.flags&(Context.BIND_ABOVE_CLIENT
-                                                |Context.BIND_IMPORTANT)) != 0) {
-                                            adj = clientAdj;
-                                        } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
-                                                && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
-                                                && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                            adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                                        } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
-                                            adj = clientAdj;
-                                        } else {
-                                            app.pendingUiClean = true;
-                                            if (adj > ProcessList.VISIBLE_APP_ADJ) {
-                                                adj = ProcessList.VISIBLE_APP_ADJ;
-                                            }
-                                        }
-                                        if (!client.hidden) {
-                                            app.hidden = false;
-                                        }
-                                        if (client.keeping) {
-                                            app.keeping = true;
-                                        }
-                                        adjType = "service";
-                                    }
-                                }
-                                if (adjType != null) {
-                                    app.adjType = adjType;
-                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                            .REASON_SERVICE_IN_USE;
-                                    app.adjSource = cr.binding.client;
-                                    app.adjSourceOom = clientAdj;
-                                    app.adjTarget = s.name;
-                                }
-                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
-                                    }
-                                }
-                            }
-                            final ActivityRecord a = cr.activity;
-                            if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
-                                if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
-                                        (a.visible || a.state == ActivityState.RESUMED
-                                         || a.state == ActivityState.PAUSING)) {
-                                    adj = ProcessList.FOREGROUND_APP_ADJ;
-                                    if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                                     }
                                     app.hidden = false;
-                                    app.adjType = "service";
-                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                            .REASON_SERVICE_IN_USE;
-                                    app.adjSource = a;
-                                    app.adjSourceOom = adj;
-                                    app.adjTarget = s.name;
+                                    clientAdj = adj;
+                                } else {
+                                    if (now >= (s.lastActivity
+                                            + ActiveServices.MAX_SERVICE_INACTIVITY)) {
+                                        // This service has not seen activity within
+                                        // recent memory, so allow it to drop to the
+                                        // LRU list if there is no other reason to keep
+                                        // it around.  We'll also tag it with a label just
+                                        // to help debug and undertand what is going on.
+                                        if (adj > clientAdj) {
+                                            adjType = "bound-bg-services";
+                                        }
+                                        clientAdj = adj;
+                                    }
                                 }
+                            } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                                if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
+                                    // If this connection is keeping the service
+                                    // created, then we want to try to better follow
+                                    // its memory management semantics for activities.
+                                    // That is, if it is sitting in the background
+                                    // LRU list as a hidden process (with activities),
+                                    // we don't want the service it is connected to
+                                    // to go into the empty LRU and quickly get killed,
+                                    // because I'll we'll do is just end up restarting
+                                    // the service.
+                                    app.hasClientActivities |= client.hasActivities;
+                                }
+                            }
+                            if (adj > clientAdj) {
+                                // If this process has recently shown UI, and
+                                // the process that is binding to it is less
+                                // important than being visible, then we don't
+                                // care about the binding as much as we care
+                                // about letting this process get into the LRU
+                                // list to be killed and restarted if needed for
+                                // memory.
+                                if (app.hasShownUi && app != mHomeProcess
+                                        && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                    adjType = "bound-bg-ui-services";
+                                } else {
+                                    if ((cr.flags&(Context.BIND_ABOVE_CLIENT
+                                            |Context.BIND_IMPORTANT)) != 0) {
+                                        adj = clientAdj;
+                                    } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
+                                            && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+                                            && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+                                    } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
+                                        adj = clientAdj;
+                                    } else {
+                                        app.pendingUiClean = true;
+                                        if (adj > ProcessList.VISIBLE_APP_ADJ) {
+                                            adj = ProcessList.VISIBLE_APP_ADJ;
+                                        }
+                                    }
+                                    if (!client.hidden) {
+                                        app.hidden = false;
+                                    }
+                                    if (client.keeping) {
+                                        app.keeping = true;
+                                    }
+                                    adjType = "service";
+                                }
+                            }
+                            if (adjType != null) {
+                                app.adjType = adjType;
+                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                        .REASON_SERVICE_IN_USE;
+                                app.adjSource = cr.binding.client;
+                                app.adjSourceOom = clientAdj;
+                                app.adjTarget = s.name;
+                            }
+                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                }
+                            }
+                        }
+                        final ActivityRecord a = cr.activity;
+                        if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+                            if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
+                                    (a.visible || a.state == ActivityState.RESUMED
+                                     || a.state == ActivityState.PAUSING)) {
+                                adj = ProcessList.FOREGROUND_APP_ADJ;
+                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                }
+                                app.hidden = false;
+                                app.adjType = "service";
+                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                        .REASON_SERVICE_IN_USE;
+                                app.adjSource = a;
+                                app.adjSourceOom = adj;
+                                app.adjTarget = s.name;
                             }
                         }
                     }
@@ -13289,86 +13302,84 @@
             }
         }
 
-        if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-            Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
-            while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
-                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                ContentProviderRecord cpr = jt.next();
-                for (int i = cpr.connections.size()-1;
-                        i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
-                        i--) {
-                    ContentProviderConnection conn = cpr.connections.get(i);
-                    ProcessRecord client = conn.client;
-                    if (client == app) {
-                        // Being our own client is not interesting.
-                        continue;
-                    }
-                    int myHiddenAdj = hiddenAdj;
-                    if (myHiddenAdj > client.hiddenAdj) {
-                        if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
-                            myHiddenAdj = client.hiddenAdj;
-                        } else {
-                            myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int myClientHiddenAdj = clientHiddenAdj;
-                    if (myClientHiddenAdj > client.clientHiddenAdj) {
-                        if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
-                            myClientHiddenAdj = client.clientHiddenAdj;
-                        } else {
-                            myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int myEmptyAdj = emptyAdj;
-                    if (myEmptyAdj > client.emptyAdj) {
-                        if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
-                            myEmptyAdj = client.emptyAdj;
-                        } else {
-                            myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
-                        }
-                    }
-                    int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
-                            myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
-                    if (adj > clientAdj) {
-                        if (app.hasShownUi && app != mHomeProcess
-                                && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                            app.adjType = "bg-ui-provider";
-                        } else {
-                            adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
-                                    ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
-                            app.adjType = "provider";
-                        }
-                        if (!client.hidden) {
-                            app.hidden = false;
-                        }
-                        if (client.keeping) {
-                            app.keeping = true;
-                        }
-                        app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                .REASON_PROVIDER_IN_USE;
-                        app.adjSource = client;
-                        app.adjSourceOom = clientAdj;
-                        app.adjTarget = cpr.name;
-                    }
-                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                        schedGroup = Process.THREAD_GROUP_DEFAULT;
+        for (int provi = app.pubProviders.size()-1;
+                provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                provi--) {
+            ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
+            for (int i = cpr.connections.size()-1;
+                    i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+                            || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                    i--) {
+                ContentProviderConnection conn = cpr.connections.get(i);
+                ProcessRecord client = conn.client;
+                if (client == app) {
+                    // Being our own client is not interesting.
+                    continue;
+                }
+                int myHiddenAdj = hiddenAdj;
+                if (myHiddenAdj > client.hiddenAdj) {
+                    if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
+                        myHiddenAdj = client.hiddenAdj;
+                    } else {
+                        myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                     }
                 }
-                // If the provider has external (non-framework) process
-                // dependencies, ensure that its adjustment is at least
-                // FOREGROUND_APP_ADJ.
-                if (cpr.hasExternalProcessHandles()) {
-                    if (adj > ProcessList.FOREGROUND_APP_ADJ) {
-                        adj = ProcessList.FOREGROUND_APP_ADJ;
-                        schedGroup = Process.THREAD_GROUP_DEFAULT;
-                        app.hidden = false;
-                        app.keeping = true;
-                        app.adjType = "provider";
-                        app.adjTarget = cpr.name;
+                int myClientHiddenAdj = clientHiddenAdj;
+                if (myClientHiddenAdj > client.clientHiddenAdj) {
+                    if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+                        myClientHiddenAdj = client.clientHiddenAdj;
+                    } else {
+                        myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                     }
                 }
+                int myEmptyAdj = emptyAdj;
+                if (myEmptyAdj > client.emptyAdj) {
+                    if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
+                        myEmptyAdj = client.emptyAdj;
+                    } else {
+                        myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
+                    }
+                }
+                int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                        myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+                if (adj > clientAdj) {
+                    if (app.hasShownUi && app != mHomeProcess
+                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                        app.adjType = "bg-ui-provider";
+                    } else {
+                        adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
+                                ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
+                        app.adjType = "provider";
+                    }
+                    if (!client.hidden) {
+                        app.hidden = false;
+                    }
+                    if (client.keeping) {
+                        app.keeping = true;
+                    }
+                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                            .REASON_PROVIDER_IN_USE;
+                    app.adjSource = client;
+                    app.adjSourceOom = clientAdj;
+                    app.adjTarget = cpr.name;
+                }
+                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                }
+            }
+            // If the provider has external (non-framework) process
+            // dependencies, ensure that its adjustment is at least
+            // FOREGROUND_APP_ADJ.
+            if (cpr.hasExternalProcessHandles()) {
+                if (adj > ProcessList.FOREGROUND_APP_ADJ) {
+                    adj = ProcessList.FOREGROUND_APP_ADJ;
+                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    app.hidden = false;
+                    app.keeping = true;
+                    app.adjType = "provider";
+                    app.adjTarget = cpr.name;
+                }
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d6a6eb8..f97b720 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3333,14 +3333,16 @@
         }
     }
 
-    void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
-            boolean dumpClient, String dumpPackage) {
+    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
+            boolean dumpClient, String dumpPackage, boolean needSep) {
+        boolean printed = false;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            pw.print("  Task "); pw.print(taskNdx); pw.print(": id #"); pw.println(task.taskId);
-            ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
-                "    ", "Hist", true, !dumpAll, dumpClient, dumpPackage);
+            printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
+                    mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
+                    dumpClient, dumpPackage, needSep, "    Task " + taskNdx + ": id #" + task.taskId);
         }
+        return printed;
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index bddca2b..a638981 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2215,82 +2215,95 @@
         return getFocusedStack().getDumpActivitiesLocked(name);
     }
 
+    static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
+            boolean needSep, String prefix) {
+        if (activity != null) {
+            if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
+                if (needSep) {
+                    pw.println();
+                    needSep = false;
+                }
+                pw.print(prefix);
+                pw.println(activity);
+            }
+        }
+        return needSep;
+    }
+
     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
             boolean dumpClient, String dumpPackage) {
-        pw.print("  mStackState="); pw.println(stackStateToString(mStackState));
-        if (mGoingToSleepActivities.size() > 0) {
-            pw.println("  Activities waiting to sleep:");
-            dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
-                    dumpPackage);
-        }
-        if (dumpAll) {
-            pw.println("  mSleepTimeout: " + mSleepTimeout);
-        }
         final int numStacks = mStacks.size();
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
+            if (stackNdx != 0) {
+                pw.println();
+            }
             pw.print("  Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
-            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
-            pw.println(" ");
-            pw.println("  Running activities (most recent first):");
-            dumpHistoryList(fd, pw, stack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
-                    dumpPackage);
+            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+            dumpHistoryList(fd, pw, stack.mLRUActivities, "    ", "Run", false, !dumpAll, false,
+                    dumpPackage, true, "    Running activities (most recent first):");
 
-            pw.print("  Stack #"); pw.println(mStacks.indexOf(stack));
-            if (stack.mPausingActivity != null) {
-                pw.println("  mPausingActivity: " + stack.mPausingActivity);
-            }
-            pw.println("  mResumedActivity: " + stack.mResumedActivity);
+            boolean needSep = true;
+            needSep = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+                    "    mPausingActivity: ");
+            needSep = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+                    "    mResumedActivity: ");
             if (dumpAll) {
-                pw.println("  mLastPausedActivity: " + stack.mLastPausedActivity);
+                printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+                        "    mLastPausedActivity: ");
             }
         }
 
-        if (mFinishingActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting to finish:");
-            dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll, false,
-                    dumpPackage);
-        }
+        dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to finish:");
+        dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to stop:");
+        dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
+                false, dumpPackage, true, "  Activities waiting for another to become visible:");
+        dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to sleep:");
+        dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
+                dumpPackage, true, "  Activities waiting to sleep:");
 
-        if (mStoppingActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting to stop:");
-            dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
-                    dumpPackage);
-        }
-
-        if (mWaitingVisibleActivities.size() > 0) {
-            pw.println(" ");
-            pw.println("  Activities waiting for another to become visible:");
-            dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
-                    false, dumpPackage);
-        }
-
-        if (dumpAll) {
-            pw.println(" ");
-            pw.println("  mCurTaskId: " + mCurTaskId);
+        if (dumpPackage == null) {
+            pw.println();
+            pw.print("  mStackState="); pw.println(stackStateToString(mStackState));
+            if (dumpAll) {
+                pw.println("  mSleepTimeout: " + mSleepTimeout);
+            }
+            if (dumpAll) {
+                pw.println("  mCurTaskId: " + mCurTaskId);
+            }
         }
         return true;
     }
 
-    static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
+    static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
             String prefix, String label, boolean complete, boolean brief, boolean client,
-            String dumpPackage) {
+            String dumpPackage, boolean needNL, String header) {
         TaskRecord lastTask = null;
-        boolean needNL = false;
-        final String innerPrefix = prefix + "      ";
-        final String[] args = new String[0];
+        String innerPrefix = null;
+        String[] args = null;
+        boolean printed = false;
         for (int i=list.size()-1; i>=0; i--) {
             final ActivityRecord r = list.get(i);
             if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
                 continue;
             }
+            if (innerPrefix == null) {
+                innerPrefix = prefix + "      ";
+                args = new String[0];
+            }
+            printed = true;
             final boolean full = !brief && (complete || !r.isInHistory());
             if (needNL) {
-                pw.println(" ");
+                pw.println("");
                 needNL = false;
             }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
             if (lastTask != r.task) {
                 lastTask = r.task;
                 pw.print(prefix);
@@ -2341,6 +2354,7 @@
                 needNL = true;
             }
         }
+        return printed;
     }
 
     void scheduleIdleTimeoutLocked(ActivityRecord next) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 7929f96..3a4a34c 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -32,12 +32,12 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.PrintWriterPrinter;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 
 /**
@@ -129,8 +129,8 @@
     // all IIntentReceivers that are registered from this process.
     final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>();
     // class (String) -> ContentProviderRecord
-    final HashMap<String, ContentProviderRecord> pubProviders
-            = new HashMap<String, ContentProviderRecord>(); 
+    final ArrayMap<String, ContentProviderRecord> pubProviders
+            = new ArrayMap<String, ContentProviderRecord>();
     // All ContentProviderRecord process is using
     final ArrayList<ContentProviderConnection> conProviders
             = new ArrayList<ContentProviderConnection>();
@@ -302,9 +302,9 @@
         }
         if (pubProviders.size() > 0) {
             pw.print(prefix); pw.println("Published Providers:");
-            for (HashMap.Entry<String, ContentProviderRecord> ent : pubProviders.entrySet()) {
-                pw.print(prefix); pw.print("  - "); pw.println(ent.getKey());
-                pw.print(prefix); pw.print("    -> "); pw.println(ent.getValue());
+            for (int i=0; i<pubProviders.size(); i++) {
+                pw.print(prefix); pw.print("  - "); pw.println(pubProviders.keyAt(i));
+                pw.print(prefix); pw.print("    -> "); pw.println(pubProviders.valueAt(i));
             }
         }
         if (conProviders.size() > 0) {
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 9dbf5f5..3249e1e 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -230,58 +230,88 @@
         return didSomething;
     }
 
-    private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
-            HashMap<ComponentName, ContentProviderRecord> map) {
+    private boolean dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll, String dumpPackage,
+            String header, boolean needSep, HashMap<ComponentName, ContentProviderRecord> map) {
         Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
+        boolean written = false;
         while (it.hasNext()) {
             Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
             ContentProviderRecord r = e.getValue();
+            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                continue;
+            }
+            if (needSep) {
+                pw.println("");
+                needSep = false;
+            }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
+            written = true;
             pw.print("  * ");
             pw.println(r);
             r.dump(pw, "    ", dumpAll);
         }
+        return written;
     }
 
-    private void dumpProvidersByNameLocked(PrintWriter pw,
-            HashMap<String, ContentProviderRecord> map) {
+    private boolean dumpProvidersByNameLocked(PrintWriter pw, String dumpPackage,
+            String header, boolean needSep, HashMap<String, ContentProviderRecord> map) {
         Iterator<Map.Entry<String, ContentProviderRecord>> it = map.entrySet().iterator();
+        boolean written = false;
         while (it.hasNext()) {
             Map.Entry<String, ContentProviderRecord> e = it.next();
             ContentProviderRecord r = e.getValue();
+            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                continue;
+            }
+            if (needSep) {
+                pw.println("");
+                needSep = false;
+            }
+            if (header != null) {
+                pw.println(header);
+                header = null;
+            }
+            written = true;
             pw.print("  ");
             pw.print(e.getKey());
             pw.print(": ");
             pw.println(r.toShortString());
         }
+        return written;
     }
 
-    void dumpProvidersLocked(PrintWriter pw, boolean dumpAll) {
+    boolean dumpProvidersLocked(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+        boolean needSep = false;
+
         if (mSingletonByClass.size() > 0) {
             pw.println("  Published single-user content providers (by class):");
-            dumpProvidersByClassLocked(pw, dumpAll, mSingletonByClass);
+            needSep = dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+                    "  Published single-user content providers (by class):", needSep,
+                    mSingletonByClass);
         }
 
-        pw.println("");
         for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
             HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
-            pw.println("");
-            pw.println("  Published user " + mProvidersByClassPerUser.keyAt(i)
-                    + " content providers (by class):");
-            dumpProvidersByClassLocked(pw, dumpAll, map);
+            needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+                    "  Published user " + mProvidersByClassPerUser.keyAt(i)
+                            + " content providers (by class):", needSep, map);
         }
 
         if (dumpAll) {
-            pw.println("");
-            pw.println("  Single-user authority to provider mappings:");
-            dumpProvidersByNameLocked(pw, mSingletonByName);
+            needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+                    "  Single-user authority to provider mappings:", needSep, mSingletonByName);
 
             for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
-                pw.println("");
-                pw.println("  User " + mProvidersByNamePerUser.keyAt(i)
-                        + " authority to provider mappings:");
-                dumpProvidersByNameLocked(pw, mProvidersByNamePerUser.valueAt(i));
+                needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+                        "  User " + mProvidersByNamePerUser.keyAt(i)
+                                + " authority to provider mappings:", needSep,
+                        mProvidersByNamePerUser.valueAt(i));
             }
         }
+        return needSep;
     }
 
     protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 9fdd293..707e8ee 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -16,34 +16,32 @@
 
 package com.android.server.am;
 
-import android.app.PendingIntent;
-import android.net.Uri;
-import android.provider.Settings;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.NotificationManagerService;
 
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -76,11 +74,11 @@
     final boolean exported; // from ServiceInfo.exported
     final Runnable restarter; // used to schedule retries of starting the service
     final long createTime;  // when this service was created
-    final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
-            = new HashMap<Intent.FilterComparison, IntentBindRecord>();
+    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
+            = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
                             // All active bindings to the service.
-    final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
-            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
+    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
+            = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
                             // IBinder -> ConnectionRecord of all bound clients
 
     ProcessRecord app;      // where this service is running or null.
@@ -258,10 +256,9 @@
             dumpStartList(pw, prefix, pendingStarts, 0);
         }
         if (bindings.size() > 0) {
-            Iterator<IntentBindRecord> it = bindings.values().iterator();
             pw.print(prefix); pw.println("Bindings:");
-            while (it.hasNext()) {
-                IntentBindRecord b = it.next();
+            for (int i=0; i<bindings.size(); i++) {
+                IntentBindRecord b = bindings.valueAt(i);
                 pw.print(prefix); pw.print("* IntentBindRecord{");
                         pw.print(Integer.toHexString(System.identityHashCode(b)));
                         if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
@@ -273,9 +270,8 @@
         }
         if (connections.size() > 0) {
             pw.print(prefix); pw.println("All Connections:");
-            Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
-            while (it.hasNext()) {
-                ArrayList<ConnectionRecord> c = it.next();
+            for (int conni=0; conni<connections.size(); conni++) {
+                ArrayList<ConnectionRecord> c = connections.valueAt(conni);
                 for (int i=0; i<c.size(); i++) {
                     pw.print(prefix); pw.print("  "); pw.println(c.get(i));
                 }