Merge change Ia53c6725 into eclair-mr2

* changes:
  Add bindService API to not bring ot foreground.
diff --git a/api/current.xml b/api/current.xml
index a5d1967..af9c67d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -32352,6 +32352,17 @@
  visibility="public"
 >
 </field>
+<field name="BIND_NOT_FOREGROUND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CLIPBOARD_SERVICE"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3344158..2ab5357 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -104,6 +104,18 @@
      */
     public static final int BIND_DEBUG_UNBIND = 0x0002;
 
+    /**
+     * Flag for {@link #bindService}: don't allow this binding to raise
+     * the target service's process to the foreground scheduling priority.
+     * It will still be raised to the at least the same memory priority
+     * as the client (so that its process will not be killable in any
+     * situation where the client is not killable), but for CPU scheduling
+     * purposes it may be left in the background.  This only has an impact
+     * in the situation where the binding client is a foreground process
+     * and the target service is in a background process.
+     */
+    public static final int BIND_NOT_FOREGROUND = 0x0004;
+
     /** Return an AssetManager instance for your application's package. */
     public abstract AssetManager getAssets();
 
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 0589ce6..d436365 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -557,7 +557,7 @@
         intent.setAction("android.content.SyncAdapter");
         intent.setComponent(syncAdapterInfo.componentName);
         mContext.bindService(intent, new InitializerServiceConnection(account, authority),
-                Context.BIND_AUTO_CREATE);
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND);
     }
 
     private class InitializerServiceConnection implements ServiceConnection {
@@ -1145,7 +1145,8 @@
                     com.android.internal.R.string.sync_binding_label);
             intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                     mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
-            return mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
+            return mContext.bindService(intent, this,
+                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND);
         }
 
         void unBindFromSyncAdapter() {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 65070dd..6c5c52f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -5258,7 +5258,8 @@
         
         app.thread = thread;
         app.curAdj = app.setAdj = -100;
-        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
+        app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
+        app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.forcingToForeground = null;
         app.foregroundServices = false;
         app.debugging = false;
@@ -9133,7 +9134,7 @@
                 if (needSep) pw.println(" ");
                 needSep = true;
                 pw.println("  Running processes (most recent first):");
-                dumpProcessList(pw, mLRUProcesses, "    ",
+                dumpProcessList(pw, this, mLRUProcesses, "    ",
                         "App ", "PERS", true);
                 needSep = true;
             }
@@ -9164,7 +9165,7 @@
                 if (needSep) pw.println(" ");
                 needSep = true;
                 pw.println("  Persisent processes that are starting:");
-                dumpProcessList(pw, mPersistentStartingProcesses, "    ",
+                dumpProcessList(pw, this, mPersistentStartingProcesses, "    ",
                         "Starting Norm", "Restarting PERS", false);
             }
 
@@ -9172,7 +9173,7 @@
                 if (needSep) pw.println(" ");
                 needSep = true;
                 pw.println("  Processes that are starting:");
-                dumpProcessList(pw, mStartingProcesses, "    ",
+                dumpProcessList(pw, this, mStartingProcesses, "    ",
                         "Starting Norm", "Starting PERS", false);
             }
 
@@ -9180,7 +9181,7 @@
                 if (needSep) pw.println(" ");
                 needSep = true;
                 pw.println("  Processes that are being removed:");
-                dumpProcessList(pw, mRemovedProcesses, "    ",
+                dumpProcessList(pw, this, mRemovedProcesses, "    ",
                         "Removed Norm", "Removed PERS", false);
             }
             
@@ -9188,7 +9189,7 @@
                 if (needSep) pw.println(" ");
                 needSep = true;
                 pw.println("  Processes that are on old until the system is ready:");
-                dumpProcessList(pw, mProcessesOnHold, "    ",
+                dumpProcessList(pw, this, mProcessesOnHold, "    ",
                         "OnHold Norm", "OnHold PERS", false);
             }
 
@@ -9617,7 +9618,16 @@
         }
     }
 
