blob: 69ebc46cb4564eb466cbbc7cd8db0cabcc098473 [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
Mathew Inwoode5ad5982018-08-17 15:07:52 +010019import android.annotation.UnsupportedAppUsage;
Michael Wrighta44dd262013-04-10 21:12:00 -070020import android.os.Looper;
21import android.os.MessageQueue;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070022import android.util.LongSparseArray;
Michael Wrighta44dd262013-04-10 21:12:00 -070023import android.util.Pools.Pool;
24import android.util.Pools.SimplePool;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070025
26import dalvik.system.CloseGuard;
Michael Wrighta44dd262013-04-10 21:12:00 -070027
28import java.lang.ref.WeakReference;
29
Jeff Brown46b9ac02010-04-22 18:58:52 -070030/**
31 * An input queue provides a mechanism for an application to receive incoming
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -070032 * input events. Currently only usable from native code.
Jeff Brown46b9ac02010-04-22 18:58:52 -070033 */
34public final class InputQueue {
Ashok Bhata931d5212014-01-08 14:04:51 +000035 private final LongSparseArray<ActiveInputEvent> mActiveEventArray =
36 new LongSparseArray<ActiveInputEvent>(20);
Michael Wrighta44dd262013-04-10 21:12:00 -070037 private final Pool<ActiveInputEvent> mActiveInputEventPool =
38 new SimplePool<ActiveInputEvent>(20);
39
40 private final CloseGuard mCloseGuard = CloseGuard.get();
41
Ashok Bhata931d5212014-01-08 14:04:51 +000042 private long mPtr;
Michael Wrighta44dd262013-04-10 21:12:00 -070043
Ashok Bhata931d5212014-01-08 14:04:51 +000044 private static native long nativeInit(WeakReference<InputQueue> weakQueue,
Michael Wrighta44dd262013-04-10 21:12:00 -070045 MessageQueue messageQueue);
Ashok Bhata931d5212014-01-08 14:04:51 +000046 private static native long nativeSendKeyEvent(long ptr, KeyEvent e, boolean preDispatch);
47 private static native long nativeSendMotionEvent(long ptr, MotionEvent e);
48 private static native void nativeDispose(long ptr);
Michael Wrighta44dd262013-04-10 21:12:00 -070049
50 /** @hide */
51 public InputQueue() {
52 mPtr = nativeInit(new WeakReference<InputQueue>(this), Looper.myQueue());
53
54 mCloseGuard.open("dispose");
55 }
56
57 @Override
58 protected void finalize() throws Throwable {
59 try {
60 dispose(true);
61 } finally {
62 super.finalize();
63 }
64 }
65
66 /** @hide */
67 public void dispose() {
68 dispose(false);
69 }
70
71 /** @hide */
72 public void dispose(boolean finalized) {
73 if (mCloseGuard != null) {
74 if (finalized) {
75 mCloseGuard.warnIfOpen();
76 }
77 mCloseGuard.close();
78 }
79
80 if (mPtr != 0) {
81 nativeDispose(mPtr);
82 mPtr = 0;
83 }
84 }
85
86 /** @hide */
Ashok Bhata931d5212014-01-08 14:04:51 +000087 public long getNativePtr() {
Michael Wrighta44dd262013-04-10 21:12:00 -070088 return mPtr;
89 }
90
91 /** @hide */
92 public void sendInputEvent(InputEvent e, Object token, boolean predispatch,
93 FinishedInputEventCallback callback) {
94 ActiveInputEvent event = obtainActiveInputEvent(token, callback);
Ashok Bhata931d5212014-01-08 14:04:51 +000095 long id;
Michael Wrighta44dd262013-04-10 21:12:00 -070096 if (e instanceof KeyEvent) {
97 id = nativeSendKeyEvent(mPtr, (KeyEvent) e, predispatch);
98 } else {
99 id = nativeSendMotionEvent(mPtr, (MotionEvent) e);
100 }
101 mActiveEventArray.put(id, event);
102 }
103
Mathew Inwoode5ad5982018-08-17 15:07:52 +0100104 @UnsupportedAppUsage
Ashok Bhata931d5212014-01-08 14:04:51 +0000105 private void finishInputEvent(long id, boolean handled) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700106 int index = mActiveEventArray.indexOfKey(id);
107 if (index >= 0) {
108 ActiveInputEvent e = mActiveEventArray.valueAt(index);
109 mActiveEventArray.removeAt(index);
110 e.mCallback.onFinishedInputEvent(e.mToken, handled);
111 recycleActiveInputEvent(e);
112 }
113 }
114
115 private ActiveInputEvent obtainActiveInputEvent(Object token,
116 FinishedInputEventCallback callback) {
117 ActiveInputEvent e = mActiveInputEventPool.acquire();
118 if (e == null) {
119 e = new ActiveInputEvent();
120 }
121 e.mToken = token;
122 e.mCallback = callback;
123 return e;
124 }
125
126 private void recycleActiveInputEvent(ActiveInputEvent e) {
127 e.recycle();
128 mActiveInputEventPool.release(e);
129 }
130
131 private final class ActiveInputEvent {
132 public Object mToken;
133 public FinishedInputEventCallback mCallback;
134
135 public void recycle() {
136 mToken = null;
137 mCallback = null;
138 }
139 }
140
Dianne Hackbornbfba7ca2010-09-24 17:18:14 -0700141 /**
142 * Interface to receive notification of when an InputQueue is associated
143 * and dissociated with a thread.
144 */
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700145 public static interface Callback {
Dianne Hackbornbfba7ca2010-09-24 17:18:14 -0700146 /**
147 * Called when the given InputQueue is now associated with the
148 * thread making this call, so it can start receiving events from it.
149 */
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700150 void onInputQueueCreated(InputQueue queue);
Michael Wrighta44dd262013-04-10 21:12:00 -0700151
Dianne Hackbornbfba7ca2010-09-24 17:18:14 -0700152 /**
153 * Called when the given InputQueue is no longer associated with
154 * the thread and thus not dispatching events.
155 */
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700156 void onInputQueueDestroyed(InputQueue queue);
157 }
158
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700159 /** @hide */
Michael Wrighta44dd262013-04-10 21:12:00 -0700160 public static interface FinishedInputEventCallback {
161 void onFinishedInputEvent(Object token, boolean handled);
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700162 }
Michael Wrighta44dd262013-04-10 21:12:00 -0700163
Jeff Brown46b9ac02010-04-22 18:58:52 -0700164}