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

Commit f4c81d45 authored by Ameer Armaly's avatar Ameer Armaly
Browse files

Add motion event observing feature.

Bug: 297595990

Test: atest AccessibilityEndToEndTest
Change-Id: Ic6fbcdb00ea18f2a5ee2796462eed4ea3cce0e7b
parent fb9e3cfe
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
package android {

  public static final class Manifest.permission {
    field @FlaggedApi("com.android.server.accessibility.motion_event_observing") public static final String ACCESSIBILITY_MOTION_EVENT_OBSERVING = "android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING";
    field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
    field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
    field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
@@ -99,6 +100,8 @@ package android.accessibilityservice {

  public class AccessibilityServiceInfo implements android.os.Parcelable {
    method @NonNull public android.content.ComponentName getComponentName();
    method @FlaggedApi("android.view.accessibility.motion_event_observing") public int getObservedMotionEventSources();
    method @FlaggedApi("android.view.accessibility.motion_event_observing") public void setObservedMotionEventSources(int);
  }

}
+77 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.accessibilityservice.util.AccessibilityUtils.getFilteredHt
import static android.accessibilityservice.util.AccessibilityUtils.loadSafeAnimatedImage;
import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -53,6 +54,7 @@ import android.view.InputDevice;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.Flags;

import com.android.internal.R;
import com.android.internal.compat.IPlatformCompat;
@@ -630,7 +632,8 @@ public class AccessibilityServiceInfo implements Parcelable {
            InputDevice.SOURCE_TOUCH_NAVIGATION,
            InputDevice.SOURCE_ROTARY_ENCODER,
            InputDevice.SOURCE_JOYSTICK,
            InputDevice.SOURCE_SENSOR
            InputDevice.SOURCE_SENSOR,
            InputDevice.SOURCE_TOUCHSCREEN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MotionEventSources {}
@@ -642,6 +645,8 @@ public class AccessibilityServiceInfo implements Parcelable {
    @MotionEventSources
    private int mMotionEventSources = 0;

    private int mObservedMotionEventSources = 0;

    /**
     * Creates a new instance.
     */
@@ -817,6 +822,9 @@ public class AccessibilityServiceInfo implements Parcelable {
        mInteractiveUiTimeout = other.mInteractiveUiTimeout;
        flags = other.flags;
        mMotionEventSources = other.mMotionEventSources;
        if (Flags.motionEventObserving()) {
            setObservedMotionEventSources(other.mObservedMotionEventSources);
        }
        // NOTE: Ensure that only properties that are safe to be modified by the service itself
        // are included here (regardless of hidden setters, etc.).
    }
@@ -1024,16 +1032,75 @@ public class AccessibilityServiceInfo implements Parcelable {
     */
    public void setMotionEventSources(@MotionEventSources int motionEventSources) {
        mMotionEventSources = motionEventSources;
        mObservedMotionEventSources = 0;
    }

    /**
     * Sets the bit mask of {@link android.view.InputDevice} sources that the accessibility service
     * wants to observe generic {@link android.view.MotionEvent}s from if it has already requested
     * to listen to them using {@link #setMotionEventSources(int)}. Events from these sources will
     * be sent to the rest of the input pipeline without being consumed by accessibility services.
     * This service will still be able to see them.
     *
     * <p><strong>Note:</strong> you will need to call this function every time you call {@link
     * #setMotionEventSources(int)}. Calling {@link #setMotionEventSources(int)} clears the list of
     * observed motion event sources for this service.
     *
     * <p><strong>Note:</strong> {@link android.view.InputDevice} sources contain source class bits
     * that complicate bitwise flag removal operations. To remove a specific source you should
     * rebuild the entire value using bitwise OR operations on the individual source constants.
     *
     * <p>Including an {@link android.view.InputDevice} source that does not send {@link
     * android.view.MotionEvent}s is effectively a no-op for that source, since you will not receive
     * any events from that source.
     *
     * <p><strong>Note:</strong> Calling this function with a source that has not been listened to
     * using {@link #setMotionEventSources(int)} will throw an exception.
     *
     * @see AccessibilityService#onMotionEvent
     * @see #MotionEventSources
     * @see #setMotionEventSources(int)
     * @hide
     */
    @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
    @TestApi
    public void setObservedMotionEventSources(int observedMotionEventSources) {
        // Confirm that any sources requested here have already been requested for listening.
        if ((observedMotionEventSources & ~mMotionEventSources) != 0) {
            String message =
                    String.format(
                            "Requested motion event sources for listening = 0x%x but requested"
                                    + " motion event sources for observing = 0x%x.",
                            mMotionEventSources, observedMotionEventSources);
            throw new IllegalArgumentException(message);
        }
        mObservedMotionEventSources = observedMotionEventSources;
    }

    /**
     * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
     * service wants to observe generic {@link android.view.MotionEvent}s from if it has already
     * requested to listen to them using {@link #setMotionEventSources(int)}. Events from these
     * sources will be sent to the rest of the input pipeline without being consumed by
     * accessibility services. This service will still be able to see them.
     *
     * @hide
     */
    @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
    @MotionEventSources
    @TestApi
    public int getObservedMotionEventSources() {
        return mObservedMotionEventSources;
    }

    /**
     * The localized summary of the accessibility service.
     * <p>
     *    <strong>Statically set from
     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
     * </p>
     * @return The localized summary if available, and {@code null} if a summary
     * has not been provided.
     *
     * <p><strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
     * meta-data}.</strong>
     *
     * @return The localized summary if available, and {@code null} if a summary has not been
     *     provided.
     */
    public CharSequence loadSummary(PackageManager packageManager) {
        if (mSummaryResId == 0) {
@@ -1260,6 +1327,7 @@ public class AccessibilityServiceInfo implements Parcelable {
        parcel.writeString(mTileServiceName);
        parcel.writeInt(mIntroResId);
        parcel.writeInt(mMotionEventSources);
        parcel.writeInt(mObservedMotionEventSources);
    }

    private void initFromParcel(Parcel parcel) {
@@ -1285,6 +1353,8 @@ public class AccessibilityServiceInfo implements Parcelable {
        mTileServiceName = parcel.readString();
        mIntroResId = parcel.readInt();
        mMotionEventSources = parcel.readInt();
        // use the setter here because it throws an exception for invalid values.
        setObservedMotionEventSources(parcel.readInt());
    }

    @Override
+7 −0
Original line number Diff line number Diff line
@@ -44,6 +44,13 @@ flag {
    bug: "282821643"
}

flag {
    name: "motion_event_observing"
    namespace: "accessibility"
    description: "Allows accessibility services to intercept but not consume motion events from specified sources."
    bug: "297595990"
}

flag {
    namespace: "accessibility"
    name: "granular_scrolling"
+7 −0
Original line number Diff line number Diff line
@@ -4806,6 +4806,13 @@
    <permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME"
                android:protectionLevel="signature" />

    <!-- @FlaggedApi("com.android.server.accessibility.motion_event_observing")
    @hide
    @TestApi
    Allows an accessibility service to observe motion events without consuming them. -->
    <permission android:name="android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING"
                android:protectionLevel="signature" />

    <!-- @hide Allows an application to collect frame statistics -->
    <permission android:name="android.permission.FRAME_STATS"
         android:protectionLevel="signature" />
+3 −0
Original line number Diff line number Diff line
@@ -873,6 +873,9 @@

    <uses-permission android:name="android.permission.GET_BINDING_UID_IMPORTANCE" />

    <!-- Permissions required for CTS test - CtsAccessibilityServiceTestCases-->
    <uses-permission android:name="android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING" />

    <application
        android:label="@string/app_label"
        android:theme="@android:style/Theme.DeviceDefault.DayNight"
Loading