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

Commit 6f87bed5 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Retrying the remoteview application on the ui thread" into...

Merge "Merge "Retrying the remoteview application on the ui thread" into oc-dev am: 07b93779 am: 12a9c8ea" into oc-dr1-dev-plus-aosp
parents 5bed7b69 18b714c7
Loading
Loading
Loading
Loading
+32 −7
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 */
public class NotificationInflater {

    public static final String TAG = "NotificationInflater";
    @VisibleForTesting
    static final int FLAG_REINFLATE_ALL = ~0;
    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
@@ -315,7 +316,8 @@ public class NotificationInflater {
        return cancellationSignal;
    }

    private static void applyRemoteView(final InflationProgress result,
    @VisibleForTesting
    static void applyRemoteView(final InflationProgress result,
            final int reInflateFlags, int inflationId,
            final ExpandableNotificationRow row,
            final boolean redactAmbient, boolean isNewView,
@@ -325,6 +327,7 @@ public class NotificationInflater {
            NotificationViewWrapper existingWrapper,
            final HashMap<Integer, CancellationSignal> runningInflations,
            ApplyCallback applyCallback) {
        RemoteViews newContentView = applyCallback.getRemoteView();
        RemoteViews.OnViewAppliedListener listener
                = new RemoteViews.OnViewAppliedListener() {

@@ -343,12 +346,31 @@ public class NotificationInflater {

            @Override
            public void onError(Exception e) {
                // Uh oh the async inflation failed. Due to some bugs (see b/38190555), this could
                // actually also be a system issue, so let's try on the UI thread again to be safe.
                try {
                    View newView = existingView;
                    if (isNewView) {
                        newView = newContentView.apply(
                                result.packageContext,
                                parentLayout,
                                remoteViewClickHandler);
                    } else {
                        newContentView.reapply(
                                result.packageContext,
                                existingView,
                                remoteViewClickHandler);
                    }
                    Log.wtf(TAG, "Async Inflation failed but normal inflation finished normally.",
                            e);
                    onViewApplied(newView);
                } catch (Exception anotherException) {
                    runningInflations.remove(inflationId);
                    handleInflationError(runningInflations, e, entry.notification, callback);
                }
            }
        };
        CancellationSignal cancellationSignal;
        RemoteViews newContentView = applyCallback.getRemoteView();
        if (isNewView) {
            cancellationSignal = newContentView.applyAsync(
                    result.packageContext,
@@ -620,14 +642,16 @@ public class NotificationInflater {
        }
    }

    private static class InflationProgress {
    @VisibleForTesting
    static class InflationProgress {
        private RemoteViews newContentView;
        private RemoteViews newHeadsUpView;
        private RemoteViews newExpandedView;
        private RemoteViews newAmbientView;
        private RemoteViews newPublicView;

        private Context packageContext;
        @VisibleForTesting
        Context packageContext;

        private View inflatedContentView;
        private View inflatedHeadsUpView;
@@ -636,7 +660,8 @@ public class NotificationInflater {
        private View inflatedPublicView;
    }

    private abstract static class ApplyCallback {
    @VisibleForTesting
    abstract static class ApplyCallback {
        public abstract void setResultView(View v);
        public abstract RemoteViews getRemoteView();
    }
+68 −0
Original line number Diff line number Diff line
@@ -24,12 +24,17 @@ import static org.mockito.Mockito.verify;

import android.app.Notification;
import android.content.Context;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RemoteViews;

import com.android.systemui.R;
@@ -45,7 +50,9 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;

@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -142,6 +149,41 @@ public class NotificationInflaterTest extends SysuiTestCase {
        Assert.assertNull(mRow.getEntry().getRunningTask());
    }

    @Test
    public void testInflationIsRetriedIfAsyncFails() throws Exception {
        NotificationInflater.InflationProgress result =
                new NotificationInflater.InflationProgress();
        result.packageContext = mContext;
        CountDownLatch countDownLatch = new CountDownLatch(1);
        NotificationInflater.applyRemoteView(result,
                NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow,
                false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(),
                new NotificationInflater.InflationCallback() {
                    @Override
                    public void handleInflationException(StatusBarNotification notification,
                            Exception e) {
                        countDownLatch.countDown();
                        throw new RuntimeException("No Exception expected");
                    }

                    @Override
                    public void onAsyncInflationFinished(NotificationData.Entry entry) {
                        countDownLatch.countDown();
                    }
                }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(),
                new NotificationInflater.ApplyCallback() {
                    @Override
                    public void setResultView(View v) {
                    }

                    @Override
                    public RemoteViews getRemoteView() {
                        return new AsyncFailRemoteView(mContext.getPackageName(),
                                R.layout.custom_view_dark);
                    }
                });
        countDownLatch.await();
    }

    @Test
    public void testSupersedesExistingTask() throws Exception {
@@ -200,4 +242,30 @@ public class NotificationInflaterTest extends SysuiTestCase {
            mException = exception;
        }
    }

    private class AsyncFailRemoteView extends RemoteViews {
        Handler mHandler = new Handler(Looper.getMainLooper());

        public AsyncFailRemoteView(String packageName, int layoutId) {
            super(packageName, layoutId);
        }

        @Override
        public View apply(Context context, ViewGroup parent) {
            return super.apply(context, parent);
        }

        @Override
        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
                OnViewAppliedListener listener, OnClickHandler handler) {
            mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async")));
            return new CancellationSignal();
        }

        @Override
        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
                OnViewAppliedListener listener) {
            return applyAsync(context, parent, executor, listener, null);
        }
    }
}