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

Commit 1536db86 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Add SurfaceControlInputReceiver" into main

parents acd03c25 f29c06a9
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -51850,6 +51850,10 @@ package android.view {
    ctor public SurfaceControl.TrustedPresentationThresholds(@FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @IntRange(from=1) int);
  }
  @FlaggedApi("com.android.window.flags.surface_control_input_receiver") public interface SurfaceControlInputReceiver {
    method public boolean onInputEvent(@NonNull android.view.InputEvent);
  }
  public class SurfaceControlViewHost {
    ctor public SurfaceControlViewHost(@NonNull android.content.Context, @NonNull android.view.Display, @Nullable android.os.IBinder);
    method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage getSurfacePackage();
@@ -53973,10 +53977,13 @@ package android.view {
    method @Deprecated public android.view.Display getDefaultDisplay();
    method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
    method public default boolean isCrossWindowBlurEnabled();
    method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") @NonNull public default android.os.IBinder registerBatchedSurfaceControlInputReceiver(int, @NonNull android.os.IBinder, @NonNull android.view.SurfaceControl, @NonNull android.view.Choreographer, @NonNull android.view.SurfaceControlInputReceiver);
    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public default void registerTrustedPresentationListener(@NonNull android.os.IBinder, @NonNull android.window.TrustedPresentationThresholds, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") @NonNull public default android.os.IBinder registerUnbatchedSurfaceControlInputReceiver(int, @NonNull android.os.IBinder, @NonNull android.view.SurfaceControl, @NonNull android.os.Looper, @NonNull android.view.SurfaceControlInputReceiver);
    method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
    method public default void removeProposedRotationListener(@NonNull java.util.function.IntConsumer);
    method public void removeViewImmediate(android.view.View);
    method @FlaggedApi("com.android.window.flags.surface_control_input_receiver") public default void unregisterSurfaceControlInputReceiver(@NonNull android.os.IBinder);
    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public default void unregisterTrustedPresentationListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
    field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
    field public static final String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED = "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
+7 −0
Original line number Diff line number Diff line
@@ -377,6 +377,13 @@ public final class Choreographer {
        return mLooper == looper;
    }

    /**
     * @hide
     */
    public Looper getLooper() {
        return mLooper;
    }

    /**
     * The amount of time, in milliseconds, between each frame of the animation.
     * <p>
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.view;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;

import com.android.window.flags.Flags;

/**
 * Provides a mechanism for a SurfaceControl to receive input events.
 */
@FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
public interface SurfaceControlInputReceiver {
    /**
     * When input events are batched, this is called at most once per frame. When non batched, this
     * is called immediately for the input event.
     *
     * @param event The input event that was received. This input event object will become invalid
     *              and recycled after this method is invoked. If there is need to persist this
     *              object beyond the scope of this method, the overriding code should make a copy
     *              of this object. For example, using
     *              {@link MotionEvent#obtain(MotionEvent other)} or
     *              {@link KeyEvent#KeyEvent(KeyEvent)} }
     * @return true if the event was handled, false otherwise.
     */
    boolean onInputEvent(@NonNull InputEvent event);

}
+91 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ import android.graphics.Region;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
@@ -6015,4 +6016,94 @@ public interface WindowManager extends ViewManager {
    default void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
        throw new UnsupportedOperationException();
    }

    /**
     * Registers a {@link SurfaceControlInputReceiver} for a {@link SurfaceControl} that will
     * receive batched input event. For those events that are batched, the invocation will happen
     * once per {@link Choreographer} frame, and other input events will be delivered immediately.
     * This is different from
     * {@link #registerUnbatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Looper,
     * SurfaceControlInputReceiver)} in that the input events are received batched. The caller must
     * invoke {@link #unregisterSurfaceControlInputReceiver(IBinder)} to clean up the resources when
     * no longer needing to use the {@link SurfaceControlInputReceiver}
     *
     * @param displayId      The display that the SurfaceControl will be placed on. Input will
     *                       only work
     *                       if SurfaceControl is on that display and that display was touched.
     * @param surfaceControl The SurfaceControl to register the InputChannel for
     * @param hostToken      The host token to link the InputChannel for. This is primarily for ANRs
     *                       to ensure the host receives the ANR if any issues with touch on the
     *                       InputChannel
     * @param choreographer  The Choreographer used for batching. This should match the rendering
     *                       Choreographer.
     * @param receiver       The SurfaceControlInputReceiver that will receive the input events
     * @return an {@link IBinder} token that is used to unregister the input receiver via
     * {@link #unregisterSurfaceControlInputReceiver(IBinder)}.
     * @see #registerUnbatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Looper,
     * SurfaceControlInputReceiver)
     */
    @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
    @NonNull
    default IBinder registerBatchedSurfaceControlInputReceiver(int displayId,
            @NonNull IBinder hostToken, @NonNull SurfaceControl surfaceControl,
            @NonNull Choreographer choreographer, @NonNull SurfaceControlInputReceiver receiver) {
        throw new UnsupportedOperationException(
                "registerBatchedSurfaceControlInputReceiver is not implemented");
    }

    /**
     * Registers a {@link SurfaceControlInputReceiver} for a {@link SurfaceControl} that will
     * receive every input event. This is different than calling @link
     * #registerBatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Choreographer,
     * SurfaceControlInputReceiver)} in that the input events are received unbatched. The caller
     * must invoke {@link #unregisterSurfaceControlInputReceiver(IBinder)} to clean up the resources
     * when no longer needing to use the {@link SurfaceControlInputReceiver}
     *
     * @param displayId      The display that the SurfaceControl will be placed on. Input will only
     *                       work if SurfaceControl is on that display and that display was
     *                       touched.
     * @param hostToken      The host token to link the InputChannel for. This is primarily for ANRs
     *                       to ensure the host receives the ANR if any issues with touch on the
     *                       InputChannel
     * @param surfaceControl The SurfaceControl to register the InputChannel for
     * @param looper         The looper to use when invoking callbacks.
     * @param receiver       The SurfaceControlInputReceiver that will receive the input events
     * @return an {@link IBinder} token that is used to unregister the input receiver via
     * {@link #unregisterSurfaceControlInputReceiver(IBinder)}.
     * @see #registerBatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Choreographer,
     * SurfaceControlInputReceiver)
     **/
    @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
    @NonNull
    default IBinder registerUnbatchedSurfaceControlInputReceiver(int displayId,
            @NonNull IBinder hostToken, @NonNull SurfaceControl surfaceControl,
            @NonNull Looper looper, @NonNull SurfaceControlInputReceiver receiver) {
        throw new UnsupportedOperationException(
                "registerUnbatchedSurfaceControlInputReceiver is not implemented");
    }

    /**
     * Unregisters and cleans up the registered {@link SurfaceControlInputReceiver} for the
     * specified token.
     * <p>
     * Must be called on the same {@link Looper} thread to which was passed to the
     * {@link #registerBatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl,
     * Choreographer,
     * SurfaceControlInputReceiver)} or
     * {@link #registerUnbatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Looper,
     * SurfaceControlInputReceiver)}
     *
     * @param token The token that was returned via
     *              {@link #registerBatchedSurfaceControlInputReceiver(int, IBinder,
     *              SurfaceControl,
     *              Choreographer, SurfaceControlInputReceiver)} or
     *              {@link #registerUnbatchedSurfaceControlInputReceiver(int, IBinder,
     *              SurfaceControl,
     *              Looper, SurfaceControlInputReceiver)}
     */
    @FlaggedApi(Flags.FLAG_SURFACE_CONTROL_INPUT_RECEIVER)
    default void unregisterSurfaceControlInputReceiver(@NonNull IBinder token) {
        throw new UnsupportedOperationException(
                "unregisterSurfaceControlInputReceiver is not implemented");
    }
}
+76 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.view;

import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;

import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -24,8 +26,10 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.HardwareRenderer;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -46,6 +50,7 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
@@ -151,6 +156,9 @@ public final class WindowManagerGlobal {
    private final TrustedPresentationListener mTrustedPresentationListener =
            new TrustedPresentationListener();

    private final ConcurrentHashMap<IBinder, InputEventReceiver> mSurfaceControlInputReceivers =
            new ConcurrentHashMap<>();

    private WindowManagerGlobal() {
    }

@@ -808,6 +816,74 @@ public final class WindowManagerGlobal {
        mTrustedPresentationListener.removeListener(listener);
    }

    IBinder registerBatchedSurfaceControlInputReceiver(int displayId,
            @NonNull IBinder hostToken, @NonNull SurfaceControl surfaceControl,
            @NonNull Choreographer choreographer, @NonNull SurfaceControlInputReceiver receiver) {
        IBinder clientToken = new Binder();
        InputChannel inputChannel = new InputChannel();
        try {
            WindowManagerGlobal.getWindowSession().grantInputChannel(displayId, surfaceControl,
                    clientToken, hostToken, 0, 0, TYPE_APPLICATION, 0, null, null,
                    surfaceControl.getName(), inputChannel);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to create input channel", e);
            e.rethrowAsRuntimeException();
        }

        mSurfaceControlInputReceivers.put(clientToken,
                new BatchedInputEventReceiver(inputChannel, choreographer.getLooper(),
                        choreographer) {
                    @Override
                    public void onInputEvent(InputEvent event) {
                        boolean handled = receiver.onInputEvent(event);
                        finishInputEvent(event, handled);
                    }
                });
        return clientToken;
    }

    IBinder registerUnbatchedSurfaceControlInputReceiver(
            int displayId, @NonNull IBinder hostToken, @NonNull SurfaceControl surfaceControl,
            @NonNull Looper looper, @NonNull SurfaceControlInputReceiver receiver) {
        IBinder clientToken = new Binder();
        InputChannel inputChannel = new InputChannel();
        try {
            WindowManagerGlobal.getWindowSession().grantInputChannel(displayId, surfaceControl,
                    clientToken, hostToken, 0, 0, TYPE_APPLICATION, 0, null, null,
                    surfaceControl.getName(), inputChannel);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to create input channel", e);
            e.rethrowAsRuntimeException();
        }

        mSurfaceControlInputReceivers.put(clientToken,
                new InputEventReceiver(inputChannel, looper) {
                    @Override
                    public void onInputEvent(InputEvent event) {
                        boolean handled = receiver.onInputEvent(event);
                        finishInputEvent(event, handled);
                    }
                });

        return clientToken;
    }

    void unregisterSurfaceControlInputReceiver(IBinder token) {
        InputEventReceiver inputEventReceiver = mSurfaceControlInputReceivers.get(token);
        if (inputEventReceiver == null) {
            Log.w(TAG, "No registered input event receiver with token: " + token);
            return;
        }
        try {
            WindowManagerGlobal.getWindowSession().remove(token);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to remove input channel", e);
            e.rethrowAsRuntimeException();
        }

        inputEventReceiver.dispose();
    }

    private final class TrustedPresentationListener extends
            ITrustedPresentationListener.Stub {
        private static int sId = 0;
Loading