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

Commit 35641ae2 authored by Willie Koomson's avatar Willie Koomson
Browse files

Propagate apply flags to nested RemoteViews

This change propagates FLAG_WIDGET_IS_COLLECTION_CHILD and
FLAG_USE_LIGHT_BACKGROUND_LAYOUT to nested RemoteViews (either added by
addView, or set as portrait/landscape/sized RemoteViews) if that flag is
also present on the parent RemoteView.

For FLAG_WIDGET_IS_COLLECTION_CHILD, this prevents a PendingIntent from
being set on a RemoteView that is a child of a collection item RemoteView.

For FLAG_USE_LIGHT_BACKGROUND_LAYOUT, this ensures that nested
RemoteViews use their light background layout if this is set on the
parent.

Bug: 214288099
Test: RemoteViewsTest
Change-Id: I8da92d0d338631a99ee718a136bf9674827437bb
parent 3a83f0e9
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -300,6 +300,13 @@ public class RemoteViews implements Parcelable, Filter {
     */
    public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4;

    /**
     * This mask determines which flags are propagated to nested RemoteViews (either added by
     * addView, or set as portrait/landscape/sized RemoteViews).
     */
    static final int FLAG_MASK_TO_PROPAGATE =
            FLAG_WIDGET_IS_COLLECTION_CHILD | FLAG_USE_LIGHT_BACKGROUND_LAYOUT;

    /**
     * A ReadWriteHelper which has the same behavior as ReadWriteHelper.DEFAULT, but which is
     * intentionally a different instance in order to trick Bundle reader so that it doesn't allow
@@ -467,6 +474,18 @@ public class RemoteViews implements Parcelable, Filter {
     */
    public void addFlags(@ApplyFlags int flags) {
        mApplyFlags = mApplyFlags | flags;

        int flagsToPropagate = flags & FLAG_MASK_TO_PROPAGATE;
        if (flagsToPropagate != 0) {
            if (hasSizedRemoteViews()) {
                for (RemoteViews remoteView : mSizedRemoteViews) {
                    remoteView.addFlags(flagsToPropagate);
                }
            } else if (hasLandscapeAndPortraitLayouts()) {
                mLandscape.addFlags(flagsToPropagate);
                mPortrait.addFlags(flagsToPropagate);
            }
        }
    }

    /**
@@ -2407,6 +2426,10 @@ public class RemoteViews implements Parcelable, Filter {
            // will return -1.
            final int nextChild = getNextRecyclableChild(target);
            RemoteViews rvToApply = mNestedViews.getRemoteViewsToApply(context);

            int flagsToPropagate = mApplyFlags & FLAG_MASK_TO_PROPAGATE;
            if (flagsToPropagate != 0) rvToApply.addFlags(flagsToPropagate);

            if (nextChild >= 0 && mStableId != NO_ID) {
                // At that point, the views starting at index nextChild are the ones recyclable but
                // not yet recycled. All views added on that round of application are placed before.
+21 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2016 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
  -->

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/light_background_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
+98 −0
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@

package android.widget;

import static com.android.internal.R.id.pending_intent_tag;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

@@ -34,6 +37,7 @@ import android.os.AsyncTask;
import android.os.Binder;
import android.os.Looper;
import android.os.Parcel;
import android.util.SizeF;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.ViewGroup;
@@ -52,6 +56,7 @@ import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
@@ -313,6 +318,99 @@ public class RemoteViewsTest {
        assertNotNull(listView.getAdapter());
    }

    @Test
    public void nestedViews_collectionChildFlag() throws Exception {
        RemoteViews nested = new RemoteViews(mPackage, R.layout.remote_views_text);
        nested.setOnClickPendingIntent(
                R.id.text,
                PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
        );

        RemoteViews listItem = new RemoteViews(mPackage, R.layout.remote_view_host);
        listItem.addView(R.id.container, nested);
        listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);

        View view = listItem.apply(mContext, mContainer);
        TextView text = (TextView) view.findViewById(R.id.text);
        assertNull(text.getTag(pending_intent_tag));
    }

    @Test
    public void landscapePortraitViews_collectionChildFlag() throws Exception {
        RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
        inner.setOnClickPendingIntent(
                R.id.text,
                PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
        );

        RemoteViews listItem = new RemoteViews(inner, inner);
        listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);

        View view = listItem.apply(mContext, mContainer);
        TextView text = (TextView) view.findViewById(R.id.text);
        assertNull(text.getTag(pending_intent_tag));
    }

    @Test
    public void sizedViews_collectionChildFlag() throws Exception {
        RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
        inner.setOnClickPendingIntent(
                R.id.text,
                PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
        );

        RemoteViews listItem = new RemoteViews(
                Map.of(new SizeF(0, 0), inner, new SizeF(100, 100), inner));
        listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);

        View view = listItem.apply(mContext, mContainer);
        TextView text = (TextView) view.findViewById(R.id.text);
        assertNull(text.getTag(pending_intent_tag));
    }

    @Test
    public void nestedViews_lightBackgroundLayoutFlag() {
        RemoteViews nested = new RemoteViews(mPackage, R.layout.remote_views_text);
        nested.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);

        RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_view_host);
        parent.addView(R.id.container, nested);
        parent.setLightBackgroundLayoutId(R.layout.remote_view_host);
        parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);

        View view = parent.apply(mContext, mContainer);
        assertNull(view.findViewById(R.id.text));
        assertNotNull(view.findViewById(R.id.light_background_text));
    }


    @Test
    public void landscapePortraitViews_lightBackgroundLayoutFlag() {
        RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
        inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);

        RemoteViews parent = new RemoteViews(inner, inner);
        parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);

        View view = parent.apply(mContext, mContainer);
        assertNull(view.findViewById(R.id.text));
        assertNotNull(view.findViewById(R.id.light_background_text));
    }

    @Test
    public void sizedViews_lightBackgroundLayoutFlag() {
        RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
        inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);

        RemoteViews parent = new RemoteViews(
                Map.of(new SizeF(0, 0), inner, new SizeF(100, 100), inner));
        parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);

        View view = parent.apply(mContext, mContainer);
        assertNull(view.findViewById(R.id.text));
        assertNotNull(view.findViewById(R.id.light_background_text));
    }

    private RemoteViews createViewChained(int depth, String... texts) {
        RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host);