am 85a31767: Add support for secure views.

Merge commit '85a3176704b5bfbeece9bd928369fbb76eec7dc6' into gingerbread-plus-aosp

* commit '85a3176704b5bfbeece9bd928369fbb76eec7dc6':
  Add support for secure views.
This commit is contained in:
Jeff Brown
2010-09-08 11:55:24 -07:00
committed by Android Git Automerger
21 changed files with 467 additions and 73 deletions

View File

@ -5861,17 +5861,6 @@
visibility="public" visibility="public"
> >
</field> </field>
<field name="kraken_resource_pad61"
type="int"
transient="false"
volatile="false"
value="16843460"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="kraken_resource_pad7" <field name="kraken_resource_pad7"
type="int" type="int"
transient="false" transient="false"
@ -8248,6 +8237,17 @@
visibility="public" visibility="public"
> >
</field> </field>
<field name="securityMode"
type="int"
transient="false"
volatile="false"
value="16843460"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="seekBarStyle" <field name="seekBarStyle"
type="int" type="int"
transient="false" transient="false"
@ -181733,6 +181733,17 @@
visibility="public" visibility="public"
> >
</method> </method>
<method name="getFlags"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="true"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getHistoricalEventTime" <method name="getHistoricalEventTime"
return="long" return="long"
abstract="false" abstract="false"
@ -182370,6 +182381,8 @@
</parameter> </parameter>
<parameter name="source" type="int"> <parameter name="source" type="int">
</parameter> </parameter>
<parameter name="flags" type="int">
</parameter>
</method> </method>
<method name="obtain" <method name="obtain"
return="android.view.MotionEvent" return="android.view.MotionEvent"
@ -182826,6 +182839,17 @@
visibility="public" visibility="public"
> >
</field> </field>
<field name="FLAG_WINDOW_MAY_BE_OBSCURED"
type="int"
transient="false"
volatile="false"
value="1"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
</class> </class>
<class name="MotionEvent.PointerCoords" <class name="MotionEvent.PointerCoords"
extends="java.lang.Object" extends="java.lang.Object"
@ -186006,6 +186030,17 @@
visibility="public" visibility="public"
> >
</method> </method>
<method name="getSecurityMode"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getSolidColor" <method name="getSolidColor"
return="int" return="int"
abstract="false" abstract="false"
@ -186836,6 +186871,19 @@
<parameter name="canvas" type="android.graphics.Canvas"> <parameter name="canvas" type="android.graphics.Canvas">
</parameter> </parameter>
</method> </method>
<method name="onFilterTouchEventForSecurity"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="event" type="android.view.MotionEvent">
</parameter>
</method>
<method name="onFinishInflate" <method name="onFinishInflate"
return="void" return="void"
abstract="false" abstract="false"
@ -188127,6 +188175,19 @@
<parameter name="fadeScrollbars" type="boolean"> <parameter name="fadeScrollbars" type="boolean">
</parameter> </parameter>
</method> </method>
<method name="setSecurityMode"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="securityMode" type="int">
</parameter>
</method>
<method name="setSelected" <method name="setSelected"
return="void" return="void"
abstract="false" abstract="false"
@ -188907,6 +188968,28 @@
visibility="public" visibility="public"
> >
</field> </field>
<field name="SECURITY_MODE_FILTER_TOUCHES_WHEN_OBSCURED"
type="int"
transient="false"
volatile="false"
value="1"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SECURITY_MODE_NORMAL"
type="int"
transient="false"
volatile="false"
value="0"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="SELECTED_STATE_SET" <field name="SELECTED_STATE_SET"
type="int[]" type="int[]"
transient="false" transient="false"

View File

