Merge "Integrate with RemoteComposePlayer" into main
diff --git a/core/java/android/widget/RemoteCanvas.java b/core/java/android/widget/RemoteCanvas.java
deleted file mode 100644
index 9a0898c..0000000
--- a/core/java/android/widget/RemoteCanvas.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-package android.widget;
-
-import static android.appwidget.flags.Flags.FLAG_DRAW_DATA_PARCEL;
-
-import android.annotation.AttrRes;
-import android.annotation.FlaggedApi;
-import android.annotation.StyleRes;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.util.function.IntConsumer;
-
-/**
- * {@link RemoteCanvas} is designed to support arbitrary protocols between two processes using
- * {@link RemoteViews.DrawInstructions}. Upon instantiation in the host process,
- * {@link RemoteCanvas#setDrawInstructions(RemoteViews.DrawInstructions)} is called so that the
- * host process can render the {@link RemoteViews.DrawInstructions} from the provider process
- * accordingly.
- *
- * @hide
- */
-@FlaggedApi(FLAG_DRAW_DATA_PARCEL)
-public class RemoteCanvas extends View {
-
- private static final String TAG = "RemoteCanvas";
-
- @Nullable
- private SparseArray<Runnable> mCallbacks;
-
- private final IntConsumer mOnClickHandler = (viewId) -> {
- if (mCallbacks == null) {
- Log.w(TAG, "Cannot find callback for " + viewId
- + ", in fact there were no callbacks from this RemoteViews at all.");
- return;
- }
- final Runnable cb = getCallbacks().get(viewId);
- if (cb != null) {
- cb.run();
- } else {
- Log.w(TAG, "Cannot find callback for " + viewId);
- }
- };
-
- RemoteCanvas(@NonNull Context context) {
- super(context);
- }
-
- RemoteCanvas(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- }
-
- RemoteCanvas(@NonNull Context context, @Nullable AttributeSet attrs,
- @AttrRes int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- RemoteCanvas(@NonNull Context context, @Nullable AttributeSet attrs,
- @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- /**
- * Setter method for the {@link RemoteViews.DrawInstructions} from the provider process for
- * the host process to render accordingly.
- *
- * @param instructions {@link RemoteViews.DrawInstructions} from the provider process.
- */
- void setDrawInstructions(@NonNull final RemoteViews.DrawInstructions instructions) {
- setTag(instructions);
- // TODO: handle draw instructions
- // TODO: attach mOnClickHandler
- }
-
- /**
- * Adds a callback function to a clickable area in the RemoteCanvas.
- *
- * @param viewId the viewId of the clickable area
- * @param cb the callback function to be triggered when clicked
- */
- void addOnClickHandler(final int viewId, @NonNull final Runnable cb) {
- getCallbacks().set(viewId, cb);
- }
-
- /**
- * Returns all callbacks added to the RemoteCanvas through
- * {@link #addOnClickHandler(int, Runnable)}.
- */
- @VisibleForTesting
- public SparseArray<Runnable> getCallbacks() {
- if (mCallbacks == null) {
- mCallbacks = new SparseArray<>();
- }
- return mCallbacks;
- }
-}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 738bb1f..5bf1b5b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -112,7 +112,10 @@
import com.android.internal.R;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.IRemoteViewsFactory;
+import com.android.internal.widget.remotecompose.player.RemoteComposeDocument;
+import com.android.internal.widget.remotecompose.player.RemoteComposePlayer;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -1479,9 +1482,7 @@
@Override
public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
- if (hasDrawInstructions() && root instanceof RemoteCanvas target) {
- target.addOnClickHandler(mViewId, () ->
- mResponse.handleViewInteraction(root, params.handler));
+ if (hasDrawInstructions() && root instanceof RemoteComposePlayer) {
return;
}
final View target = root.findViewById(mViewId);
@@ -3900,8 +3901,17 @@
public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
throws ActionException {
if (drawDataParcel() && mInstructions != null
- && root instanceof RemoteCanvas remoteCanvas) {
- remoteCanvas.setDrawInstructions(mInstructions);
+ && root instanceof RemoteComposePlayer player) {
+ player.setTag(mInstructions);
+ final List<byte[]> bytes = mInstructions.mInstructions;
+ if (bytes.isEmpty()) {
+ return;
+ }
+ try (ByteArrayInputStream is = new ByteArrayInputStream(bytes.get(0))) {
+ player.setDocument(new RemoteComposeDocument(is));
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Failed to render draw instructions", e);
+ }
}
}
@@ -6041,6 +6051,16 @@
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
View result = inflateView(context, rvToApply, directParent,
params.applyThemeResId, params.colorResources);
+ if (result instanceof RemoteComposePlayer player) {
+ player.addClickListener((viewId, metadata) -> {
+ mActions.forEach(action -> {
+ if (viewId == action.mViewId
+ && action instanceof SetOnClickResponse setOnClickResponse) {
+ setOnClickResponse.mResponse.handleViewInteraction(player, params.handler);
+ }
+ });
+ });
+ }
rvToApply.performApply(result, rootParent, params);
return result;
}
@@ -6064,7 +6084,7 @@
}
// If the RemoteViews contains draw instructions, just use it instead.
if (rv.hasDrawInstructions()) {
- return new RemoteCanvas(inflationContext);
+ return new RemoteComposePlayer(inflationContext);
}
LayoutInflater inflater = LayoutInflater.from(context);
@@ -7546,7 +7566,7 @@
public static final class DrawInstructions {
@NonNull
- private final List<byte[]> mInstructions;
+ final List<byte[]> mInstructions;
private DrawInstructions() {
throw new UnsupportedOperationException(
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 5862711..3d5494d 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -422,19 +422,9 @@
if (!drawDataParcel()) {
return;
}
- final RemoteViews.DrawInstructions drawInstructions = getDrawInstructions();
- final RemoteViews rv = new RemoteViews(drawInstructions);
- final View view = rv.apply(mContext, mContainer);
- assertTrue(view instanceof RemoteCanvas);
- assertEquals(drawInstructions, view.getTag());
- }
-
- @Test
- public void remoteCanvasWiresClickHandlers() {
- if (!drawDataParcel()) {
- return;
- }
- final RemoteViews.DrawInstructions drawInstructions = getDrawInstructions();
+ final byte[] bytes = new byte[] {'h', 'e', 'l', 'l', 'o'};
+ final RemoteViews.DrawInstructions drawInstructions =
+ new RemoteViews.DrawInstructions.Builder(Collections.singletonList(bytes)).build();
final RemoteViews rv = new RemoteViews(drawInstructions);
final PendingIntent pi = PendingIntent.getActivity(mContext, 0,
new Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE);
@@ -443,15 +433,7 @@
rv.setPendingIntentTemplate(viewId, pi);
rv.setOnClickFillInIntent(viewId, i);
final View view = rv.apply(mContext, mContainer);
- assertTrue(view instanceof RemoteCanvas);
- RemoteCanvas target = (RemoteCanvas) view;
- assertEquals(1, target.getCallbacks().size());
- assertNotNull(target.getCallbacks().get(viewId));
- }
-
- private RemoteViews.DrawInstructions getDrawInstructions() {
- final byte[] bytes = new byte[] {'h', 'e', 'l', 'l', 'o'};
- return new RemoteViews.DrawInstructions.Builder(Collections.singletonList(bytes)).build();
+ assertEquals(drawInstructions, view.getTag());
}
private RemoteViews createViewChained(int depth, String... texts) {