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

Commit e98ecc58 authored by Omar Abdelmonem's avatar Omar Abdelmonem
Browse files

Create getTouchpadHardwareProperties() and link it to native code

Added a new method getHardwareProperties that returns an instance of a
new class, HardwareProperties, in Java. This method is also linked to
its native implementation.

Bug: 286551975

Test: Verified that new method correctly calls its native counterpart.
Flag: com.android.hardware.input.touchpad_visualizer
Change-Id: I1fe1553bf19bcc71f679c3cdf243219da61ff333
parent 1a16f030
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -466,7 +466,7 @@ public class InputManagerService extends IInputManager.Stub
                injector.getLooper());
        mTouchpadDebugViewController =
                touchpadVisualizer() ? new TouchpadDebugViewController(mContext,
                        injector.getLooper()) : null;
                        injector.getLooper(), this) : null;
        mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(),
                injector.getUEventManager());
        mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
@@ -1798,6 +1798,16 @@ public class InputManagerService extends IInputManager.Stub
        return mNative.getSensorList(deviceId);
    }

    /**
     * Retrieves the hardware properties of the touchpad for the given device ID.
     * Returns null if the device has no touchpad hardware properties
     * or if the device ID is invalid.
     */
    @Nullable
    public TouchpadHardwareProperties getTouchpadHardwareProperties(int deviceId) {
        return mNative.getTouchpadHardwareProperties(deviceId);
    }

    @Override // Binder call
    public boolean registerSensorListener(IInputSensorEventListener listener) {
        if (DEBUG) {
+6 −0
Original line number Diff line number Diff line
@@ -214,6 +214,9 @@ interface NativeInputManagerService {

    InputSensorInfo[] getSensorList(int deviceId);

    @Nullable
    TouchpadHardwareProperties getTouchpadHardwareProperties(int deviceId);

    boolean flushSensor(int deviceId, int sensorType);

    boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
@@ -506,6 +509,9 @@ interface NativeInputManagerService {
        @Override
        public native InputSensorInfo[] getSensorList(int deviceId);

        @Override
        public native TouchpadHardwareProperties getTouchpadHardwareProperties(int deviceId);

        @Override
        public native boolean flushSensor(int deviceId, int sensorType);

+535 −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 com.android.server.input;

import com.android.internal.util.DataClass;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
import com.android.tools.r8.keepanno.annotations.UsedByNative;

/**
 * A Java representation of hardware properties for a touchpad or mouse device.
 * This class mirrors the Gestures library HardwareProperties C++ struct used for representing
 * touchpad and mouse device properties, including touch area, resolution, and features like haptic
 * feedback, multitouch, and scroll wheels. It facilitates interaction between native and managed
 * code in Android.
 */
@DataClass(
        genToString = true
)
@UsedByNative(
        description = "Called from JNI in jni/com_android_server_input_InputManagerService.cpp",
        kind = KeepItemKind.CLASS_AND_MEMBERS)
public class TouchpadHardwareProperties {
    /**
     * The minimum X coordinate that the device can report.
     */
    private float mLeft;

    /**
     * The minimum Y coordinate that the device can report.
     */
    private float mTop;

    /**
     * The maximum X coordinate that the device can report.
     */
    private float mRight;

    /**
     * The maximum Y coordinate that the device can report.
     */
    private float mBottom;

    /**
     * The resolution of the X axis, in units per mm. Set to 0 if the
     * resolution is unknown.
     */
    private float mResX;
    /**
     * The resolutions of the Y axis, in units per mm. Set to 0 if the
     * resolution is unknown.
     */
    private float mResY;

    /**
     * The minimum orientation value.
     */
    private float mOrientationMinimum;
    /**
     * The maximum orientation value.
     */
    private float mOrientationMaximum;

    /**
     * The maximum number of finger slots that the device can report in one
     * HardwareState struct.
     */
    private short mMaxFingerCount;

    /**
     * Whether the touchpad has a button under its touch surface, allowing the
     * user to click by pressing (almost) anywhere on the pad, as opposed to
     * having one or more separate buttons for clicking.
     */
    private boolean mIsButtonPad;

    /**
     * Whether the touchpad is haptic, meaning that it reports true pressure (not
     * just touch area) via the pressure axis, and can provide haptic feedback.
     */
    private boolean mIsHapticPad;

    /**
     * Whether the touchpad reports pressure values in any way.
     */
    private boolean mReportsPressure = true;

    /**
     * Returns a string representation of this instance, including all fields.
     */
    public String toString() {
        return "HardwareProperties{"
                + "left=" + mLeft
                + ", top=" + mTop
                + ", right=" + mRight
                + ", bottom=" + mBottom
                + ", resX=" + mResX
                + ", resY=" + mResY
                + ", orientationMinimum=" + mOrientationMinimum
                + ", orientationMaximum=" + mOrientationMaximum
                + ", maxFingerCount=" + mMaxFingerCount
                + ", isButtonPad=" + mIsButtonPad
                + ", isHapticPad=" + mIsHapticPad
                + ", reportsPressure=" + mReportsPressure
                + '}';
    }


    // Code below generated by codegen v1.0.23.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
    //
    // To regenerate run:
    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/input
    // /TouchpadHardwareProperties.java
    //
    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
    //   Settings > Editor > Code Style > Formatter Control
    //@formatter:off


    @DataClass.Generated.Member
    /* package-private */ TouchpadHardwareProperties(
            float left,
            float top,
            float right,
            float bottom,
            float resX,
            float resY,
            float orientationMinimum,
            float orientationMaximum,
            short maxFingerCount,
            boolean isButtonPad,
            boolean isHapticPad,
            boolean reportsPressure) {
        this.mLeft = left;
        this.mTop = top;
        this.mRight = right;
        this.mBottom = bottom;
        this.mResX = resX;
        this.mResY = resY;
        this.mOrientationMinimum = orientationMinimum;
        this.mOrientationMaximum = orientationMaximum;
        this.mMaxFingerCount = maxFingerCount;
        this.mIsButtonPad = isButtonPad;
        this.mIsHapticPad = isHapticPad;
        this.mReportsPressure = reportsPressure;

        // onConstructed(); // You can define this method to get a callback
    }

    /**
     * The minimum X coordinate that the device can report.
     */
    @DataClass.Generated.Member
    public float getLeft() {
        return mLeft;
    }

    /**
     * The minimum Y coordinate that the device can report.
     */
    @DataClass.Generated.Member
    public float getTop() {
        return mTop;
    }

    /**
     * The maximum X coordinate that the device can report.
     */
    @DataClass.Generated.Member
    public float getRight() {
        return mRight;
    }

    /**
     * The maximum Y coordinate that the device can report.
     */
    @DataClass.Generated.Member
    public float getBottom() {
        return mBottom;
    }

    /**
     * The resolution of the X axis, in units per mm. Set to 0 if the
     * resolution is unknown.
     */
    @DataClass.Generated.Member
    public float getResX() {
        return mResX;
    }

    /**
     * The resolutions of the Y axis, in units per mm. Set to 0 if the
     * resolution is unknown.
     */
    @DataClass.Generated.Member
    public float getResY() {
        return mResY;
    }

    /**
     * The minimum orientation value.
     */
    @DataClass.Generated.Member
    public float getOrientationMinimum() {
        return mOrientationMinimum;
    }

    /**
     * The maximum orientation value.
     */
    @DataClass.Generated.Member
    public float getOrientationMaximum() {
        return mOrientationMaximum;
    }

    /**
     * The maximum number of finger slots that the device can report in one
     * HardwareState struct.
     */
    @DataClass.Generated.Member
    public short getMaxFingerCount() {
        return mMaxFingerCount;
    }

    /**
     * Whether the touchpad has a button under its touch surface, allowing the
     * user to click by pressing (almost) anywhere on the pad, as opposed to
     * having one or more separate buttons for clicking.
     */
    @DataClass.Generated.Member
    public boolean isIsButtonPad() {
        return mIsButtonPad;
    }

    /**
     * Whether the touchpad is haptic, meaning that it reports true pressure (not
     * just touch area) via the pressure axis, and can provide haptic feedback.
     */
    @DataClass.Generated.Member
    public boolean isIsHapticPad() {
        return mIsHapticPad;
    }

    /**
     * Whether the touchpad reports pressure values in any way.
     */
    @DataClass.Generated.Member
    public boolean isReportsPressure() {
        return mReportsPressure;
    }

    /**
     * A builder for {@link TouchpadHardwareProperties}
     */
    @SuppressWarnings("WeakerAccess")
    @DataClass.Generated.Member
    public static class Builder {

        private float mLeft;
        private float mTop;
        private float mRight;
        private float mBottom;
        private float mResX;
        private float mResY;
        private float mOrientationMinimum;
        private float mOrientationMaximum;
        private short mMaxFingerCount;
        private boolean mIsButtonPad;
        private boolean mIsHapticPad;
        private boolean mReportsPressure;

        private long mBuilderFieldsSet = 0L;

        /**
         * Creates a new Builder.
         *
         * @param left
         *   The minimum X coordinate that the device can report.
         * @param top
         *   The minimum Y coordinate that the device can report.
         * @param right
         *   The maximum X coordinate that the device can report.
         * @param bottom
         *   The maximum Y coordinate that the device can report.
         * @param resX
         *   The resolution of the X axis, in units per mm. Set to 0 if the
         *   resolution is unknown.
         * @param resY
         *   The resolutions of the Y axis, in units per mm. Set to 0 if the
         *   resolution is unknown.
         * @param orientationMinimum
         *   The minimum orientation value.
         * @param orientationMaximum
         *   The maximum orientation value.
         * @param maxFingerCount
         *   The maximum number of finger slots that the device can report in one
         *   HardwareState struct.
         * @param isButtonPad
         *   Whether the touchpad has a button under its touch surface, allowing the
         *   user to click by pressing (almost) anywhere on the pad, as opposed to
         *   having one or more separate buttons for clicking.
         * @param isHapticPad
         *   Whether the touchpad is haptic, meaning that it reports true pressure (not
         *   just touch area) via the pressure axis, and can provide haptic feedback.
         */
        public Builder(
                float left,
                float top,
                float right,
                float bottom,
                float resX,
                float resY,
                float orientationMinimum,
                float orientationMaximum,
                short maxFingerCount,
                boolean isButtonPad,
                boolean isHapticPad) {
            mLeft = left;
            mTop = top;
            mRight = right;
            mBottom = bottom;
            mResX = resX;
            mResY = resY;
            mOrientationMinimum = orientationMinimum;
            mOrientationMaximum = orientationMaximum;
            mMaxFingerCount = maxFingerCount;
            mIsButtonPad = isButtonPad;
            mIsHapticPad = isHapticPad;
        }

        /**
         * The minimum X coordinate that the device can report.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setLeft(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x1;
            mLeft = value;
            return this;
        }

        /**
         * The minimum Y coordinate that the device can report.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setTop(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x2;
            mTop = value;
            return this;
        }

        /**
         * The maximum X coordinate that the device can report.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setRight(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x4;
            mRight = value;
            return this;
        }

        /**
         * The maximum Y coordinate that the device can report.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setBottom(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x8;
            mBottom = value;
            return this;
        }

        /**
         * The resolution of the X axis, in units per mm. Set to 0 if the
         * resolution is unknown.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setResX(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x10;
            mResX = value;
            return this;
        }

        /**
         * The resolutions of the Y axis, in units per mm. Set to 0 if the
         * resolution is unknown.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setResY(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x20;
            mResY = value;
            return this;
        }

        /**
         * The minimum orientation value.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setOrientationMinimum(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x40;
            mOrientationMinimum = value;
            return this;
        }

        /**
         * The maximum orientation value.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setOrientationMaximum(float value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x80;
            mOrientationMaximum = value;
            return this;
        }

        /**
         * The maximum number of finger slots that the device can report in one
         * HardwareState struct.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setMaxFingerCount(short value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x100;
            mMaxFingerCount = value;
            return this;
        }

        /**
         * Whether the touchpad has a button under its touch surface, allowing the
         * user to click by pressing (almost) anywhere on the pad, as opposed to
         * having one or more separate buttons for clicking.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setIsButtonPad(boolean value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x200;
            mIsButtonPad = value;
            return this;
        }

        /**
         * Whether the touchpad is haptic, meaning that it reports true pressure (not
         * just touch area) via the pressure axis, and can provide haptic feedback.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setIsHapticPad(boolean value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x400;
            mIsHapticPad = value;
            return this;
        }

        /**
         * Whether the touchpad reports pressure values in any way.
         */
        @DataClass.Generated.Member
        public @android.annotation.NonNull Builder setReportsPressure(boolean value) {
            checkNotUsed();
            mBuilderFieldsSet |= 0x800;
            mReportsPressure = value;
            return this;
        }

        /** Builds the instance. This builder should not be touched after calling this! */
        public @android.annotation.NonNull TouchpadHardwareProperties build() {
            checkNotUsed();
            mBuilderFieldsSet |= 0x1000; // Mark builder used

            if ((mBuilderFieldsSet & 0x800) == 0) {
                mReportsPressure = true;
            }
            TouchpadHardwareProperties o = new TouchpadHardwareProperties(
                    mLeft,
                    mTop,
                    mRight,
                    mBottom,
                    mResX,
                    mResY,
                    mOrientationMinimum,
                    mOrientationMaximum,
                    mMaxFingerCount,
                    mIsButtonPad,
                    mIsHapticPad,
                    mReportsPressure);
            return o;
        }

        private void checkNotUsed() {
            if ((mBuilderFieldsSet & 0x1000) != 0) {
                throw new IllegalStateException(
                        "This Builder should not be reused. Use a new Builder instance instead");
            }
        }
    }

    @DataClass.Generated(
            time = 1723570664889L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/services/core"
                    + "/java/com/android/server/input/TouchpadHardwareProperties.java",
            inputSignatures = "private  float mLeft\nprivate  float mTop\nprivate  float mRight\n"
                    + "private  float mBottom\nprivate  float mResX\nprivate  float mResY\n"
                    + "private  float mOrientationMinimum\nprivate  float mOrientationMaximum\n"
                    + "private  short mMaxFingerCount\nprivate  boolean mIsButtonPad\n"
                    + "private  boolean mIsHapticPad\nprivate  boolean mReportsPressure\n"
                    + "public  java.lang.String toString()\n"
                    + "class TouchpadHardwareProperties extends java.lang.Object implements []\n"
                    + "@com.android.internal.util.DataClass(genToString=true)")
    @Deprecated
    private void __metadata() {}

    //@formatter:on
    // End of generated code
}
+19 −2
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ import android.view.Gravity;
import android.view.InputDevice;
import android.view.WindowManager;

import com.android.server.input.InputManagerService;
import com.android.server.input.TouchpadHardwareProperties;

import java.util.Objects;

public class TouchpadDebugViewController {
@@ -39,13 +42,16 @@ public class TouchpadDebugViewController {
    private final Handler mHandler;
    @Nullable
    private TouchpadDebugView mTouchpadDebugView;
    private final InputManagerService mInputManagerService;

    public TouchpadDebugViewController(Context context, Looper looper) {
    public TouchpadDebugViewController(Context context, Looper looper,
                                       InputManagerService inputManagerService) {
        final DisplayManager displayManager = Objects.requireNonNull(
                context.getSystemService(DisplayManager.class));
        final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        mContext = context.createDisplayContext(defaultDisplay);
        mHandler = new Handler(looper);
        mInputManagerService = inputManagerService;
    }

    public void systemRunning() {
@@ -110,6 +116,17 @@ public class TouchpadDebugViewController {

        wm.addView(mTouchpadDebugView, lp);
        Slog.d(TAG, "Touchpad debug view created.");

        TouchpadHardwareProperties mTouchpadHardwareProperties =
                mInputManagerService.getTouchpadHardwareProperties(
                        touchpadId);
        // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
        if (mTouchpadHardwareProperties != null) {
            Slog.d(TAG, mTouchpadHardwareProperties.toString());
        } else {
            Slog.w(TAG, "Failed to retrieve touchpad hardware properties for "
                    + "device ID: " + touchpadId);
        }
    }

    private void hideDebugView(int touchpadId) {
+96 −0

File changed.

Preview size limit exceeded, changes collapsed.