-    private static final int dumpProcessList(PrintWriter pw, List list,
+    private static String buildOomTag(String prefix, String space, int val, int base) {
+        if (val == base) {
+            if (space == null) return prefix;
+            return prefix + "  ";
+        }
+        return prefix + "+" + Integer.toString(val-base);
+    }
+    
+    private static final int dumpProcessList(PrintWriter pw,
+            ActivityManagerService service, List list,
             String prefix, String normalLabel, String persistentLabel,
             boolean inclOomAdj) {
         int numPers = 0;
@@ -9628,9 +9638,55 @@
                       + " #" + i + ":");
                 r.dump(pw, prefix + "  ");
             } else if (inclOomAdj) {
-                pw.println(String.format("%s%s #%2d: adj=%4d/%d %s (%s)",
+                String oomAdj;
+                if (r.setAdj >= EMPTY_APP_ADJ) {
+                    oomAdj = buildOomTag("empty", null, r.setAdj,
+                            EMPTY_APP_ADJ);
+                } else if (r.setAdj >= CONTENT_PROVIDER_ADJ) {
+                    oomAdj = buildOomTag("cprov", null, r.setAdj,
+                            CONTENT_PROVIDER_ADJ);
+                } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
+                    oomAdj = buildOomTag("hid", "  ", r.setAdj,
+                            HIDDEN_APP_MIN_ADJ);
+                } else if (r.setAdj >= service.HOME_APP_ADJ) {
+                    oomAdj = buildOomTag("home ", null, r.setAdj,
+                            service.HOME_APP_ADJ);
+                } else if (r.setAdj >= service.SECONDARY_SERVER_ADJ) {
+                    oomAdj = buildOomTag("svc", "  ", r.setAdj,
+                            service.SECONDARY_SERVER_ADJ);
+                } else if (r.setAdj >= service.BACKUP_APP_ADJ) {
+                    oomAdj = buildOomTag("bckup", null, r.setAdj,
+                            service.BACKUP_APP_ADJ);
+                } else if (r.setAdj >= service.VISIBLE_APP_ADJ) {
+                    oomAdj = buildOomTag("vis  ", null, r.setAdj,
+                            service.VISIBLE_APP_ADJ);
+                } else if (r.setAdj >= service.FOREGROUND_APP_ADJ) {
+                    oomAdj = buildOomTag("fore ", null, r.setAdj,
+                            service.FOREGROUND_APP_ADJ);
+                } else if (r.setAdj >= CORE_SERVER_ADJ) {
+                    oomAdj = buildOomTag("core ", null, r.setAdj,
+                            CORE_SERVER_ADJ);
+                } else if (r.setAdj >= SYSTEM_ADJ) {
+                    oomAdj = buildOomTag("sys  ", null, r.setAdj,
+                            SYSTEM_ADJ);
+                } else {
+                    oomAdj = Integer.toString(r.setAdj);
+                }
+                String schedGroup;
+                switch (r.setSchedGroup) {
+                    case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+                        schedGroup = "B";
+                        break;
+                    case Process.THREAD_GROUP_DEFAULT:
+                        schedGroup = "F";
+                        break;
+                    default:
+                        schedGroup = Integer.toString(r.setSchedGroup);
+                        break;
+                }
+                pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
                         prefix, (r.persistent ? persistentLabel : normalLabel),
-                        i, r.setAdj, r.setSchedGroup, r.toString(), r.adjType));
+                        i, oomAdj, schedGroup, r.toString(), r.adjType));
                 if (r.adjSource != null || r.adjTarget != null) {
                     pw.println(prefix + "          " + r.adjTarget
                             + " used by " + r.adjSource);
@@ -13038,6 +13094,7 @@
 
         if (app.thread == null) {
             app.adjSeq = mAdjSeq;
+            app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             return (app.curAdj=EMPTY_APP_ADJ);
         }
 
@@ -13058,52 +13115,63 @@
         // Determine the importance of the process, starting with most
         // important to least, and assign an appropriate OOM adjustment.
         int adj;
+        int schedGroup;
         int N;
         if (app == TOP_APP) {
             // The last app on the list is the foreground app.
             adj = FOREGROUND_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "top-activity";
         } else if (app.instrumentationClass != null) {
             // Don't want to kill running instrumentation.
             adj = FOREGROUND_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "instrumentation";
         } else if (app.persistentActivities > 0) {
             // Special persistent activities...  shouldn't be used these days.
             adj = FOREGROUND_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "persistent";
         } else if (app.curReceiver != null ||
                 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground.
             adj = FOREGROUND_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "broadcast";
         } else if (app.executingServices.size() > 0) {
             // An app that is currently executing a service callback also
             // counts as being in the foreground.
             adj = FOREGROUND_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "exec-service";
         } else if (app.foregroundServices) {
             // The user is aware of this app, so make it visible.
             adj = VISIBLE_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "foreground-service";
         } else if (app.forcingToForeground != null) {
             // The user is aware of this app, so make it visible.
             adj = VISIBLE_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "force-foreground";
             app.adjSource = app.forcingToForeground;
         } else if (app == mHomeProcess) {
             // This process is hosting what we currently consider to be the
             // home app, so we don't want to let it go into the background.
             adj = HOME_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.adjType = "home";
         } else if ((N=app.activities.size()) != 0) {
             // This app is in the background with paused activities.
             adj = hiddenAdj;
+            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.adjType = "bg-activities";
             for (int j=0; j<N; j++) {
                 if (((HistoryRecord)app.activities.get(j)).visible) {
                     // This app has a visible activity!
                     adj = VISIBLE_APP_ADJ;
+                    schedGroup = Process.THREAD_GROUP_DEFAULT;
                     app.adjType = "visible";
                     break;
                 }
@@ -13111,6 +13179,7 @@
         } else {
             // A very not-needed process.
             adj = EMPTY_APP_ADJ;
+            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.adjType = "empty";
         }
 
@@ -13120,7 +13189,6 @@
         // infinite recursion.
         app.adjSeq = mAdjSeq;
         app.curRawAdj = adj;
-        app.curAdj = adj <= app.maxAdj ? adj : app.maxAdj;
 
         if (mBackupTarget != null && app == mBackupTarget.app) {
             // If possible we want to avoid killing apps while they're being backed up
@@ -13131,7 +13199,8 @@
             }
         }
 
-        if (app.services.size() != 0 && adj > FOREGROUND_APP_ADJ) {
+        if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
+                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
             final long now = SystemClock.uptimeMillis();
             // This process is more important if the top activity is
             // bound to the service.
@@ -13149,7 +13218,8 @@
                         }
                     }
                 }
