Add support for power keys, improve behavior of virtual keys.
The platform now knows how to deal with a platform key, which at this point is "just like end call, but don't end a call." Also improve the handling of virtual keys, to allow for canceling when sliding off into the display and providing haptic feedback. Finally fixes a bug where the raw x and y in motion event were not always set which caused the status bar to not work.
This commit is contained in:
@@ -141896,6 +141896,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="VIRTUAL_KEY"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<class name="InflateException"
|
||||
extends="java.lang.RuntimeException"
|
||||
@@ -142736,6 +142747,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isCanceled"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isModifierKey"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
@@ -142851,6 +142873,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_CANCELED"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="32"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_EDITOR_ACTION"
|
||||
type="int"
|
||||
transient="false"
|
||||
@@ -142895,6 +142928,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_VIRTUAL_HARD_KEY"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="64"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_WOKE_HERE"
|
||||
type="int"
|
||||
transient="false"
|
||||
|
||||
@@ -24,8 +24,17 @@ public class HapticFeedbackConstants {
|
||||
|
||||
private HapticFeedbackConstants() {}
|
||||
|
||||
/**
|
||||
* The user has performed a long press on an object that is resulting
|
||||
* in an action being performed.
|
||||
*/
|
||||
public static final int LONG_PRESS = 0;
|
||||
|
||||
/**
|
||||
* The user has pressed on a virtual on-screen key.
|
||||
*/
|
||||
public static final int VIRTUAL_KEY = 1;
|
||||
|
||||
/**
|
||||
* Flag for {@link View#performHapticFeedback(int, int)
|
||||
* View.performHapticFeedback(int, int)}: Ignore the setting in the
|
||||
|
||||
@@ -257,6 +257,25 @@ public class KeyEvent implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_EDITOR_ACTION = 0x10;
|
||||
|
||||
/**
|
||||
* When associated with up key events, this indicates that the key press
|
||||
* has been canceled. Typically this is used with virtual touch screen
|
||||
* keys, where the user can slide from the virtual key area on to the
|
||||
* display: in that case, the application will receive a canceled up
|
||||
* event and should not perform the action normally associated with the
|
||||
* key. Note that for this to work, the application can not perform an
|
||||
* action for a key until it receives an up or the long press timeout has
|
||||
* expired.
|
||||
*/
|
||||
public static final int FLAG_CANCELED = 0x20;
|
||||
|
||||
/**
|
||||
* This key event was generated by a virtual (on-screen) hard key area.
|
||||
* Typically this is an area of the touchscreen, outside of the regular
|
||||
* display, dedicated to "hardware" buttons.
|
||||
*/
|
||||
public static final int FLAG_VIRTUAL_HARD_KEY = 0x40;
|
||||
|
||||
/**
|
||||
* Returns the maximum keycode.
|
||||
*/
|
||||
@@ -693,6 +712,14 @@ public class KeyEvent implements Parcelable {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* For {@link #ACTION_UP} events, indicates that the event has been
|
||||
* canceled as per {@link #FLAG_CANCELED}.
|
||||
*/
|
||||
public final boolean isCanceled() {
|
||||
return (mFlags&FLAG_CANCELED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the key code of the key event. This is the physical key that
|
||||
* was pressed, <em>not</em> the Unicode character.
|
||||
|
||||
@@ -288,9 +288,10 @@ public final class MotionEvent implements Parcelable {
|
||||
ev.mEventTimeNano = eventTimeNano;
|
||||
ev.mAction = action;
|
||||
ev.mMetaState = metaState;
|
||||
ev.mRawX = inData[SAMPLE_X];
|
||||
ev.mRawY = inData[SAMPLE_Y];
|
||||
ev.mXPrecision = xPrecision;
|
||||
ev.mYPrecision = yPrecision;
|
||||
|
||||
ev.mNumPointers = pointers;
|
||||
ev.mNumSamples = 1;
|
||||
|
||||
|
||||
@@ -1665,7 +1665,9 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
if(Config.LOGV) {
|
||||
captureMotionLog("captureDispatchPointer", event);
|
||||
}
|
||||
event.offsetLocation(0, mCurScrollY);
|
||||
if (mCurScrollY != 0) {
|
||||
event.offsetLocation(0, mCurScrollY);
|
||||
}
|
||||
if (MEASURE_LATENCY) {
|
||||
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
|
||||
}
|
||||
|
||||
@@ -533,14 +533,15 @@ public interface WindowManagerPolicy {
|
||||
* @param win The window that currently has focus. This is where the key
|
||||
* event will normally go.
|
||||
* @param code Key code.
|
||||
* @param metaKeys TODO
|
||||
* @param metaKeys bit mask of meta keys that are held.
|
||||
* @param down Is this a key press (true) or release (false)?
|
||||
* @param repeatCount Number of times a key down has repeated.
|
||||
* @param flags event's flags.
|
||||
* @return Returns true if the policy consumed the event and it should
|
||||
* not be further dispatched.
|
||||
*/
|
||||
public boolean interceptKeyTi(WindowState win, int code,
|
||||
int metaKeys, boolean down, int repeatCount);
|
||||
int metaKeys, boolean down, int repeatCount, int flags);
|
||||
|
||||
/**
|
||||
* Called when layout of the windows is about to start.
|
||||
@@ -791,6 +792,13 @@ public interface WindowManagerPolicy {
|
||||
*/
|
||||
public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
|
||||
|
||||
/**
|
||||
* A special function that is called from the very low-level input queue
|
||||
* to provide feedback to the user. Currently only called for virtual
|
||||
* keys.
|
||||
*/
|
||||
public void keyFeedbackFromInput(KeyEvent event);
|
||||
|
||||
/**
|
||||
* Called when we have stopped keeping the screen on because a window
|
||||
* requesting this is no longer visible.
|
||||
|
||||
@@ -213,7 +213,7 @@ public class InputDevice {
|
||||
|
||||
// We only consider the first pointer when computing the edge
|
||||
// flags, since they are global to the event.
|
||||
if (action != MotionEvent.ACTION_DOWN) {
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
if (scaled[MotionEvent.SAMPLE_X] <= 0) {
|
||||
edgeFlags |= MotionEvent.EDGE_LEFT;
|
||||
} else if (scaled[MotionEvent.SAMPLE_X] >= dispW) {
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.view.WindowManagerPolicy;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@@ -55,6 +54,7 @@ public abstract class KeyInputQueue {
|
||||
|
||||
final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>();
|
||||
final ArrayList<VirtualKey> mVirtualKeys = new ArrayList<VirtualKey>();
|
||||
final HapticFeedbackCallback mHapticFeedbackCallback;
|
||||
|
||||
int mGlobalMetaState = 0;
|
||||
boolean mHaveGlobalMetaState = false;
|
||||
@@ -107,6 +107,10 @@ public abstract class KeyInputQueue {
|
||||
int filterEvent(QueuedEvent ev);
|
||||
}
|
||||
|
||||
public interface HapticFeedbackCallback {
|
||||
void virtualKeyFeedback(KeyEvent event);
|
||||
}
|
||||
|
||||
static class QueuedEvent {
|
||||
InputDevice inputDevice;
|
||||
long whenNano;
|
||||
@@ -264,11 +268,13 @@ public abstract class KeyInputQueue {
|
||||
}
|
||||
}
|
||||
|
||||
KeyInputQueue(Context context) {
|
||||
KeyInputQueue(Context context, HapticFeedbackCallback hapticFeedbackCallback) {
|
||||
if (MEASURE_LATENCY) {
|
||||
lt = new LatencyTimer(100, 1000);
|
||||
}
|
||||
|
||||
mHapticFeedbackCallback = hapticFeedbackCallback;
|
||||
|
||||
readVirtualKeys();
|
||||
readExcludedDevices();
|
||||
|
||||
@@ -539,14 +545,40 @@ public abstract class KeyInputQueue {
|
||||
ms.mLastDown[0] = ms.mDown[0];
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Generate key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode,
|
||||
0, vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
newKeyEvent(di, di.mKeyDownTime,
|
||||
curTime, false,
|
||||
vk.lastKeycode,
|
||||
0, vk.scancode, 0));
|
||||
event);
|
||||
} else if (isInsideDisplay(di)) {
|
||||
// Whoops the pointer has moved into
|
||||
// the display area! Cancel the
|
||||
// virtual key and start a pointer
|
||||
// motion.
|
||||
mPressedVirtualKey = null;
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Cancel key up for: " + vk.scancode);
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, false,
|
||||
vk.lastKeycode,
|
||||
0, vk.scancode,
|
||||
KeyEvent.FLAG_CANCELED |
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
event);
|
||||
doMotion = true;
|
||||
for (int i=InputDevice.MAX_POINTERS-1; i>=0; i--) {
|
||||
ms.mLastDown[i] = false;
|
||||
}
|
||||
}
|
||||
} else if (ms.mDown[0] && !ms.mLastDown[0]) {
|
||||
}
|
||||
if (doMotion && ms.mDown[0] && !ms.mLastDown[0]) {
|
||||
vk = findSoftButton(di);
|
||||
if (vk != null) {
|
||||
doMotion = false;
|
||||
@@ -558,12 +590,15 @@ public abstract class KeyInputQueue {
|
||||
if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
|
||||
"Generate key down for: " + vk.scancode
|
||||
+ " (keycode=" + vk.lastKeycode + ")");
|
||||
KeyEvent event = newKeyEvent(di,
|
||||
di.mKeyDownTime, curTime, true,
|
||||
vk.lastKeycode, 0,
|
||||
vk.scancode,
|
||||
KeyEvent.FLAG_VIRTUAL_HARD_KEY);
|
||||
mHapticFeedbackCallback.virtualKeyFeedback(event);
|
||||
addLocked(di, curTimeNano, ev.flags,
|
||||
RawInputEvent.CLASS_KEYBOARD,
|
||||
newKeyEvent(di, di.mKeyDownTime,
|
||||
curTime, true,
|
||||
vk.lastKeycode, 0,
|
||||
vk.scancode, 0));
|
||||
event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,17 +653,12 @@ public abstract class KeyInputQueue {
|
||||
}
|
||||
};
|
||||
|
||||
private VirtualKey findSoftButton(InputDevice dev) {
|
||||
final int N = mVirtualKeys.size();
|
||||
if (N <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isInsideDisplay(InputDevice dev) {
|
||||
final InputDevice.AbsoluteInfo absx = dev.absX;
|
||||
final InputDevice.AbsoluteInfo absy = dev.absY;
|
||||
final InputDevice.MotionState absm = dev.mAbs;
|
||||
if (absx == null || absy == null || absm == null) {
|
||||
return null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (absm.mCurData[MotionEvent.SAMPLE_X] >= absx.minValue
|
||||
@@ -639,9 +669,23 @@ public abstract class KeyInputQueue {
|
||||
+ absm.mCurData[MotionEvent.SAMPLE_X]
|
||||
+ "," + absm.mCurData[MotionEvent.SAMPLE_Y]
|
||||
+ ") inside of display");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private VirtualKey findSoftButton(InputDevice dev) {
|
||||
final int N = mVirtualKeys.size();
|
||||
if (N <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isInsideDisplay(dev)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final InputDevice.MotionState absm = dev.mAbs;
|
||||
for (int i=0; i<N; i++) {
|
||||
VirtualKey sb = mVirtualKeys.get(i);
|
||||
sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight);
|
||||
|
||||
@@ -125,7 +125,8 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/** {@hide} */
|
||||
public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor {
|
||||
public class WindowManagerService extends IWindowManager.Stub
|
||||
implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
|
||||
static final String TAG = "WindowManager";
|
||||
static final boolean DEBUG = false;
|
||||
static final boolean DEBUG_FOCUS = false;
|
||||
@@ -4686,7 +4687,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
|
||||
callingPid, callingUid)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
mPolicy.interceptKeyTi(null, keycode,
|
||||
nextKey.getMetaState(), down, repeatCount);
|
||||
nextKey.getMetaState(), down, repeatCount,
|
||||
nextKey.getFlags());
|
||||
}
|
||||
Log.w(TAG, "Event timeout during app switch: dropping "
|
||||
+ nextKey);
|
||||
@@ -4709,7 +4711,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
|
||||
callingPid, callingUid)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
if (mPolicy.interceptKeyTi(focus,
|
||||
keycode, nextKey.getMetaState(), down, repeatCount)) {
|
||||
keycode, nextKey.getMetaState(), down, repeatCount,
|
||||
nextKey.getFlags())) {
|
||||
return CONSUMED_EVENT_TOKEN;
|
||||
}
|
||||
}
|
||||
@@ -5129,7 +5132,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
|
||||
PowerManager.WakeLock mHoldingScreen;
|
||||
|
||||
KeyQ() {
|
||||
super(mContext);
|
||||
super(mContext, WindowManagerService.this);
|
||||
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
|
||||
"KEEP_SCREEN_ON_FLAG");
|
||||
@@ -9202,6 +9205,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
|
||||
synchronized (mKeyWaiter) { }
|
||||
}
|
||||
|
||||
public void virtualKeyFeedback(KeyEvent event) {
|
||||
mPolicy.keyFeedbackFromInput(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* DimAnimator class that controls the dim animation. This holds the surface and
|
||||
* all state used for dim animation.
|
||||
|
||||
Reference in New Issue
Block a user