Jeff Brown | 46b9ac0 | 2010-04-22 18:58:52 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.view; |
| 18 | |
Mathew Inwood | a570dee | 2018-08-17 14:56:00 +0100 | [diff] [blame] | 19 | import android.annotation.UnsupportedAppUsage; |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 20 | import android.os.Looper; |
| 21 | import android.os.MessageQueue; |
Aurimas Liutikas | 67e2ae8 | 2016-10-11 18:17:42 -0700 | [diff] [blame] | 22 | import android.util.LongSparseArray; |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 23 | import android.util.Pools.Pool; |
| 24 | import android.util.Pools.SimplePool; |
Aurimas Liutikas | 67e2ae8 | 2016-10-11 18:17:42 -0700 | [diff] [blame] | 25 | |
| 26 | import dalvik.system.CloseGuard; |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 27 | |
| 28 | import java.lang.ref.WeakReference; |
| 29 | |
Jeff Brown | 46b9ac0 | 2010-04-22 18:58:52 -0700 | [diff] [blame] | 30 | /** |
| 31 | * An input queue provides a mechanism for an application to receive incoming |
Dianne Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 32 | * input events. Currently only usable from native code. |
Jeff Brown | 46b9ac0 | 2010-04-22 18:58:52 -0700 | [diff] [blame] | 33 | */ |
| 34 | public final class InputQueue { |
Ashok Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 35 | private final LongSparseArray<ActiveInputEvent> mActiveEventArray = |
| 36 | new LongSparseArray<ActiveInputEvent>(20); |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 37 | private final Pool<ActiveInputEvent> mActiveInputEventPool = |
| 38 | new SimplePool<ActiveInputEvent>(20); |
| 39 | |
| 40 | private final CloseGuard mCloseGuard = CloseGuard.get(); |
| 41 | |
Ashok Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 42 | private long mPtr; |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 43 | |
Ashok Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 44 | private static native long nativeInit(WeakReference<InputQueue> weakQueue, |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 45 | MessageQueue messageQueue); |
Ashok Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 46 | 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 Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 49 | |
| 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 Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 87 | public long getNativePtr() { |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 88 | 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 Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 95 | long id; |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 96 | 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 Inwood | a570dee | 2018-08-17 14:56:00 +0100 | [diff] [blame] | 104 | @UnsupportedAppUsage |
Ashok Bhat | a931d521 | 2014-01-08 14:04:51 +0000 | [diff] [blame] | 105 | private void finishInputEvent(long id, boolean handled) { |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 106 | 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 Hackborn | bfba7ca | 2010-09-24 17:18:14 -0700 | [diff] [blame] | 141 | /** |
| 142 | * Interface to receive notification of when an InputQueue is associated |
| 143 | * and dissociated with a thread. |
| 144 | */ |
Dianne Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 145 | public static interface Callback { |
Dianne Hackborn | bfba7ca | 2010-09-24 17:18:14 -0700 | [diff] [blame] | 146 | /** |
| 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 Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 150 | void onInputQueueCreated(InputQueue queue); |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 151 | |
Dianne Hackborn | bfba7ca | 2010-09-24 17:18:14 -0700 | [diff] [blame] | 152 | /** |
| 153 | * Called when the given InputQueue is no longer associated with |
| 154 | * the thread and thus not dispatching events. |
| 155 | */ |
Dianne Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 156 | void onInputQueueDestroyed(InputQueue queue); |
| 157 | } |
| 158 | |
Dianne Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 159 | /** @hide */ |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 160 | public static interface FinishedInputEventCallback { |
| 161 | void onFinishedInputEvent(Object token, boolean handled); |
Dianne Hackborn | 1e4b9f3 | 2010-06-23 14:10:57 -0700 | [diff] [blame] | 162 | } |
Michael Wright | a44dd26 | 2013-04-10 21:12:00 -0700 | [diff] [blame] | 163 | |
Jeff Brown | 46b9ac0 | 2010-04-22 18:58:52 -0700 | [diff] [blame] | 164 | } |