Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29b5b9e2 authored by Jing Ji's avatar Jing Ji
Browse files

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
parent 19cf36b0
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -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 {
+4 −0
Original line number Diff line number Diff line
@@ -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;