InputEventSender.java revision c28867a1d67121ce5963de135e3ae2b1dbd9a33d
1/* 2 * Copyright (C) 2013 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 19import dalvik.system.CloseGuard; 20 21import android.os.Looper; 22import android.os.MessageQueue; 23import android.util.Log; 24 25/** 26 * Provides a low-level mechanism for an application to send input events. 27 * @hide 28 */ 29public abstract class InputEventSender { 30 private static final String TAG = "InputEventSender"; 31 32 private final CloseGuard mCloseGuard = CloseGuard.get(); 33 34 private int mSenderPtr; 35 36 // We keep references to the input channel and message queue objects here so that 37 // they are not GC'd while the native peer of the receiver is using them. 38 private InputChannel mInputChannel; 39 private MessageQueue mMessageQueue; 40 41 private static native int nativeInit(InputEventSender sender, 42 InputChannel inputChannel, MessageQueue messageQueue); 43 private static native void nativeDispose(int senderPtr); 44 private static native boolean nativeSendKeyEvent(int senderPtr, int seq, KeyEvent event); 45 private static native boolean nativeSendMotionEvent(int senderPtr, int seq, MotionEvent event); 46 47 /** 48 * Creates an input event sender bound to the specified input channel. 49 * 50 * @param inputChannel The input channel. 51 * @param looper The looper to use when invoking callbacks. 52 */ 53 public InputEventSender(InputChannel inputChannel, Looper looper) { 54 if (inputChannel == null) { 55 throw new IllegalArgumentException("inputChannel must not be null"); 56 } 57 if (looper == null) { 58 throw new IllegalArgumentException("looper must not be null"); 59 } 60 61 mInputChannel = inputChannel; 62 mMessageQueue = looper.getQueue(); 63 mSenderPtr = nativeInit(this, inputChannel, mMessageQueue); 64 65 mCloseGuard.open("dispose"); 66 } 67 68 @Override 69 protected void finalize() throws Throwable { 70 try { 71 dispose(true); 72 } finally { 73 super.finalize(); 74 } 75 } 76 77 /** 78 * Disposes the receiver. 79 */ 80 public void dispose() { 81 dispose(false); 82 } 83 84 private void dispose(boolean finalized) { 85 if (mCloseGuard != null) { 86 if (finalized) { 87 mCloseGuard.warnIfOpen(); 88 } 89 mCloseGuard.close(); 90 } 91 92 if (mSenderPtr != 0) { 93 nativeDispose(mSenderPtr); 94 mSenderPtr = 0; 95 } 96 mInputChannel = null; 97 mMessageQueue = null; 98 } 99 100 /** 101 * Called when an input event is finished. 102 * 103 * @param seq The input event sequence number. 104 * @param handled True if the input event was handled. 105 */ 106 public void onInputEventFinished(int seq, boolean handled) { 107 } 108 109 /** 110 * Sends an input event. 111 * Must be called on the same Looper thread to which the sender is attached. 112 * 113 * @param seq The input event sequence number. 114 * @param event The input event to send. 115 * @return True if the entire event was sent successfully. May return false 116 * if the input channel buffer filled before all samples were dispatched. 117 */ 118 public final boolean sendInputEvent(int seq, InputEvent event) { 119 if (event == null) { 120 throw new IllegalArgumentException("event must not be null"); 121 } 122 if (mSenderPtr == 0) { 123 Log.w(TAG, "Attempted to send an input event but the input event " 124 + "sender has already been disposed."); 125 return false; 126 } 127 128 if (event instanceof KeyEvent) { 129 return nativeSendKeyEvent(mSenderPtr, seq, (KeyEvent)event); 130 } else { 131 return nativeSendMotionEvent(mSenderPtr, seq, (MotionEvent)event); 132 } 133 } 134 135 // Called from native code. 136 @SuppressWarnings("unused") 137 private void dispatchInputEventFinished(int seq, boolean handled) { 138 onInputEventFinished(seq, handled); 139 } 140} 141