From 7976d884e44d7d4277b8c89851bca41925339465 Mon Sep 17 00:00:00 2001 From: Nan Wu Date: Wed, 19 Feb 2025 18:40:57 +0000 Subject: Fix AppWidget nested extra keys not collected issue An app widget provider app provides a fillInIntent to the RemoteViews This fillInIntent is sent (together with the RemoteViews) over to AppWidgetManagerService without keys collected. The AppWidgetManagerService make a callback to AppWidgetHostView which includes the fillInIntent. The appWidgetHostView eventually calls Activity.startIntenSender with the fillInIntent, which tries to collect the keys. Unfortunately, at this point, the fillInIntent extra bundle is parceled (sent over to AppWidgetManagerService thru IPC). Since we no longer unparcels the extra bundle when trying to collect keys, they are missed. After investigating the code, it seems the fillInIntent always comes into RemoteViews from a few places in the code. It is easier to collect keys at those points, although there is no guarantee that the fillInIntent will be sent over IPC yet. But there is no harm to collect it. The alternative is to collect keys right before the RemoteViews is sent over IPC, but it is much harder to probe the RemoteViews to find all the fillInIntents at that point. Also, it is not necessary to generate the creator token in the AppWidgetManagerService right after the fillInIntent is sent over IPC. We can wait until AppWidgetHostView calls Activity. startIntentSender to generate the creator token because both RemoteViews and AppWidgetHostView are systemUI. Bug: 395568288 Test: manual test. RemoteViewsTest, RemoteViewsAdapterTest, RemoteViewsSerializersTest Flag: EXEMPT bug fix Change-Id: Id9ec09e0f1ed906282bdeb085ca89302f52e05e4 --- core/java/android/widget/RemoteViews.java | 2 ++ .../coretests/src/android/widget/RemoteViewsTest.java | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 0f5476f58f74..d9f1943d211b 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -9212,6 +9212,7 @@ public class RemoteViews implements Parcelable, Filter { public static RemoteResponse fromFillInIntent(@NonNull Intent fillIntent) { RemoteResponse response = new RemoteResponse(); response.mFillIntent = fillIntent; + fillIntent.collectExtraIntentKeys(); return response; } @@ -9220,6 +9221,7 @@ public class RemoteViews implements Parcelable, Filter { RemoteResponse response = new RemoteResponse(); response.mPendingIntent = pendingIntent; response.mFillIntent = intent; + intent.collectExtraIntentKeys(); return response; } diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java index 8b0d3158e9e7..9110898e18c9 100644 --- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java +++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java @@ -22,6 +22,7 @@ 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.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; @@ -1065,6 +1066,22 @@ public class RemoteViewsTest { assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage()); } + @Test + public void remoteResponse_FillInIntentNestedIntentKeysCollected() { + Intent fillInIntent = new Intent(); + fillInIntent.putExtra("extraIntent", new Intent()); + RemoteViews.RemoteResponse.fromFillInIntent(fillInIntent); + assertNotEquals(0, fillInIntent.getExtendedFlags() + & Intent.EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED); + + fillInIntent = new Intent(); + fillInIntent.putExtra("extraIntent", new Intent()); + RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test); + rv.setOnClickFillInIntent(R.id.view, fillInIntent); + assertNotEquals(0, fillInIntent.getExtendedFlags() + & Intent.EXTENDED_FLAG_NESTED_INTENT_KEYS_COLLECTED); + } + private static LayoutInflater.Factory2 createLayoutInflaterFactory(String viewTypeToReplace, View replacementView) { return new LayoutInflater.Factory2() { -- cgit v1.2.3-59-g8ed1b