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

Commit 64b5e1c4 authored by Robert Carr's avatar Robert Carr Committed by Rob Carr
Browse files

Enforce a timeout for Content Providers to be published.

ActivityManagerService: In the case where we are launching
an application on behalf of a Content Provider request,
enforce a timeout inbetween the application attaching and
the content providers being published. Consider that a defective
content provider may block in ContentProvider::onCreate
indefinitely: in such a case the PROC_START_TIMEOUT has already
been removed as the activity manager must have called bindApplication.

In these cases, there will be nothing to wake threads blocking
on the (non timed) wait for provider to be published at the end of
ActivityManagerService::getContentProviderImpl. This can cause binder
threads to block 1 by 1 until eventually AMS runs out and becomes
unresponsive.

Bug: 22141958
Change-Id: I2226da5df5c79b37f0b896423b3c1eaa4a7ecbba
(cherry picked from commit da33c134)
parent 7aa79efe
Loading
Loading
Loading
Loading
+43 −7
Original line number Diff line number Diff line
@@ -316,6 +316,9 @@ public final class ActivityManagerService extends ActivityManagerNative
    // How long we wait for a launched process to attach to the activity manager
    // before we decide it's never going to come up for real.
    static final int PROC_START_TIMEOUT = 10*1000;
    // How long we wait for an attached process to publish its content providers
    // before we decide it must be hung.
    static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
    // How long we wait for a launched process to attach to the activity manager
    // before we decide it's never going to come up for real, when the process was
@@ -1368,6 +1371,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
    static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
    static final int APP_BOOST_DEACTIVATE_MSG = 58;
    static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
    static final int FIRST_ACTIVITY_STACK_MSG = 100;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1701,6 +1705,12 @@ public final class ActivityManagerService extends ActivityManagerNative
                    processStartTimedOutLocked(app);
                }
            } break;
            case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
                ProcessRecord app = (ProcessRecord)msg.obj;
                synchronized (ActivityManagerService.this) {
                    processContentProviderPublishTimedOutLocked(app);
                }
            } break;
            case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
                synchronized (ActivityManagerService.this) {
                    mStackSupervisor.doPendingActivityLaunchesLocked(true);
@@ -5944,6 +5954,11 @@ public final class ActivityManagerService extends ActivityManagerNative
        return needRestart;
    }
    private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
        cleanupAppInLaunchingProvidersLocked(app, true);
        removeProcessLocked(app, false, true, "timeout publishing content providers");
    }
    private final void processStartTimedOutLocked(ProcessRecord app) {
        final int pid = app.pid;
        boolean gone = false;
@@ -5970,7 +5985,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
            }
            // Take care of any launching providers waiting for this process.
            checkAppInLaunchingProvidersLocked(app, true);
            cleanupAppInLaunchingProvidersLocked(app, true);
            // Take care of any services that are waiting for the process.
            mServices.processStartTimedOutLocked(app);
            app.kill("start timeout", true);
@@ -6066,6 +6081,12 @@ public final class ActivityManagerService extends ActivityManagerNative
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
        }
        if (!normalMode) {
            Slog.i(TAG, "Launching preboot mode app: " + app);
        }
@@ -9912,14 +9933,19 @@ public final class ActivityManagerService extends ActivityManagerNative
                        mProviderMap.putProviderByName(names[j], dst);
                    }
                    int NL = mLaunchingProviders.size();
                    int launchingCount = mLaunchingProviders.size();
                    int j;
                    for (j=0; j<NL; j++) {
                    boolean wasInLaunchingProviders = false;
                    for (j = 0; j < launchingCount; j++) {
                        if (mLaunchingProviders.get(j) == dst) {
                            mLaunchingProviders.remove(j);
                            wasInLaunchingProviders = true;
                            j--;
                            NL--;
                            launchingCount--;
                        }
                    }
                    if (wasInLaunchingProviders) {
                        mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                    }
                    synchronized (dst) {
                        dst.provider = src.provider;
@@ -15531,7 +15557,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        app.pubProviders.clear();
        // Take care of any launching providers waiting for this process.
        if (checkAppInLaunchingProvidersLocked(app, false)) {
        if (cleanupAppInLaunchingProvidersLocked(app, false)) {
            restart = true;
        }
@@ -15653,7 +15679,17 @@ public final class ActivityManagerService extends ActivityManagerNative
        return false;
    }
    boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
    boolean checkAppInLaunchingProvidersLocked(ProcessRecord app) {
        for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
            ContentProviderRecord cpr = mLaunchingProviders.get(i);
            if (cpr.launchingApp == app) {
                return true;
            }
        }
        return false;
    }
    boolean cleanupAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
        // Look through the content providers we are waiting to have launched,
        // and if any run in this process then either schedule a restart of
        // the process or kill the client waiting for it if this process has