Merge "Hopefully fix issue #2662536: Why is launcher being killed?" into froyo

This commit is contained in:
Dianne Hackborn
2010-05-10 17:27:14 -07:00
committed by Android (Google) Code Review
4 changed files with 91 additions and 17 deletions

View File

@ -747,6 +747,24 @@ public class Process {
*/ */
public static final native void sendSignal(int pid, int signal); public static final native void sendSignal(int pid, int signal);
/**
* @hide
* Private impl for avoiding a log message... DO NOT USE without doing
* your own log, or the Android Illuminati will find you some night and
* beat you up.
*/
public static final void killProcessQuiet(int pid) {
sendSignalQuiet(pid, SIGNAL_KILL);
}
/**
* @hide
* Private impl for avoiding a log message... DO NOT USE without doing
* your own log, or the Android Illuminati will find you some night and
* beat you up.
*/
public static final native void sendSignalQuiet(int pid, int signal);
/** @hide */ /** @hide */
public static final native long getFreeMemory(); public static final native long getFreeMemory();

View File

@ -311,8 +311,8 @@ jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz,
sprintf(text, "%d", adj); sprintf(text, "%d", adj);
write(fd, text, strlen(text)); write(fd, text, strlen(text));
close(fd); close(fd);
return true;
} }
return true;
} }
#endif #endif
return false; return false;
@ -797,6 +797,13 @@ void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint si
} }
} }
void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig)
{
if (pid > 0) {
kill(pid, sig);
}
}
static jlong android_os_Process_getElapsedCpuTime(JNIEnv* env, jobject clazz) static jlong android_os_Process_getElapsedCpuTime(JNIEnv* env, jobject clazz)
{ {
struct timespec ts; struct timespec ts;
@ -854,6 +861,7 @@ static const JNINativeMethod methods[] = {
{"setUid", "(I)I", (void*)android_os_Process_setUid}, {"setUid", "(I)I", (void*)android_os_Process_setUid},
{"setGid", "(I)I", (void*)android_os_Process_setGid}, {"setGid", "(I)I", (void*)android_os_Process_setGid},
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal}, {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
{"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
{"supportsProcesses", "()Z", (void*)android_os_Process_supportsProcesses}, {"supportsProcesses", "()Z", (void*)android_os_Process_supportsProcesses},
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory}, {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines}, {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},

View File

@ -321,12 +321,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
static final int MAX_HIDDEN_APPS = 15; static final int MAX_HIDDEN_APPS = 15;
// We put empty content processes after any hidden processes that have // We put empty content processes after any hidden processes that have
// been idle for less than 30 seconds. // been idle for less than 15 seconds.
static final long CONTENT_APP_IDLE_OFFSET = 30*1000; static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
// We put empty content processes after any hidden processes that have // We put empty content processes after any hidden processes that have
// been idle for less than 60 seconds. // been idle for less than 120 seconds.
static final long EMPTY_APP_IDLE_OFFSET = 60*1000; static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
static { static {
// These values are set in system/rootdir/init.rc on startup. // These values are set in system/rootdir/init.rc on startup.
@ -879,6 +879,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
*/ */
int mAdjSeq = 0; int mAdjSeq = 0;
/**
* Current sequence id for process LRU updating.
*/
int mLruSeq = 0;
/** /**
* Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
* is set, indicating the user wants processes started in such a way * is set, indicating the user wants processes started in such a way
@ -1588,8 +1593,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
} }
} }
private final void updateLruProcessLocked(ProcessRecord app, private final void updateLruProcessInternalLocked(ProcessRecord app,
boolean oomAdj, boolean updateActivityTime) { boolean oomAdj, boolean updateActivityTime, int bestPos) {
// put it on the LRU to keep track of when it should be exited. // put it on the LRU to keep track of when it should be exited.
int lrui = mLruProcesses.indexOf(app); int lrui = mLruProcesses.indexOf(app);
if (lrui >= 0) mLruProcesses.remove(lrui); if (lrui >= 0) mLruProcesses.remove(lrui);
@ -1597,6 +1602,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
int i = mLruProcesses.size()-1; int i = mLruProcesses.size()-1;
int skipTop = 0; int skipTop = 0;
app.lruSeq = mLruSeq;
// compute the new weight for this process. // compute the new weight for this process.
if (updateActivityTime) { if (updateActivityTime) {
app.lastActivityTime = SystemClock.uptimeMillis(); app.lastActivityTime = SystemClock.uptimeMillis();
@ -1619,6 +1626,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// Also don't let it kick out the first few "real" hidden processes. // Also don't let it kick out the first few "real" hidden processes.
skipTop = MIN_HIDDEN_APPS; skipTop = MIN_HIDDEN_APPS;
} }
while (i >= 0) { while (i >= 0) {
ProcessRecord p = mLruProcesses.get(i); ProcessRecord p = mLruProcesses.get(i);
// If this app shouldn't be in front of the first N background // If this app shouldn't be in front of the first N background
@ -1626,7 +1634,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) { if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
skipTop--; skipTop--;
} }
if (p.lruWeight <= app.lruWeight){ if (p.lruWeight <= app.lruWeight || i < bestPos) {
mLruProcesses.add(i+1, app); mLruProcesses.add(i+1, app);
break; break;
} }
@ -1636,12 +1644,39 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mLruProcesses.add(0, app); mLruProcesses.add(0, app);
} }
// If the app is currently using a content provider or service,
// bump those processes as well.
if (app.connections.size() > 0) {
for (ConnectionRecord cr : app.connections) {
if (cr.binding != null && cr.binding.service != null
&& cr.binding.service.app != null
&& cr.binding.service.app.lruSeq != mLruSeq) {
updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
updateActivityTime, i+1);
}
}
}
if (app.conProviders.size() > 0) {
for (ContentProviderRecord cpr : app.conProviders.keySet()) {
if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
updateLruProcessInternalLocked(cpr.app, oomAdj,
updateActivityTime, i+1);
}
}
}
//Slog.i(TAG, "Putting proc to front: " + app.processName); //Slog.i(TAG, "Putting proc to front: " + app.processName);
if (oomAdj) { if (oomAdj) {
updateOomAdjLocked(); updateOomAdjLocked();
} }
} }
private final void updateLruProcessLocked(ProcessRecord app,
boolean oomAdj, boolean updateActivityTime) {
mLruSeq++;
updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
}
private final boolean updateLRUListLocked(HistoryRecord r) { private final boolean updateLRUListLocked(HistoryRecord r) {
final boolean hadit = mLRUActivities.remove(r); final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r); mLRUActivities.add(r);
@ -4677,8 +4712,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// Clean up already done if the process has been re-started. // Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null && if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) { app.thread.asBinder() == thread.asBinder()) {
Slog.i(TAG, "Process " + app.processName + " (pid " + pid if (!app.killedBackground) {
+ ") has died."); Slog.i(TAG, "Process " + app.processName + " (pid " + pid
+ ") has died.");
}
EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName); EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
if (localLOGV) Slog.v( if (localLOGV) Slog.v(
TAG, "Dying app: " + app + ", pid: " + pid TAG, "Dying app: " + app + ", pid: " + pid
@ -7826,6 +7863,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
} }
if (cpr.app != null) { if (cpr.app != null) {
if (r.setAdj >= VISIBLE_APP_ADJ) {
// If this is a visible app accessing the provider,
// make sure to count it as being accessed and thus
// back up on the LRU list. This is good because
// content providers are often expensive to start.
updateLruProcessLocked(cpr.app, false, true);
}
updateOomAdjLocked(cpr.app); updateOomAdjLocked(cpr.app);
} }
@ -8492,12 +8536,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
continue; continue;
} }
int adj = proc.setAdj; int adj = proc.setAdj;
if (adj >= worstType) { if (adj >= worstType && !proc.killedBackground) {
Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason); Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid, EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
proc.processName, adj, reason); proc.processName, adj, reason);
killed = true; killed = true;
Process.killProcess(pids[i]); proc.killedBackground = true;
Process.killProcessQuiet(pids[i]);
} }
} }
} }
@ -9829,6 +9874,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
+ " mFactoryTest=" + mFactoryTest); + " mFactoryTest=" + mFactoryTest);
pw.println(" mGoingToSleep=" + mGoingToSleep); pw.println(" mGoingToSleep=" + mGoingToSleep);
pw.println(" mLaunchingActivity=" + mLaunchingActivity); pw.println(" mLaunchingActivity=" + mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
} }
return true; return true;
@ -14292,13 +14338,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (!app.killedBackground) { if (!app.killedBackground) {
numHidden++; numHidden++;
if (numHidden > MAX_HIDDEN_APPS) { if (numHidden > MAX_HIDDEN_APPS) {
Slog.i(TAG, "Kill " + app.processName Slog.i(TAG, "No longer want " + app.processName
+ " (pid " + app.pid + "): hidden #" + numHidden + " (pid " + app.pid + "): hidden #" + numHidden);
+ " beyond limit " + MAX_HIDDEN_APPS);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
app.processName, app.setAdj, "too many background"); app.processName, app.setAdj, "too many background");
app.killedBackground = true; app.killedBackground = true;
Process.killProcess(app.pid); Process.killProcessQuiet(app.pid);
} }
} }
} }

View File

@ -66,7 +66,8 @@ class ProcessRecord implements Watchdog.PssRequestor {
boolean bad; // True if disabled in the bad process list boolean bad; // True if disabled in the bad process list
boolean killedBackground; // True when proc has been killed due to too many bg boolean killedBackground; // True when proc has been killed due to too many bg
IBinder forcingToForeground;// Token that is forcing this process to be foreground IBinder forcingToForeground;// Token that is forcing this process to be foreground
int adjSeq; // Sequence id for identifying repeated trav int adjSeq; // Sequence id for identifying oom_adj assignment cycles
int lruSeq; // Sequence id for identifying LRU update cycles
ComponentName instrumentationClass;// class installed to instrument app ComponentName instrumentationClass;// class installed to instrument app
ApplicationInfo instrumentationInfo; // the application being instrumented ApplicationInfo instrumentationInfo; // the application being instrumented
String instrumentationProfileFile; // where to save profiling String instrumentationProfileFile; // where to save profiling
@ -175,6 +176,8 @@ class ProcessRecord implements Watchdog.PssRequestor {
pw.print(prefix); pw.print("persistent="); pw.print(persistent); pw.print(prefix); pw.print("persistent="); pw.print(persistent);
pw.print(" removed="); pw.print(removed); pw.print(" removed="); pw.print(removed);
pw.print(" persistentActivities="); pw.println(persistentActivities); pw.print(" persistentActivities="); pw.println(persistentActivities);
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.println(lruSeq);
if (killedBackground) { if (killedBackground) {
pw.print(prefix); pw.print("killedBackground="); pw.println(killedBackground); pw.print(prefix); pw.print("killedBackground="); pw.println(killedBackground);
} }