146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/* 246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Copyright (C) 2010 The Android Open Source Project 346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * you may not use this file except in compliance with the License. 646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * You may obtain a copy of the License at 746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 1046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Unless required by applicable law or agreed to in writing, software 1146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * See the License for the specific language governing permissions and 1446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * limitations under the License. 1546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */ 1646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownpackage android.view; 1846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 19a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport dalvik.system.CloseGuard; 20a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 21a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.os.Handler; 22a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.os.Looper; 23a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.os.MessageQueue; 24a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.util.Pools.Pool; 25a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.util.Pools.SimplePool; 26a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport android.util.SparseArray; 27a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 28a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightimport java.lang.ref.WeakReference; 29a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/** 3146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * An input queue provides a mechanism for an application to receive incoming 321e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn * input events. Currently only usable from native code. 3346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */ 3446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownpublic final class InputQueue { 35a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private final SparseArray<ActiveInputEvent> mActiveEventArray = 36a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright new SparseArray<ActiveInputEvent>(20); 37a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private final Pool<ActiveInputEvent> mActiveInputEventPool = 38a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright new SimplePool<ActiveInputEvent>(20); 39a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 40a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private final CloseGuard mCloseGuard = CloseGuard.get(); 41a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 42a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private int mPtr; 43a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 44a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private static native int nativeInit(WeakReference<InputQueue> weakQueue, 45a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright MessageQueue messageQueue); 46a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private static native int nativeSendKeyEvent(int ptr, KeyEvent e, boolean preDispatch); 47a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private static native int nativeSendMotionEvent(int ptr, MotionEvent e); 48a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private static native void nativeDispose(int ptr); 49a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 50a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright /** @hide */ 51a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public InputQueue() { 52a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mPtr = nativeInit(new WeakReference<InputQueue>(this), Looper.myQueue()); 53a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 54a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mCloseGuard.open("dispose"); 55a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 56a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 57a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright @Override 58a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright protected void finalize() throws Throwable { 59a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright try { 60a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright dispose(true); 61a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } finally { 62a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright super.finalize(); 63a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 64a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 65a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 66a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright /** @hide */ 67a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public void dispose() { 68a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright dispose(false); 69a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 70a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 71a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright /** @hide */ 72a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public void dispose(boolean finalized) { 73a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (mCloseGuard != null) { 74a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (finalized) { 75a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mCloseGuard.warnIfOpen(); 76a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 77a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mCloseGuard.close(); 78a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 79a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 80a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (mPtr != 0) { 81a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright nativeDispose(mPtr); 82a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mPtr = 0; 83a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 84a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 85a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 86a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright /** @hide */ 87a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public int getNativePtr() { 88a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright return mPtr; 89a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 90a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 91a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright /** @hide */ 92a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public void sendInputEvent(InputEvent e, Object token, boolean predispatch, 93a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright FinishedInputEventCallback callback) { 94a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright ActiveInputEvent event = obtainActiveInputEvent(token, callback); 95a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright int id; 96a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (e instanceof KeyEvent) { 97a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright id = nativeSendKeyEvent(mPtr, (KeyEvent) e, predispatch); 98a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } else { 99a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright id = nativeSendMotionEvent(mPtr, (MotionEvent) e); 100a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 101a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mActiveEventArray.put(id, event); 102a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 103a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 104a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private void finishInputEvent(int id, boolean handled) { 105a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright int index = mActiveEventArray.indexOfKey(id); 106a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (index >= 0) { 107a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright ActiveInputEvent e = mActiveEventArray.valueAt(index); 108a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mActiveEventArray.removeAt(index); 109a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright e.mCallback.onFinishedInputEvent(e.mToken, handled); 110a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright recycleActiveInputEvent(e); 111a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 112a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 113a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 114a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private ActiveInputEvent obtainActiveInputEvent(Object token, 115a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright FinishedInputEventCallback callback) { 116a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright ActiveInputEvent e = mActiveInputEventPool.acquire(); 117a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright if (e == null) { 118a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright e = new ActiveInputEvent(); 119a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 120a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright e.mToken = token; 121a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright e.mCallback = callback; 122a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright return e; 123a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 124a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 125a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private void recycleActiveInputEvent(ActiveInputEvent e) { 126a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright e.recycle(); 127a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mActiveInputEventPool.release(e); 128a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 129a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 130a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright private final class ActiveInputEvent { 131a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public Object mToken; 132a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public FinishedInputEventCallback mCallback; 133a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 134a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public void recycle() { 135a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mToken = null; 136a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright mCallback = null; 137a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 138a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright } 139a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 140bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn /** 141bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * Interface to receive notification of when an InputQueue is associated 142bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * and dissociated with a thread. 143bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn */ 1441e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn public static interface Callback { 145bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn /** 146bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * Called when the given InputQueue is now associated with the 147bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * thread making this call, so it can start receiving events from it. 148bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn */ 1491e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn void onInputQueueCreated(InputQueue queue); 150a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 151bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn /** 152bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * Called when the given InputQueue is no longer associated with 153bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn * the thread and thus not dispatching events. 154bfba7cab94cd9cf28e561159dbbe934dc83a6f0aDianne Hackborn */ 1551e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn void onInputQueueDestroyed(InputQueue queue); 1561e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn } 1571e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn 1581e4b9f3936d6f357e89360293e05a0e16d5fa440Dianne Hackborn /** @hide */ 159a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright public static interface FinishedInputEventCallback { 160a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright void onFinishedInputEvent(Object token, boolean handled); 16146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 162a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright 16346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 164