diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index c67ff6ea0111c..7986ceb988dbe 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -127,6 +127,19 @@ public abstract class InputEventReceiver { finishInputEvent(event, false); } + /** + * Called when a focus event is received. + * + * @param hasFocus if true, the window associated with this input channel has just received + * focus + * if false, the window associated with this input channel has just lost focus + * @param inTouchMode if true, the device is in touch mode + * if false, the device is not in touch mode + */ + // Called from native code. + public void onFocusEvent(boolean hasFocus, boolean inTouchMode) { + } + /** * Called when a batched input event is pending. * @@ -213,8 +226,13 @@ public abstract class InputEventReceiver { onBatchedInputEventPending(); } - public static interface Factory { - public InputEventReceiver createInputEventReceiver( - InputChannel inputChannel, Looper looper); + /** + * Factory for InputEventReceiver + */ + public interface Factory { + /** + * Create a new InputReceiver for a given inputChannel + */ + InputEventReceiver createInputEventReceiver(InputChannel inputChannel, Looper looper); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e0f6e0668f8b2..2ef944f359827 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -8043,6 +8043,11 @@ public final class ViewRootImpl implements ViewParent, } } + @Override + public void onFocusEvent(boolean hasFocus, boolean inTouchMode) { + windowFocusChanged(hasFocus, inTouchMode); + } + @Override public void dispose() { unscheduleConsumeBatchedInput(); diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 59dab0c821624..649e5d2f49fe7 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -40,10 +40,15 @@ namespace android { static const bool kDebugDispatchCycle = false; +static const char* toString(bool value) { + return value ? "true" : "false"; +} + static struct { jclass clazz; jmethodID dispatchInputEvent; + jmethodID onFocusEvent; jmethodID dispatchBatchedInputEventPending; } gInputEventReceiverClassInfo; @@ -219,8 +224,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) { if (kDebugDispatchCycle) { ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%" PRId64, - getInputChannelName().c_str(), - consumeBatches ? "true" : "false", frameTime); + getInputChannelName().c_str(), toString(consumeBatches), frameTime); } if (consumeBatches) { @@ -235,6 +239,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, for (;;) { uint32_t seq; InputEvent* inputEvent; + status_t status = mInputConsumer.consume(&mInputEventFactory, consumeBatches, frameTime, &seq, &inputEvent); if (status) { @@ -302,6 +307,19 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent); break; } + case AINPUT_EVENT_TYPE_FOCUS: { + FocusEvent* focusEvent = static_cast(inputEvent); + if (kDebugDispatchCycle) { + ALOGD("channel '%s' ~ Received focus event: hasFocus=%s, inTouchMode=%s.", + getInputChannelName().c_str(), toString(focusEvent->getHasFocus()), + toString(focusEvent->getInTouchMode())); + } + env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent, + jboolean(focusEvent->getHasFocus()), + jboolean(focusEvent->getInTouchMode())); + finishInputEvent(seq, true /* handled */); + return OK; + } default: assert(false); // InputConsumer should prevent this from ever happening @@ -421,6 +439,8 @@ int register_android_view_InputEventReceiver(JNIEnv* env) { gInputEventReceiverClassInfo.dispatchInputEvent = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "dispatchInputEvent", "(ILandroid/view/InputEvent;)V"); + gInputEventReceiverClassInfo.onFocusEvent = + GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(ZZ)V"); gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V"); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 74fdba1cd13e6..e3b593e90fa51 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4602,13 +4602,13 @@ public class WindowManagerService extends IWindowManager.Stub if (newFocus != null) { ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Gaining focus: %s", newFocus); - newFocus.reportFocusChangedSerialized(true, mInTouchMode); + newFocus.reportFocusChangedSerialized(true); notifyFocusChanged(); } if (lastFocus != null) { ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Losing focus: %s", lastFocus); - lastFocus.reportFocusChangedSerialized(false, mInTouchMode); + lastFocus.reportFocusChangedSerialized(false); } break; } @@ -4626,7 +4626,7 @@ public class WindowManagerService extends IWindowManager.Stub for (int i = 0; i < N; i++) { ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Losing delayed focus: %s", losers.get(i)); - losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); + losers.get(i).reportFocusChangedSerialized(false); } break; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index ba40f623ea664..c2eb0e4492d59 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3339,11 +3339,7 @@ class WindowState extends WindowContainer implements WindowManagerP * Report a focus change. Must be called with no locks held, and consistently * from the same serialized thread (such as dispatched from a handler). */ - void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) { - try { - mClient.windowFocusChanged(focused, inTouchMode); - } catch (RemoteException e) { - } + void reportFocusChangedSerialized(boolean focused) { if (mFocusCallbacks != null) { final int N = mFocusCallbacks.beginBroadcast(); for (int i=0; i