diff options
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"); |