1c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown/* 2c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Copyright (C) 2013 The Android Open Source Project 3c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 4c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * you may not use this file except in compliance with the License. 6c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * You may obtain a copy of the License at 7c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 8c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 10c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Unless required by applicable law or agreed to in writing, software 11c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * See the License for the specific language governing permissions and 14c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * limitations under the License. 15c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 16c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 17c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownpackage android.view; 18c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 19c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport dalvik.system.CloseGuard; 20c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 21c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.os.Looper; 22c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.os.MessageQueue; 23c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.util.Log; 24c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 25a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brownimport java.lang.ref.WeakReference; 26a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown 27c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown/** 28c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Provides a low-level mechanism for an application to send input events. 29c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @hide 30c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 31c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownpublic abstract class InputEventSender { 32c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private static final String TAG = "InputEventSender"; 33c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 34c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private final CloseGuard mCloseGuard = CloseGuard.get(); 35c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 36a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat private long mSenderPtr; 37c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 38c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown // We keep references to the input channel and message queue objects here so that 39c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown // they are not GC'd while the native peer of the receiver is using them. 40c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private InputChannel mInputChannel; 41c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private MessageQueue mMessageQueue; 42c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 43a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat private static native long nativeInit(WeakReference<InputEventSender> sender, 44c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown InputChannel inputChannel, MessageQueue messageQueue); 45a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat private static native void nativeDispose(long senderPtr); 46a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat private static native boolean nativeSendKeyEvent(long senderPtr, int seq, KeyEvent event); 47a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat private static native boolean nativeSendMotionEvent(long senderPtr, int seq, MotionEvent event); 48c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 49c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown /** 50c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Creates an input event sender bound to the specified input channel. 51c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 52c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param inputChannel The input channel. 53c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param looper The looper to use when invoking callbacks. 54c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 55c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown public InputEventSender(InputChannel inputChannel, Looper looper) { 56c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (inputChannel == null) { 57c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown throw new IllegalArgumentException("inputChannel must not be null"); 58c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 59c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (looper == null) { 60c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown throw new IllegalArgumentException("looper must not be null"); 61c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 62c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 63c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mInputChannel = inputChannel; 64c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mMessageQueue = looper.getQueue(); 65a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown mSenderPtr = nativeInit(new WeakReference<InputEventSender>(this), 66a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown inputChannel, mMessageQueue); 67c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 68c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mCloseGuard.open("dispose"); 69c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 70c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 71c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown @Override 72c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown protected void finalize() throws Throwable { 73c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown try { 74c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown dispose(true); 75c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } finally { 76c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown super.finalize(); 77c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 78c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 79c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 80c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown /** 81c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Disposes the receiver. 82c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 83c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown public void dispose() { 84c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown dispose(false); 85c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 86c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 87c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private void dispose(boolean finalized) { 88c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (mCloseGuard != null) { 89c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (finalized) { 90c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mCloseGuard.warnIfOpen(); 91c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 92c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mCloseGuard.close(); 93c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 94c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 95c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (mSenderPtr != 0) { 96c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown nativeDispose(mSenderPtr); 97c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mSenderPtr = 0; 98c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 99c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mInputChannel = null; 100c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown mMessageQueue = null; 101c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 102c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 103c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown /** 104c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Called when an input event is finished. 105c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 106c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param seq The input event sequence number. 107c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param handled True if the input event was handled. 108c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 109c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown public void onInputEventFinished(int seq, boolean handled) { 110c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 111c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 112c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown /** 113c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Sends an input event. 114c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Must be called on the same Looper thread to which the sender is attached. 115c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * 116c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param seq The input event sequence number. 117c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @param event The input event to send. 118c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * @return True if the entire event was sent successfully. May return false 119c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * if the input channel buffer filled before all samples were dispatched. 120c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */ 121c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown public final boolean sendInputEvent(int seq, InputEvent event) { 122c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (event == null) { 123c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown throw new IllegalArgumentException("event must not be null"); 124c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 125c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (mSenderPtr == 0) { 126c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown Log.w(TAG, "Attempted to send an input event but the input event " 127c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown + "sender has already been disposed."); 128c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown return false; 129c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 130c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 131c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown if (event instanceof KeyEvent) { 132c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown return nativeSendKeyEvent(mSenderPtr, seq, (KeyEvent)event); 133c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } else { 134c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown return nativeSendMotionEvent(mSenderPtr, seq, (MotionEvent)event); 135c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 136c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 137c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown 138c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown // Called from native code. 139c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown @SuppressWarnings("unused") 140c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown private void dispatchInputEventFinished(int seq, boolean handled) { 141c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown onInputEventFinished(seq, handled); 142c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown } 143c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown} 144