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

Commit cf212926 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Prevents an NPE when content provider is slow to start"

parents 4889c7a8 140fc2e9
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -700,6 +700,27 @@ public abstract class ContentResolver implements ContentInterface {
    /** @hide */
    public static final String REMOTE_CALLBACK_RESULT = "result";

    /**
     * How long we wait for an attached process to publish its content providers
     * before we decide it must be hung.
     * @hide
     */
    public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000;

    /**
     * How long we wait for an provider to be published. Should be longer than
     * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}.
     * @hide
     */
    public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS =
            CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000;

    // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how
    // long ActivityManagerService is giving a content provider to get published if a new process
    // needs to be started for that.
    private static final int GET_TYPE_TIMEOUT_MILLIS =
            CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000;

    public ContentResolver(@Nullable Context context) {
        this(context, null);
    }
@@ -849,8 +870,6 @@ public abstract class ContentResolver implements ContentInterface {
        }
    }

    private static final int GET_TYPE_TIMEOUT_MILLIS = 3000;

    private static class GetTypeResultListener implements RemoteCallback.OnResultListener {
        @GuardedBy("this")
        public boolean done;
+6 −0
Original line number Diff line number Diff line
@@ -1330,6 +1330,12 @@
            android:process=":FakeProvider">
        </provider>

        <provider
            android:name="android.content.SlowProvider"
            android:authorities="android.content.SlowProvider"
            android:process=":SlowProvider">
        </provider>

        <!-- Application components used for os tests -->

        <service android:name="android.os.MessengerService"
+9 −0
Original line number Diff line number Diff line
@@ -209,4 +209,13 @@ public class ContentResolverTest {
        String type = mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote"));
        assertEquals("fake/remote", type);
    }


    @Test
    public void testGetType_slowProvider() {
        // This provider is running in a different process and is intentionally slow to start.
        // We are trying to confirm that it does not cause an ANR
        String type = mResolver.getType(Uri.parse("content://android.content.SlowProvider"));
        assertEquals("slow", type);
    }
}
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content;

import android.database.Cursor;
import android.net.Uri;

/**
 * A dummy content provider for tests.  This provider runs in a different process from the test and
 * is intentionally slow.
 */
public class SlowProvider extends ContentProvider {

    private static final int ON_CREATE_LATENCY_MILLIS = 3000;

    @Override
    public boolean onCreate() {
        try {
            Thread.sleep(ON_CREATE_LATENCY_MILLIS);
        } catch (InterruptedException e) {
            // Ignore
        }
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return "slow";
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}
+11 −16
Original line number Diff line number Diff line
@@ -466,18 +466,9 @@ public class ActivityManagerService extends IActivityManager.Stub
    // 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 to kill an application zygote, after the last process using
    // it has gone away.
    static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000;
    /**
     * How long we wait for an provider to be published. Should be longer than
     * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT}.
     */
    static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 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
@@ -4934,7 +4925,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
            mHandler.sendMessageDelayed(msg,
                    ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
        }
        checkTime(startTime, "attachApplicationLocked: before bindApplication");
@@ -7201,7 +7193,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        // Wait for the provider to be published...
        final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT;
        final long timeout =
                SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS;
        boolean timedOut = false;
        synchronized (cpr) {
            while (cpr.provider == null) {
@@ -7238,14 +7231,16 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        if (timedOut) {
            // Note we do it afer releasing the lock.
            // Note we do it after releasing the lock.
            String callerName = "unknown";
            if (caller != null) {
                synchronized (this) {
                    final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller);
                    if (record != null) {
                        callerName = record.processName;
                    }
                }
            }
            Slog.wtf(TAG, "Timeout waiting for provider "
                    + cpi.applicationInfo.packageName + "/"