Merge "Add support for injecting events into ActivityContainers."

This commit is contained in:
Jeff Brown
2014-02-12 00:35:07 +00:00
committed by Android (Google) Code Review
6 changed files with 74 additions and 10 deletions

View File

@@ -27,6 +27,9 @@ import android.os.RemoteException;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
import android.view.TextureView; import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener; import android.view.TextureView.SurfaceTextureListener;
@@ -112,6 +115,29 @@ public class ActivityView extends ViewGroup {
} }
} }
private boolean injectInputEvent(InputEvent event) {
try {
return mActivityContainer != null && mActivityContainer.injectEvent(event);
} catch (RemoteException e) {
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return injectInputEvent(event) || super.onTouchEvent(event);
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
if (injectInputEvent(event)) {
return true;
}
}
return super.onGenericMotionEvent(event);
}
public boolean isAttachedToDisplay() { public boolean isAttachedToDisplay() {
return mSurface != null; return mSurface != null;
} }

View File

@@ -20,6 +20,7 @@ import android.app.IActivityContainerCallback;
import android.content.Intent; import android.content.Intent;
import android.content.IIntentSender; import android.content.IIntentSender;
import android.os.IBinder; import android.os.IBinder;
import android.view.InputEvent;
import android.view.Surface; import android.view.Surface;
/** @hide */ /** @hide */
@@ -30,4 +31,5 @@ interface IActivityContainer {
int startActivity(in Intent intent); int startActivity(in Intent intent);
int startActivityIntentSender(in IIntentSender intentSender); int startActivityIntentSender(in IIntentSender intentSender);
int getDisplayId(); int getDisplayId();
boolean injectEvent(in InputEvent event);
} }

View File

@@ -17,6 +17,7 @@
package android.hardware.input; package android.hardware.input;
import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayViewport;
import android.view.InputEvent;
/** /**
* Input manager local system service interface. * Input manager local system service interface.
@@ -30,4 +31,6 @@ public abstract class InputManagerInternal {
*/ */
public abstract void setDisplayViewports(DisplayViewport defaultViewport, public abstract void setDisplayViewports(DisplayViewport defaultViewport,
DisplayViewport externalTouchViewport); DisplayViewport externalTouchViewport);
public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
} }

View File

