Limit the number of attempts to launch bad content providers

Previously if a content provider gets killed/exits by itself
during launching, the system would keep retrying to launch it;
now limit the maximum attempts to 3 and give up after that.

Bug: 141020060
Test: atest CtsAppTestCases:BadProviderTest
Change-Id: Idcc308c2761c444b62c0edf377c78622dd1c39b5
This commit is contained in:
Jing Ji
2019-09-16 20:15:03 -07:00
parent 19cf36b0a5
commit 29b5b9e229
2 changed files with 23 additions and 1 deletions

View File

@@ -7441,6 +7441,7 @@ public class ActivityManagerService extends IActivityManager.Stub
dst.setProcess(r);
dst.notifyAll();
}
dst.mRestartCount = 0;
updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
src.info.authority);
@@ -13884,9 +13885,20 @@ public class ActivityManagerService extends IActivityManager.Stub
return false;
}
/**
* Remove the dying provider from known provider map and launching provider map.
* @param proc The dying process recoder
* @param cpr The provider to be removed.
* @param always If true, remove the provider from launching map always, no more restart attempt
* @return true if the given provider is in launching
*/
private final boolean removeDyingProviderLocked(ProcessRecord proc,
ContentProviderRecord cpr, boolean always) {
final boolean inLaunching = mLaunchingProviders.contains(cpr);
boolean inLaunching = mLaunchingProviders.contains(cpr);
if (inLaunching && !always && ++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) {
// It's being launched but we've reached maximum attempts, force the removal
always = true;
}
if (!inLaunching || always) {
synchronized (cpr) {
@@ -13938,6 +13950,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (inLaunching && always) {
mLaunchingProviders.remove(cpr);
cpr.mRestartCount = 0;
inLaunching = false;
}
return inLaunching;
}
@@ -14153,6 +14167,10 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
ContentProviderRecord cpr = mLaunchingProviders.get(i);
if (cpr.launchingApp == app) {
if (++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) {
// It's being launched but we've reached maximum attempts, mark it as bad
alwaysBad = true;
}
if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
restart = true;
} else {

View File

@@ -38,6 +38,9 @@ import java.io.PrintWriter;
import java.util.ArrayList;
final class ContentProviderRecord implements ComponentName.WithComponentName {
// Maximum attempts to bring up the content provider before giving up.
static final int MAX_RETRY_COUNT = 3;
final ActivityManagerService service;
public final ProviderInfo info;
final int uid;
@@ -54,6 +57,7 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
ArrayMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
// Count for external process for which we have no handles.
int externalProcessNoHandleCount;
int mRestartCount; // number of times we tried before bringing up it successfully.
ProcessRecord proc; // if non-null, hosting process.
ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
String stringName;