summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/PointerIcon.java54
-rw-r--r--libs/input/PointerController.cpp8
-rw-r--r--libs/input/PointerController.h6
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java24
-rw-r--r--services/core/java/com/android/server/wm/TaskTapPointerEventListener.java22
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp45
6 files changed, 126 insertions, 33 deletions
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index cf11fd04efdf..c3d13bd46eb3 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -31,6 +31,7 @@ import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -144,7 +145,8 @@ public final class PointerIcon implements Parcelable {
public static final int TYPE_DEFAULT = TYPE_ARROW;
private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL);
- private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
+ private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay =
+ new SparseArray<SparseArray<PointerIcon>>();
private static boolean sUseLargeIcons = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -163,6 +165,12 @@ public final class PointerIcon implements Parcelable {
@UnsupportedAppUsage
private int mDurationPerFrame;
+ /**
+ * Listener for displays lifecycle.
+ * @hide
+ */
+ private static DisplayManager.DisplayListener sDisplayListener;
+
private PointerIcon(int type) {
mType = type;
}
@@ -211,7 +219,19 @@ public final class PointerIcon implements Parcelable {
return gNullIcon;
}
- PointerIcon icon = gSystemIcons.get(type);
+ if (sDisplayListener == null) {
+ registerDisplayListener(context);
+ }
+
+ final int displayId = context.getDisplayId();
+ SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId);
+ if (systemIcons == null) {
+ systemIcons = new SparseArray<>();
+ gSystemIconsByDisplay.put(displayId, systemIcons);
+ }
+
+ PointerIcon icon = systemIcons.get(type);
+ // Reload if not in the same display.
if (icon != null) {
return icon;
}
@@ -240,7 +260,7 @@ public final class PointerIcon implements Parcelable {
} else {
icon.loadResource(context, context.getResources(), resourceId);
}
- gSystemIcons.append(type, icon);
+ systemIcons.append(type, icon);
return icon;
}
@@ -250,7 +270,7 @@ public final class PointerIcon implements Parcelable {
*/
public static void setUseLargeIcons(boolean use) {
sUseLargeIcons = use;
- gSystemIcons.clear();
+ gSystemIconsByDisplay.clear();
}
/**
@@ -576,4 +596,30 @@ public final class PointerIcon implements Parcelable {
return 0;
}
}
+
+ /**
+ * Manage system icon cache handled by display lifecycle.
+ * @param context The context.
+ */
+ private static void registerDisplayListener(@NonNull Context context) {
+ sDisplayListener = new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ gSystemIconsByDisplay.remove(displayId);
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ gSystemIconsByDisplay.remove(displayId);
+ }
+ };
+
+ DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+ displayManager.registerDisplayListener(sDisplayListener, null /* handler */);
+ }
+
}
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index b4f19c99c6fe..d742cc34b57e 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -255,7 +255,7 @@ void PointerController::setPresentation(Presentation presentation) {
if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources);
+ &mLocked.animationResources, mLocked.viewport.displayId);
}
if (mLocked.presentation != presentation) {
@@ -727,14 +727,14 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() {
}
void PointerController::loadResourcesLocked() REQUIRES(mLock) {
- mPolicy->loadPointerResources(&mResources);
+ mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
if (mLocked.presentation == PRESENTATION_POINTER) {
mLocked.additionalMouseResources.clear();
mLocked.animationResources.clear();
- mPolicy->loadPointerIcon(&mLocked.pointerIcon);
+ mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources);
+ &mLocked.animationResources, mLocked.viewport.displayId);
}
mLocked.pointerIconChanged = true;
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index a32cc42a3342..be057867890d 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -62,10 +62,10 @@ protected:
virtual ~PointerControllerPolicyInterface() { }
public:
- virtual void loadPointerIcon(SpriteIcon* icon) = 0;
- virtual void loadPointerResources(PointerResources* outResources) = 0;
+ virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0;
+ virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0;
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0;
virtual int32_t getDefaultPointerIconId() = 0;
virtual int32_t getCustomPointerIconId() = 0;
};
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 979de66f1dc8..669ff2b7bad5 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -138,6 +138,9 @@ public class InputManagerService extends IInputManager.Stub
private final Context mContext;
private final InputManagerHandler mHandler;
+ // Context cache used for loading pointer resources.
+ private Context mDisplayContext;
+
private final File mDoubleTouchGestureEnableFile;
private WindowManagerCallbacks mWindowManagerCallbacks;
@@ -1923,8 +1926,25 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private PointerIcon getPointerIcon() {
- return PointerIcon.getDefaultIcon(mContext);
+ private PointerIcon getPointerIcon(int displayId) {
+ return PointerIcon.getDefaultIcon(getContextForDisplay(displayId));
+ }
+
+ private Context getContextForDisplay(int displayId) {
+ if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) {
+ return mDisplayContext;
+ }
+
+ if (mContext.getDisplay().getDisplayId() == displayId) {
+ mDisplayContext = mContext;
+ return mDisplayContext;
+ }
+
+ // Create and cache context for non-default display.
+ final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ final Display display = displayManager.getDisplay(displayId);
+ mDisplayContext = mContext.createDisplayContext(display);
+ return mDisplayContext;
}
// Native callback.
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index b2194190f4f4..685e9bfa6025 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -31,6 +31,10 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.server.wm.WindowManagerService.H;
+/**
+ * 1. Adjust the top most focus display if touch down on some display.
+ * 2. Adjust the pointer icon when cursor moves to the task bounds.
+ */
public class TaskTapPointerEventListener implements PointerEventListener {
private final Region mTouchExcludeRegion = new Region();
@@ -80,8 +84,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
if (motionEvent.getDisplayId() != getDisplayId()) {
return;
}
- final int action = motionEvent.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
+ switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
final int x = (int) motionEvent.getX();
final int y = (int) motionEvent.getY();
@@ -97,7 +100,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
}
}
break;
-
+ case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE: {
final int x = (int) motionEvent.getX();
final int y = (int) motionEvent.getY();
@@ -125,6 +128,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
mPointerIconType = iconType;
if (mPointerIconType == TYPE_NOT_SPECIFIED) {
// Find the underlying window and ask it restore the pointer icon.
+ mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
x, y, mDisplayContent).sendToTarget();
} else {
@@ -133,6 +137,18 @@ public class TaskTapPointerEventListener implements PointerEventListener {
}
}
break;
+ case MotionEvent.ACTION_HOVER_EXIT: {
+ final int x = (int) motionEvent.getX();
+ final int y = (int) motionEvent.getY();
+ if (mPointerIconType != TYPE_NOT_SPECIFIED) {
+ mPointerIconType = TYPE_NOT_SPECIFIED;
+ // Find the underlying window and ask it to restore the pointer icon.
+ mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
+ mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
+ x, y, mDisplayContent).sendToTarget();
+ }
+ }
+ break;
}
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 641200769cf0..90c9cc2b0a35 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -111,6 +111,7 @@ static struct {
jmethodID getKeyboardLayoutOverlay;
jmethodID getDeviceAlias;
jmethodID getTouchCalibrationForInputDevice;
+ jmethodID getContextForDisplay;
} gServiceClassInfo;
static struct {
@@ -260,17 +261,16 @@ public:
/* --- PointerControllerPolicyInterface implementation --- */
- virtual void loadPointerIcon(SpriteIcon* icon);
- virtual void loadPointerResources(PointerResources* outResources);
+ virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId);
+ virtual void loadPointerResources(PointerResources* outResources, int32_t displayId);
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources);
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId);
virtual int32_t getDefaultPointerIconId();
virtual int32_t getCustomPointerIconId();
private:
sp<InputManager> mInputManager;
- jobject mContextObj;
jobject mServiceObj;
sp<Looper> mLooper;
@@ -329,7 +329,6 @@ NativeInputManager::NativeInputManager(jobject contextObj,
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
- mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
{
@@ -351,7 +350,6 @@ NativeInputManager::NativeInputManager(jobject contextObj,
NativeInputManager::~NativeInputManager() {
JNIEnv* env = jniEnv();
- env->DeleteGlobalRef(mContextObj);
env->DeleteGlobalRef(mServiceObj);
}
@@ -1202,19 +1200,22 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
return result;
}
-void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
+void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod(
- mServiceObj, gServiceClassInfo.getPointerIcon));
+ mServiceObj, gServiceClassInfo.getPointerIcon, displayId));
if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
return;
}
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
PointerIcon pointerIcon;
status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
- mContextObj, &pointerIcon);
+ displayContext.get(), &pointerIcon);
if (!status && !pointerIcon.isNullIcon()) {
*icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
} else {
@@ -1222,28 +1223,34 @@ void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
}
}
-void NativeInputManager::loadPointerResources(PointerResources* outResources) {
+void NativeInputManager::loadPointerResources(PointerResources* outResources, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_HOVER,
&outResources->spotHover);
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_TOUCH,
&outResources->spotTouch);
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_ANCHOR,
&outResources->spotAnchor);
}
void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources) {
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
++iconId) {
PointerIcon pointerIcon;
loadSystemIconAsSpriteWithPointerIcon(
- env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId]));
+ env, displayContext.get(), iconId, &pointerIcon, &((*outResources)[iconId]));
if (!pointerIcon.bitmapFrames.empty()) {
PointerAnimation& animationData = (*outAnimationResources)[iconId];
size_t numFrames = pointerIcon.bitmapFrames.size() + 1;
@@ -1258,7 +1265,7 @@ void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIc
}
}
}
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_NULL,
&((*outResources)[POINTER_ICON_STYLE_NULL]));
}
@@ -1819,7 +1826,7 @@ int register_android_server_InputManager(JNIEnv* env) {
"getPointerLayer", "()I");
GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
- "getPointerIcon", "()Landroid/view/PointerIcon;");
+ "getPointerIcon", "(I)Landroid/view/PointerIcon;");
GET_METHOD_ID(gServiceClassInfo.getPointerDisplayId, clazz,
"getPointerDisplayId", "()I");
@@ -1835,6 +1842,10 @@ int register_android_server_InputManager(JNIEnv* env) {
"getTouchCalibrationForInputDevice",
"(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
+ GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz,
+ "getContextForDisplay",
+ "(I)Landroid/content/Context;")
+
// InputDevice
FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");