Merge "Fix for bug 2672749: StringIndexOutOfBoundsException in Uri.getQueryParameter" into froyo
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 4887783..5640a06 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -747,6 +747,24 @@
*/
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 */
public static final native long getFreeMemory();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6b316ce..f921caa 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -30,10 +30,12 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Interpolator;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
@@ -1994,6 +1996,23 @@
}
/**
+ * Given a x coordinate in view space, convert it to content space.
+ * Returns the result as a float.
+ */
+ private float viewToContentXf(int x) {
+ return x * mInvActualScale;
+ }
+
+ /**
+ * Given a y coordinate in view space, convert it to content space.
+ * Takes into account the height of the title bar if there is one
+ * embedded into the WebView. Returns the result as a float.
+ */
+ private float viewToContentYf(int y) {
+ return (y - getTitleHeight()) * mInvActualScale;
+ }
+
+ /**
* Given a distance in content space, convert it to view space. Note: this
* does not reflect translation, just scaling, so this should not be called
* with coordinates, but should be called for dimensions like width or
@@ -2230,6 +2249,24 @@
r.bottom = Math.min(viewToContentY(r.bottom), mContentHeight);
}
+ // Sets r to be our visible rectangle in content coordinates. We use this
+ // method on the native side to compute the position of the fixed layers.
+ // Uses floating coordinates (necessary to correctly place elements when
+ // the scale factor is not 1)
+ private void calcOurContentVisibleRectF(RectF r) {
+ Rect ri = new Rect(0,0,0,0);
+ calcOurVisibleRect(ri);
+ // pin the rect to the bounds of the content
+ r.left = Math.max(viewToContentXf(ri.left), 0.0f);
+ // viewToContentY will remove the total height of the title bar. Add
+ // the visible height back in to account for the fact that if the title
+ // bar is partially visible, the part of the visible rect which is
+ // displaying our content is displaced by that amount.
+ r.top = Math.max(viewToContentYf(ri.top + getVisibleTitleHeight()), 0.0f);
+ r.right = Math.min(viewToContentXf(ri.right), (float)mContentWidth);
+ r.bottom = Math.min(viewToContentYf(ri.bottom), (float)mContentHeight);
+ }
+
static class ViewSizeData {
int mWidth;
int mHeight;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index e84f2e5..68be741 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -311,8 +311,8 @@
sprintf(text, "%d", adj);
write(fd, text, strlen(text));
close(fd);
- return true;
}
+ return true;
}
#endif
return false;
@@ -797,6 +797,13 @@
}
}
+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)
{
struct timespec ts;
@@ -854,6 +861,7 @@
{"setUid", "(I)I", (void*)android_os_Process_setUid},
{"setGid", "(I)I", (void*)android_os_Process_setGid},
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
+ {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
{"supportsProcesses", "()Z", (void*)android_os_Process_supportsProcesses},
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 706e15a..948d292 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -321,12 +321,12 @@
static final int MAX_HIDDEN_APPS = 15;
// We put empty content processes after any hidden processes that have
- // been idle for less than 30 seconds.
- static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
+ // been idle for less than 15 seconds.
+ static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
// We put empty content processes after any hidden processes that have
- // been idle for less than 60 seconds.
- static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
+ // been idle for less than 120 seconds.
+ static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
static {
// These values are set in system/rootdir/init.rc on startup.
@@ -880,6 +880,11 @@
int mAdjSeq = 0;
/**
+ * Current sequence id for process LRU updating.
+ */
+ int mLruSeq = 0;
+
+ /**
* Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
* is set, indicating the user wants processes started in such a way
* that they can use ANDROID_PROCESS_WRAPPER and know what will be
@@ -1588,8 +1593,8 @@
}
}
- private final void updateLruProcessLocked(ProcessRecord app,
- boolean oomAdj, boolean updateActivityTime) {
+ private final void updateLruProcessInternalLocked(ProcessRecord app,
+ boolean oomAdj, boolean updateActivityTime, int bestPos) {
// put it on the LRU to keep track of when it should be exited.
int lrui = mLruProcesses.indexOf(app);
if (lrui >= 0) mLruProcesses.remove(lrui);
@@ -1597,6 +1602,8 @@
int i = mLruProcesses.size()-1;
int skipTop = 0;
+ app.lruSeq = mLruSeq;
+
// compute the new weight for this process.
if (updateActivityTime) {
app.lastActivityTime = SystemClock.uptimeMillis();
@@ -1619,6 +1626,7 @@
// Also don't let it kick out the first few "real" hidden processes.
skipTop = MIN_HIDDEN_APPS;
}
+
while (i >= 0) {
ProcessRecord p = mLruProcesses.get(i);
// If this app shouldn't be in front of the first N background
@@ -1626,7 +1634,7 @@
if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
skipTop--;
}
- if (p.lruWeight <= app.lruWeight){
+ if (p.lruWeight <= app.lruWeight || i < bestPos) {
mLruProcesses.add(i+1, app);
break;
}
@@ -1636,12 +1644,39 @@
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);
if (oomAdj) {
updateOomAdjLocked();
}
}
+ private final void updateLruProcessLocked(ProcessRecord app,
+ boolean oomAdj, boolean updateActivityTime) {
+ mLruSeq++;
+ updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
+ }
+
private final boolean updateLRUListLocked(HistoryRecord r) {
final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r);
@@ -4677,8 +4712,10 @@
// Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
- Slog.i(TAG, "Process " + app.processName + " (pid " + pid
- + ") has died.");
+ if (!app.killedBackground) {
+ Slog.i(TAG, "Process " + app.processName + " (pid " + pid
+ + ") has died.");
+ }
EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
if (localLOGV) Slog.v(
TAG, "Dying app: " + app + ", pid: " + pid
@@ -7826,6 +7863,13 @@
}
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);
}
@@ -8492,12 +8536,13 @@
continue;
}
int adj = proc.setAdj;
- if (adj >= worstType) {
+ if (adj >= worstType && !proc.killedBackground) {
Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
proc.processName, adj, reason);
killed = true;
- Process.killProcess(pids[i]);
+ proc.killedBackground = true;
+ Process.killProcessQuiet(pids[i]);
}
}
}
@@ -9829,6 +9874,7 @@
+ " mFactoryTest=" + mFactoryTest);
pw.println(" mGoingToSleep=" + mGoingToSleep);
pw.println(" mLaunchingActivity=" + mLaunchingActivity);
+ pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
}
return true;
@@ -14292,13 +14338,12 @@
if (!app.killedBackground) {
numHidden++;
if (numHidden > MAX_HIDDEN_APPS) {
- Slog.i(TAG, "Kill " + app.processName
- + " (pid " + app.pid + "): hidden #" + numHidden
- + " beyond limit " + MAX_HIDDEN_APPS);
+ Slog.i(TAG, "No longer want " + app.processName
+ + " (pid " + app.pid + "): hidden #" + numHidden);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
app.processName, app.setAdj, "too many background");
app.killedBackground = true;
- Process.killProcess(app.pid);
+ Process.killProcessQuiet(app.pid);
}
}
}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 7620468..f49a182 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -66,7 +66,8 @@
boolean bad; // True if disabled in the bad process list
boolean killedBackground; // True when proc has been killed due to too many bg
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
ApplicationInfo instrumentationInfo; // the application being instrumented
String instrumentationProfileFile; // where to save profiling
@@ -175,6 +176,8 @@
pw.print(prefix); pw.print("persistent="); pw.print(persistent);
pw.print(" removed="); pw.print(removed);
pw.print(" persistentActivities="); pw.println(persistentActivities);
+ pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
+ pw.print(" lruSeq="); pw.println(lruSeq);
if (killedBackground) {
pw.print(prefix); pw.print("killedBackground="); pw.println(killedBackground);
}