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

Commit b66cc4d5 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Automerger Merge Worker
Browse files

Merge "Propagate exception thrown by ContentProvider.getType" into rvc-dev am:...

Merge "Propagate exception thrown by ContentProvider.getType" into rvc-dev am: f903ef10 am: b75ca085

Change-Id: I70d291a30944ce370302a9c440045b64aed4aecd
parents b4a2275c b75ca085
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.ICancellationSignal;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallback;
@@ -303,7 +304,23 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
        @Override
        @Override
        public void getTypeAsync(Uri uri, RemoteCallback callback) {
        public void getTypeAsync(Uri uri, RemoteCallback callback) {
            final Bundle result = new Bundle();
            final Bundle result = new Bundle();
            try {
                result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
                result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
            } catch (Exception e) {
                Parcel parcel = Parcel.obtain();
                try {
                    try {
                        parcel.writeException(e);
                    } catch (Exception ex) {
                        // getType threw an unparcelable exception. Wrap the message into
                        // a parcelable exception type
                        parcel.writeException(new IllegalStateException(e.getMessage()));
                    }
                    result.putByteArray(ContentResolver.REMOTE_CALLBACK_ERROR, parcel.marshall());
                } finally {
                    parcel.recycle();
                }
            }
            callback.sendResult(result);
            callback.sendResult(result);
        }
        }


+40 −1
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.ICancellationSignal;
import android.os.OperationCanceledException;
import android.os.OperationCanceledException;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -735,6 +736,9 @@ public abstract class ContentResolver implements ContentInterface {
    /** @hide */
    /** @hide */
    public static final String REMOTE_CALLBACK_RESULT = "result";
    public static final String REMOTE_CALLBACK_RESULT = "result";


    /** @hide */
    public static final String REMOTE_CALLBACK_ERROR = "error";

    /**
    /**
     * How long we wait for an attached process to publish its content providers
     * How long we wait for an attached process to publish its content providers
     * before we decide it must be hung.
     * before we decide it must be hung.
@@ -874,6 +878,9 @@ public abstract class ContentResolver implements ContentInterface {
                final StringResultListener resultListener = new StringResultListener();
                final StringResultListener resultListener = new StringResultListener();
                provider.getTypeAsync(url, new RemoteCallback(resultListener));
                provider.getTypeAsync(url, new RemoteCallback(resultListener));
                resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
                resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
                if (resultListener.exception != null) {
                    throw resultListener.exception;
                }
                return resultListener.result;
                return resultListener.result;
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                // Arbitrary and not worth documenting, as Activity
                // Arbitrary and not worth documenting, as Activity
@@ -898,6 +905,9 @@ public abstract class ContentResolver implements ContentInterface {
                    resolveUserId(url),
                    resolveUserId(url),
                    new RemoteCallback(resultListener));
                    new RemoteCallback(resultListener));
            resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
            resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
            if (resultListener.exception != null) {
                throw resultListener.exception;
            }
            return resultListener.result;
            return resultListener.result;
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // We just failed to send a oneway request to the System Server. Nothing to do.
            // We just failed to send a oneway request to the System Server. Nothing to do.
@@ -915,15 +925,41 @@ public abstract class ContentResolver implements ContentInterface {
        @GuardedBy("this")
        @GuardedBy("this")
        public T result;
        public T result;


        @GuardedBy("this")
        public RuntimeException exception;

        @Override
        @Override
        public void onResult(Bundle result) {
        public void onResult(Bundle result) {
            synchronized (this) {
            synchronized (this) {
                this.exception = getExceptionFromBundle(result);
                if (this.exception == null) {
                    this.result = getResultFromBundle(result);
                    this.result = getResultFromBundle(result);
                }
                done = true;
                done = true;
                notifyAll();
                notifyAll();
            }
            }
        }
        }


        private RuntimeException getExceptionFromBundle(Bundle result) {
            byte[] bytes = result.getByteArray(REMOTE_CALLBACK_ERROR);
            if (bytes == null) {
                return null;
            }

            Parcel parcel = Parcel.obtain();
            try {
                parcel.unmarshall(bytes, 0, bytes.length);
                parcel.setDataPosition(0);
                parcel.readException();
            } catch (RuntimeException ex) {
                return ex;
            } finally {
                parcel.recycle();
            }

            return null;
        }

        protected abstract T getResultFromBundle(Bundle result);
        protected abstract T getResultFromBundle(Bundle result);


        public void waitForResult(long timeout) {
        public void waitForResult(long timeout) {
@@ -1250,6 +1286,9 @@ public abstract class ContentResolver implements ContentInterface {
            provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
            provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
                    new RemoteCallback(resultListener));
                    new RemoteCallback(resultListener));
            resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
            resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
            if (resultListener.exception != null) {
                throw resultListener.exception;
            }
            return resultListener.result;
            return resultListener.result;
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Arbitrary and not worth documenting, as Activity
+11 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
@@ -235,6 +236,16 @@ public class ContentResolverTest {
        assertThat(end).isLessThan(start + 5000);
        assertThat(end).isLessThan(start + 5000);
    }
    }


    @Test
    public void testGetType_providerException() {
        try {
            mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote/error"));
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // Expected
        }
    }

    @Test
    @Test
    public void testCanonicalize() {
    public void testCanonicalize() {
        Uri canonical = mResolver.canonicalize(
        Uri canonical = mResolver.canonicalize(
+3 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,9 @@ public class FakeProviderRemote extends ContentProvider {


    @Override
    @Override
    public String getType(Uri uri) {
    public String getType(Uri uri) {
        if (uri.getPath() != null && uri.getPath().contains("error")) {
            throw new IllegalArgumentException("Expected exception");
        }
        return "fake/remote";
        return "fake/remote";
    }
    }