-                if (s.connections.size() > 0 && adj > FOREGROUND_APP_ADJ) {
+                if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
+                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
                     Iterator<ConnectionRecord> kt
                             = s.connections.values().iterator();
                     while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
@@ -13181,6 +13251,11 @@
                                 app.adjSource = cr.binding.client;
                                 app.adjTarget = s.serviceInfo.name;
                             }
+                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                }
+                            }
                         }
                         HistoryRecord a = cr.activity;
                         //if (a != null) {
@@ -13190,6 +13265,7 @@
                                 (a.state == ActivityState.RESUMED
                                  || a.state == ActivityState.PAUSING)) {
                             adj = FOREGROUND_APP_ADJ;
+                            schedGroup = Process.THREAD_GROUP_DEFAULT;
                             app.adjType = "service";
                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                     .REASON_SERVICE_IN_USE;
@@ -13211,9 +13287,11 @@
             }
         }
 
-        if (app.pubProviders.size() != 0 && adj > FOREGROUND_APP_ADJ) {
+        if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
+                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
             Iterator jt = app.pubProviders.values().iterator();
-            while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
+            while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
+                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
                 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
                 if (cpr.clients.size() != 0) {
                     Iterator<ProcessRecord> kt = cpr.clients.iterator();
@@ -13242,6 +13320,9 @@
                             app.adjSource = client;
                             app.adjTarget = cpr.info.name;
                         }
+                        if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                            schedGroup = Process.THREAD_GROUP_DEFAULT;
+                        }
                     }
                 }
                 // If the provider has external (non-framework) process
@@ -13250,6 +13331,7 @@
                 if (cpr.externals != 0) {
                     if (adj > FOREGROUND_APP_ADJ) {
                         adj = FOREGROUND_APP_ADJ;
+                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                         app.adjType = "provider";
                         app.adjTarget = cpr.info.name;
                     }
@@ -13272,12 +13354,13 @@
         //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
         if (adj > app.maxAdj) {
             adj = app.maxAdj;
+            if (app.maxAdj <= VISIBLE_APP_ADJ) {
+                schedGroup = Process.THREAD_GROUP_DEFAULT;
+            }
         }
 
         app.curAdj = adj;
-        app.curSchedGroup = adj > VISIBLE_APP_ADJ
-                ? Process.THREAD_GROUP_BG_NONINTERACTIVE
-                : Process.THREAD_GROUP_DEFAULT;
+        app.curSchedGroup = schedGroup;
         
         return adj;
     }
@@ -13422,7 +13505,7 @@
 
         int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP);
 
-        if (app.pid != 0 && app.pid != MY_PID) {
+        if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
             if (app.curRawAdj != app.setRawAdj) {
                 if (app.curRawAdj > FOREGROUND_APP_ADJ
                         && app.setRawAdj <= FOREGROUND_APP_ADJ) {