Add support for secure views.
Added the MotionEvent.FLAG_WINDOW_IS_OBSCURED flag which is set by the input manager whenever another visible window is partly or wholly obscured the target of a touch event so that applications can filter touches accordingly. Added a "filterTouchesWhenObscured" attribute to View which can be used to enable filtering of touches when the view's window is obscured. Change-Id: I936d9c85013fd2d77fb296a600528d30a29027d2
This commit is contained in:
@@ -30,6 +30,7 @@ import android.os.SystemClock;
|
||||
*/
|
||||
public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
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.
|
||||
@@ -155,7 +156,17 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
@Deprecated
|
||||
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.
|
||||
@@ -251,6 +262,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
private float mYPrecision;
|
||||
private int mEdgeFlags;
|
||||
private int mMetaState;
|
||||
private int mFlags;
|
||||
|
||||
private int mNumPointers;
|
||||
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
|
||||
* zero indicates that the event didn't come from a physical device; other
|
||||
* 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.
|
||||
* @param source The source of this event.
|
||||
* @param flags The motion event flags.
|
||||
*/
|
||||
static public MotionEvent obtain(long downTime, long eventTime,
|
||||
int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
|
||||
int metaState, float xPrecision, float yPrecision, int deviceId,
|
||||
int edgeFlags, int source) {
|
||||
int edgeFlags, int source, int flags) {
|
||||
MotionEvent ev = obtain(pointers, 1);
|
||||
ev.mDeviceId = deviceId;
|
||||
ev.mSource = source;
|
||||
ev.mEdgeFlags = edgeFlags;
|
||||
ev.mDownTimeNano = downTime * MS_PER_NS;
|
||||
ev.mAction = action;
|
||||
ev.mFlags = flags;
|
||||
ev.mMetaState = metaState;
|
||||
ev.mXOffset = 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
|
||||
* zero indicates that the event didn't come from a physical device; other
|
||||
* 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.
|
||||
*/
|
||||
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.mDownTimeNano = downTime * MS_PER_NS;
|
||||
ev.mAction = action;
|
||||
ev.mFlags = 0;
|
||||
ev.mMetaState = metaState;
|
||||
ev.mXOffset = 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
|
||||
* zero indicates that the event didn't come from a physical device; other
|
||||
* 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.
|
||||
*
|
||||
* @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.mDownTimeNano = o.mDownTimeNano;
|
||||
ev.mAction = o.mAction;
|
||||
ev.mFlags = o.mFlags;
|
||||
ev.mMetaState = o.mMetaState;
|
||||
ev.mXOffset = o.mXOffset;
|
||||
ev.mYOffset = o.mYOffset;
|
||||
@@ -540,6 +556,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
ev.mEdgeFlags = o.mEdgeFlags;
|
||||
ev.mDownTimeNano = o.mDownTimeNano;
|
||||
ev.mAction = o.mAction;
|
||||
o.mFlags = o.mFlags;
|
||||
ev.mMetaState = o.mMetaState;
|
||||
ev.mXOffset = o.mXOffset;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* @see #getEdgeFlags()
|
||||
@@ -1480,6 +1506,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
ev.mYPrecision = in.readFloat();
|
||||
ev.mEdgeFlags = in.readInt();
|
||||
ev.mMetaState = in.readInt();
|
||||
ev.mFlags = in.readInt();
|
||||
|
||||
final int[] pointerIdentifiers = ev.mPointerIdentifiers;
|
||||
for (int i = 0; i < NP; i++) {
|
||||
@@ -1521,6 +1548,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
|
||||
out.writeFloat(mYPrecision);
|
||||
out.writeInt(mEdgeFlags);
|
||||
out.writeInt(mMetaState);
|
||||
out.writeInt(mFlags);
|
||||
|
||||
final int[] pointerIdentifiers = mPointerIdentifiers;
|
||||
for (int i = 0; i < NP; i++) {
|
||||
|
||||
@@ -542,6 +542,28 @@ import java.util.WeakHashMap;
|
||||
* take care of redrawing the appropriate views until the animation completes.
|
||||
* </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_clickable
|
||||
* @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_fadingEdge
|
||||
* @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_isScrollContainer
|
||||
* @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;
|
||||
|
||||
// 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>
|
||||
@@ -2052,6 +2082,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
viewFlagMasks |= KEEP_SCREEN_ON;
|
||||
}
|
||||
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:
|
||||
mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
|
||||
break;
|
||||
@@ -3389,6 +3425,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
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.
|
||||
@@ -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.
|
||||
*/
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (!onFilterTouchEventForSecurity(event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
|
||||
mOnTouchListener.onTouch(this, event)) {
|
||||
return true;
|
||||
@@ -3815,6 +3884,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -822,6 +822,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
*/
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (!onFilterTouchEventForSecurity(ev)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int action = ev.getAction();
|
||||
final float xf = ev.getX();
|
||||
final float yf = ev.getY();
|
||||
|
||||
@@ -74,6 +74,8 @@ public interface WindowManagerPolicy {
|
||||
public final static int FLAG_MENU = 0x00000040;
|
||||
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_BRIGHT_HERE = 0x20000000;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user