am 95af0c14: Merge "Add support for the PointerLocation overlay." into gingerbread

Merge commit '95af0c14a64ef264d2b362ded4ca2b5a169d1066' into gingerbread-plus-aosp

* commit '95af0c14a64ef264d2b362ded4ca2b5a169d1066':
  Add support for the PointerLocation overlay.
This commit is contained in:
Jeff Brown
2010-08-11 16:18:36 -07:00
committed by Android Git Automerger
8 changed files with 150 additions and 31 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
/**

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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.");

View File

@@ -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) {

View File

@@ -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 },