1b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan/* 2b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * Copyright (C) 2016 The Android Open Source Project 3b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * 4b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * Licensed under the Apache License, Version 2.0 (the "License"); 5b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * you may not use this file except in compliance with the License. 6b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * You may obtain a copy of the License at 7b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * 8b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * http://www.apache.org/licenses/LICENSE-2.0 9b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * 10b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * Unless required by applicable law or agreed to in writing, software 11b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * distributed under the License is distributed on an "AS IS" BASIS, 12b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * See the License for the specific language governing permissions and 14b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * limitations under the License. 15b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan */ 16b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 17b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanpackage com.android.server.tv; 18b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 19b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanimport android.os.Binder; 20b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanimport android.os.IBinder; 21b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 22b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanimport java.io.IOException; 23b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 24b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanimport dalvik.system.CloseGuard; 25b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 26b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan/** 27b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan * Sends the input event to the linux driver. 28b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan */ 29b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnanpublic final class UinputBridge { 30b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private final CloseGuard mCloseGuard = CloseGuard.get(); 31b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private long mPtr; 32b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private IBinder mToken = null; 33b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 34b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native long nativeOpen(String name, String uniqueId, int width, int height, 35b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan int maxPointers); 36b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeClose(long ptr); 37b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeClear(long ptr); 38b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeSendTimestamp(long ptr, long timestamp); 39b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeSendKey(long ptr, int keyCode, boolean down); 40b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeSendPointerDown(long ptr, int pointerId, int x, int y); 41b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeSendPointerUp(long ptr, int pointerId); 42b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan private static native void nativeSendPointerSync(long ptr); 43b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 44b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public UinputBridge(IBinder token, String name, int width, int height, int maxPointers) 45b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan throws IOException { 46b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (width < 1 || height < 1) { 47b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan throw new IllegalArgumentException("Touchpad must be at least 1x1."); 48b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 49b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (maxPointers < 1 || maxPointers > 32) { 50b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan throw new IllegalArgumentException("Touchpad must support between 1 and 32 pointers."); 51b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 52b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (token == null) { 53b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan throw new IllegalArgumentException("Token cannot be null"); 54b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 55b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mPtr = nativeOpen(name, token.toString(), width, height, maxPointers); 56b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (mPtr == 0) { 57b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan throw new IOException("Could not open uinput device " + name); 58b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 59b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mToken = token; 60b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mCloseGuard.open("close"); 61b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 62b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 63b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan @Override 64b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan protected void finalize() throws Throwable { 65b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan try { 66b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (mPtr != 0) { 67b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mCloseGuard.warnIfOpen(); 68b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 69b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan close(mToken); 70b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } finally { 71b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mToken = null; 72b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan super.finalize(); 73b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 74b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 75b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 76b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void close(IBinder token) { 77b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 78b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (mPtr != 0) { 79b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan clear(token); 80b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeClose(mPtr); 81b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 82b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mPtr = 0; 83b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan mCloseGuard.close(); 84b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 85b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 86b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 87b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 88b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public IBinder getToken() { 89b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan return mToken; 90b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 91b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 92b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan protected boolean isTokenValid(IBinder token) { 93b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan return mToken.equals(token); 94b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 95b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 96b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendTimestamp(IBinder token, long timestamp) { 97b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 98b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendTimestamp(mPtr, timestamp); 99b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 100b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 101b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 102b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendKeyDown(IBinder token, int keyCode) { 103b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 104b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendKey(mPtr, keyCode, true /*down*/); 105b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 106b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 107b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 108b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendKeyUp(IBinder token, int keyCode) { 109b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 110b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendKey(mPtr, keyCode, false /*down*/); 111b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 112b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 113b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 114b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendPointerDown(IBinder token, int pointerId, int x, int y) { 115b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 116b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendPointerDown(mPtr, pointerId, x, y); 117b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 118b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 119b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 120b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendPointerUp(IBinder token, int pointerId) { 121b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 122b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendPointerUp(mPtr, pointerId); 123b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 124b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 125b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 126b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void sendPointerSync(IBinder token) { 127b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 128b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeSendPointerSync(mPtr); 129b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 130b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 131b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 132b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 133b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan public void clear(IBinder token) { 134b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan if (isTokenValid(token)) { 135b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan nativeClear(mPtr); 136b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 137b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan } 138b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan 139b5b86c11008422ac4bf5af5fed736f04ebbaa858Sujith Ramakrishnan} 140