diff options
-rw-r--r-- | api/current.xml | 11 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 12 | ||||
-rw-r--r-- | core/java/android/content/SyncManager.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 119 |
4 files changed, 127 insertions, 20 deletions
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 abstract class Context { */ 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 @@ class SyncManager implements OnAccountsUpdateListener { 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 @@ class SyncManager implements OnAccountsUpdateListener { 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " #" + 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (app.thread == null) { app.adjSeq = mAdjSeq; + app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; return (app.curAdj=EMPTY_APP_ADJ); } @@ -13058,52 +13115,63 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } else { // A very not-needed process. adj = EMPTY_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.adjType = "empty"; } @@ -13120,7 +13189,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen (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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // " 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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) { |