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

Commit e7ece5a6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix leak where system held onto slice providers"

parents 0000c054 e1c0c2cb
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -154,8 +154,8 @@ public class PinnedSliceState {
    }

    ContentProviderClient getClient() {
        ContentProviderClient client =
                mService.getContext().getContentResolver().acquireContentProviderClient(mUri);
        ContentProviderClient client = mService.getContext().getContentResolver()
                .acquireUnstableContentProviderClient(mUri);
        if (client == null) return null;
        client.setDetectNotResponding(SLICE_TIMEOUT);
        return client;
+5 −4
Original line number Diff line number Diff line
package com.android.server.slice;

import static android.testing.TestableContentResolver.UNSTABLE;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -71,11 +71,12 @@ public class PinnedSliceStateTest extends UiServiceTestCase {
        mSliceService = mock(SliceManagerService.class);
        when(mSliceService.getContext()).thenReturn(mContext);
        when(mSliceService.getLock()).thenReturn(new Object());
        when(mSliceService.getHandler()).thenReturn(new Handler(TestableLooper.get(this).getLooper()));
        when(mSliceService.getHandler()).thenReturn(
                new Handler(TestableLooper.get(this).getLooper()));
        mContentProvider = mock(ContentProvider.class);
        mIContentProvider = mock(IContentProvider.class);
        when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
        mContext.getContentResolver().addProvider(AUTH, mContentProvider);
        mContext.getContentResolver().addProvider(AUTH, mContentProvider, UNSTABLE);
        mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
    }

+26 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.IContentProvider;
import android.database.ContentObserver;
import android.net.Uri;
import android.util.ArrayMap;
import android.util.ArraySet;

import com.google.android.collect.Maps;
@@ -35,7 +36,11 @@ import java.util.Map;
 */
public class TestableContentResolver extends ContentResolver {

    private final Map<String, ContentProvider> mProviders = Maps.newHashMap();
    public static final int STABLE = 1;
    public static final int UNSTABLE = 2;

    private final Map<String, ContentProvider> mProviders = new ArrayMap<>();
    private final Map<String, ContentProvider> mUnstableProviders = new ArrayMap<>();
    private final ContentResolver mParent;
    private final ArraySet<ContentProvider> mInUse = new ArraySet<>();
    private boolean mFallbackToExisting;
@@ -62,8 +67,24 @@ public class TestableContentResolver extends ContentResolver {
     * subclasses, or null.
     */
    public void addProvider(String name, ContentProvider provider) {
        addProvider(name, provider, STABLE | UNSTABLE);
    }

    /**
     * Adds access to a provider based on its authority
     *
     * @param name The authority name associated with the provider.
     * @param provider An instance of {@link android.content.ContentProvider} or one of its
     * subclasses, or null.
     */
    public void addProvider(String name, ContentProvider provider, int flags) {
        if ((flags & STABLE) != 0) {
            mProviders.put(name, provider);
        }
        if ((flags & UNSTABLE) != 0) {
            mUnstableProviders.put(name, provider);
        }
    }

    @Override
    protected IContentProvider acquireProvider(Context context, String name) {
@@ -98,7 +119,7 @@ public class TestableContentResolver extends ContentResolver {

    @Override
    protected IContentProvider acquireUnstableProvider(Context c, String name) {
        final ContentProvider provider = mProviders.get(name);
        final ContentProvider provider = mUnstableProviders.get(name);
        if (provider != null) {
            return provider.getIContentProvider();
        } else {
@@ -128,7 +149,8 @@ public class TestableContentResolver extends ContentResolver {
    @Override
    public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
        if (!mFallbackToExisting) return;
        if (!mProviders.containsKey(uri.getAuthority())) {
        if (!mProviders.containsKey(uri.getAuthority())
                && !mUnstableProviders.containsKey(uri.getAuthority())) {
            super.notifyChange(uri, observer, syncToNetwork);
        }
    }
+61 −0
Original line number Diff line number Diff line
package android.testing;

import android.content.ContentProvider;
import android.content.IContentProvider;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class TestableContentResolverTest {

    @Rule
    public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext());
    private TestableContentResolver mContentResolver;

    @Before
    public void setup() {
        mContentResolver = new TestableContentResolver(mContext);
        mContentResolver.setFallbackToExisting(false);
    }

    @Test
    public void testDefaultContentProvider() {
        ContentProvider provider = Mockito.mock(ContentProvider.class);
        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
        mContentResolver.addProvider("test", provider);

        Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
        Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
    }

    @Test
    public void testStableContentProvider() {
        ContentProvider provider = Mockito.mock(ContentProvider.class);
        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
        mContentResolver.addProvider("test", provider, TestableContentResolver.STABLE);

        Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
        Assert.assertNull(mContentResolver.acquireUnstableProvider(mContext, "test"));
    }

    @Test
    public void testUnstableContentProvider() {
        ContentProvider provider = Mockito.mock(ContentProvider.class);
        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
        mContentResolver.addProvider("test", provider, TestableContentResolver.UNSTABLE);

        Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
        Assert.assertNull(mContentResolver.acquireProvider(mContext, "test"));
    }
}