summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Byoungho Jung <bh.jung@samsung.corp-partner.google.com> 2023-11-03 20:12:50 +0900
committer Prabir Pradhan <prabirmsp@google.com> 2023-12-04 21:42:08 +0000
commit1a1571d994a0e6c754f46db1a63b09c8f76aa8eb (patch)
treef1d43ec1dc1f7d6304a3e602e2440e270ea0b49b
parentc1ac283d9908e2d4881b9a1542bb12d2e46c7fa0 (diff)
Add setPointerIcon for PointerChoreographer (base)
To set pointer icon for mouse or stylus, we are going to use setPointerIcon with more parameters which will be useful for multi-device experience and security. Test: Manual Bug: 293587049 Change-Id: I17bb047b0bfbff6cf3a129e4fa742ec489420faf
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl2
-rw-r--r--core/java/android/hardware/input/InputManager.java6
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java12
-rw-r--r--core/java/android/view/InputDevice.java18
-rw-r--r--core/java/android/view/PointerIcon.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java19
-rw-r--r--libs/input/PointerController.h8
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java17
-rw-r--r--services/core/java/com/android/server/input/NativeInputManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/DragState.java1
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp37
12 files changed, 128 insertions, 32 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 88d7231bc7be..6626baffd134 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -169,6 +169,8 @@ interface IInputManager {
void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon);
+ boolean setPointerIcon(in PointerIcon icon, int displayId, int deviceId, int pointerId,
+ in IBinder inputToken);
oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index abbf95403d80..f941ad87bac5 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1057,6 +1057,12 @@ public final class InputManager {
mGlobal.setCustomPointerIcon(icon);
}
+ /** @hide */
+ public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId,
+ IBinder inputToken) {
+ return mGlobal.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken);
+ }
+
/**
* Check if showing a {@link android.view.PointerIcon} for styluses is enabled.
*
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index cf1dfe3fceb1..24a69116e77e 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -1286,6 +1286,18 @@ public final class InputManagerGlobal {
}
/**
+ * @see InputManager#setPointerIcon(PointerIcon, int, int, int, IBinder)
+ */
+ public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId,
+ IBinder inputToken) {
+ try {
+ return mIm.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @see InputManager#requestPointerCapture(IBinder, boolean)
*/
public void requestPointerCapture(IBinder windowToken, boolean enable) {
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index d131dc9a4c7d..f2c3abc8edb4 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -1308,24 +1308,6 @@ public final class InputDevice implements Parcelable {
}
/**
- * Sets the current pointer type.
- * @param pointerType the type of the pointer icon.
- * @hide
- */
- public void setPointerType(int pointerType) {
- InputManagerGlobal.getInstance().setPointerIconType(pointerType);
- }
-
- /**
- * Specifies the current custom pointer.
- * @param icon the icon data.
- * @hide
- */
- public void setCustomPointerIcon(PointerIcon icon) {
- InputManagerGlobal.getInstance().setCustomPointerIcon(icon);
- }
-
- /**
* Reports whether the device has a battery.
* @return true if the device has a battery, false otherwise.
* @hide
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index fee88d91283d..7800c28ae089 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -223,6 +223,9 @@ public final class PointerIcon implements Parcelable {
* @throws IllegalArgumentException if context is null.
*/
public static @NonNull PointerIcon getSystemIcon(@NonNull Context context, int type) {
+ // TODO(b/293587049): Pointer Icon Refactor: There is no need to load the system
+ // icon resource into memory outside of system server. Remove the need to load
+ // resources when getting a system icon.
if (context == null) {
throw new IllegalArgumentException("context must not be null");
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d27f787072e2..8d469ee454ae 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -97,6 +97,8 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
+import static com.android.input.flags.Flags.enablePointerChoreographer;
+
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.animation.AnimationHandler;
@@ -7485,18 +7487,34 @@ public final class ViewRootImpl implements ViewParent,
mPointerIconType = pointerType;
mCustomPointerIcon = null;
if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
- InputManagerGlobal
- .getInstance()
- .setPointerIconType(pointerType);
+ if (enablePointerChoreographer()) {
+ InputManagerGlobal
+ .getInstance()
+ .setPointerIcon(PointerIcon.getSystemIcon(mContext, pointerType),
+ event.getDisplayId(), event.getDeviceId(),
+ event.getPointerId(pointerIndex), getInputToken());
+ } else {
+ InputManagerGlobal
+ .getInstance()
+ .setPointerIconType(pointerType);
+ }
return true;
}
}
if (mPointerIconType == PointerIcon.TYPE_CUSTOM &&
!pointerIcon.equals(mCustomPointerIcon)) {
mCustomPointerIcon = pointerIcon;
- InputManagerGlobal
- .getInstance()
- .setCustomPointerIcon(mCustomPointerIcon);
+ if (enablePointerChoreographer()) {
+ InputManagerGlobal
+ .getInstance()
+ .setPointerIcon(mCustomPointerIcon,
+ event.getDisplayId(), event.getDeviceId(),
+ event.getPointerId(pointerIndex), getInputToken());
+ } else {
+ InputManagerGlobal
+ .getInstance()
+ .setCustomPointerIcon(mCustomPointerIcon);
+ }
}
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 53ec20192f2b..8511a21d4294 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
+import static com.android.input.flags.Flags.enablePointerChoreographer;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
@@ -63,6 +64,7 @@ import java.util.function.Supplier;
class DragResizeInputListener implements AutoCloseable {
private static final String TAG = "DragResizeInputListener";
private final IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession();
+ private final Context mContext;
private final Handler mHandler;
private final Choreographer mChoreographer;
private final InputManager mInputManager;
@@ -110,6 +112,7 @@ class DragResizeInputListener implements AutoCloseable {
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
DisplayController displayController) {
mInputManager = context.getSystemService(InputManager.class);
+ mContext = context;
mHandler = handler;
mChoreographer = choreographer;
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
@@ -451,7 +454,9 @@ class DragResizeInputListener implements AutoCloseable {
}
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE: {
- updateCursorType(e.getXCursorPosition(), e.getYCursorPosition());
+ updateCursorType(e.getDisplayId(), e.getDeviceId(),
+ e.getPointerId(/*pointerIndex=*/0), e.getXCursorPosition(),
+ e.getYCursorPosition());
result = true;
break;
}
@@ -579,7 +584,8 @@ class DragResizeInputListener implements AutoCloseable {
return 0;
}
- private void updateCursorType(float x, float y) {
+ private void updateCursorType(int displayId, int deviceId, int pointerId, float x,
+ float y) {
@DragPositioningCallback.CtrlType int ctrlType = calculateResizeHandlesCtrlType(x, y);
int cursorType = PointerIcon.TYPE_DEFAULT;
@@ -611,9 +617,14 @@ class DragResizeInputListener implements AutoCloseable {
// where views in the task can receive input events because we can't set touch regions
// of input sinks to have rounded corners.
if (mLastCursorType != cursorType || cursorType != PointerIcon.TYPE_DEFAULT) {
- mInputManager.setPointerIconType(cursorType);
+ if (enablePointerChoreographer()) {
+ mInputManager.setPointerIcon(PointerIcon.getSystemIcon(mContext, cursorType),
+ displayId, deviceId, pointerId, mInputChannel.getToken());
+ } else {
+ mInputManager.setPointerIconType(cursorType);
+ }
mLastCursorType = cursorType;
}
}
}
-} \ No newline at end of file
+}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index fa07c3989720..a8b963367f4c 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -65,9 +65,9 @@ public:
void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
BitSet32 spotIdBits, int32_t displayId) override;
void clearSpots() override;
+ void updatePointerIcon(PointerIconStyle iconId) override;
+ void setCustomPointerIcon(const SpriteIcon& icon) override;
- void updatePointerIcon(PointerIconStyle iconId);
- void setCustomPointerIcon(const SpriteIcon& icon);
virtual void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void doInactivityTimeout();
void reloadPointerResources();
@@ -192,10 +192,10 @@ public:
void setPresentation(Presentation) override {
LOG_ALWAYS_FATAL("Should not be called");
}
- void updatePointerIcon(PointerIconStyle) {
+ void updatePointerIcon(PointerIconStyle) override {
LOG_ALWAYS_FATAL("Should not be called");
}
- void setCustomPointerIcon(const SpriteIcon&) {
+ void setCustomPointerIcon(const SpriteIcon&) override {
LOG_ALWAYS_FATAL("Should not be called");
}
// fade() should not be called by inactivity timeout. Do nothing.
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2533e0297679..3fc9594965a2 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -295,6 +295,8 @@ public class InputManagerService extends IInputManager.Stub
@GuardedBy("mAdditionalDisplayInputPropertiesLock")
private final AdditionalDisplayInputProperties mCurrentDisplayProperties =
new AdditionalDisplayInputProperties();
+ // TODO(b/293587049): Pointer Icon Refactor: There can be more than one pointer icon
+ // visible at once. Update this to support multi-pointer use cases.
@GuardedBy("mAdditionalDisplayInputPropertiesLock")
private int mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
@GuardedBy("mAdditionalDisplayInputPropertiesLock")
@@ -1756,6 +1758,21 @@ public class InputManagerService extends IInputManager.Stub
}
}
+ // Binder call
+ @Override
+ public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId,
+ IBinder inputToken) {
+ Objects.requireNonNull(icon);
+ synchronized (mAdditionalDisplayInputPropertiesLock) {
+ mPointerIconType = icon.getType();
+ mPointerIcon = mPointerIconType == PointerIcon.TYPE_CUSTOM ? icon : null;
+
+ if (!mCurrentDisplayProperties.pointerIconVisible) return false;
+
+ return mNative.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken);
+ }
+ }
+
/**
* Add a runtime association between the input port and the display port. This overrides any
* static associations.
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index f126a89eedf7..620cde59fb52 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -186,6 +186,9 @@ interface NativeInputManagerService {
void setCustomPointerIcon(PointerIcon icon);
+ boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId,
+ IBinder inputToken);
+
void requestPointerCapture(IBinder windowToken, boolean enabled);
boolean canDispatchToDisplay(int deviceId, int displayId);
@@ -434,6 +437,10 @@ interface NativeInputManagerService {
public native void setCustomPointerIcon(PointerIcon icon);
@Override
+ public native boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId,
+ int pointerId, IBinder inputToken);
+
+ @Override
public native void requestPointerCapture(IBinder windowToken, boolean enabled);
@Override
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 7af4aadb2f0e..a888f8467b3a 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -692,6 +692,7 @@ class DragState {
void overridePointerIconLocked(int touchSource) {
mTouchSource = touchSource;
if (isFromSource(InputDevice.SOURCE_MOUSE)) {
+ // TODO(b/293587049): Pointer Icon Refactor: Set the pointer icon from the drag window.
InputManagerGlobal.getInstance().setPointerIconType(PointerIcon.TYPE_GRABBING);
}
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index f1cddc643422..7de50e8f1ecf 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -308,6 +308,8 @@ public:
void reloadPointerIcons();
void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled);
void setCustomPointerIcon(const SpriteIcon& icon);
+ bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
+ int32_t displayId, DeviceId deviceId);
void setMotionClassifierEnabled(bool enabled);
std::optional<std::string> getBluetoothAddress(int32_t deviceId);
void setStylusButtonMotionEventsEnabled(bool enabled);
@@ -1347,6 +1349,12 @@ void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
}
}
+bool NativeInputManager::setPointerIcon(
+ std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
+ DeviceId deviceId) {
+ return mInputManager->getChoreographer().setPointerIcon(std::move(icon), displayId, deviceId);
+}
+
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
JNIEnv *env, jfloatArray matrixArr) {
ATRACE_CALL();
@@ -2511,6 +2519,33 @@ static void nativeSetCustomPointerIcon(JNIEnv* env, jobject nativeImplObj, jobje
im->setCustomPointerIcon(spriteIcon);
}
+static bool nativeSetPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject iconObj,
+ jint displayId, jint deviceId, jint pointerId,
+ jobject inputTokenObj) {
+ NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+
+ PointerIcon pointerIcon;
+ status_t result = android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
+ if (result) {
+ jniThrowRuntimeException(env, "Failed to load pointer icon.");
+ return false;
+ }
+
+ std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon;
+ if (pointerIcon.style == PointerIconStyle::TYPE_CUSTOM) {
+ icon = std::make_unique<SpriteIcon>(pointerIcon.bitmap.copy(
+ ANDROID_BITMAP_FORMAT_RGBA_8888),
+ pointerIcon.style, pointerIcon.hotSpotX,
+ pointerIcon.hotSpotY);
+ } else {
+ icon = pointerIcon.style;
+ }
+ // TODO(b/293587049): Perform hit test to ensure the pointer is dispatched to the channel.
+ sp<IBinder> inputToken = ibinderForJavaObject(env, inputTokenObj);
+
+ return im->setPointerIcon(std::move(icon), displayId, deviceId);
+}
+
static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jobject nativeImplObj, jint deviceId,
jint displayId) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
@@ -2769,6 +2804,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"reloadPointerIcons", "()V", (void*)nativeReloadPointerIcons},
{"setCustomPointerIcon", "(Landroid/view/PointerIcon;)V",
(void*)nativeSetCustomPointerIcon},
+ {"setPointerIcon", "(Landroid/view/PointerIcon;IIILandroid/os/IBinder;)Z",
+ (void*)nativeSetPointerIcon},
{"canDispatchToDisplay", "(II)Z", (void*)nativeCanDispatchToDisplay},
{"notifyPortAssociationsChanged", "()V", (void*)nativeNotifyPortAssociationsChanged},
{"changeUniqueIdAssociation", "()V", (void*)nativeChangeUniqueIdAssociation},