diff options
-rw-r--r-- | core/java/android/os/Looper.java | 5 | ||||
-rw-r--r-- | core/java/android/view/IWindowManager.aidl | 2 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 5 | ||||
-rw-r--r-- | include/utils/String8.h | 3 | ||||
-rwxr-xr-x | policy/src/com/android/internal/policy/impl/PhoneWindowManager.java | 49 | ||||
-rw-r--r-- | services/java/com/android/server/InputManager.java | 29 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 10 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 78 |
8 files changed, 150 insertions, 31 deletions
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index 69b3540..a9d7342 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -180,6 +180,11 @@ public class Looper { return mThread; } + /** @hide */ + public MessageQueue getQueue() { + return mQueue; + } + public void dump(Printer pw, String prefix) { pw.println(prefix + this); pw.println(prefix + "mRun=" + mRun); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index d6b9212..e86e3bf 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -28,6 +28,7 @@ import android.view.IWindowSession; import android.view.KeyEvent; import android.view.InputEvent; import android.view.MotionEvent; +import android.view.InputChannel; /** * System private interface to the window manager. @@ -119,6 +120,7 @@ interface IWindowManager int getKeycodeStateForDevice(int devid, int sw); int getTrackballKeycodeState(int sw); int getDPadKeycodeState(int sw); + InputChannel monitorInput(String inputChannelName); // Report whether the hardware supports the given keys; returns true if successful boolean hasKeys(in int[] keycodes, inout boolean[] keyExists); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 33757f0..659f9cd 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -779,11 +779,6 @@ public interface WindowManagerPolicy { */ public void enableScreenAfterBoot(); - /** - * Called every time the window manager is dispatching a pointer event. - */ - public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY); - public void setCurrentOrientationLw(int newOrientation); /** diff --git a/include/utils/String8.h b/include/utils/String8.h index 4e41410..ef0b51a 100644 --- a/include/utils/String8.h +++ b/include/utils/String8.h @@ -171,7 +171,8 @@ public: status_t append(const char* other); status_t append(const char* other, size_t numChars); - status_t appendFormat(const char* fmt, ...); + status_t appendFormat(const char* fmt, ...) + __attribute__((format (printf, 2, 3))); // Note that this function takes O(N) time to calculate the value. // No cache value is stored. diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 83d9c47..e2e6f1a 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -37,6 +37,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.os.LocalPowerManager; +import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -48,15 +49,20 @@ import android.provider.Settings; import com.android.internal.policy.PolicyManager; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.telephony.ITelephony; +import com.android.internal.view.BaseInputHandler; import com.android.internal.widget.PointerLocationView; import android.util.Config; import android.util.EventLog; import android.util.Log; +import android.util.Slog; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.IWindowManager; +import android.view.InputChannel; +import android.view.InputQueue; +import android.view.InputHandler; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.WindowOrientationListener; @@ -220,6 +226,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mPointerLocationMode = 0; PointerLocationView mPointerLocationView = null; + InputChannel mPointerLocationInputChannel; + + private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() { + @Override + public void handleMotion(MotionEvent event, Runnable finishedCallback) { + finishedCallback.run(); + synchronized (mLock) { + mPointerLocationView.addTouchEvent(event); + } + } + }; // The current size of the screen. int mW, mH; @@ -613,8 +630,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE); wm.addView(addView, lp); + + if (mPointerLocationInputChannel == null) { + try { + mPointerLocationInputChannel = + mWindowManager.monitorInput("PointerLocationView"); + InputQueue.registerInputChannel(mPointerLocationInputChannel, + mPointerLocationInputHandler, mHandler.getLooper().getQueue()); + } catch (RemoteException ex) { + Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.", + ex); + } + } } if (removeView != null) { + if (mPointerLocationInputChannel != null) { + InputQueue.unregisterInputChannel(mPointerLocationInputChannel); + mPointerLocationInputChannel.dispose(); + mPointerLocationInputChannel = null; + } + WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE); wm.removeView(removeView); @@ -728,20 +763,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { : Configuration.KEYBOARDHIDDEN_YES; } - public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY) { - if (mPointerLocationView == null) { - return; - } - synchronized (mLock) { - if (mPointerLocationView == null) { - return; - } - ev.offsetLocation(targetX, targetY); - mPointerLocationView.addTouchEvent(ev); - ev.offsetLocation(-targetX, -targetY); - } - } - /** {@inheritDoc} */ public int windowTypeToLayerLw(int type) { if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index 9195123..c2c799b 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -75,7 +75,8 @@ public class InputManager { int sw); private static native boolean nativeHasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists); - private static native void nativeRegisterInputChannel(InputChannel inputChannel); + private static native void nativeRegisterInputChannel(InputChannel inputChannel, + boolean monitor); private static native void nativeUnregisterInputChannel(InputChannel inputChannel); private static native int nativeInjectInputEvent(InputEvent event, int injectorPid, int injectorUid, int syncMode, int timeoutMillis); @@ -225,14 +226,38 @@ public class InputManager { return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists); } + /** + * Creates an input channel that will receive all input from the input dispatcher. + * @param inputChannelName The input channel name. + * @return The input channel. + */ + public InputChannel monitorInput(String inputChannelName) { + if (inputChannelName == null) { + throw new IllegalArgumentException("inputChannelName must not be null."); + } + + InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName); + nativeRegisterInputChannel(inputChannels[0], true); + inputChannels[0].dispose(); // don't need to retain the Java object reference + return inputChannels[1]; + } + + /** + * Registers an input channel so that it can be used as an input event target. + * @param inputChannel The input channel to register. + */ public void registerInputChannel(InputChannel inputChannel) { if (inputChannel == null) { throw new IllegalArgumentException("inputChannel must not be null."); } - nativeRegisterInputChannel(inputChannel); + nativeRegisterInputChannel(inputChannel, false); } + /** + * Unregisters an input channel. + * @param inputChannel The input channel to unregister. + */ public void unregisterInputChannel(InputChannel inputChannel) { if (inputChannel == null) { throw new IllegalArgumentException("inputChannel must not be null."); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 0def5f2..11fcca8 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -4382,11 +4382,19 @@ public class WindowManagerService extends IWindowManager.Stub } return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw); } - + public boolean hasKeys(int[] keycodes, boolean[] keyExists) { return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists); } + public InputChannel monitorInput(String inputChannelName) { + if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, + "monitorInput()")) { + throw new SecurityException("Requires READ_INPUT_STATE permission"); + } + return mInputManager.monitorInput(inputChannelName); + } + public void enableScreenAfterBoot() { synchronized(mWindowMap) { if (mSystemBooted) { diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 0982b32..ebe71ab 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -213,7 +213,7 @@ public: void setDisplayOrientation(int32_t displayId, int32_t orientation); status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, - jweak inputChannelObjWeak); + jweak inputChannelObjWeak, bool monitor); status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel); void setInputWindows(JNIEnv* env, jobjectArray windowObjArray); @@ -334,6 +334,7 @@ private: bool mWindowsReady; Vector<InputWindow> mWindows; Vector<InputWindow*> mWallpaperWindows; + Vector<sp<InputChannel> > mMonitoringChannels; // Focus tracking for keys, trackball, etc. InputWindow* mFocusedWindow; @@ -382,6 +383,10 @@ private: static void addTarget(const InputWindow* window, int32_t targetFlags, nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets); + void registerMonitoringChannel(const sp<InputChannel>& inputChannel); + void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel); + void addMonitoringTargetsLd(Vector<InputTarget>& outTargets); + static inline JNIEnv* jniEnv() { return AndroidRuntime::getJNIEnv(); } @@ -492,7 +497,7 @@ void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orient } status_t NativeInputManager::registerInputChannel(JNIEnv* env, - const sp<InputChannel>& inputChannel, jobject inputChannelObj) { + const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) { jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj); if (! inputChannelObjWeak) { LOGE("Could not create weak reference for input channel."); @@ -519,9 +524,14 @@ status_t NativeInputManager::registerInputChannel(JNIEnv* env, status = mInputManager->registerInputChannel(inputChannel); if (! status) { + // Success. + if (monitor) { + registerMonitoringChannel(inputChannel); + } return OK; } + // Failed! { AutoMutex _l(mInputChannelRegistryLock); mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd()); @@ -552,6 +562,8 @@ status_t NativeInputManager::unregisterInputChannel(JNIEnv* env, env->DeleteWeakGlobalRef(inputChannelObjWeak); + unregisterMonitoringChannel(inputChannel); + return mInputManager->unregisterInputChannel(inputChannel); } @@ -829,6 +841,8 @@ void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputC env->DeleteLocalRef(inputChannelObjLocal); } + + unregisterMonitoringChannel(inputChannel); } bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel, @@ -1429,7 +1443,9 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin // If there is no currently touched window then fail. if (! mTouchedWindow) { - LOGW("Dropping event because there is no touched window to receive it."); +#if DEBUG_INPUT_DISPATCHER_POLICY + LOGD("Dropping event because there is no touched window to receive it."); +#endif injectionResult = INPUT_EVENT_INJECTION_FAILED; injectionPermission = INJECTION_PERMISSION_GRANTED; break; // failed, exit wait loop @@ -1587,6 +1603,8 @@ int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t outTargets.clear(); return INPUT_EVENT_INJECTION_SUCCEEDED; } + + addMonitoringTargetsLd(outTargets); } pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT); @@ -1631,6 +1649,8 @@ int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent } windowType = focusedWindow->layoutParamsType; + + addMonitoringTargetsLd(outTargets); } // release lock pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT); @@ -1657,6 +1677,8 @@ int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent, } windowType = touchedWindow->layoutParamsType; + + addMonitoringTargetsLd(outTargets); } // release lock int32_t eventType; @@ -1714,6 +1736,39 @@ void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) android_server_PowerManagerService_userActivity(eventTime, eventType); } +void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) { + { // acquire lock + AutoMutex _l(mDispatchLock); + mMonitoringChannels.push(inputChannel); + } // release lock +} + +void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) { + { // acquire lock + AutoMutex _l(mDispatchLock); + + for (size_t i = 0; i < mMonitoringChannels.size(); i++) { + if (mMonitoringChannels[i] == inputChannel) { + mMonitoringChannels.removeAt(i); + break; + } + } + } // release lock +} + +void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) { + for (size_t i = 0; i < mMonitoringChannels.size(); i++) { + outTargets.push(); + + InputTarget& target = outTargets.editTop(); + target.inputChannel = mMonitoringChannels[i]; + target.flags = 0; + target.timeout = -1; + target.xOffset = 0; + target.yOffset = 0; + } +} + static void dumpMotionRange(String8& dump, const char* name, const InputDeviceInfo::MotionRange* range) { if (range) { @@ -1805,6 +1860,11 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) { mWindows[i].ownerPid, mWindows[i].ownerUid, mWindows[i].dispatchingTimeout / 1000000.0); } + + for (size_t i = 0; i < mMonitoringChannels.size(); i++) { + dump.appendFormat(" monitoringChannel[%d]: '%s'\n", + i, mMonitoringChannels[i]->getName().string()); + } } // ---------------------------------------------------------------------------- @@ -2012,7 +2072,7 @@ static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env, } static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz, - jobject inputChannelObj) { + jobject inputChannelObj, jboolean monitor) { if (checkInputManagerUnitialized(env)) { return; } @@ -2026,15 +2086,17 @@ static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, status_t status = gNativeInputManager->registerInputChannel( - env, inputChannel, inputChannelObj); + env, inputChannel, inputChannelObj, monitor); if (status) { jniThrowRuntimeException(env, "Failed to register input channel. " "Check logs for details."); return; } - android_view_InputChannel_setDisposeCallback(env, inputChannelObj, - android_server_InputManager_handleInputChannelDisposed, NULL); + if (! monitor) { + android_view_InputChannel_setDisposeCallback(env, inputChannelObj, + android_server_InputManager_handleInputChannelDisposed, NULL); + } } static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz, @@ -2149,7 +2211,7 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) android_server_InputManager_nativeGetSwitchState }, { "nativeHasKeys", "(II[I[Z)Z", (void*) android_server_InputManager_nativeHasKeys }, - { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V", + { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V", (void*) android_server_InputManager_nativeRegisterInputChannel }, { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V", (void*) android_server_InputManager_nativeUnregisterInputChannel }, |