Merge "Add support for injecting events into ActivityContainers."
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|||||||
Reference in New Issue
Block a user