@@ -61,6 +61,8 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.VirtualDisplay; import android.hardware.display.VirtualDisplay;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
@@ -81,9 +83,11 @@ import android.util.SparseArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.view.Display; import android.view.Display;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import android.view.InputEvent;
import android.view.Surface; import android.view.Surface;
import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.os.TransferPipe; import com.android.internal.os.TransferPipe;
import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch; import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.am.ActivityStack.ActivityState; import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.WindowManagerService; import com.android.server.wm.WindowManagerService;
@@ -225,6 +229,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
/** Mapping from displayId to display current state */ /** Mapping from displayId to display current state */
private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>(); private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
InputManagerInternal mInputManagerInternal;
public ActivityStackSupervisor(ActivityManagerService service) { public ActivityStackSupervisor(ActivityManagerService service) {
mService = service; mService = service;
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
@@ -255,6 +261,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY); createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID); mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
} }
} }
@@ -2941,7 +2949,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
} }
@Override @Override
public void attachToDisplay(int displayId) throws RemoteException { public void attachToDisplay(int displayId) {
synchronized (mService) { synchronized (mService) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) { if (activityDisplay == null) {
@@ -2952,13 +2960,28 @@ public final class ActivityStackSupervisor implements DisplayListener {
} }
@Override @Override
public int getDisplayId() throws RemoteException { public int getDisplayId() {
if (mActivityDisplay != null) { if (mActivityDisplay != null) {
return mActivityDisplay.mDisplayId; return mActivityDisplay.mDisplayId;
} }
return -1; return -1;
} }
@Override
public boolean injectEvent(InputEvent event) {
final long origId = Binder.clearCallingIdentity();
try {
if (mActivityDisplay != null) {
return mInputManagerInternal.injectInputEvent(event,
mActivityDisplay.mDisplayId,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
return false;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
private void detachLocked() { private void detachLocked() {
if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display=" if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
+ mActivityDisplay + " Callers=" + Debug.getCallers(2)); + mActivityDisplay + " Callers=" + Debug.getCallers(2));
@@ -2972,7 +2995,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
} }
@Override @Override
public void detachFromDisplay() throws RemoteException { public void detachFromDisplay() {
synchronized (mService) { synchronized (mService) {
detachLocked(); detachLocked();
} }

View File

@@ -16,6 +16,7 @@
package com.android.server.input; package com.android.server.input;
import android.view.Display;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.util.XmlUtils; import com.android.internal.util.XmlUtils;
import com.android.server.DisplayThread; import com.android.server.DisplayThread;
@@ -170,7 +171,7 @@ public class InputManagerService extends IInputManager.Stub
InputWindowHandle inputWindowHandle, boolean monitor); InputWindowHandle inputWindowHandle, boolean monitor);
private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel); private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable); private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
private static native int nativeInjectInputEvent(long ptr, InputEvent event, private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags); int policyFlags);
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles); private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
@@ -509,6 +510,10 @@ public class InputManagerService extends IInputManager.Stub
@Override // Binder call @Override // Binder call
public boolean injectInputEvent(InputEvent event, int mode) { public boolean injectInputEvent(InputEvent event, int mode) {
return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
}
private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
if (event == null) { if (event == null) {
throw new IllegalArgumentException("event must not be null"); throw new IllegalArgumentException("event must not be null");
} }
@@ -523,7 +528,7 @@ public class InputManagerService extends IInputManager.Stub
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
final int result; final int result;
try { try {
result = nativeInjectInputEvent(mPtr, event, pid, uid, mode, result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -1588,7 +1593,7 @@ public class InputManagerService extends IInputManager.Stub
synchronized (mInputFilterLock) { synchronized (mInputFilterLock) {
if (!mDisconnected) { if (!mDisconnected) {
nativeInjectInputEvent(mPtr, event, 0, 0, nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
policyFlags | WindowManagerPolicy.FLAG_FILTERED); policyFlags | WindowManagerPolicy.FLAG_FILTERED);
} }
@@ -1685,5 +1690,10 @@ public class InputManagerService extends IInputManager.Stub
DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) { DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
setDisplayViewportsInternal(defaultViewport, externalTouchViewport); setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
} }
@Override
public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
return injectInputEventInternal(event, displayId, mode);
}
} }
} }

View File

@@ -1153,7 +1153,7 @@ static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
} }
static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
jlong ptr, jobject inputEventObj, jint injectorPid, jint injectorUid, jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
jint syncMode, jint timeoutMillis, jint policyFlags) { jint syncMode, jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1166,7 +1166,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
} }
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
& keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis, & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
uint32_t(policyFlags)); uint32_t(policyFlags));
} else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj); const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
@@ -1176,7 +1176,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
} }
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis, motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
uint32_t(policyFlags)); uint32_t(policyFlags));
} else { } else {
jniThrowRuntimeException(env, "Invalid input event type."); jniThrowRuntimeException(env, "Invalid input event type.");
@@ -1336,7 +1336,7 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) nativeUnregisterInputChannel }, (void*) nativeUnregisterInputChannel },
{ "nativeSetInputFilterEnabled", "(JZ)V", { "nativeSetInputFilterEnabled", "(JZ)V",
(void*) nativeSetInputFilterEnabled }, (void*) nativeSetInputFilterEnabled },
{ "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIII)I", { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
(void*) nativeInjectInputEvent }, (void*) nativeInjectInputEvent },
{ "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
(void*) nativeSetInputWindows }, (void*) nativeSetInputWindows },