@ -30,6 +30,7 @@ import android.os.SystemClock;
*/ */
public final class MotionEvent extends InputEvent implements Parcelable { public final class MotionEvent extends InputEvent implements Parcelable {
private static final long MS_PER_NS = 1000000; private static final long MS_PER_NS = 1000000;
private static final boolean TRACK_RECYCLED_LOCATION = false;
/** /**
* Bit mask of the parts of the action code that are the action itself. * Bit mask of the parts of the action code that are the action itself.
@ -155,7 +156,17 @@ public final class MotionEvent extends InputEvent implements Parcelable {
@Deprecated @Deprecated
public static final int ACTION_POINTER_ID_SHIFT = 8; public static final int ACTION_POINTER_ID_SHIFT = 8;
private static final boolean TRACK_RECYCLED_LOCATION = false; /**
* This flag indicates that the window that received this motion event is partly
* or wholly obscured by another visible window above it. This flag is set to true
* even if the event did not directly pass through the obscured area.
* A security sensitive application can check this flag to identify situations in which
* a malicious application may have covered up part of its content for the purpose
* of misleading the user or hijacking touches. An appropriate response might be
* to drop the suspect touches or to take additional precautions to confirm the user's
* actual intent.
*/
public static final int FLAG_WINDOW_IS_OBSCURED = 0x1;
/** /**
* Flag indicating the motion event intersected the top edge of the screen. * Flag indicating the motion event intersected the top edge of the screen.
@ -251,6 +262,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
private float mYPrecision; private float mYPrecision;
private int mEdgeFlags; private int mEdgeFlags;
private int mMetaState; private int mMetaState;
private int mFlags;
private int mNumPointers; private int mNumPointers;
private int mNumSamples; private int mNumSamples;
@ -338,20 +350,22 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param deviceId The id for the device that this event came from. An id of * @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other * zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values. * numbers are arbitrary and you shouldn't depend on the values.
* @param edgeFlags A bitfield indicating which edges, if any, where touched by this * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent. * MotionEvent.
* @param source The source of this event. * @param source The source of this event.
* @param flags The motion event flags.
*/ */
static public MotionEvent obtain(long downTime, long eventTime, static public MotionEvent obtain(long downTime, long eventTime,
int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords, int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
int metaState, float xPrecision, float yPrecision, int deviceId, int metaState, float xPrecision, float yPrecision, int deviceId,
int edgeFlags, int source) { int edgeFlags, int source, int flags) {
MotionEvent ev = obtain(pointers, 1); MotionEvent ev = obtain(pointers, 1);
ev.mDeviceId = deviceId; ev.mDeviceId = deviceId;
ev.mSource = source; ev.mSource = source;
ev.mEdgeFlags = edgeFlags; ev.mEdgeFlags = edgeFlags;
ev.mDownTimeNano = downTime * MS_PER_NS; ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action; ev.mAction = action;
ev.mFlags = flags;
ev.mMetaState = metaState; ev.mMetaState = metaState;
ev.mXOffset = 0; ev.mXOffset = 0;
ev.mYOffset = 0; ev.mYOffset = 0;
@ -401,7 +415,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param deviceId The id for the device that this event came from. An id of * @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other * zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values. * numbers are arbitrary and you shouldn't depend on the values.
* @param edgeFlags A bitfield indicating which edges, if any, where touched by this * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent. * MotionEvent.
*/ */
static public MotionEvent obtain(long downTime, long eventTime, int action, static public MotionEvent obtain(long downTime, long eventTime, int action,
@ -413,6 +427,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
ev.mEdgeFlags = edgeFlags; ev.mEdgeFlags = edgeFlags;
ev.mDownTimeNano = downTime * MS_PER_NS; ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action; ev.mAction = action;
ev.mFlags = 0;
ev.mMetaState = metaState; ev.mMetaState = metaState;
ev.mXOffset = 0; ev.mXOffset = 0;
ev.mYOffset = 0; ev.mYOffset = 0;
@ -462,7 +477,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @param deviceId The id for the device that this event came from. An id of * @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other * zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values. * numbers are arbitrary and you shouldn't depend on the values.
* @param edgeFlags A bitfield indicating which edges, if any, where touched by this * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent. * MotionEvent.
* *
* @deprecated Use {@link #obtain(long, long, int, float, float, float, float, int, float, float, int, int)} * @deprecated Use {@link #obtain(long, long, int, float, float, float, float, int, float, float, int, int)}
@ -509,6 +524,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
ev.mEdgeFlags = o.mEdgeFlags; ev.mEdgeFlags = o.mEdgeFlags;
ev.mDownTimeNano = o.mDownTimeNano; ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction; ev.mAction = o.mAction;
ev.mFlags = o.mFlags;
ev.mMetaState = o.mMetaState; ev.mMetaState = o.mMetaState;
ev.mXOffset = o.mXOffset; ev.mXOffset = o.mXOffset;
ev.mYOffset = o.mYOffset; ev.mYOffset = o.mYOffset;
@ -540,6 +556,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
ev.mEdgeFlags = o.mEdgeFlags; ev.mEdgeFlags = o.mEdgeFlags;
ev.mDownTimeNano = o.mDownTimeNano; ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction; ev.mAction = o.mAction;
o.mFlags = o.mFlags;
ev.mMetaState = o.mMetaState; ev.mMetaState = o.mMetaState;
ev.mXOffset = o.mXOffset; ev.mXOffset = o.mXOffset;
ev.mYOffset = o.mYOffset; ev.mYOffset = o.mYOffset;
@ -650,6 +667,15 @@ public final class MotionEvent extends InputEvent implements Parcelable {
return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT; return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
} }
/**
* Gets the motion event flags.
*
* @see #FLAG_WINDOW_IS_OBSCURED
*/
public final int getFlags() {
return mFlags;
}
/** /**
* Returns the time (in ms) when the user originally pressed down to start * Returns the time (in ms) when the user originally pressed down to start
* a stream of position events. * a stream of position events.
@ -1285,7 +1311,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/** /**
* Sets the bitfield indicating which edges, if any, where touched by this * Sets the bitfield indicating which edges, if any, were touched by this
* MotionEvent. * MotionEvent.
* *
* @see #getEdgeFlags() * @see #getEdgeFlags()
@ -1480,6 +1506,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
ev.mYPrecision = in.readFloat(); ev.mYPrecision = in.readFloat();
ev.mEdgeFlags = in.readInt(); ev.mEdgeFlags = in.readInt();
ev.mMetaState = in.readInt(); ev.mMetaState = in.readInt();
ev.mFlags = in.readInt();
final int[] pointerIdentifiers = ev.mPointerIdentifiers; final int[] pointerIdentifiers = ev.mPointerIdentifiers;
for (int i = 0; i < NP; i++) { for (int i = 0; i < NP; i++) {
@ -1521,6 +1548,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
out.writeFloat(mYPrecision); out.writeFloat(mYPrecision);
out.writeInt(mEdgeFlags); out.writeInt(mEdgeFlags);
out.writeInt(mMetaState); out.writeInt(mMetaState);
out.writeInt(mFlags);
final int[] pointerIdentifiers = mPointerIdentifiers; final int[] pointerIdentifiers = mPointerIdentifiers;
for (int i = 0; i < NP; i++) { for (int i = 0; i < NP; i++) {

View File

@ -542,6 +542,28 @@ import java.util.WeakHashMap;
* take care of redrawing the appropriate views until the animation completes. * take care of redrawing the appropriate views until the animation completes.
* </p> * </p>
* *
* <a name="Security"></a>
* <h3>Security</h3>
* <p>
* Sometimes it is essential that an application be able to verify that an action
* is being performed with the full knowledge and consent of the user, such as
* granting a permission request, making a purchase or clicking on an advertisement.
* Unfortunately, a malicious application could try to spoof the user into
* performing these actions, unaware, by concealing the intended purpose of the view.
* As a remedy, the framework offers a touch filtering mechanism that can be used to
* improve the security of views that provide access to sensitive functionality.
* </p><p>
* To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
* andoird:filterTouchesWhenObscured attribute to true. When enabled, the framework
* will discard touches that are received whenever the view's window is obscured by
* another visible window. As a result, the view will not receive touches whenever a
* toast, dialog or other window appears above the view's window.
* </p><p>
* For more fine-grained control over security, consider overriding the
* {@link #onFilterTouchEventForSecurity} method to implement your own security policy.
* See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
* </p>
*
* @attr ref android.R.styleable#View_background * @attr ref android.R.styleable#View_background
* @attr ref android.R.styleable#View_clickable * @attr ref android.R.styleable#View_clickable
* @attr ref android.R.styleable#View_contentDescription * @attr ref android.R.styleable#View_contentDescription
@ -550,6 +572,7 @@ import java.util.WeakHashMap;
* @attr ref android.R.styleable#View_id * @attr ref android.R.styleable#View_id
* @attr ref android.R.styleable#View_fadingEdge * @attr ref android.R.styleable#View_fadingEdge
* @attr ref android.R.styleable#View_fadingEdgeLength * @attr ref android.R.styleable#View_fadingEdgeLength
* @attr ref android.R.styleable#View_filterTouchesWhenObscured
* @attr ref android.R.styleable#View_fitsSystemWindows * @attr ref android.R.styleable#View_fitsSystemWindows
* @attr ref android.R.styleable#View_isScrollContainer * @attr ref android.R.styleable#View_isScrollContainer
* @attr ref android.R.styleable#View_focusable * @attr ref android.R.styleable#View_focusable
@ -711,7 +734,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/ */
static final int SCROLLBARS_MASK = 0x00000300; static final int SCROLLBARS_MASK = 0x00000300;
// note 0x00000400 and 0x00000800 are now available for next flags... /**
* Indicates that the view should filter touches when its window is obscured.
* Refer to the class comments for more information about this security feature.
* {@hide}
*/
static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
// note flag value 0x00000800 is now available for next flags...
/** /**
* <p>This view doesn't show fading edges.</p> * <p>This view doesn't show fading edges.</p>
@ -2052,6 +2082,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
viewFlagMasks |= KEEP_SCREEN_ON; viewFlagMasks |= KEEP_SCREEN_ON;
} }
break; break;
case R.styleable.View_filterTouchesWhenObscured:
if (a.getBoolean(attr, false)) {
viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
}
break;
case R.styleable.View_nextFocusLeft: case R.styleable.View_nextFocusLeft:
mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
break; break;
@ -3389,6 +3425,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
} }
/**
* Gets whether the framework should discard touches when the view's
* window is obscured by another visible window.
* Refer to the {@link View} security documentation for more details.
*
* @return True if touch filtering is enabled.
*
* @see #setFilterTouchesWhenObscured(boolean)
* @attr ref android.R.styleable#View_filterTouchesWhenObscured
*/
@ViewDebug.ExportedProperty
public boolean getFilterTouchesWhenObscured() {
return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
}
/**
* Sets whether the framework should discard touches when the view's
* window is obscured by another visible window.
* Refer to the {@link View} security documentation for more details.
*
* @param enabled True if touch filtering should be enabled.
*
* @see #getFilterTouchesWhenObscured
* @attr ref android.R.styleable#View_filterTouchesWhenObscured
*/
public void setFilterTouchesWhenObscured(boolean enabled) {
setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
FILTER_TOUCHES_WHEN_OBSCURED);
}
/** /**
* Returns whether this View is able to take focus. * Returns whether this View is able to take focus.
@ -3808,6 +3873,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @return True if the event was handled by the view, false otherwise. * @return True if the event was handled by the view, false otherwise.
*/ */
public boolean dispatchTouchEvent(MotionEvent event) { public boolean dispatchTouchEvent(MotionEvent event) {
if (!onFilterTouchEventForSecurity(event)) {
return false;
}
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) { mOnTouchListener.onTouch(this, event)) {
return true; return true;
@ -3815,6 +3884,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return onTouchEvent(event); return onTouchEvent(event);
} }
/**
* Filter the touch event to apply security policies.
*
* @param event The motion event to be filtered.
* @return True if the event should be dispatched, false if the event should be dropped.
*
* @see #getFilterTouchesWhenObscured
*/
public boolean onFilterTouchEventForSecurity(MotionEvent event) {
if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
&& (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
// Window is obscured, drop this touch.
return false;
}
return true;
}
/** /**
* Pass a trackball motion event down to the focused view. * Pass a trackball motion event down to the focused view.
* *

View File

@ -822,6 +822,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/ */
@Override @Override
public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) {
if (!onFilterTouchEventForSecurity(ev)) {
return false;
}
final int action = ev.getAction(); final int action = ev.getAction();
final float xf = ev.getX(); final float xf = ev.getX();
final float yf = ev.getY(); final float yf = ev.getY();

View File

@ -74,6 +74,8 @@ public interface WindowManagerPolicy {
public final static int FLAG_MENU = 0x00000040; public final static int FLAG_MENU = 0x00000040;
public final static int FLAG_LAUNCHER = 0x00000080; public final static int FLAG_LAUNCHER = 0x00000080;
public final static int FLAG_INJECTED = 0x01000000;
public final static int FLAG_WOKE_HERE = 0x10000000; public final static int FLAG_WOKE_HERE = 0x10000000;
public final static int FLAG_BRIGHT_HERE = 0x20000000; public final static int FLAG_BRIGHT_HERE = 0x20000000;

View File

@ -46,6 +46,7 @@ static struct {
jfieldID mYPrecision; jfieldID mYPrecision;
jfieldID mEdgeFlags; jfieldID mEdgeFlags;
jfieldID mMetaState; jfieldID mMetaState;
jfieldID mFlags;
jfieldID mNumPointers; jfieldID mNumPointers;
jfieldID mNumSamples; jfieldID mNumSamples;
jfieldID mPointerIdentifiers; jfieldID mPointerIdentifiers;
@ -91,6 +92,8 @@ jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* even
event->getEdgeFlags()); event->getEdgeFlags());
env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState, env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState,
event->getMetaState()); event->getMetaState());
env->SetIntField(eventObj, gMotionEventClassInfo.mFlags,
event->getFlags());
env->SetIntField(eventObj, gMotionEventClassInfo.mNumPointers, env->SetIntField(eventObj, gMotionEventClassInfo.mNumPointers,
numPointers); numPointers);
env->SetIntField(eventObj, gMotionEventClassInfo.mNumSamples, env->SetIntField(eventObj, gMotionEventClassInfo.mNumSamples,
@ -162,6 +165,7 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision); jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision);
jint edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags); jint edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags);
jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState); jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState);
jint flags = env->GetIntField(eventObj, gMotionEventClassInfo.mFlags);
jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers); jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers);
jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples); jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples);
jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj, jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj,
@ -196,7 +200,7 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
samplePointerCoords[j].orientation = *(srcDataSamples++); samplePointerCoords[j].orientation = *(srcDataSamples++);
} }
event->initialize(deviceId, source, action, edgeFlags, metaState, event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime, xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime,
numPointers, pointerIdentifiers, samplePointerCoords); numPointers, pointerIdentifiers, samplePointerCoords);
@ -281,6 +285,8 @@ int register_android_view_MotionEvent(JNIEnv* env) {
"mEdgeFlags", "I"); "mEdgeFlags", "I");
GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz, GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz,
"mMetaState", "I"); "mMetaState", "I");
GET_FIELD_ID(gMotionEventClassInfo.mFlags, gMotionEventClassInfo.clazz,
"mFlags", "I");
GET_FIELD_ID(gMotionEventClassInfo.mNumPointers, gMotionEventClassInfo.clazz, GET_FIELD_ID(gMotionEventClassInfo.mNumPointers, gMotionEventClassInfo.clazz,
"mNumPointers", "I"); "mNumPointers", "I");
GET_FIELD_ID(gMotionEventClassInfo.mNumSamples, gMotionEventClassInfo.clazz, GET_FIELD_ID(gMotionEventClassInfo.mNumSamples, gMotionEventClassInfo.clazz,

View File

@ -1274,6 +1274,12 @@
be saved. --> be saved. -->
<attr name="saveEnabled" format="boolean" /> <attr name="saveEnabled" format="boolean" />
<!-- Specifies whether to filter touches when the view's window is obscured by
another visible window. When set to true, the view will not receive touches
whenever a toast, dialog or other window appears above the view's window.
Refer to the {@link android.view.View} security documentation for more details. -->
<attr name="filterTouchesWhenObscured" format="boolean" />
<!-- Defines the quality of translucent drawing caches. This property is used <!-- Defines the quality of translucent drawing caches. This property is used
only when the drawing cache is enabled and translucent. The default value is auto. --> only when the drawing cache is enabled and translucent. The default value is auto. -->
<attr name="drawingCacheQuality"> <attr name="drawingCacheQuality">

View File

@ -1254,6 +1254,7 @@
<public type="attr" name="overscrollMode" id="0x010102c1" /> <public type="attr" name="overscrollMode" id="0x010102c1" />
<public type="attr" name="overscrollHeader" id="0x010102c2" /> <public type="attr" name="overscrollHeader" id="0x010102c2" />
<public type="attr" name="overscrollFooter" id="0x010102c3" /> <public type="attr" name="overscrollFooter" id="0x010102c3" />
<public type="attr" name="filterTouchesWhenObscured" id="0x010102c4" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" /> <public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />

View File

@ -78,6 +78,11 @@ enum {
POLICY_FLAG_RAW_MASK = 0x0000ffff, POLICY_FLAG_RAW_MASK = 0x0000ffff,
/* These flags are set by the input dispatcher. */
// Indicates that the input event was injected.
POLICY_FLAG_INJECTED = 0x01000000,
/* These flags are set by the input reader policy as it intercepts each event. */ /* These flags are set by the input reader policy as it intercepts each event. */
// Indicates that the screen was off when the event was received and the event // Indicates that the screen was off when the event was received and the event
@ -225,6 +230,8 @@ public:
inline int32_t getAction() const { return mAction; } inline int32_t getAction() const { return mAction; }
inline int32_t getFlags() const { return mFlags; }
inline int32_t getEdgeFlags() const { return mEdgeFlags; } inline int32_t getEdgeFlags() const { return mEdgeFlags; }
inline int32_t getMetaState() const { return mMetaState; } inline int32_t getMetaState() const { return mMetaState; }
@ -343,6 +350,7 @@ public:
int32_t deviceId, int32_t deviceId,
int32_t source, int32_t source,
int32_t action, int32_t action,
int32_t flags,
int32_t edgeFlags, int32_t edgeFlags,
int32_t metaState, int32_t metaState,
float xOffset, float xOffset,
@ -370,6 +378,7 @@ public:
private: private:
int32_t mAction; int32_t mAction;
int32_t mFlags;
int32_t mEdgeFlags; int32_t mEdgeFlags;
int32_t mMetaState; int32_t mMetaState;
float mXOffset; float mXOffset;

View File

@ -84,14 +84,22 @@ struct InputTarget {
* current event is delivered to this target or a timeout occurs. */ * current event is delivered to this target or a timeout occurs. */
FLAG_SYNC = 0x01, FLAG_SYNC = 0x01,
/* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
* this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */ * of the area of this target and so should instead be delivered as an
* AMOTION_EVENT_ACTION_OUTSIDE to this target. */
FLAG_OUTSIDE = 0x02, FLAG_OUTSIDE = 0x02,
/* This flag indicates that a KeyEvent or MotionEvent is being canceled. /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
* In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set. * In the case of a key event, it should be delivered with flag
* In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */ * AKEY_EVENT_FLAG_CANCELED set.
FLAG_CANCEL = 0x04 * In the case of a motion event, it should be delivered with action
* AMOTION_EVENT_ACTION_CANCEL instead. */
FLAG_CANCEL = 0x04,
/* This flag indicates that the target of a MotionEvent is partly or wholly
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
FLAG_WINDOW_IS_OBSCURED = 0x08,
}; };
// The input channel to be targeted. // The input channel to be targeted.
@ -193,7 +201,8 @@ public:
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0; int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source, virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords, uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) = 0; float xPrecision, float yPrecision, nsecs_t downTime) = 0;
@ -257,7 +266,8 @@ public:
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime); int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source, virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords, uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime); float xPrecision, float yPrecision, nsecs_t downTime);
@ -327,6 +337,7 @@ private:
int32_t source; int32_t source;
uint32_t policyFlags; uint32_t policyFlags;
int32_t action; int32_t action;
int32_t flags;
int32_t metaState; int32_t metaState;
int32_t edgeFlags; int32_t edgeFlags;
float xPrecision; float xPrecision;
@ -458,7 +469,8 @@ private:
int32_t repeatCount, nsecs_t downTime); int32_t repeatCount, nsecs_t downTime);
MotionEntry* obtainMotionEntry(nsecs_t eventTime, MotionEntry* obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision, int32_t flags, int32_t metaState, int32_t edgeFlags,
float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount, nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords); const int32_t* pointerIds, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry); DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);

View File

@ -135,6 +135,7 @@ struct InputMessage {
struct { struct {
int32_t action; int32_t action;
int32_t flags;
int32_t metaState; int32_t metaState;
int32_t edgeFlags; int32_t edgeFlags;
nsecs_t downTime; nsecs_t downTime;
@ -218,6 +219,7 @@ public:
int32_t deviceId, int32_t deviceId,
int32_t source, int32_t source,
int32_t action, int32_t action,
int32_t flags,
int32_t edgeFlags, int32_t edgeFlags,
int32_t metaState, int32_t metaState,
float xOffset, float xOffset,

View File

@ -129,6 +129,7 @@ void MotionEvent::initialize(
int32_t deviceId, int32_t deviceId,
int32_t source, int32_t source,
int32_t action, int32_t action,
int32_t flags,
int32_t edgeFlags, int32_t edgeFlags,
int32_t metaState, int32_t metaState,
float xOffset, float xOffset,
@ -142,6 +143,7 @@ void MotionEvent::initialize(
const PointerCoords* pointerCoords) { const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source); InputEvent::initialize(deviceId, source);
mAction = action; mAction = action;
mFlags = flags;
mEdgeFlags = edgeFlags; mEdgeFlags = edgeFlags;
mMetaState = metaState; mMetaState = metaState;
mXOffset = xOffset; mXOffset = xOffset;

View File

@ -392,9 +392,11 @@ void InputDispatcher::processKeyRepeatLockedInterruptible(
void InputDispatcher::processMotionLockedInterruptible( void InputDispatcher::processMotionLockedInterruptible(
nsecs_t currentTime, MotionEntry* entry) { nsecs_t currentTime, MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS #if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, " LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, "
"metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld", "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action, entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->flags,
entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision, entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
entry->downTime); entry->downTime);
@ -406,7 +408,7 @@ void InputDispatcher::processMotionLockedInterruptible(
} }
for (uint32_t i = 0; i < entry->pointerCount; i++) { for (uint32_t i = 0; i < entry->pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, " LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, " "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f", "orientation=%f",
i, entry->pointerIds[i], i, entry->pointerIds[i],
sample->pointerCoords[i].x, sample->pointerCoords[i].y, sample->pointerCoords[i].x, sample->pointerCoords[i].y,
@ -465,7 +467,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
mCurrentInputTargetsValid = false; mCurrentInputTargetsValid = false;
mLock.unlock(); mLock.unlock();
mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
entry->edgeFlags, entry->metaState, entry->edgeFlags, entry->metaState,
0, 0, entry->xPrecision, entry->yPrecision, 0, 0, entry->xPrecision, entry->yPrecision,
entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds, entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
@ -698,12 +700,16 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Apply target flags. // Apply target flags.
int32_t action = motionEntry->action; int32_t action = motionEntry->action;
int32_t flags = motionEntry->flags;
if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) { if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
action = AMOTION_EVENT_ACTION_OUTSIDE; action = AMOTION_EVENT_ACTION_OUTSIDE;
} }
if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) { if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
action = AMOTION_EVENT_ACTION_CANCEL; action = AMOTION_EVENT_ACTION_CANCEL;
} }
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
}
// If headMotionSample is non-NULL, then it points to the first new sample that we // If headMotionSample is non-NULL, then it points to the first new sample that we
// were unable to dispatch during the previous cycle so we resume dispatching from // were unable to dispatch during the previous cycle so we resume dispatching from
@ -726,7 +732,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Publish the motion event and the first motion sample. // Publish the motion event and the first motion sample.
status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId, status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
xOffset, yOffset, xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, firstMotionSample->eventTime, motionEntry->downTime, firstMotionSample->eventTime,
@ -1073,18 +1079,18 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
} }
void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source, void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags, uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords, uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) { float xPrecision, float yPrecision, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS #if DEBUG_INBOUND_EVENT_DETAILS
LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, " LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
"action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, " "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
"downTime=%lld", "xPrecision=%f, yPrecision=%f, downTime=%lld",
eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags, eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime); xPrecision, yPrecision, downTime);
for (uint32_t i = 0; i < pointerCount; i++) { for (uint32_t i = 0; i < pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, " LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, " "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f", "orientation=%f",
i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y, i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
pointerCoords[i].pressure, pointerCoords[i].size, pointerCoords[i].pressure, pointerCoords[i].size,
@ -1209,7 +1215,7 @@ NoBatchingOrStreaming:;
// Just enqueue a new motion event. // Just enqueue a new motion event.
MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime, MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
deviceId, source, policyFlags, action, metaState, edgeFlags, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime, xPrecision, yPrecision, downTime,
pointerCount, pointerIds, pointerCoords); pointerCount, pointerIds, pointerCoords);
@ -1359,7 +1365,7 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
switch (event->getType()) { switch (event->getType()) {
case AINPUT_EVENT_TYPE_KEY: { case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event); const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events uint32_t policyFlags = POLICY_FLAG_INJECTED;
KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(), KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags, keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
@ -1371,7 +1377,7 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
case AINPUT_EVENT_TYPE_MOTION: { case AINPUT_EVENT_TYPE_MOTION: {
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events uint32_t policyFlags = POLICY_FLAG_INJECTED;
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
@ -1379,7 +1385,8 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes, MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(), motionEvent->getAction(), motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(), motionEvent->getXPrecision(), motionEvent->getYPrecision(),
motionEvent->getDownTime(), uint32_t(pointerCount), motionEvent->getDownTime(), uint32_t(pointerCount),
motionEvent->getPointerIds(), samplePointerCoords); motionEvent->getPointerIds(), samplePointerCoords);
@ -1664,7 +1671,7 @@ InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t ev
} }
InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime, InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision, int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount, nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords) { const int32_t* pointerIds, const PointerCoords* pointerCoords) {
@ -1676,6 +1683,7 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
entry->source = source; entry->source = source;
entry->policyFlags = policyFlags; entry->policyFlags = policyFlags;
entry->action = action; entry->action = action;
entry->flags = flags;
entry->metaState = metaState; entry->metaState = metaState;
entry->edgeFlags = edgeFlags; entry->edgeFlags = edgeFlags;
entry->xPrecision = xPrecision; entry->xPrecision = xPrecision;

View File

@ -1153,7 +1153,7 @@ void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEv
int32_t pointerId = 0; int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags, getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE, motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime); 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
} }
@ -2324,7 +2324,7 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
} // release lock } // release lock
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags, getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags, motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
pointerCount, pointerIds, pointerCoords, pointerCount, pointerIds, pointerCoords,
xPrecision, yPrecision, mDownTime); xPrecision, yPrecision, mDownTime);
} }

View File

@ -318,8 +318,8 @@ status_t InputPublisher::publishKeyEvent(
nsecs_t downTime, nsecs_t downTime,
nsecs_t eventTime) { nsecs_t eventTime) {
#if DEBUG_TRANSPORT_ACTIONS #if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=%d, " LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
"action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d," "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
"downTime=%lld, eventTime=%lld", "downTime=%lld, eventTime=%lld",
mChannel->getName().string(), mChannel->getName().string(),
deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
@ -346,6 +346,7 @@ status_t InputPublisher::publishMotionEvent(
int32_t deviceId, int32_t deviceId,
int32_t source, int32_t source,
int32_t action, int32_t action,
int32_t flags,
int32_t edgeFlags, int32_t edgeFlags,
int32_t metaState, int32_t metaState,
float xOffset, float xOffset,
@ -358,12 +359,12 @@ status_t InputPublisher::publishMotionEvent(
const int32_t* pointerIds, const int32_t* pointerIds,
const PointerCoords* pointerCoords) { const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS #if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=%d, " LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
"action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, " "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, " "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%d", "pointerCount=%d",
mChannel->getName().string(), mChannel->getName().string(),
deviceId, source, action, edgeFlags, metaState, xOffset, yOffset, deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
xPrecision, yPrecision, downTime, eventTime, pointerCount); xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif #endif
@ -379,6 +380,7 @@ status_t InputPublisher::publishMotionEvent(
} }
mSharedMessage->motion.action = action; mSharedMessage->motion.action = action;
mSharedMessage->motion.flags = flags;
mSharedMessage->motion.edgeFlags = edgeFlags; mSharedMessage->motion.edgeFlags = edgeFlags;
mSharedMessage->motion.metaState = metaState; mSharedMessage->motion.metaState = metaState;
mSharedMessage->motion.xOffset = xOffset; mSharedMessage->motion.xOffset = xOffset;
@ -664,6 +666,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->deviceId, mSharedMessage->deviceId,
mSharedMessage->source, mSharedMessage->source,
mSharedMessage->motion.action, mSharedMessage->motion.action,
mSharedMessage->motion.flags,
mSharedMessage->motion.edgeFlags, mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState, mSharedMessage->motion.metaState,
mSharedMessage->motion.xOffset, mSharedMessage->motion.xOffset,

View File

@ -138,6 +138,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
const int32_t deviceId = 1; const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN; const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
const int32_t action = AMOTION_EVENT_ACTION_MOVE; const int32_t action = AMOTION_EVENT_ACTION_MOVE;
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP; const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
const float xOffset = -10; const float xOffset = -10;
@ -167,7 +168,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
} }
} }
status = mPublisher->publishMotionEvent(deviceId, source, action, edgeFlags, status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
metaState, xOffset, yOffset, xPrecision, yPrecision, metaState, xOffset, yOffset, xPrecision, yPrecision,
downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array()); downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
ASSERT_EQ(OK, status) ASSERT_EQ(OK, status)
@ -213,6 +214,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
EXPECT_EQ(deviceId, motionEvent->getDeviceId()); EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource()); EXPECT_EQ(source, motionEvent->getSource());
EXPECT_EQ(action, motionEvent->getAction()); EXPECT_EQ(action, motionEvent->getAction());
EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags()); EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
EXPECT_EQ(metaState, motionEvent->getMetaState()); EXPECT_EQ(metaState, motionEvent->getMetaState());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision()); EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
@ -322,12 +324,12 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr
int32_t pointerIds[pointerCount] = { 0 }; int32_t pointerIds[pointerCount] = { 0 };
PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords); pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status) ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK"; << "publisher publishMotionEvent should return OK";
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords); pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(INVALID_OPERATION, status) ASSERT_EQ(INVALID_OPERATION, status)
<< "publisher publishMotionEvent should return INVALID_OPERATION because "; << "publisher publishMotionEvent should return INVALID_OPERATION because ";
@ -342,7 +344,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha
int32_t pointerIds[pointerCount]; int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount]; PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords); pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status) ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE"; << "publisher publishMotionEvent should return BAD_VALUE";
@ -356,7 +358,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreater
int32_t pointerIds[pointerCount]; int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount]; PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords); pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status) ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE"; << "publisher publishMotionEvent should return BAD_VALUE";
@ -402,7 +404,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEven
PointerCoords pointerCoords[pointerCount]; PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN, status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status); ASSERT_EQ(OK, status);
status = mPublisher->appendMotionSample(0, pointerCoords); status = mPublisher->appendMotionSample(0, pointerCoords);
@ -419,7 +421,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_Ret
PointerCoords pointerCoords[pointerCount]; PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE, status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status); ASSERT_EQ(OK, status);
status = mPublisher->sendDispatchSignal(); status = mPublisher->sendDispatchSignal();
@ -446,7 +448,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsE
PointerCoords pointerCoords[pointerCount]; PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE, status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status); ASSERT_EQ(OK, status);
for (int count = 1;; count++) { for (int count = 1;; count++) {

View File

@ -84,6 +84,10 @@ int32_t AMotionEvent_getAction(const AInputEvent* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getAction(); return static_cast<const MotionEvent*>(motion_event)->getAction();
} }
int32_t AMotionEvent_getFlags(const AInputEvent* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getFlags();
}
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event) { int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getMetaState(); return static_cast<const MotionEvent*>(motion_event)->getMetaState();
} }

View File

@ -246,6 +246,22 @@ enum {
AMOTION_EVENT_ACTION_POINTER_UP = 6 AMOTION_EVENT_ACTION_POINTER_UP = 6
}; };
/*
* Motion event flags.
*/
enum {
/* This flag indicates that the window that received this motion event is partly
* or wholly obscured by another visible window above it. This flag is set to true
* even if the event did not directly pass through the obscured area.
* A security sensitive application can check this flag to identify situations in which
* a malicious application may have covered up part of its content for the purpose
* of misleading the user or hijacking touches. An appropriate response might be
* to drop the suspect touches or to take additional precautions to confirm the user's
* actual intent.
*/
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
};
/* /*
* Motion event edge touch flags. * Motion event edge touch flags.
*/ */
@ -395,6 +411,9 @@ int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
/* Get the combined motion event action code and pointer index. */ /* Get the combined motion event action code and pointer index. */
int32_t AMotionEvent_getAction(const AInputEvent* motion_event); int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
/* Get the motion event flags. */
int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
/* Get the state of any meta / modifier keys that were in effect when the /* Get the state of any meta / modifier keys that were in effect when the
* event was generated. */ * event was generated. */
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event); int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);

View File

@ -34,9 +34,17 @@ public final class InputWindow {
// Dispatching timeout. // Dispatching timeout.
public long dispatchingTimeoutNanos; public long dispatchingTimeoutNanos;
// Window frame position. // Window frame area.
public int frameLeft; public int frameLeft;
public int frameTop; public int frameTop;
public int frameRight;
public int frameBottom;
// Window visible frame area.
public int visibleFrameLeft;
public int visibleFrameTop;
public int visibleFrameRight;
public int visibleFrameBottom;
// Window touchable area. // Window touchable area.
public int touchableAreaLeft; public int touchableAreaLeft;

View File

@ -5218,6 +5218,14 @@ public class WindowManagerService extends IWindowManager.Stub
final Rect frame = child.mFrame; final Rect frame = child.mFrame;
inputWindow.frameLeft = frame.left; inputWindow.frameLeft = frame.left;
inputWindow.frameTop = frame.top; inputWindow.frameTop = frame.top;
inputWindow.frameRight = frame.right;
inputWindow.frameBottom = frame.bottom;
final Rect visibleFrame = child.mVisibleFrame;
inputWindow.visibleFrameLeft = visibleFrame.left;
inputWindow.visibleFrameTop = visibleFrame.top;
inputWindow.visibleFrameRight = visibleFrame.right;
inputWindow.visibleFrameBottom = visibleFrame.bottom;
switch (child.mTouchableInsets) { switch (child.mTouchableInsets) {
default: default:

View File

@ -169,6 +169,12 @@ static struct {
jfieldID dispatchingTimeoutNanos; jfieldID dispatchingTimeoutNanos;
jfieldID frameLeft; jfieldID frameLeft;
jfieldID frameTop; jfieldID frameTop;
jfieldID frameRight;
jfieldID frameBottom;
jfieldID visibleFrameLeft;
jfieldID visibleFrameTop;
jfieldID visibleFrameRight;
jfieldID visibleFrameBottom;
jfieldID touchableAreaLeft; jfieldID touchableAreaLeft;
jfieldID touchableAreaTop; jfieldID touchableAreaTop;
jfieldID touchableAreaRight; jfieldID touchableAreaRight;
@ -283,6 +289,12 @@ private:
nsecs_t dispatchingTimeout; nsecs_t dispatchingTimeout;
int32_t frameLeft; int32_t frameLeft;
int32_t frameTop; int32_t frameTop;
int32_t frameRight;
int32_t frameBottom;
int32_t visibleFrameLeft;
int32_t visibleFrameTop;
int32_t visibleFrameRight;
int32_t visibleFrameBottom;
int32_t touchableAreaLeft; int32_t touchableAreaLeft;
int32_t touchableAreaTop; int32_t touchableAreaTop;
int32_t touchableAreaRight; int32_t touchableAreaRight;
@ -294,10 +306,8 @@ private:
int32_t ownerPid; int32_t ownerPid;
int32_t ownerUid; int32_t ownerUid;
inline bool touchableAreaContainsPoint(int32_t x, int32_t y) { bool visibleFrameIntersects(const InputWindow* other) const;
return x >= touchableAreaLeft && x <= touchableAreaRight bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
&& y >= touchableAreaTop && y <= touchableAreaBottom;
}
}; };
struct InputApplication { struct InputApplication {
@ -370,9 +380,13 @@ private:
// Focus tracking for touch. // Focus tracking for touch.
bool mTouchDown; bool mTouchDown;
InputWindow* mTouchedWindow; // primary target for current down InputWindow* mTouchedWindow; // primary target for current down
bool mTouchedWindowIsObscured; // true if other windows may obscure the target
Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
struct OutsideTarget {
Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets InputWindow* window;
bool obscured;
};
Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
// Focused application. // Focused application.
@ -391,6 +405,7 @@ private:
int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags, int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow); Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
bool isWindowObscuredLocked(const InputWindow* window);
void releaseTouchedWindowLd(); void releaseTouchedWindowLd();
@ -1117,6 +1132,18 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
gInputWindowClassInfo.frameLeft); gInputWindowClassInfo.frameLeft);
jint frameTop = env->GetIntField(windowObj, jint frameTop = env->GetIntField(windowObj,
gInputWindowClassInfo.frameTop); gInputWindowClassInfo.frameTop);
jint frameRight = env->GetIntField(windowObj,
gInputWindowClassInfo.frameRight);
jint frameBottom = env->GetIntField(windowObj,
gInputWindowClassInfo.frameBottom);
jint visibleFrameLeft = env->GetIntField(windowObj,
gInputWindowClassInfo.visibleFrameLeft);
jint visibleFrameTop = env->GetIntField(windowObj,
gInputWindowClassInfo.visibleFrameTop);
jint visibleFrameRight = env->GetIntField(windowObj,
gInputWindowClassInfo.visibleFrameRight);
jint visibleFrameBottom = env->GetIntField(windowObj,
gInputWindowClassInfo.visibleFrameBottom);
jint touchableAreaLeft = env->GetIntField(windowObj, jint touchableAreaLeft = env->GetIntField(windowObj,
gInputWindowClassInfo.touchableAreaLeft); gInputWindowClassInfo.touchableAreaLeft);
jint touchableAreaTop = env->GetIntField(windowObj, jint touchableAreaTop = env->GetIntField(windowObj,
@ -1144,6 +1171,12 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
outWindow.dispatchingTimeout = dispatchingTimeoutNanos; outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
outWindow.frameLeft = frameLeft; outWindow.frameLeft = frameLeft;
outWindow.frameTop = frameTop; outWindow.frameTop = frameTop;
outWindow.frameRight = frameRight;
outWindow.frameBottom = frameBottom;
outWindow.visibleFrameLeft = visibleFrameLeft;
outWindow.visibleFrameTop = visibleFrameTop;
outWindow.visibleFrameRight = visibleFrameRight;
outWindow.visibleFrameBottom = visibleFrameBottom;
outWindow.touchableAreaLeft = touchableAreaLeft; outWindow.touchableAreaLeft = touchableAreaLeft;
outWindow.touchableAreaTop = touchableAreaTop; outWindow.touchableAreaTop = touchableAreaTop;
outWindow.touchableAreaRight = touchableAreaRight; outWindow.touchableAreaRight = touchableAreaRight;
@ -1417,11 +1450,12 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
/* Case 1: ACTION_DOWN */ /* Case 1: ACTION_DOWN */
InputWindow* newTouchedWindow = NULL; InputWindow* newTouchedWindow = NULL;
mTempTouchedOutsideWindows.clear(); mTempTouchedOutsideTargets.clear();
int32_t x = int32_t(motionEvent->getX(0)); int32_t x = int32_t(motionEvent->getX(0));
int32_t y = int32_t(motionEvent->getY(0)); int32_t y = int32_t(motionEvent->getY(0));
InputWindow* topErrorWindow = NULL; InputWindow* topErrorWindow = NULL;
bool obscured = false;
// Traverse windows from front to back to find touched window and outside targets. // Traverse windows from front to back to find touched window and outside targets.
size_t numWindows = mWindows.size(); size_t numWindows = mWindows.size();
@ -1442,13 +1476,17 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
if (isTouchModal || window->touchableAreaContainsPoint(x, y)) { if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) { if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
newTouchedWindow = window; newTouchedWindow = window;
obscured = isWindowObscuredLocked(window);
} }
break; // found touched window, exit window loop break; // found touched window, exit window loop
} }
} }
if (flags & FLAG_WATCH_OUTSIDE_TOUCH) { if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
mTempTouchedOutsideWindows.push(window); OutsideTarget outsideTarget;
outsideTarget.window = window;
outsideTarget.obscured = isWindowObscuredLocked(window);
mTempTouchedOutsideTargets.push(outsideTarget);
} }
} }
} }
@ -1501,6 +1539,7 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
releaseTouchedWindowLd(); releaseTouchedWindowLd();
mTouchedWindow = newTouchedWindow; mTouchedWindow = newTouchedWindow;
mTouchedWindowIsObscured = obscured;
if (newTouchedWindow->hasWallpaper) { if (newTouchedWindow->hasWallpaper) {
mTouchedWallpaperWindows.appendVector(mWallpaperWindows); mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
@ -1557,21 +1596,31 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) { if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
size_t numWallpaperWindows = mTouchedWallpaperWindows.size(); size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
for (size_t i = 0; i < numWallpaperWindows; i++) { for (size_t i = 0; i < numWallpaperWindows; i++) {
addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets); addTarget(mTouchedWallpaperWindows[i],
InputTarget::FLAG_WINDOW_IS_OBSCURED, 0, outTargets);
} }
size_t numOutsideWindows = mTempTouchedOutsideWindows.size(); size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
for (size_t i = 0; i < numOutsideWindows; i++) { for (size_t i = 0; i < numOutsideTargets; i++) {
addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets); const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
if (outsideTarget.obscured) {
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
}
addTarget(outsideTarget.window, outsideTargetFlags, 0, outTargets);
} }
addTarget(mTouchedWindow, InputTarget::FLAG_SYNC, int32_t targetFlags = InputTarget::FLAG_SYNC;
if (mTouchedWindowIsObscured) {
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
}
addTarget(mTouchedWindow, targetFlags,
anrTimer.getTimeSpentWaitingForApplication(), outTargets); anrTimer.getTimeSpentWaitingForApplication(), outTargets);
outTouchedWindow = mTouchedWindow; outTouchedWindow = mTouchedWindow;
} else { } else {
outTouchedWindow = NULL; outTouchedWindow = NULL;
} }
mTempTouchedOutsideWindows.clear(); mTempTouchedOutsideTargets.clear();
// Check injection permission once and for all. // Check injection permission once and for all.
if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) { if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
@ -1616,6 +1665,7 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin
void NativeInputManager::releaseTouchedWindowLd() { void NativeInputManager::releaseTouchedWindowLd() {
mTouchedWindow = NULL; mTouchedWindow = NULL;
mTouchedWindowIsObscured = false;
mTouchedWallpaperWindows.clear(); mTouchedWallpaperWindows.clear();
} }
@ -1661,6 +1711,20 @@ bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
return true; return true;
} }
bool NativeInputManager::isWindowObscuredLocked(const InputWindow* window) {
size_t numWindows = mWindows.size();
for (size_t i = 0; i < numWindows; i++) {
const InputWindow* other = & mWindows.itemAt(i);
if (other == window) {
break;
}
if (other->visible && window->visibleFrameIntersects(other)) {
return true;
}
}
return false;
}
int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags, int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) { int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
#if DEBUG_INPUT_DISPATCHER_POLICY #if DEBUG_INPUT_DISPATCHER_POLICY
@ -1935,12 +1999,17 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) {
for (size_t i = 0; i < mWindows.size(); i++) { for (size_t i = 0; i < mWindows.size(); i++) {
dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, " dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
"visible=%d, flags=0x%08x, type=0x%08x, " "visible=%d, flags=0x%08x, type=0x%08x, "
"frame=[%d,%d], touchableArea=[%d,%d][%d,%d], " "frame=[%d,%d][%d,%d], "
"visibleFrame=[%d,%d][%d,%d], "
"touchableArea=[%d,%d][%d,%d], "
"ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
i, mWindows[i].inputChannel->getName().string(), i, mWindows[i].inputChannel->getName().string(),
mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper, mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType, mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
mWindows[i].frameLeft, mWindows[i].frameTop, mWindows[i].frameLeft, mWindows[i].frameTop,
mWindows[i].frameRight, mWindows[i].frameBottom,
mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop, mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom, mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
mWindows[i].ownerPid, mWindows[i].ownerUid, mWindows[i].ownerPid, mWindows[i].ownerUid,
@ -1955,6 +2024,20 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool NativeInputManager::InputWindow::visibleFrameIntersects(const InputWindow* other) const {
return visibleFrameRight > other->visibleFrameLeft
&& visibleFrameLeft < other->visibleFrameRight
&& visibleFrameBottom > other->visibleFrameTop
&& visibleFrameTop < other->visibleFrameBottom;
}
bool NativeInputManager::InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
return x >= touchableAreaLeft && x <= touchableAreaRight
&& y >= touchableAreaTop && y <= touchableAreaBottom;
}
// ----------------------------------------------------------------------------
NativeInputManager::ANRTimer::ANRTimer() : NativeInputManager::ANRTimer::ANRTimer() :
mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) { mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
} }
@ -2507,6 +2590,24 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz, GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
"frameTop", "I"); "frameTop", "I");
GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
"frameRight", "I");
GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
"frameBottom", "I");
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
"visibleFrameLeft", "I");
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
"visibleFrameTop", "I");
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
"visibleFrameRight", "I");
GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
"visibleFrameBottom", "I");
GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz, GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
"touchableAreaLeft", "I"); "touchableAreaLeft", "I");