summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/am/ActivityManagerService.java
diff options
context:
space:
mode:
authorriddle_hsu <riddle_hsu@htc.com>2015-10-23 23:58:31 +0800
committerSteve Kondik <steve@cyngn.com>2015-11-07 05:40:43 -0800
commitea69b5663c9917c0be656096301b6751d0b635ab (patch)
tree8a490c4d8ea0a3fd705aeb2a4d0431a84cc42f4d /services/core/java/com/android/server/am/ActivityManagerService.java
parentccd5383ea172bd6b036dd8b8e78353d059c97b87 (diff)
downloadframeworks_base-ea69b5663c9917c0be656096301b6751d0b635ab.zip
frameworks_base-ea69b5663c9917c0be656096301b6751d0b635ab.tar.gz
frameworks_base-ea69b5663c9917c0be656096301b6751d0b635ab.tar.bz2
Improve handling of accessing dying provider.
Case 1: The provider process has been killed and marked killedByAm, but the death recipient does not be called immediately. Case 2: Just before updating oom adj, low memory killer has killed the provider process. When a process is dying, it may be temporary Z state or R state with pending signal. If we restart the process immediately, the dying process may be D state temporarily and still holds file lock of database file. Then the new process will meet problem in sqlite. By adding the provider into launching list, when the death recipient is called, the provider process t will be restarted and use the same ContentProviderRecord to notify the caller. And also because the restart is depends on binder died event which is triggered from exit_files of kernel, it has higher confidence that the previous process is completely cleared. Change-Id: Ie69ce6c99f29f47358d0fd977ab77cae31409ca8
Diffstat (limited to 'services/core/java/com/android/server/am/ActivityManagerService.java')
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java55
1 files changed, 29 insertions, 26 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2fdc45a..1ced13b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9678,6 +9678,7 @@ public final class ActivityManagerService extends ActivityManagerNative
checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
+ boolean importantCaller = false;
// In this case the provider instance already exists, so we can
// return it right away.
conn = incProviderCountLocked(r, cpr, token, stable);
@@ -9687,6 +9688,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// 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.
+ importantCaller = true;
checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
updateLruProcessLocked(cpr.proc, false, null);
checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
@@ -9699,36 +9701,37 @@ public final class ActivityManagerService extends ActivityManagerNative
"com.android.providers.calendar/.CalendarProvider2")) {
Slog.v(TAG, "****************** KILLING "
+ cpr.name.flattenToShortString());
- Process.killProcess(cpr.proc.pid);
+ cpr.proc.kill("test killing calendar provider", true);
}
}
- checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
- boolean success = updateOomAdjLocked(cpr.proc);
- maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
- checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
- if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
- // NOTE: there is still a race here where a signal could be
- // pending on the process even though we managed to update its
- // adj level. Not sure what to do about this, but at least
- // the race is now smaller.
+
+ boolean success = !cpr.proc.killedByAm;
+ if (success) {
+ checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
+ success = updateOomAdjLocked(cpr.proc);
+ maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
+ checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
+ if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
+ }
+
+ // There is still a race here where a signal could be pending on
+ // the process even though we managed to update its adj level.
+ // We check this case for perceptible app but exclude persistent
+ // because it should not be killed normally.
+ if (success && importantCaller && r != null && !r.persistent
+ && r.pid != cpr.proc.pid && !cpr.proc.persistent) {
+ success = ProcessList.isAlive(cpr.proc.pid, true);
+ }
+
if (!success) {
- // Uh oh... it looks like the provider's process
- // has been killed on us. We need to wait for a new
- // process to be started, and make sure its death
- // doesn't kill our process.
+ // It looks like the provider's process has been killed.
+ // We need to wait for a new process to be started,
+ // and make sure its death doesn't kill caller process.
Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
- + " is crashing; detaching " + r);
- boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
- if (!lastRef) {
- // This wasn't the last ref our process had on
- // the provider... we have now been killed, bail.
- return null;
- }
- providerRunning = false;
- conn = null;
+ + " is gone; waiting it to restart for " + r);
+ cpr.provider = null;
+ cpr.launchingApp = cpr.proc;
+ mLaunchingProviders.add(cpr);
}
}