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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user