Merge "More native input dispatch work." into gingerbread
This commit is contained in:
@ -216,20 +216,7 @@ public abstract class WallpaperService extends Service {
|
||||
@Override
|
||||
public void handleTouch(MotionEvent event, Runnable finishedCallback) {
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (mPendingMove != null) {
|
||||
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
|
||||
mPendingMove.recycle();
|
||||
}
|
||||
mPendingMove = event;
|
||||
} else {
|
||||
mPendingMove = null;
|
||||
}
|
||||
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT,
|
||||
event);
|
||||
mCaller.sendMessage(msg);
|
||||
}
|
||||
dispatchPointer(event);
|
||||
} finally {
|
||||
finishedCallback.run();
|
||||
}
|
||||
@ -237,26 +224,6 @@ public abstract class WallpaperService extends Service {
|
||||
};
|
||||
|
||||
final BaseIWindow mWindow = new BaseIWindow() {
|
||||
@Override
|
||||
public boolean onDispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
synchronized (mLock) {
|
||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (mPendingMove != null) {
|
||||
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
|
||||
mPendingMove.recycle();
|
||||
}
|
||||
mPendingMove = event;
|
||||
} else {
|
||||
mPendingMove = null;
|
||||
}
|
||||
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT,
|
||||
event);
|
||||
mCaller.sendMessage(msg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resized(int w, int h, Rect coveredInsets,
|
||||
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
|
||||
@ -466,6 +433,22 @@ public abstract class WallpaperService extends Service {
|
||||
*/
|
||||
public void onSurfaceDestroyed(SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
private void dispatchPointer(MotionEvent event) {
|
||||
synchronized (mLock) {
|
||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (mPendingMove != null) {
|
||||
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
|
||||
mPendingMove.recycle();
|
||||
}
|
||||
mPendingMove = event;
|
||||
} else {
|
||||
mPendingMove = null;
|
||||
}
|
||||
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
|
||||
mCaller.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void updateSurface(boolean forceRelayout, boolean forceReport) {
|
||||
if (mDestroyed) {
|
||||
@ -523,10 +506,8 @@ public abstract class WallpaperService extends Service {
|
||||
mInputChannel);
|
||||
mCreated = true;
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
|
||||
Looper.myQueue());
|
||||
}
|
||||
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
|
||||
Looper.myQueue());
|
||||
}
|
||||
|
||||
mSurfaceHolder.mSurfaceLock.lock();
|
||||
@ -770,10 +751,8 @@ public abstract class WallpaperService extends Service {
|
||||
if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
|
||||
+ mSurfaceHolder.getSurface() + " of: " + this);
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
if (mInputChannel != null) {
|
||||
InputQueue.unregisterInputChannel(mInputChannel);
|
||||
}
|
||||
if (mInputChannel != null) {
|
||||
InputQueue.unregisterInputChannel(mInputChannel);
|
||||
}
|
||||
|
||||
mSession.remove(mWindow);
|
||||
@ -782,13 +761,11 @@ public abstract class WallpaperService extends Service {
|
||||
mSurfaceHolder.mSurface.release();
|
||||
mCreated = false;
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
// Dispose the input channel after removing the window so the Window Manager
|
||||
// doesn't interpret the input channel being closed as an abnormal termination.
|
||||
if (mInputChannel != null) {
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
}
|
||||
// Dispose the input channel after removing the window so the Window Manager
|
||||
// doesn't interpret the input channel being closed as an abnormal termination.
|
||||
if (mInputChannel != null) {
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -841,7 +818,7 @@ public abstract class WallpaperService extends Service {
|
||||
|
||||
public void dispatchPointer(MotionEvent event) {
|
||||
if (mEngine != null) {
|
||||
mEngine.mWindow.onDispatchPointer(event, event.getEventTime(), false);
|
||||
mEngine.dispatchPointer(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,6 @@ oneway interface IWindow {
|
||||
|
||||
void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
|
||||
boolean reportDraw, in Configuration newConfig);
|
||||
void dispatchKey(in KeyEvent event);
|
||||
void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
|
||||
void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
|
||||
void dispatchAppVisibility(boolean visible);
|
||||
void dispatchGetNewSurface();
|
||||
|
||||
|
@ -109,10 +109,6 @@ interface IWindowSession {
|
||||
void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
|
||||
|
||||
void finishDrawing(IWindow window);
|
||||
|
||||
void finishKey(IWindow window);
|
||||
MotionEvent getPendingPointerMove(IWindow window);
|
||||
MotionEvent getPendingTrackballMove(IWindow window);
|
||||
|
||||
void setInTouchMode(boolean showFocus);
|
||||
boolean getInTouchMode();
|
||||
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* This really belongs in services.jar; WindowManagerPolicy should go there too.
|
||||
*/
|
||||
public class RawInputEvent {
|
||||
// Event class as defined by EventHub.
|
||||
public static final int CLASS_KEYBOARD = 0x00000001;
|
||||
public static final int CLASS_ALPHAKEY = 0x00000002;
|
||||
public static final int CLASS_TOUCHSCREEN = 0x00000004;
|
||||
public static final int CLASS_TRACKBALL = 0x00000008;
|
||||
public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
|
||||
public static final int CLASS_DPAD = 0x00000020;
|
||||
|
||||
// More special classes for QueuedEvent below.
|
||||
public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;
|
||||
|
||||
// Event types.
|
||||
|
||||
public static final int EV_SYN = 0x00;
|
||||
public static final int EV_KEY = 0x01;
|
||||
public static final int EV_REL = 0x02;
|
||||
public static final int EV_ABS = 0x03;
|
||||
public static final int EV_MSC = 0x04;
|
||||
public static final int EV_SW = 0x05;
|
||||
public static final int EV_LED = 0x11;
|
||||
public static final int EV_SND = 0x12;
|
||||
public static final int EV_REP = 0x14;
|
||||
public static final int EV_FF = 0x15;
|
||||
public static final int EV_PWR = 0x16;
|
||||
public static final int EV_FF_STATUS = 0x17;
|
||||
|
||||
// Platform-specific event types.
|
||||
|
||||
public static final int EV_DEVICE_ADDED = 0x10000000;
|
||||
public static final int EV_DEVICE_REMOVED = 0x20000000;
|
||||
|
||||
// Special key (EV_KEY) scan codes for pointer buttons.
|
||||
|
||||
public static final int BTN_FIRST = 0x100;
|
||||
|
||||
public static final int BTN_MISC = 0x100;
|
||||
public static final int BTN_0 = 0x100;
|
||||
public static final int BTN_1 = 0x101;
|
||||
public static final int BTN_2 = 0x102;
|
||||
public static final int BTN_3 = 0x103;
|
||||
public static final int BTN_4 = 0x104;
|
||||
public static final int BTN_5 = 0x105;
|
||||
public static final int BTN_6 = 0x106;
|
||||
public static final int BTN_7 = 0x107;
|
||||
public static final int BTN_8 = 0x108;
|
||||
public static final int BTN_9 = 0x109;
|
||||
|
||||
public static final int BTN_MOUSE = 0x110;
|
||||
public static final int BTN_LEFT = 0x110;
|
||||
public static final int BTN_RIGHT = 0x111;
|
||||
public static final int BTN_MIDDLE = 0x112;
|
||||
public static final int BTN_SIDE = 0x113;
|
||||
public static final int BTN_EXTRA = 0x114;
|
||||
public static final int BTN_FORWARD = 0x115;
|
||||
public static final int BTN_BACK = 0x116;
|
||||
public static final int BTN_TASK = 0x117;
|
||||
|
||||
public static final int BTN_JOYSTICK = 0x120;
|
||||
public static final int BTN_TRIGGER = 0x120;
|
||||
public static final int BTN_THUMB = 0x121;
|
||||
public static final int BTN_THUMB2 = 0x122;
|
||||
public static final int BTN_TOP = 0x123;
|
||||
public static final int BTN_TOP2 = 0x124;
|
||||
public static final int BTN_PINKIE = 0x125;
|
||||
public static final int BTN_BASE = 0x126;
|
||||
public static final int BTN_BASE2 = 0x127;
|
||||
public static final int BTN_BASE3 = 0x128;
|
||||
public static final int BTN_BASE4 = 0x129;
|
||||
public static final int BTN_BASE5 = 0x12a;
|
||||
public static final int BTN_BASE6 = 0x12b;
|
||||
public static final int BTN_DEAD = 0x12f;
|
||||
|
||||
public static final int BTN_GAMEPAD = 0x130;
|
||||
public static final int BTN_A = 0x130;
|
||||
public static final int BTN_B = 0x131;
|
||||
public static final int BTN_C = 0x132;
|
||||
public static final int BTN_X = 0x133;
|
||||
public static final int BTN_Y = 0x134;
|
||||
public static final int BTN_Z = 0x135;
|
||||
public static final int BTN_TL = 0x136;
|
||||
public static final int BTN_TR = 0x137;
|
||||
public static final int BTN_TL2 = 0x138;
|
||||
public static final int BTN_TR2 = 0x139;
|
||||
public static final int BTN_SELECT = 0x13a;
|
||||
public static final int BTN_START = 0x13b;
|
||||
public static final int BTN_MODE = 0x13c;
|
||||
public static final int BTN_THUMBL = 0x13d;
|
||||
public static final int BTN_THUMBR = 0x13e;
|
||||
|
||||
public static final int BTN_DIGI = 0x140;
|
||||
public static final int BTN_TOOL_PEN = 0x140;
|
||||
public static final int BTN_TOOL_RUBBER = 0x141;
|
||||
public static final int BTN_TOOL_BRUSH = 0x142;
|
||||
public static final int BTN_TOOL_PENCIL = 0x143;
|
||||
public static final int BTN_TOOL_AIRBRUSH = 0x144;
|
||||
public static final int BTN_TOOL_FINGER = 0x145;
|
||||
public static final int BTN_TOOL_MOUSE = 0x146;
|
||||
public static final int BTN_TOOL_LENS = 0x147;
|
||||
public static final int BTN_TOUCH = 0x14a;
|
||||
public static final int BTN_STYLUS = 0x14b;
|
||||
public static final int BTN_STYLUS2 = 0x14c;
|
||||
public static final int BTN_TOOL_DOUBLETAP = 0x14d;
|
||||
public static final int BTN_TOOL_TRIPLETAP = 0x14e;
|
||||
|
||||
public static final int BTN_WHEEL = 0x150;
|
||||
public static final int BTN_GEAR_DOWN = 0x150;
|
||||
public static final int BTN_GEAR_UP = 0x151;
|
||||
|
||||
public static final int BTN_LAST = 0x15f;
|
||||
|
||||
// Relative axes (EV_REL) scan codes.
|
||||
|
||||
public static final int REL_X = 0x00;
|
||||
public static final int REL_Y = 0x01;
|
||||
public static final int REL_Z = 0x02;
|
||||
public static final int REL_RX = 0x03;
|
||||
public static final int REL_RY = 0x04;
|
||||
public static final int REL_RZ = 0x05;
|
||||
public static final int REL_HWHEEL = 0x06;
|
||||
public static final int REL_DIAL = 0x07;
|
||||
public static final int REL_WHEEL = 0x08;
|
||||
public static final int REL_MISC = 0x09;
|
||||
public static final int REL_MAX = 0x0f;
|
||||
|
||||
// Absolute axes (EV_ABS) scan codes.
|
||||
|
||||
public static final int ABS_X = 0x00;
|
||||
public static final int ABS_Y = 0x01;
|
||||
public static final int ABS_Z = 0x02;
|
||||
public static final int ABS_RX = 0x03;
|
||||
public static final int ABS_RY = 0x04;
|
||||
public static final int ABS_RZ = 0x05;
|
||||
public static final int ABS_THROTTLE = 0x06;
|
||||
public static final int ABS_RUDDER = 0x07;
|
||||
public static final int ABS_WHEEL = 0x08;
|
||||
public static final int ABS_GAS = 0x09;
|
||||
public static final int ABS_BRAKE = 0x0a;
|
||||
public static final int ABS_HAT0X = 0x10;
|
||||
public static final int ABS_HAT0Y = 0x11;
|
||||
public static final int ABS_HAT1X = 0x12;
|
||||
public static final int ABS_HAT1Y = 0x13;
|
||||
public static final int ABS_HAT2X = 0x14;
|
||||
public static final int ABS_HAT2Y = 0x15;
|
||||
public static final int ABS_HAT3X = 0x16;
|
||||
public static final int ABS_HAT3Y = 0x17;
|
||||
public static final int ABS_PRESSURE = 0x18;
|
||||
public static final int ABS_DISTANCE = 0x19;
|
||||
public static final int ABS_TILT_X = 0x1a;
|
||||
public static final int ABS_TILT_Y = 0x1b;
|
||||
public static final int ABS_TOOL_WIDTH = 0x1c;
|
||||
public static final int ABS_VOLUME = 0x20;
|
||||
public static final int ABS_MISC = 0x28;
|
||||
public static final int ABS_MT_TOUCH_MAJOR = 0x30;
|
||||
public static final int ABS_MT_TOUCH_MINOR = 0x31;
|
||||
public static final int ABS_MT_WIDTH_MAJOR = 0x32;
|
||||
public static final int ABS_MT_WIDTH_MINOR = 0x33;
|
||||
public static final int ABS_MT_ORIENTATION = 0x34;
|
||||
public static final int ABS_MT_POSITION_X = 0x35;
|
||||
public static final int ABS_MT_POSITION_Y = 0x36;
|
||||
public static final int ABS_MT_TOOL_TYPE = 0x37;
|
||||
public static final int ABS_MT_BLOB_ID = 0x38;
|
||||
public static final int ABS_MAX = 0x3f;
|
||||
|
||||
// Switch events
|
||||
public static final int SW_LID = 0x00;
|
||||
|
||||
public static final int SYN_REPORT = 0;
|
||||
public static final int SYN_CONFIG = 1;
|
||||
public static final int SYN_MT_REPORT = 2;
|
||||
|
||||
public int deviceId;
|
||||
public int type;
|
||||
public int scancode;
|
||||
public int keycode;
|
||||
public int flags;
|
||||
public int value;
|
||||
public long when;
|
||||
}
|
@ -625,41 +625,6 @@ public class SurfaceView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchKey(KeyEvent event) {
|
||||
SurfaceView surfaceView = mSurfaceView.get();
|
||||
if (surfaceView != null) {
|
||||
//Log.w("SurfaceView", "Unexpected key event in surface: " + event);
|
||||
if (surfaceView.mSession != null && surfaceView.mSurface != null) {
|
||||
try {
|
||||
surfaceView.mSession.finishKey(surfaceView.mWindow);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);
|
||||
//if (mSession != null && mSurface != null) {
|
||||
// try {
|
||||
// //mSession.finishKey(mWindow);
|
||||
// } catch (RemoteException ex) {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);
|
||||
//if (mSession != null && mSurface != null) {
|
||||
// try {
|
||||
// //mSession.finishKey(mWindow);
|
||||
// } catch (RemoteException ex) {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public void dispatchAppVisibility(boolean visible) {
|
||||
// The point of SurfaceView is to let the app control the surface.
|
||||
}
|
||||
@ -686,7 +651,6 @@ public class SurfaceView extends View {
|
||||
private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
|
||||
|
||||
private static final String LOG_TAG = "SurfaceHolder";
|
||||
private int mSaveCount;
|
||||
|
||||
public boolean isCreating() {
|
||||
return mIsCreating;
|
||||
|
@ -556,18 +556,16 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
"Unable to add window -- unknown error code " + res);
|
||||
}
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
if (view instanceof RootViewSurfaceTaker) {
|
||||
mInputQueueCallback =
|
||||
((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
|
||||
}
|
||||
if (mInputQueueCallback != null) {
|
||||
mInputQueue = new InputQueue(mInputChannel);
|
||||
mInputQueueCallback.onInputQueueCreated(mInputQueue);
|
||||
} else {
|
||||
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
|
||||
Looper.myQueue());
|
||||
}
|
||||
if (view instanceof RootViewSurfaceTaker) {
|
||||
mInputQueueCallback =
|
||||
((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
|
||||
}
|
||||
if (mInputQueueCallback != null) {
|
||||
mInputQueue = new InputQueue(mInputChannel);
|
||||
mInputQueueCallback.onInputQueueCreated(mInputQueue);
|
||||
} else {
|
||||
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
|
||||
Looper.myQueue());
|
||||
}
|
||||
|
||||
view.assignParent(this);
|
||||
@ -1745,16 +1743,12 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
mSurface.release();
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
if (mInputChannel != null) {
|
||||
if (mInputQueueCallback != null) {
|
||||
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
|
||||
mInputQueueCallback = null;
|
||||
} else {
|
||||
InputQueue.unregisterInputChannel(mInputChannel);
|
||||
}
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
if (mInputChannel != null) {
|
||||
if (mInputQueueCallback != null) {
|
||||
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
|
||||
mInputQueueCallback = null;
|
||||
} else {
|
||||
InputQueue.unregisterInputChannel(mInputChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1763,13 +1757,11 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
// Dispose the input channel after removing the window so the Window Manager
|
||||
// doesn't interpret the input channel being closed as an abnormal termination.
|
||||
if (mInputChannel != null) {
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
}
|
||||
// Dispose the input channel after removing the window so the Window Manager
|
||||
// doesn't interpret the input channel being closed as an abnormal termination.
|
||||
if (mInputChannel != null) {
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1869,105 +1861,22 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
deliverKeyEvent((KeyEvent)msg.obj, true);
|
||||
break;
|
||||
case DISPATCH_POINTER: {
|
||||
MotionEvent event = (MotionEvent)msg.obj;
|
||||
boolean callWhenDone = msg.arg1 != 0;
|
||||
|
||||
if (event == null) {
|
||||
long timeBeforeGettingEvents;
|
||||
if (MEASURE_LATENCY) {
|
||||
timeBeforeGettingEvents = System.nanoTime();
|
||||
}
|
||||
|
||||
event = getPendingPointerMotionEvent();
|
||||
|
||||
if (MEASURE_LATENCY && event != null) {
|
||||
lt.sample("9 Client got events ", System.nanoTime() - event.getEventTimeNano());
|
||||
lt.sample("8 Client getting events ", timeBeforeGettingEvents - event.getEventTimeNano());
|
||||
}
|
||||
callWhenDone = false;
|
||||
}
|
||||
if (event != null && mTranslator != null) {
|
||||
mTranslator.translateEventInScreenToAppWindow(event);
|
||||
}
|
||||
MotionEvent event = (MotionEvent) msg.obj;
|
||||
try {
|
||||
boolean handled;
|
||||
if (mView != null && mAdded && event != null) {
|
||||
|
||||
// enter touch mode on the down
|
||||
boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
|
||||
if (isDown) {
|
||||
ensureTouchMode(true);
|
||||
}
|
||||
if(Config.LOGV) {
|
||||
captureMotionLog("captureDispatchPointer", event);
|
||||
}
|
||||
if (mCurScrollY != 0) {
|
||||
event.offsetLocation(0, mCurScrollY);
|
||||
}
|
||||
if (MEASURE_LATENCY) {
|
||||
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
|
||||
}
|
||||
handled = mView.dispatchTouchEvent(event);
|
||||
if (MEASURE_LATENCY) {
|
||||
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
|
||||
}
|
||||
if (!handled && isDown) {
|
||||
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
|
||||
|
||||
final int edgeFlags = event.getEdgeFlags();
|
||||
int direction = View.FOCUS_UP;
|
||||
int x = (int)event.getX();
|
||||
int y = (int)event.getY();
|
||||
final int[] deltas = new int[2];
|
||||
|
||||
if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
|
||||
direction = View.FOCUS_DOWN;
|
||||
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
deltas[0] = edgeSlop;
|
||||
x += edgeSlop;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
deltas[0] = -edgeSlop;
|
||||
x -= edgeSlop;
|
||||
}
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
|
||||
direction = View.FOCUS_UP;
|
||||
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
deltas[0] = edgeSlop;
|
||||
x += edgeSlop;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
deltas[0] = -edgeSlop;
|
||||
x -= edgeSlop;
|
||||
}
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
direction = View.FOCUS_RIGHT;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
direction = View.FOCUS_LEFT;
|
||||
}
|
||||
|
||||
if (edgeFlags != 0 && mView instanceof ViewGroup) {
|
||||
View nearest = FocusFinder.getInstance().findNearestTouchable(
|
||||
((ViewGroup) mView), x, y, direction, deltas);
|
||||
if (nearest != null) {
|
||||
event.offsetLocation(deltas[0], deltas[1]);
|
||||
event.setEdgeFlags(0);
|
||||
mView.dispatchTouchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
deliverPointerEvent(event);
|
||||
} finally {
|
||||
if (callWhenDone) {
|
||||
finishMotionEvent();
|
||||
}
|
||||
recycleMotionEvent(event);
|
||||
event.recycle();
|
||||
if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
|
||||
// Let the exception fall through -- the looper will catch
|
||||
// it and take care of the bad app for us.
|
||||
}
|
||||
} break;
|
||||
case DISPATCH_TRACKBALL:
|
||||
deliverTrackballEvent((MotionEvent)msg.obj, msg.arg1 != 0);
|
||||
break;
|
||||
case DISPATCH_TRACKBALL: {
|
||||
MotionEvent event = (MotionEvent) msg.obj;
|
||||
try {
|
||||
deliverTrackballEvent(event);
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
} break;
|
||||
case DISPATCH_APP_VISIBILITY:
|
||||
handleAppVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
@ -2101,61 +2010,12 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
|
||||
private void finishKeyEvent(KeyEvent event) {
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
if (mFinishedCallback != null) {
|
||||
mFinishedCallback.run();
|
||||
mFinishedCallback = null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sWindowSession.finishKey(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
if (mFinishedCallback != null) {
|
||||
mFinishedCallback.run();
|
||||
mFinishedCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void finishMotionEvent() {
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
throw new IllegalStateException("Should not be reachable with native input dispatch.");
|
||||
}
|
||||
|
||||
try {
|
||||
sWindowSession.finishKey(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private void recycleMotionEvent(MotionEvent event) {
|
||||
if (event != null) {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
private MotionEvent getPendingPointerMotionEvent() {
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
throw new IllegalStateException("Should not be reachable with native input dispatch.");
|
||||
}
|
||||
|
||||
try {
|
||||
return sWindowSession.getPendingPointerMove(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private MotionEvent getPendingTrackballMotionEvent() {
|
||||
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
|
||||
throw new IllegalStateException("Should not be reachable with native input dispatch.");
|
||||
}
|
||||
|
||||
try {
|
||||
return sWindowSession.getPendingTrackballMove(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Something in the current window tells us we need to change the touch mode. For
|
||||
* example, we are not in touch mode, and the user touches the screen.
|
||||
@ -2277,42 +2137,95 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void deliverTrackballEvent(MotionEvent event, boolean callWhenDone) {
|
||||
if (event == null) {
|
||||
event = getPendingTrackballMotionEvent();
|
||||
callWhenDone = false;
|
||||
private void deliverPointerEvent(MotionEvent event) {
|
||||
if (mTranslator != null) {
|
||||
mTranslator.translateEventInScreenToAppWindow(event);
|
||||
}
|
||||
|
||||
boolean handled;
|
||||
if (mView != null && mAdded) {
|
||||
|
||||
// enter touch mode on the down
|
||||
boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
|
||||
if (isDown) {
|
||||
ensureTouchMode(true);
|
||||
}
|
||||
if(Config.LOGV) {
|
||||
captureMotionLog("captureDispatchPointer", event);
|
||||
}
|
||||
if (mCurScrollY != 0) {
|
||||
event.offsetLocation(0, mCurScrollY);
|
||||
}
|
||||
if (MEASURE_LATENCY) {
|
||||
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
|
||||
}
|
||||
handled = mView.dispatchTouchEvent(event);
|
||||
if (MEASURE_LATENCY) {
|
||||
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
|
||||
}
|
||||
if (!handled && isDown) {
|
||||
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
|
||||
|
||||
final int edgeFlags = event.getEdgeFlags();
|
||||
int direction = View.FOCUS_UP;
|
||||
int x = (int)event.getX();
|
||||
int y = (int)event.getY();
|
||||
final int[] deltas = new int[2];
|
||||
|
||||
if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
|
||||
direction = View.FOCUS_DOWN;
|
||||
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
deltas[0] = edgeSlop;
|
||||
x += edgeSlop;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
deltas[0] = -edgeSlop;
|
||||
x -= edgeSlop;
|
||||
}
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
|
||||
direction = View.FOCUS_UP;
|
||||
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
deltas[0] = edgeSlop;
|
||||
x += edgeSlop;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
deltas[0] = -edgeSlop;
|
||||
x -= edgeSlop;
|
||||
}
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
|
||||
direction = View.FOCUS_RIGHT;
|
||||
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
|
||||
direction = View.FOCUS_LEFT;
|
||||
}
|
||||
|
||||
if (edgeFlags != 0 && mView instanceof ViewGroup) {
|
||||
View nearest = FocusFinder.getInstance().findNearestTouchable(
|
||||
((ViewGroup) mView), x, y, direction, deltas);
|
||||
if (nearest != null) {
|
||||
event.offsetLocation(deltas[0], deltas[1]);
|
||||
event.setEdgeFlags(0);
|
||||
mView.dispatchTouchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deliverTrackballEvent(MotionEvent event) {
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
|
||||
|
||||
boolean handled = false;
|
||||
try {
|
||||
if (event == null) {
|
||||
handled = true;
|
||||
} else if (mView != null && mAdded) {
|
||||
handled = mView.dispatchTrackballEvent(event);
|
||||
if (!handled) {
|
||||
// we could do something here, like changing the focus
|
||||
// or something?
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (mView != null && mAdded) {
|
||||
handled = mView.dispatchTrackballEvent(event);
|
||||
if (handled) {
|
||||
if (callWhenDone) {
|
||||
finishMotionEvent();
|
||||
}
|
||||
recycleMotionEvent(event);
|
||||
// If we reach this, we delivered a trackball event to mView and
|
||||
// mView consumed it. Because we will not translate the trackball
|
||||
// event into a key event, touch mode will not exit, so we exit
|
||||
// touch mode here.
|
||||
ensureTouchMode(false);
|
||||
//noinspection ReturnInsideFinallyBlock
|
||||
return;
|
||||
}
|
||||
// Let the exception fall through -- the looper will catch
|
||||
// it and take care of the bad app for us.
|
||||
|
||||
// Otherwise we could do something here, like changing the focus
|
||||
// or something?
|
||||
}
|
||||
|
||||
final TrackballAxis x = mTrackballAxisX;
|
||||
@ -2327,95 +2240,86 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
mLastTrackballTime = curTime;
|
||||
}
|
||||
|
||||
try {
|
||||
final int action = event.getAction();
|
||||
final int metastate = event.getMetaState();
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
x.reset(2);
|
||||
y.reset(2);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
|
||||
0, metastate), false);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
x.reset(2);
|
||||
y.reset(2);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
|
||||
0, metastate), false);
|
||||
break;
|
||||
}
|
||||
final int action = event.getAction();
|
||||
final int metastate = event.getMetaState();
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
x.reset(2);
|
||||
y.reset(2);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
|
||||
0, metastate), false);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
x.reset(2);
|
||||
y.reset(2);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
|
||||
0, metastate), false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
|
||||
+ x.step + " dir=" + x.dir + " acc=" + x.acceleration
|
||||
+ " move=" + event.getX()
|
||||
+ " / Y=" + y.position + " step="
|
||||
+ y.step + " dir=" + y.dir + " acc=" + y.acceleration
|
||||
+ " move=" + event.getY());
|
||||
final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
|
||||
final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
|
||||
+ x.step + " dir=" + x.dir + " acc=" + x.acceleration
|
||||
+ " move=" + event.getX()
|
||||
+ " / Y=" + y.position + " step="
|
||||
+ y.step + " dir=" + y.dir + " acc=" + y.acceleration
|
||||
+ " move=" + event.getY());
|
||||
final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
|
||||
final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
|
||||
|
||||
// Generate DPAD events based on the trackball movement.
|
||||
// We pick the axis that has moved the most as the direction of
|
||||
// the DPAD. When we generate DPAD events for one axis, then the
|
||||
// other axis is reset -- we don't want to perform DPAD jumps due
|
||||
// to slight movements in the trackball when making major movements
|
||||
// along the other axis.
|
||||
int keycode = 0;
|
||||
int movement = 0;
|
||||
float accel = 1;
|
||||
if (xOff > yOff) {
|
||||
movement = x.generate((2/event.getXPrecision()));
|
||||
if (movement != 0) {
|
||||
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
: KeyEvent.KEYCODE_DPAD_LEFT;
|
||||
accel = x.acceleration;
|
||||
y.reset(2);
|
||||
}
|
||||
} else if (yOff > 0) {
|
||||
movement = y.generate((2/event.getYPrecision()));
|
||||
if (movement != 0) {
|
||||
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
|
||||
: KeyEvent.KEYCODE_DPAD_UP;
|
||||
accel = y.acceleration;
|
||||
x.reset(2);
|
||||
}
|
||||
// Generate DPAD events based on the trackball movement.
|
||||
// We pick the axis that has moved the most as the direction of
|
||||
// the DPAD. When we generate DPAD events for one axis, then the
|
||||
// other axis is reset -- we don't want to perform DPAD jumps due
|
||||
// to slight movements in the trackball when making major movements
|
||||
// along the other axis.
|
||||
int keycode = 0;
|
||||
int movement = 0;
|
||||
float accel = 1;
|
||||
if (xOff > yOff) {
|
||||
movement = x.generate((2/event.getXPrecision()));
|
||||
if (movement != 0) {
|
||||
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
: KeyEvent.KEYCODE_DPAD_LEFT;
|
||||
accel = x.acceleration;
|
||||
y.reset(2);
|
||||
}
|
||||
} else if (yOff > 0) {
|
||||
movement = y.generate((2/event.getYPrecision()));
|
||||
if (movement != 0) {
|
||||
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
|
||||
: KeyEvent.KEYCODE_DPAD_UP;
|
||||
accel = y.acceleration;
|
||||
x.reset(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (keycode != 0) {
|
||||
if (movement < 0) movement = -movement;
|
||||
int accelMovement = (int)(movement * accel);
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
|
||||
+ " accelMovement=" + accelMovement
|
||||
+ " accel=" + accel);
|
||||
if (accelMovement > movement) {
|
||||
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
|
||||
+ keycode);
|
||||
movement--;
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_MULTIPLE, keycode,
|
||||
accelMovement-movement, metastate), false);
|
||||
}
|
||||
while (movement > 0) {
|
||||
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
|
||||
+ keycode);
|
||||
movement--;
|
||||
curTime = SystemClock.uptimeMillis();
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_UP, keycode, 0, metastate), false);
|
||||
}
|
||||
mLastTrackballTime = curTime;
|
||||
if (keycode != 0) {
|
||||
if (movement < 0) movement = -movement;
|
||||
int accelMovement = (int)(movement * accel);
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
|
||||
+ " accelMovement=" + accelMovement
|
||||
+ " accel=" + accel);
|
||||
if (accelMovement > movement) {
|
||||
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
|
||||
+ keycode);
|
||||
movement--;
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_MULTIPLE, keycode,
|
||||
accelMovement-movement, metastate), false);
|
||||
}
|
||||
} finally {
|
||||
if (callWhenDone) {
|
||||
finishMotionEvent();
|
||||
recycleMotionEvent(event);
|
||||
while (movement > 0) {
|
||||
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
|
||||
+ keycode);
|
||||
movement--;
|
||||
curTime = SystemClock.uptimeMillis();
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
|
||||
deliverKeyEvent(new KeyEvent(curTime, curTime,
|
||||
KeyEvent.ACTION_UP, keycode, 0, metastate), false);
|
||||
}
|
||||
// Let the exception fall through -- the looper will catch
|
||||
// it and take care of the bad app for us.
|
||||
mLastTrackballTime = curTime;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2862,45 +2766,20 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
private final InputHandler mInputHandler = new InputHandler() {
|
||||
public void handleKey(KeyEvent event, Runnable finishedCallback) {
|
||||
mFinishedCallback = finishedCallback;
|
||||
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
//noinspection ConstantConditions
|
||||
if (false && event.getKeyCode() == KeyEvent.KEYCODE_CAMERA) {
|
||||
if (Config.LOGD) Log.d("keydisp",
|
||||
"===================================================");
|
||||
if (Config.LOGD) Log.d("keydisp", "Focused view Hierarchy is:");
|
||||
debug();
|
||||
|
||||
if (Config.LOGD) Log.d("keydisp",
|
||||
"===================================================");
|
||||
}
|
||||
}
|
||||
|
||||
Message msg = obtainMessage(DISPATCH_KEY);
|
||||
msg.obj = event;
|
||||
|
||||
if (LOCAL_LOGV) Log.v(
|
||||
"ViewRoot", "sending key " + event + " to " + mView);
|
||||
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
dispatchKey(event);
|
||||
}
|
||||
|
||||
public void handleTouch(MotionEvent event, Runnable finishedCallback) {
|
||||
finishedCallback.run();
|
||||
|
||||
Message msg = obtainMessage(DISPATCH_POINTER);
|
||||
msg.obj = event;
|
||||
msg.arg1 = 0;
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
dispatchPointer(event);
|
||||
}
|
||||
|
||||
public void handleTrackball(MotionEvent event, Runnable finishedCallback) {
|
||||
finishedCallback.run();
|
||||
|
||||
Message msg = obtainMessage(DISPATCH_TRACKBALL);
|
||||
msg.obj = event;
|
||||
msg.arg1 = 0;
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
dispatchTrackball(event);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2927,22 +2806,18 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
public void dispatchPointer(MotionEvent event) {
|
||||
Message msg = obtainMessage(DISPATCH_POINTER);
|
||||
msg.obj = event;
|
||||
msg.arg1 = callWhenDone ? 1 : 0;
|
||||
sendMessageAtTime(msg, eventTime);
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
public void dispatchTrackball(MotionEvent event) {
|
||||
Message msg = obtainMessage(DISPATCH_TRACKBALL);
|
||||
msg.obj = event;
|
||||
msg.arg1 = callWhenDone ? 1 : 0;
|
||||
sendMessageAtTime(msg, eventTime);
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
}
|
||||
|
||||
|
||||
public void dispatchAppVisibility(boolean visible) {
|
||||
Message msg = obtainMessage(DISPATCH_APP_VISIBILITY);
|
||||
msg.arg1 = visible ? 1 : 0;
|
||||
@ -3073,56 +2948,11 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
class EventCompletion extends Handler {
|
||||
final IWindow mWindow;
|
||||
final KeyEvent mKeyEvent;
|
||||
final boolean mIsPointer;
|
||||
final MotionEvent mMotionEvent;
|
||||
|
||||
EventCompletion(Looper looper, IWindow window, KeyEvent key,
|
||||
boolean isPointer, MotionEvent motion) {
|
||||
super(looper);
|
||||
mWindow = window;
|
||||
mKeyEvent = key;
|
||||
mIsPointer = isPointer;
|
||||
mMotionEvent = motion;
|
||||
sendEmptyMessage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mKeyEvent != null) {
|
||||
finishKeyEvent(mKeyEvent);
|
||||
} else if (mIsPointer) {
|
||||
boolean didFinish;
|
||||
MotionEvent event = mMotionEvent;
|
||||
if (event == null) {
|
||||
event = getPendingPointerMotionEvent();
|
||||
didFinish = true;
|
||||
} else {
|
||||
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
|
||||
}
|
||||
if (!didFinish) {
|
||||
finishMotionEvent();
|
||||
}
|
||||
} else {
|
||||
MotionEvent event = mMotionEvent;
|
||||
if (event == null) {
|
||||
event = getPendingTrackballMotionEvent();
|
||||
} else {
|
||||
finishMotionEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class W extends IWindow.Stub {
|
||||
private final WeakReference<ViewRoot> mViewRoot;
|
||||
private final Looper mMainLooper;
|
||||
|
||||
public W(ViewRoot viewRoot, Context context) {
|
||||
mViewRoot = new WeakReference<ViewRoot>(viewRoot);
|
||||
mMainLooper = context.getMainLooper();
|
||||
}
|
||||
|
||||
public void resized(int w, int h, Rect coveredInsets,
|
||||
@ -3134,40 +2964,6 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchKey(KeyEvent event) {
|
||||
final ViewRoot viewRoot = mViewRoot.get();
|
||||
if (viewRoot != null) {
|
||||
viewRoot.dispatchKey(event);
|
||||
} else {
|
||||
Log.w("ViewRoot.W", "Key event " + event + " but no ViewRoot available!");
|
||||
viewRoot.new EventCompletion(mMainLooper, this, event, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
final ViewRoot viewRoot = mViewRoot.get();
|
||||
if (viewRoot != null) {
|
||||
if (MEASURE_LATENCY) {
|
||||
// Note: eventTime is in milliseconds
|
||||
ViewRoot.lt.sample("* ViewRoot b4 dispatchPtr", System.nanoTime() - eventTime * 1000000);
|
||||
}
|
||||
viewRoot.dispatchPointer(event, eventTime, callWhenDone);
|
||||
} else {
|
||||
viewRoot.new EventCompletion(mMainLooper, this, null, true, event);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
final ViewRoot viewRoot = mViewRoot.get();
|
||||
if (viewRoot != null) {
|
||||
viewRoot.dispatchTrackball(event, eventTime, callWhenDone);
|
||||
} else {
|
||||
viewRoot.new EventCompletion(mMainLooper, this, null, false, event);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchAppVisibility(boolean visible) {
|
||||
final ViewRoot viewRoot = mViewRoot.get();
|
||||
if (viewRoot != null) {
|
||||
|
@ -78,12 +78,6 @@ public interface WindowManagerPolicy {
|
||||
public final static int FLAG_BRIGHT_HERE = 0x20000000;
|
||||
|
||||
public final static boolean WATCH_POINTER = false;
|
||||
|
||||
/**
|
||||
* Temporary flag added during the transition to the new native input dispatcher.
|
||||
* This will be removed when the old input dispatch code is deleted.
|
||||
*/
|
||||
public final static boolean ENABLE_NATIVE_INPUT_DISPATCH = true;
|
||||
|
||||
// flags for interceptKeyTq
|
||||
/**
|
||||
@ -555,23 +549,26 @@ public interface WindowManagerPolicy {
|
||||
public Animation createForceHideEnterAnimation();
|
||||
|
||||
/**
|
||||
* Called from the key queue thread before a key is dispatched to the
|
||||
* input thread.
|
||||
* Called from the input reader thread before a key is enqueued.
|
||||
*
|
||||
* <p>There are some actions that need to be handled here because they
|
||||
* affect the power state of the device, for example, the power keys.
|
||||
* Generally, it's best to keep as little as possible in the queue thread
|
||||
* because it's the most fragile.
|
||||
* @param whenNanos The event time in uptime nanoseconds.
|
||||
* @param keyCode The key code.
|
||||
* @param down True if the key is down.
|
||||
* @param policyFlags The policy flags associated with the key.
|
||||
* @param isScreenOn True if the screen is already on
|
||||
*
|
||||
* @param event the raw input event as read from the driver
|
||||
* @param screenIsOn true if the screen is already on
|
||||
* @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
|
||||
* {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
|
||||
*/
|
||||
public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);
|
||||
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags,
|
||||
boolean isScreenOn);
|
||||
|
||||
/**
|
||||
* Called from the input thread before a key is dispatched to a window.
|
||||
* Called from the input dispatcher thread before a key is dispatched to a window.
|
||||
*
|
||||
* <p>Allows you to define
|
||||
* behavior for keys that can not be overridden by applications or redirect
|
||||
@ -583,16 +580,17 @@ 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 bit mask of meta keys that are held.
|
||||
* @param down Is this a key press (true) or release (false)?
|
||||
* @param action The key event action.
|
||||
* @param flags The key event flags.
|
||||
* @param keyCode The key code.
|
||||
* @param metaState bit mask of meta keys that are held.
|
||||
* @param repeatCount Number of times a key down has repeated.
|
||||
* @param flags event's flags.
|
||||
* @param policyFlags The policy flags associated with the key.
|
||||
* @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 flags);
|
||||
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
|
||||
int keyCode, int metaState, int repeatCount, int policyFlags);
|
||||
|
||||
/**
|
||||
* Called when layout of the windows is about to start.
|
||||
@ -701,84 +699,14 @@ public interface WindowManagerPolicy {
|
||||
* Return whether the screen is currently on.
|
||||
*/
|
||||
public boolean isScreenOn();
|
||||
|
||||
|
||||
/**
|
||||
* Perform any initial processing of a low-level input event before the
|
||||
* window manager handles special keys and generates a high-level event
|
||||
* that is dispatched to the application.
|
||||
*
|
||||
* @param event The input event that has occurred.
|
||||
*
|
||||
* @return Return true if you have consumed the event and do not want
|
||||
* further processing to occur; return false for normal processing.
|
||||
* Tell the policy that the lid switch has changed state.
|
||||
* @param whenNanos The time when the change occurred in uptime nanoseconds.
|
||||
* @param lidOpen True if the lid is now open.
|
||||
*/
|
||||
public boolean preprocessInputEventTq(RawInputEvent event);
|
||||
|
||||
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
|
||||
|
||||
/**
|
||||
* Determine whether a given key code is used to cause an app switch
|
||||
* to occur (most often the HOME key, also often ENDCALL). If you return
|
||||
* true, then the system will go into a special key processing state
|
||||
* where it drops any pending events that it cans and adjusts timeouts to
|
||||
* try to get to this key as quickly as possible.
|
||||
*
|
||||
* <p>Note that this function is called from the low-level input queue
|
||||
* thread, with either/or the window or input lock held; be very careful
|
||||
* about what you do here. You absolutely should never acquire a lock
|
||||
* that you would ever hold elsewhere while calling out into the window
|
||||
* manager or view hierarchy.
|
||||
*
|
||||
* @param keycode The key that should be checked for performing an
|
||||
* app switch before delivering to the application.
|
||||
*
|
||||
* @return Return true if this is an app switch key and special processing
|
||||
* should happen; return false for normal processing.
|
||||
*/
|
||||
public boolean isAppSwitchKeyTqTiLwLi(int keycode);
|
||||
|
||||
/**
|
||||
* Determine whether a given key code is used for movement within a UI,
|
||||
* and does not generally cause actions to be performed (normally the DPAD
|
||||
* movement keys, NOT the DPAD center press key). This is called
|
||||
* when {@link #isAppSwitchKeyTiLi} returns true to remove any pending events
|
||||
* in the key queue that are not needed to switch applications.
|
||||
*
|
||||
* <p>Note that this function is called from the low-level input queue
|
||||
* thread; be very careful about what you do here.
|
||||
*
|
||||
* @param keycode The key that is waiting to be delivered to the
|
||||
* application.
|
||||
*
|
||||
* @return Return true if this is a purely navigation key and can be
|
||||
* dropped without negative consequences; return false to keep it.
|
||||
*/
|
||||
public boolean isMovementKeyTi(int keycode);
|
||||
|
||||
/**
|
||||
* Given the current state of the world, should this relative movement
|
||||
* wake up the device?
|
||||
*
|
||||
* @param device The device the movement came from.
|
||||
* @param classes The input classes associated with the device.
|
||||
* @param event The input event that occurred.
|
||||
* @return
|
||||
*/
|
||||
public boolean isWakeRelMovementTq(int device, int classes,
|
||||
RawInputEvent event);
|
||||
|
||||
/**
|
||||
* Given the current state of the world, should this absolute movement
|
||||
* wake up the device?
|
||||
*
|
||||
* @param device The device the movement came from.
|
||||
* @param classes The input classes associated with the device.
|
||||
* @param event The input event that occurred.
|
||||
* @return
|
||||
*/
|
||||
public boolean isWakeAbsMovementTq(int device, int classes,
|
||||
RawInputEvent event);
|
||||
|
||||
/**
|
||||
* Tell the policy if anyone is requesting that keyguard not come on.
|
||||
*
|
||||
@ -851,18 +779,6 @@ public interface WindowManagerPolicy {
|
||||
*/
|
||||
public void enableScreenAfterBoot();
|
||||
|
||||
/**
|
||||
* Returns true if the user's cheek has been pressed against the phone. This is
|
||||
* determined by comparing the event's size attribute with a threshold value.
|
||||
* For example for a motion event like down or up or move, if the size exceeds
|
||||
* the threshold, it is considered as cheek press.
|
||||
* @param ev the motion event generated when the cheek is pressed
|
||||
* against the phone
|
||||
* @return Returns true if the user's cheek has been pressed against the phone
|
||||
* screen resulting in an invalid motion event
|
||||
*/
|
||||
public boolean isCheekPressedAgainstScreen(MotionEvent ev);
|
||||
|
||||
/**
|
||||
* Called every time the window manager is dispatching a pointer event.
|
||||
*/
|
||||
@ -875,13 +791,6 @@ 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.
|
||||
|
@ -43,59 +43,6 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchKey(KeyEvent event) {
|
||||
try {
|
||||
mSession.finishKey(this);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onDispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
event.recycle();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
try {
|
||||
if (event == null) {
|
||||
event = mSession.getPendingPointerMove(this);
|
||||
onDispatchPointer(event, eventTime, false);
|
||||
} else if (callWhenDone) {
|
||||
if (!onDispatchPointer(event, eventTime, true)) {
|
||||
mSession.finishKey(this);
|
||||
}
|
||||
} else {
|
||||
onDispatchPointer(event, eventTime, false);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onDispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
event.recycle();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
try {
|
||||
if (event == null) {
|
||||
event = mSession.getPendingTrackballMove(this);
|
||||
onDispatchTrackball(event, eventTime, false);
|
||||
} else if (callWhenDone) {
|
||||
if (!onDispatchTrackball(event, eventTime, true)) {
|
||||
mSession.finishKey(this);
|
||||
}
|
||||
} else {
|
||||
onDispatchTrackball(event, eventTime, false);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchAppVisibility(boolean visible) {
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,13 @@ struct InputDevice {
|
||||
nsecs_t downTime;
|
||||
|
||||
struct CurrentVirtualKeyState {
|
||||
bool down;
|
||||
enum Status {
|
||||
STATUS_UP,
|
||||
STATUS_DOWN,
|
||||
STATUS_CANCELED
|
||||
};
|
||||
|
||||
Status status;
|
||||
nsecs_t downTime;
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
@ -295,6 +301,7 @@ struct InputDevice {
|
||||
void calculatePointerIds();
|
||||
|
||||
bool isPointInsideDisplay(int32_t x, int32_t y) const;
|
||||
const InputDevice::VirtualKey* findVirtualKeyHit() const;
|
||||
};
|
||||
|
||||
InputDevice(int32_t id, uint32_t classes, String8 name);
|
||||
@ -390,11 +397,9 @@ public:
|
||||
virtual bool getDisplayInfo(int32_t displayId,
|
||||
int32_t* width, int32_t* height, int32_t* orientation) = 0;
|
||||
|
||||
/* Provides feedback for a virtual key.
|
||||
/* Provides feedback for a virtual key down.
|
||||
*/
|
||||
virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
|
||||
int32_t action, int32_t flags, int32_t keyCode,
|
||||
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
|
||||
virtual void virtualKeyDownFeedback() = 0;
|
||||
|
||||
/* Intercepts a key event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
|
@ -299,14 +299,13 @@ void InputDispatcher::processKeyRepeatLockedInterruptible(
|
||||
uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
|
||||
if (entry->refCount == 1) {
|
||||
entry->eventTime = currentTime;
|
||||
entry->downTime = currentTime;
|
||||
entry->policyFlags = policyFlags;
|
||||
entry->repeatCount += 1;
|
||||
} else {
|
||||
KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
|
||||
entry->deviceId, entry->nature, policyFlags,
|
||||
entry->action, entry->flags, entry->keyCode, entry->scanCode,
|
||||
entry->metaState, entry->repeatCount + 1, currentTime);
|
||||
entry->metaState, entry->repeatCount + 1, entry->downTime);
|
||||
|
||||
mKeyRepeatState.lastKeyEntry = newEntry;
|
||||
mAllocator.releaseKeyEntry(entry);
|
||||
@ -314,6 +313,10 @@ void InputDispatcher::processKeyRepeatLockedInterruptible(
|
||||
entry = newEntry;
|
||||
}
|
||||
|
||||
if (entry->repeatCount == 1) {
|
||||
entry->flags |= KEY_EVENT_FLAG_LONG_PRESS;
|
||||
}
|
||||
|
||||
mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
|
||||
|
||||
#if DEBUG_OUTBOUND_EVENT_DETAILS
|
||||
|
@ -189,7 +189,7 @@ void InputDevice::TrackballState::reset() {
|
||||
void InputDevice::TouchScreenState::reset() {
|
||||
lastTouch.clear();
|
||||
downTime = 0;
|
||||
currentVirtualKey.down = false;
|
||||
currentVirtualKey.status = CurrentVirtualKeyState::STATUS_UP;
|
||||
|
||||
for (uint32_t i = 0; i < MAX_POINTERS; i++) {
|
||||
averagingTouchFilter.historyStart[i] = 0;
|
||||
@ -746,6 +746,29 @@ bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) c
|
||||
&& y <= parameters.yAxis.maxValue;
|
||||
}
|
||||
|
||||
const InputDevice::VirtualKey* InputDevice::TouchScreenState::findVirtualKeyHit() const {
|
||||
int32_t x = currentTouch.pointers[0].x;
|
||||
int32_t y = currentTouch.pointers[0].y;
|
||||
for (size_t i = 0; i < virtualKeys.size(); i++) {
|
||||
const InputDevice::VirtualKey& virtualKey = virtualKeys[i];
|
||||
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
|
||||
"left=%d, top=%d, right=%d, bottom=%d",
|
||||
x, y,
|
||||
virtualKey.keyCode, virtualKey.scanCode,
|
||||
virtualKey.hitLeft, virtualKey.hitTop,
|
||||
virtualKey.hitRight, virtualKey.hitBottom);
|
||||
#endif
|
||||
|
||||
if (virtualKey.isHit(x, y)) {
|
||||
return & virtualKey;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDevice::SingleTouchScreenState ---
|
||||
|
||||
@ -1269,81 +1292,76 @@ void InputReader::onTouchScreenChanged(nsecs_t when,
|
||||
|
||||
bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
|
||||
InputDevice* device, uint32_t policyFlags) {
|
||||
if (device->touchScreen.currentVirtualKey.down) {
|
||||
switch (device->touchScreen.currentVirtualKey.status) {
|
||||
case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED:
|
||||
if (device->touchScreen.currentTouch.pointerCount == 0) {
|
||||
// Pointer went up while virtual key was down. Send key up event.
|
||||
device->touchScreen.currentVirtualKey.down = false;
|
||||
// Pointer went up after virtual key canceled.
|
||||
device->touchScreen.currentVirtualKey.status =
|
||||
InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
|
||||
}
|
||||
return true; // consumed
|
||||
|
||||
case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN:
|
||||
if (device->touchScreen.currentTouch.pointerCount == 0) {
|
||||
// Pointer went up while virtual key was down.
|
||||
device->touchScreen.currentVirtualKey.status =
|
||||
InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
|
||||
device->touchScreen.currentVirtualKey.keyCode,
|
||||
device->touchScreen.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
|
||||
dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
|
||||
KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
|
||||
return true; // consumed
|
||||
}
|
||||
|
||||
int32_t x = device->touchScreen.currentTouch.pointers[0].x;
|
||||
int32_t y = device->touchScreen.currentTouch.pointers[0].y;
|
||||
if (device->touchScreen.isPointInsideDisplay(x, y)
|
||||
|| device->touchScreen.currentTouch.pointerCount != 1) {
|
||||
// Pointer moved inside the display area or another pointer also went down.
|
||||
// Send key cancellation.
|
||||
device->touchScreen.currentVirtualKey.down = false;
|
||||
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
|
||||
device->touchScreen.currentVirtualKey.keyCode,
|
||||
device->touchScreen.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
|
||||
dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
|
||||
KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
|
||||
| KEY_EVENT_FLAG_CANCELED);
|
||||
|
||||
// Clear the last touch data so we will consider the pointer as having just been
|
||||
// pressed down when generating subsequent motion events.
|
||||
device->touchScreen.lastTouch.clear();
|
||||
return false; // not consumed
|
||||
if (device->touchScreen.currentTouch.pointerCount == 1) {
|
||||
const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
|
||||
if (virtualKey
|
||||
&& virtualKey->keyCode == device->touchScreen.currentVirtualKey.keyCode) {
|
||||
// Pointer is still within the space of the virtual key.
|
||||
return true; // consumed
|
||||
}
|
||||
}
|
||||
} else if (device->touchScreen.currentTouch.pointerCount == 1
|
||||
&& device->touchScreen.lastTouch.pointerCount == 0) {
|
||||
int32_t x = device->touchScreen.currentTouch.pointers[0].x;
|
||||
int32_t y = device->touchScreen.currentTouch.pointers[0].y;
|
||||
for (size_t i = 0; i < device->touchScreen.virtualKeys.size(); i++) {
|
||||
const InputDevice::VirtualKey& virtualKey = device->touchScreen.virtualKeys[i];
|
||||
|
||||
// Pointer left virtual key area or another pointer also went down.
|
||||
// Send key cancellation.
|
||||
device->touchScreen.currentVirtualKey.status =
|
||||
InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
|
||||
"left=%d, top=%d, right=%d, bottom=%d",
|
||||
x, y,
|
||||
virtualKey.keyCode, virtualKey.scanCode,
|
||||
virtualKey.hitLeft, virtualKey.hitTop,
|
||||
virtualKey.hitRight, virtualKey.hitBottom);
|
||||
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
|
||||
device->touchScreen.currentVirtualKey.keyCode,
|
||||
device->touchScreen.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
|
||||
KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
|
||||
| KEY_EVENT_FLAG_CANCELED);
|
||||
return true; // consumed
|
||||
|
||||
if (virtualKey.isHit(x, y)) {
|
||||
device->touchScreen.currentVirtualKey.down = true;
|
||||
default:
|
||||
if (device->touchScreen.currentTouch.pointerCount == 1
|
||||
&& device->touchScreen.lastTouch.pointerCount == 0) {
|
||||
// Pointer just went down. Check for virtual key hit.
|
||||
const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
|
||||
if (virtualKey) {
|
||||
device->touchScreen.currentVirtualKey.status =
|
||||
InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN;
|
||||
device->touchScreen.currentVirtualKey.downTime = when;
|
||||
device->touchScreen.currentVirtualKey.keyCode = virtualKey.keyCode;
|
||||
device->touchScreen.currentVirtualKey.scanCode = virtualKey.scanCode;
|
||||
|
||||
device->touchScreen.currentVirtualKey.keyCode = virtualKey->keyCode;
|
||||
device->touchScreen.currentVirtualKey.scanCode = virtualKey->scanCode;
|
||||
#if DEBUG_VIRTUAL_KEYS
|
||||
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
|
||||
device->touchScreen.currentVirtualKey.keyCode,
|
||||
device->touchScreen.currentVirtualKey.scanCode);
|
||||
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
|
||||
device->touchScreen.currentVirtualKey.keyCode,
|
||||
device->touchScreen.currentVirtualKey.scanCode);
|
||||
#endif
|
||||
|
||||
dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
|
||||
KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
|
||||
return true; // consumed
|
||||
}
|
||||
}
|
||||
return false; // not consumed
|
||||
}
|
||||
|
||||
return false; // not consumed
|
||||
}
|
||||
|
||||
void InputReader::dispatchVirtualKey(nsecs_t when,
|
||||
@ -1356,8 +1374,9 @@ void InputReader::dispatchVirtualKey(nsecs_t when,
|
||||
nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
|
||||
int32_t metaState = globalMetaState();
|
||||
|
||||
mPolicy->virtualKeyFeedback(when, device->id, keyEventAction, keyEventFlags,
|
||||
keyCode, scanCode, metaState, downTime);
|
||||
if (keyEventAction == KEY_EVENT_ACTION_DOWN) {
|
||||
mPolicy->virtualKeyDownFeedback();
|
||||
}
|
||||
|
||||
int32_t policyActions = mPolicy->interceptKey(when, device->id,
|
||||
keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
|
||||
@ -1852,7 +1871,7 @@ void InputReader::configureVirtualKeys(InputDevice* device) {
|
||||
uint32_t flags;
|
||||
if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
|
||||
& keyCode, & flags)) {
|
||||
LOGI(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
|
||||
LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
|
||||
device->touchScreen.virtualKeys.pop(); // drop the key
|
||||
continue;
|
||||
}
|
||||
@ -1933,7 +1952,8 @@ void InputReader::updateExportedVirtualKeyState() {
|
||||
for (size_t i = 0; i < mDevices.size(); i++) {
|
||||
InputDevice* device = mDevices.valueAt(i);
|
||||
if (device->isTouchScreen()) {
|
||||
if (device->touchScreen.currentVirtualKey.down) {
|
||||
if (device->touchScreen.currentVirtualKey.status
|
||||
== InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN) {
|
||||
keyCode = device->touchScreen.currentVirtualKey.keyCode;
|
||||
scanCode = device->touchScreen.currentVirtualKey.scanCode;
|
||||
}
|
||||
|
@ -60,7 +60,6 @@ import android.view.IWindowManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowOrientationListener;
|
||||
import android.view.RawInputEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
@ -153,8 +152,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
|
||||
static final int APPLICATION_PANEL_SUBLAYER = 1;
|
||||
static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
|
||||
|
||||
static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
|
||||
|
||||
// Debugging: set this to have the system act like there is no hard keyboard.
|
||||
static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
|
||||
@ -164,6 +161,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
|
||||
static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
|
||||
|
||||
// Useful scan codes.
|
||||
private static final int SW_LID = 0x00;
|
||||
private static final int BTN_MOUSE = 0x110;
|
||||
|
||||
final Object mLock = new Object();
|
||||
|
||||
Context mContext;
|
||||
@ -690,7 +691,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
|
||||
void readLidState() {
|
||||
try {
|
||||
int sw = mWindowManager.getSwitchState(RawInputEvent.SW_LID);
|
||||
int sw = mWindowManager.getSwitchState(SW_LID);
|
||||
if (sw >= 0) {
|
||||
mLidOpen = sw == 0;
|
||||
}
|
||||
@ -727,19 +728,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
: Configuration.KEYBOARDHIDDEN_YES;
|
||||
}
|
||||
|
||||
public boolean isCheekPressedAgainstScreen(MotionEvent ev) {
|
||||
if(ev.getSize() > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
|
||||
return true;
|
||||
}
|
||||
int size = ev.getHistorySize();
|
||||
for(int i = 0; i < size; i++) {
|
||||
if(ev.getHistoricalSize(i) > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY) {
|
||||
if (mPointerLocationView == null) {
|
||||
return;
|
||||
@ -1034,19 +1022,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
};
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
|
||||
int repeatCount, int flags) {
|
||||
boolean keyguardOn = keyguardOn();
|
||||
@Override
|
||||
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
|
||||
int keyCode, int metaState, int repeatCount, int policyFlags) {
|
||||
final boolean keyguardOn = keyguardOn();
|
||||
final boolean down = (action == KeyEvent.ACTION_DOWN);
|
||||
final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
|
||||
|
||||
if (false) {
|
||||
Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount="
|
||||
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
|
||||
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
|
||||
}
|
||||
|
||||
// Clear a pending HOME longpress if the user releases Home
|
||||
// TODO: This could probably be inside the next bit of logic, but that code
|
||||
// turned out to be a bit fragile so I'm doing it here explicitly, for now.
|
||||
if ((code == KeyEvent.KEYCODE_HOME) && !down) {
|
||||
if ((keyCode == KeyEvent.KEYCODE_HOME) && !down) {
|
||||
mHandler.removeCallbacks(mHomeLongPress);
|
||||
}
|
||||
|
||||
@ -1056,11 +1047,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
|
||||
// If we have released the home key, and didn't do anything else
|
||||
// while it was pressed, then it is time to go home!
|
||||
if (code == KeyEvent.KEYCODE_HOME) {
|
||||
if (keyCode == KeyEvent.KEYCODE_HOME) {
|
||||
if (!down) {
|
||||
mHomePressed = false;
|
||||
|
||||
if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
|
||||
if (! canceled) {
|
||||
// If an incoming call is ringing, HOME is totally disabled.
|
||||
// (The user is already on the InCallScreen at this point,
|
||||
// and his ONLY options are to answer or reject the call.)
|
||||
@ -1094,7 +1085,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// can never break it, although if keyguard is on, we do let
|
||||
// it handle it, because that gives us the correct 5 second
|
||||
// timeout.
|
||||
if (code == KeyEvent.KEYCODE_HOME) {
|
||||
if (keyCode == KeyEvent.KEYCODE_HOME) {
|
||||
|
||||
// If a system window has focus, then it doesn't make sense
|
||||
// right now to interact with applications.
|
||||
@ -1122,17 +1113,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
mHomePressed = true;
|
||||
}
|
||||
return true;
|
||||
} else if (code == KeyEvent.KEYCODE_MENU) {
|
||||
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
// Hijack modified menu keys for debugging features
|
||||
final int chordBug = KeyEvent.META_SHIFT_ON;
|
||||
|
||||
if (down && repeatCount == 0) {
|
||||
if (mEnableShiftMenuBugReports && (metaKeys & chordBug) == chordBug) {
|
||||
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
|
||||
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
|
||||
mContext.sendOrderedBroadcast(intent, null);
|
||||
return true;
|
||||
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
|
||||
(metaKeys & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
|
||||
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
|
||||
Intent service = new Intent();
|
||||
service.setClassName(mContext, "com.android.server.LoadAverageService");
|
||||
ContentResolver res = mContext.getContentResolver();
|
||||
@ -1148,7 +1139,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (code == KeyEvent.KEYCODE_SEARCH) {
|
||||
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||
if (down) {
|
||||
if (repeatCount == 0) {
|
||||
mSearchKeyPressed = true;
|
||||
@ -1167,7 +1158,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// Shortcuts are invoked through Search+key, so intercept those here
|
||||
if (mSearchKeyPressed) {
|
||||
if (down && repeatCount == 0 && !keyguardOn) {
|
||||
Intent shortcutIntent = mShortcutManager.getIntent(code, metaKeys);
|
||||
Intent shortcutIntent = mShortcutManager.getIntent(keyCode, metaState);
|
||||
if (shortcutIntent != null) {
|
||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(shortcutIntent);
|
||||
@ -1606,42 +1597,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean preprocessInputEventTq(RawInputEvent event) {
|
||||
switch (event.type) {
|
||||
case RawInputEvent.EV_SW:
|
||||
if (event.keycode == RawInputEvent.SW_LID) {
|
||||
// lid changed state
|
||||
mLidOpen = event.value == 0;
|
||||
boolean awakeNow = mKeyguardMediator.doLidChangeTq(mLidOpen);
|
||||
updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
|
||||
if (awakeNow) {
|
||||
// If the lid opening and we don't have to keep the
|
||||
// keyguard up, then we can turn on the screen
|
||||
// immediately.
|
||||
mKeyguardMediator.pokeWakelock();
|
||||
} else if (keyguardIsShowingTq()) {
|
||||
if (mLidOpen) {
|
||||
// If we are opening the lid and not hiding the
|
||||
// keyguard, then we need to have it turn on the
|
||||
// screen once it is shown.
|
||||
mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
|
||||
KeyEvent.KEYCODE_POWER);
|
||||
}
|
||||
} else {
|
||||
// Light up the keyboard if we are sliding up.
|
||||
if (mLidOpen) {
|
||||
mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
|
||||
LocalPowerManager.BUTTON_EVENT);
|
||||
} else {
|
||||
mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
|
||||
LocalPowerManager.OTHER_EVENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
||||
// lid changed state
|
||||
mLidOpen = lidOpen;
|
||||
@ -1672,26 +1627,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isAppSwitchKeyTqTiLwLi(int keycode) {
|
||||
return keycode == KeyEvent.KEYCODE_HOME
|
||||
|| keycode == KeyEvent.KEYCODE_ENDCALL;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isMovementKeyTi(int keycode) {
|
||||
switch (keycode) {
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Whether a telephone call is in progress right now.
|
||||
*/
|
||||
@ -1762,60 +1697,63 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) {
|
||||
@Override
|
||||
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
|
||||
int policyFlags, boolean isScreenOn) {
|
||||
int result = ACTION_PASS_TO_USER;
|
||||
final boolean isWakeKey = isWakeKeyTq(event);
|
||||
|
||||
final boolean isWakeKey = (policyFlags
|
||||
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
|
||||
// If screen is off then we treat the case where the keyguard is open but hidden
|
||||
// the same as if it were open and in front.
|
||||
// This will prevent any keys other than the power button from waking the screen
|
||||
// when the keyguard is hidden by another activity.
|
||||
final boolean keyguardActive = (screenIsOn ?
|
||||
final boolean keyguardActive = (isScreenOn ?
|
||||
mKeyguardMediator.isShowingAndNotHidden() :
|
||||
mKeyguardMediator.isShowing());
|
||||
|
||||
if (false) {
|
||||
Log.d(TAG, "interceptKeyTq event=" + event + " keycode=" + event.keycode
|
||||
+ " screenIsOn=" + screenIsOn + " keyguardActive=" + keyguardActive);
|
||||
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
|
||||
+ " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
|
||||
}
|
||||
|
||||
if (keyguardActive) {
|
||||
if (screenIsOn) {
|
||||
if (isScreenOn) {
|
||||
// when the screen is on, always give the event to the keyguard
|
||||
result |= ACTION_PASS_TO_USER;
|
||||
} else {
|
||||
// otherwise, don't pass it to the user
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
|
||||
final boolean isKeyDown =
|
||||
(event.type == RawInputEvent.EV_KEY) && (event.value != 0);
|
||||
if (isWakeKey && isKeyDown) {
|
||||
if (isWakeKey && down) {
|
||||
|
||||
// tell the mediator about a wake key, it may decide to
|
||||
// turn on the screen depending on whether the key is
|
||||
// appropriate.
|
||||
if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(event.keycode)
|
||||
&& (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
|
||||
|| event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode)
|
||||
&& (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|
||||
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
// when keyguard is showing and screen off, we need
|
||||
// to handle the volume key for calls and music here
|
||||
if (isInCall()) {
|
||||
handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode);
|
||||
handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
|
||||
} else if (isMusicActive()) {
|
||||
handleVolumeKey(AudioManager.STREAM_MUSIC, event.keycode);
|
||||
handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!screenIsOn) {
|
||||
} else if (!isScreenOn) {
|
||||
// If we are in-call with screen off and keyguard is not showing,
|
||||
// then handle the volume key ourselves.
|
||||
// This is necessary because the phone app will disable the keyguard
|
||||
// when the proximity sensor is in use.
|
||||
if (isInCall() && event.type == RawInputEvent.EV_KEY &&
|
||||
(event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
|
||||
|| event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
if (isInCall() &&
|
||||
(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|
||||
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode);
|
||||
handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
|
||||
}
|
||||
if (isWakeKey) {
|
||||
// a wake key has a sole purpose of waking the device; don't pass
|
||||
@ -1825,156 +1763,151 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
int type = event.type;
|
||||
int code = event.keycode;
|
||||
boolean down = event.value != 0;
|
||||
|
||||
if (type == RawInputEvent.EV_KEY) {
|
||||
if (code == KeyEvent.KEYCODE_ENDCALL
|
||||
|| code == KeyEvent.KEYCODE_POWER) {
|
||||
if (down) {
|
||||
boolean handled = false;
|
||||
boolean hungUp = false;
|
||||
// key repeats are generated by the window manager, and we don't see them
|
||||
// here, so unless the driver is doing something it shouldn't be, we know
|
||||
// this is the real press event.
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
try {
|
||||
if (code == KeyEvent.KEYCODE_ENDCALL) {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENDCALL
|
||||
|| keyCode == KeyEvent.KEYCODE_POWER) {
|
||||
if (down) {
|
||||
boolean handled = false;
|
||||
boolean hungUp = false;
|
||||
// key repeats are generated by the window manager, and we don't see them
|
||||
// here, so unless the driver is doing something it shouldn't be, we know
|
||||
// this is the real press event.
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
try {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENDCALL) {
|
||||
handled = hungUp = phoneServ.endCall();
|
||||
} else if (keyCode == KeyEvent.KEYCODE_POWER) {
|
||||
if (phoneServ.isRinging()) {
|
||||
// Pressing Power while there's a ringing incoming
|
||||
// call should silence the ringer.
|
||||
phoneServ.silenceRinger();
|
||||
handled = true;
|
||||
} else if (phoneServ.isOffhook() &&
|
||||
((mIncallPowerBehavior
|
||||
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP)
|
||||
!= 0)) {
|
||||
// Otherwise, if "Power button ends call" is enabled,
|
||||
// the Power button will hang up any current active call.
|
||||
handled = hungUp = phoneServ.endCall();
|
||||
} else if (code == KeyEvent.KEYCODE_POWER) {
|
||||
if (phoneServ.isRinging()) {
|
||||
// Pressing Power while there's a ringing incoming
|
||||
// call should silence the ringer.
|
||||
phoneServ.silenceRinger();
|
||||
handled = true;
|
||||
} else if (phoneServ.isOffhook() &&
|
||||
((mIncallPowerBehavior
|
||||
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP)
|
||||
!= 0)) {
|
||||
// Otherwise, if "Power button ends call" is enabled,
|
||||
// the Power button will hang up any current active call.
|
||||
handled = hungUp = phoneServ.endCall();
|
||||
}
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "ITelephony threw RemoteException" + ex);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
|
||||
}
|
||||
|
||||
if (!screenIsOn
|
||||
|| (handled && code != KeyEvent.KEYCODE_POWER)
|
||||
|| (handled && hungUp && code == KeyEvent.KEYCODE_POWER)) {
|
||||
mShouldTurnOffOnKeyUp = false;
|
||||
} else {
|
||||
// only try to turn off the screen if we didn't already hang up
|
||||
mShouldTurnOffOnKeyUp = true;
|
||||
mHandler.postDelayed(mPowerLongPress,
|
||||
ViewConfiguration.getGlobalActionKeyTimeout());
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "ITelephony threw RemoteException" + ex);
|
||||
}
|
||||
} else {
|
||||
mHandler.removeCallbacks(mPowerLongPress);
|
||||
if (mShouldTurnOffOnKeyUp) {
|
||||
mShouldTurnOffOnKeyUp = false;
|
||||
boolean gohome, sleeps;
|
||||
if (code == KeyEvent.KEYCODE_ENDCALL) {
|
||||
gohome = (mEndcallBehavior
|
||||
& Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0;
|
||||
sleeps = (mEndcallBehavior
|
||||
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0;
|
||||
} else {
|
||||
gohome = false;
|
||||
sleeps = true;
|
||||
}
|
||||
if (keyguardActive
|
||||
|| (sleeps && !gohome)
|
||||
|| (gohome && !goHome() && sleeps)) {
|
||||
// they must already be on the keyguad or home screen,
|
||||
// go to sleep instead
|
||||
Log.d(TAG, "I'm tired mEndcallBehavior=0x"
|
||||
+ Integer.toHexString(mEndcallBehavior));
|
||||
result &= ~ACTION_POKE_USER_ACTIVITY;
|
||||
result |= ACTION_GO_TO_SLEEP;
|
||||
}
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
|
||||
}
|
||||
} else if (isMediaKey(code)) {
|
||||
// This key needs to be handled even if the screen is off.
|
||||
// If others need to be handled while it's off, this is a reasonable
|
||||
// pattern to follow.
|
||||
if ((result & ACTION_PASS_TO_USER) == 0) {
|
||||
// Only do this if we would otherwise not pass it to the user. In that
|
||||
// case, the PhoneWindow class will do the same thing, except it will
|
||||
// only do it if the showing app doesn't process the key on its own.
|
||||
KeyEvent keyEvent = new KeyEvent(event.when, event.when,
|
||||
down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
|
||||
code, 0);
|
||||
mBroadcastWakeLock.acquire();
|
||||
mHandler.post(new PassHeadsetKey(keyEvent));
|
||||
|
||||
if (!isScreenOn
|
||||
|| (handled && keyCode != KeyEvent.KEYCODE_POWER)
|
||||
|| (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) {
|
||||
mShouldTurnOffOnKeyUp = false;
|
||||
} else {
|
||||
// only try to turn off the screen if we didn't already hang up
|
||||
mShouldTurnOffOnKeyUp = true;
|
||||
mHandler.postDelayed(mPowerLongPress,
|
||||
ViewConfiguration.getGlobalActionKeyTimeout());
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} else if (code == KeyEvent.KEYCODE_CALL) {
|
||||
// If an incoming call is ringing, answer it!
|
||||
// (We handle this key here, rather than in the InCallScreen, to make
|
||||
// sure we'll respond to the key even if the InCallScreen hasn't come to
|
||||
// the foreground yet.)
|
||||
|
||||
// We answer the call on the DOWN event, to agree with
|
||||
// the "fallback" behavior in the InCallScreen.
|
||||
if (down) {
|
||||
try {
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
if (phoneServ.isRinging()) {
|
||||
Log.i(TAG, "interceptKeyTq:"
|
||||
+ " CALL key-down while ringing: Answer the call!");
|
||||
phoneServ.answerRingingCall();
|
||||
|
||||
// And *don't* pass this key thru to the current activity
|
||||
// (which is presumably the InCallScreen.)
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "CALL button: Unable to find ITelephony interface");
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);
|
||||
} else {
|
||||
mHandler.removeCallbacks(mPowerLongPress);
|
||||
if (mShouldTurnOffOnKeyUp) {
|
||||
mShouldTurnOffOnKeyUp = false;
|
||||
boolean gohome, sleeps;
|
||||
if (keyCode == KeyEvent.KEYCODE_ENDCALL) {
|
||||
gohome = (mEndcallBehavior
|
||||
& Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0;
|
||||
sleeps = (mEndcallBehavior
|
||||
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0;
|
||||
} else {
|
||||
gohome = false;
|
||||
sleeps = true;
|
||||
}
|
||||
if (keyguardActive
|
||||
|| (sleeps && !gohome)
|
||||
|| (gohome && !goHome() && sleeps)) {
|
||||
// they must already be on the keyguad or home screen,
|
||||
// go to sleep instead
|
||||
Log.d(TAG, "I'm tired mEndcallBehavior=0x"
|
||||
+ Integer.toHexString(mEndcallBehavior));
|
||||
result &= ~ACTION_POKE_USER_ACTIVITY;
|
||||
result |= ACTION_GO_TO_SLEEP;
|
||||
}
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} else if ((code == KeyEvent.KEYCODE_VOLUME_UP)
|
||||
|| (code == KeyEvent.KEYCODE_VOLUME_DOWN)) {
|
||||
// If an incoming call is ringing, either VOLUME key means
|
||||
// "silence ringer". We handle these keys here, rather than
|
||||
// in the InCallScreen, to make sure we'll respond to them
|
||||
// even if the InCallScreen hasn't come to the foreground yet.
|
||||
}
|
||||
} else if (isMediaKey(keyCode)) {
|
||||
// This key needs to be handled even if the screen is off.
|
||||
// If others need to be handled while it's off, this is a reasonable
|
||||
// pattern to follow.
|
||||
if ((result & ACTION_PASS_TO_USER) == 0) {
|
||||
// Only do this if we would otherwise not pass it to the user. In that
|
||||
// case, the PhoneWindow class will do the same thing, except it will
|
||||
// only do it if the showing app doesn't process the key on its own.
|
||||
long when = whenNanos / 1000000;
|
||||
KeyEvent keyEvent = new KeyEvent(when, when,
|
||||
down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
|
||||
keyCode, 0);
|
||||
mBroadcastWakeLock.acquire();
|
||||
mHandler.post(new PassHeadsetKey(keyEvent));
|
||||
}
|
||||
} else if (keyCode == KeyEvent.KEYCODE_CALL) {
|
||||
// If an incoming call is ringing, answer it!
|
||||
// (We handle this key here, rather than in the InCallScreen, to make
|
||||
// sure we'll respond to the key even if the InCallScreen hasn't come to
|
||||
// the foreground yet.)
|
||||
|
||||
// Look for the DOWN event here, to agree with the "fallback"
|
||||
// behavior in the InCallScreen.
|
||||
if (down) {
|
||||
try {
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
if (phoneServ.isRinging()) {
|
||||
Log.i(TAG, "interceptKeyTq:"
|
||||
+ " VOLUME key-down while ringing: Silence ringer!");
|
||||
// Silence the ringer. (It's safe to call this
|
||||
// even if the ringer has already been silenced.)
|
||||
phoneServ.silenceRinger();
|
||||
// We answer the call on the DOWN event, to agree with
|
||||
// the "fallback" behavior in the InCallScreen.
|
||||
if (down) {
|
||||
try {
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
if (phoneServ.isRinging()) {
|
||||
Log.i(TAG, "interceptKeyTq:"
|
||||
+ " CALL key-down while ringing: Answer the call!");
|
||||
phoneServ.answerRingingCall();
|
||||
|
||||
// And *don't* pass this key thru to the current activity
|
||||
// (which is probably the InCallScreen.)
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
|
||||
// And *don't* pass this key thru to the current activity
|
||||
// (which is presumably the InCallScreen.)
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
|
||||
} else {
|
||||
Log.w(TAG, "CALL button: Unable to find ITelephony interface");
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);
|
||||
}
|
||||
}
|
||||
} else if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|
||||
|| (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
|
||||
// If an incoming call is ringing, either VOLUME key means
|
||||
// "silence ringer". We handle these keys here, rather than
|
||||
// in the InCallScreen, to make sure we'll respond to them
|
||||
// even if the InCallScreen hasn't come to the foreground yet.
|
||||
|
||||
// Look for the DOWN event here, to agree with the "fallback"
|
||||
// behavior in the InCallScreen.
|
||||
if (down) {
|
||||
try {
|
||||
ITelephony phoneServ = getPhoneInterface();
|
||||
if (phoneServ != null) {
|
||||
if (phoneServ.isRinging()) {
|
||||
Log.i(TAG, "interceptKeyTq:"
|
||||
+ " VOLUME key-down while ringing: Silence ringer!");
|
||||
// Silence the ringer. (It's safe to call this
|
||||
// even if the ringer has already been silenced.)
|
||||
phoneServ.silenceRinger();
|
||||
|
||||
// And *don't* pass this key thru to the current activity
|
||||
// (which is probably the InCallScreen.)
|
||||
result &= ~ACTION_PASS_TO_USER;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2023,35 +1956,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
};
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isWakeRelMovementTq(int device, int classes,
|
||||
RawInputEvent event) {
|
||||
// if it's tagged with one of the wake bits, it wakes up the device
|
||||
return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public boolean isWakeAbsMovementTq(int device, int classes,
|
||||
RawInputEvent event) {
|
||||
// if it's tagged with one of the wake bits, it wakes up the device
|
||||
return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the current state of the world, should this key wake up the device?
|
||||
*/
|
||||
protected boolean isWakeKeyTq(RawInputEvent event) {
|
||||
// There are not key maps for trackball devices, but we'd still
|
||||
// like to have pressing it wake the device up, so force it here.
|
||||
int keycode = event.keycode;
|
||||
int flags = event.flags;
|
||||
if (keycode == RawInputEvent.BTN_MOUSE) {
|
||||
flags |= WindowManagerPolicy.FLAG_WAKE;
|
||||
}
|
||||
return (flags
|
||||
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void screenTurnedOff(int why) {
|
||||
EventLog.writeEvent(70000, 0);
|
||||
@ -2165,7 +2069,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
|
||||
int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
|
||||
int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
|
||||
int trackballState = mWindowManager.getTrackballScancodeState(RawInputEvent.BTN_MOUSE);
|
||||
int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
|
||||
mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0;
|
||||
performHapticFeedbackLw(null, mSafeMode
|
||||
? HapticFeedbackConstants.SAFE_MODE_ENABLED
|
||||
@ -2413,13 +2317,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void keyFeedbackFromInput(KeyEvent event) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN
|
||||
&& (event.getFlags()&KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
||||
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void screenOnStoppedLw() {
|
||||
if (!mKeyguardMediator.isShowingAndNotHidden() && mPowerManager.isScreenOn()) {
|
||||
long curTime = SystemClock.uptimeMillis();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,6 @@ public class InputManager {
|
||||
private final Callbacks mCallbacks;
|
||||
private final Context mContext;
|
||||
private final WindowManagerService mWindowManagerService;
|
||||
private final WindowManagerPolicy mWindowManagerPolicy;
|
||||
private final PowerManager mPowerManager;
|
||||
private final PowerManagerService mPowerManagerService;
|
||||
|
||||
@ -103,12 +102,10 @@ public class InputManager {
|
||||
|
||||
public InputManager(Context context,
|
||||
WindowManagerService windowManagerService,
|
||||
WindowManagerPolicy windowManagerPolicy,
|
||||
PowerManager powerManager,
|
||||
PowerManagerService powerManagerService) {
|
||||
this.mContext = context;
|
||||
this.mWindowManagerService = windowManagerService;
|
||||
this.mWindowManagerPolicy = windowManagerPolicy;
|
||||
this.mPowerManager = powerManager;
|
||||
this.mPowerManagerService = powerManagerService;
|
||||
|
||||
@ -325,23 +322,8 @@ public class InputManager {
|
||||
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isScreenOn() {
|
||||
return mPowerManagerService.isScreenOn();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isScreenBright() {
|
||||
return mPowerManagerService.isScreenBright();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void virtualKeyFeedback(long whenNanos, int deviceId, int action, int flags,
|
||||
int keyCode, int scanCode, int metaState, long downTimeNanos) {
|
||||
KeyEvent keyEvent = new KeyEvent(downTimeNanos / 1000000,
|
||||
whenNanos / 1000000, action, keyCode, 0, metaState, scanCode, deviceId,
|
||||
flags);
|
||||
|
||||
mWindowManagerService.virtualKeyFeedback(keyEvent);
|
||||
public void virtualKeyDownFeedback() {
|
||||
mWindowManagerService.mInputMonitor.virtualKeyDownFeedback();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ -356,7 +338,7 @@ public class InputManager {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
|
||||
mWindowManagerPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
|
||||
mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ -380,17 +362,17 @@ public class InputManager {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public int interceptKeyBeforeQueueing(int deviceId, int type, int scanCode,
|
||||
int keyCode, int policyFlags, int value, long whenNanos, boolean isScreenOn) {
|
||||
return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(deviceId, type,
|
||||
scanCode, keyCode, policyFlags, value, whenNanos, isScreenOn);
|
||||
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
|
||||
int policyFlags, boolean isScreenOn) {
|
||||
return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
|
||||
whenNanos, keyCode, down, policyFlags, isScreenOn);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean interceptKeyBeforeDispatching(InputChannel focus, int keyCode,
|
||||
int metaState, boolean down, int repeatCount, int policyFlags) {
|
||||
public boolean interceptKeyBeforeDispatching(InputChannel focus, int action,
|
||||
int flags, int keyCode, int metaState, int repeatCount, int policyFlags) {
|
||||
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus,
|
||||
keyCode, metaState, down, repeatCount, policyFlags);
|
||||
action, flags, keyCode, metaState, repeatCount, policyFlags);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ -400,18 +382,6 @@ public class InputManager {
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void goToSleep(long whenNanos) {
|
||||
long when = whenNanos / 1000000;
|
||||
mPowerManager.goToSleep(when);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void pokeUserActivity(long eventTimeNanos, int eventType) {
|
||||
long eventTime = eventTimeNanos / 1000000;
|
||||
mPowerManagerService.userActivity(eventTime, false, eventType, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void notifyAppSwitchComing() {
|
||||
mWindowManagerService.mInputMonitor.notifyAppSwitchComing();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -247,6 +247,9 @@ class PowerManagerService extends IPowerManager.Stub
|
||||
private static final boolean mSpew = false;
|
||||
private static final boolean mDebugProximitySensor = (true || mSpew);
|
||||
private static final boolean mDebugLightSensor = (false || mSpew);
|
||||
|
||||
private native void nativeInit();
|
||||
private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
|
||||
|
||||
/*
|
||||
static PrintStream mLog;
|
||||
@ -481,6 +484,11 @@ class PowerManagerService extends IPowerManager.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nativeInit();
|
||||
synchronized (mLocks) {
|
||||
updateNativePowerStateLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void initInThread() {
|
||||
@ -1557,8 +1565,16 @@ class PowerManagerService extends IPowerManager.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateNativePowerStateLocked();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNativePowerStateLocked() {
|
||||
nativeSetPowerState(
|
||||
(mPowerState & SCREEN_ON_BIT) != 0,
|
||||
(mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
|
||||
}
|
||||
|
||||
private int screenOffFinishedAnimatingLocked(int reason) {
|
||||
// I don't think we need to check the current state here because all of these
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,9 +4,9 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES:= \
|
||||
com_android_server_AlarmManagerService.cpp \
|
||||
com_android_server_BatteryService.cpp \
|
||||
com_android_server_KeyInputQueue.cpp \
|
||||
com_android_server_InputManager.cpp \
|
||||
com_android_server_LightsService.cpp \
|
||||
com_android_server_PowerManagerService.cpp \
|
||||
com_android_server_SensorService.cpp \
|
||||
com_android_server_SystemServer.cpp \
|
||||
com_android_server_VibratorService.cpp \
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "../../core/jni/android_view_KeyEvent.h"
|
||||
#include "../../core/jni/android_view_MotionEvent.h"
|
||||
#include "../../core/jni/android_view_InputChannel.h"
|
||||
#include "com_android_server_PowerManagerService.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -107,16 +108,6 @@ enum {
|
||||
LAST_SYSTEM_WINDOW = 2999,
|
||||
};
|
||||
|
||||
enum {
|
||||
POWER_MANAGER_OTHER_EVENT = 0,
|
||||
POWER_MANAGER_CHEEK_EVENT = 1,
|
||||
POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
|
||||
// up events or LONG_TOUCH events.
|
||||
POWER_MANAGER_LONG_TOUCH_EVENT = 3,
|
||||
POWER_MANAGER_TOUCH_UP_EVENT = 4,
|
||||
POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.
|
||||
};
|
||||
|
||||
// Delay between reporting long touch events to the power manager.
|
||||
const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
|
||||
|
||||
@ -133,20 +124,16 @@ const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
|
||||
static struct {
|
||||
jclass clazz;
|
||||
|
||||
jmethodID isScreenOn;
|
||||
jmethodID isScreenBright;
|
||||
jmethodID notifyConfigurationChanged;
|
||||
jmethodID notifyLidSwitchChanged;
|
||||
jmethodID notifyInputChannelBroken;
|
||||
jmethodID notifyInputChannelANR;
|
||||
jmethodID notifyInputChannelRecoveredFromANR;
|
||||
jmethodID notifyANR;
|
||||
jmethodID virtualKeyFeedback;
|
||||
jmethodID virtualKeyDownFeedback;
|
||||
jmethodID interceptKeyBeforeQueueing;
|
||||
jmethodID interceptKeyBeforeDispatching;
|
||||
jmethodID checkInjectEventsPermission;
|
||||
jmethodID goToSleep;
|
||||
jmethodID pokeUserActivity;
|
||||
jmethodID notifyAppSwitchComing;
|
||||
jmethodID filterTouchEvents;
|
||||
jmethodID filterJumpyTouchEvents;
|
||||
@ -228,9 +215,7 @@ public:
|
||||
|
||||
virtual bool getDisplayInfo(int32_t displayId,
|
||||
int32_t* width, int32_t* height, int32_t* orientation);
|
||||
virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
|
||||
int32_t action, int32_t flags, int32_t keyCode,
|
||||
int32_t scanCode, int32_t metaState, nsecs_t downTime);
|
||||
virtual void virtualKeyDownFeedback();
|
||||
virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
|
||||
virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
|
||||
@ -321,7 +306,7 @@ private:
|
||||
int32_t mDisplayWidth, mDisplayHeight;
|
||||
int32_t mDisplayOrientation;
|
||||
|
||||
// Callbacks.
|
||||
// Power manager interactions.
|
||||
bool isScreenOn();
|
||||
bool isScreenBright();
|
||||
|
||||
@ -369,9 +354,9 @@ private:
|
||||
|
||||
void releaseTouchedWindowLd();
|
||||
|
||||
int32_t identifyTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
||||
int32_t waitForTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
||||
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
||||
int32_t identifyTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
||||
int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
|
||||
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
|
||||
|
||||
bool interceptKeyBeforeDispatching(const InputTarget& target,
|
||||
@ -391,6 +376,7 @@ private:
|
||||
}
|
||||
|
||||
static bool isAppSwitchKey(int32_t keyCode);
|
||||
static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
|
||||
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
||||
};
|
||||
|
||||
@ -422,6 +408,36 @@ bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
|
||||
return keyCode == KEYCODE_HOME || keyCode == KEYCODE_ENDCALL;
|
||||
}
|
||||
|
||||
bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
|
||||
// Special keys that the WindowManagerPolicy might care about.
|
||||
switch (keyCode) {
|
||||
case KEYCODE_VOLUME_UP:
|
||||
case KEYCODE_VOLUME_DOWN:
|
||||
case KEYCODE_ENDCALL:
|
||||
case KEYCODE_POWER:
|
||||
case KEYCODE_CALL:
|
||||
case KEYCODE_HOME:
|
||||
case KEYCODE_MENU:
|
||||
case KEYCODE_SEARCH:
|
||||
// media keys
|
||||
case KEYCODE_HEADSETHOOK:
|
||||
case KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KEYCODE_MEDIA_STOP:
|
||||
case KEYCODE_MEDIA_NEXT:
|
||||
case KEYCODE_MEDIA_PREVIOUS:
|
||||
case KEYCODE_MEDIA_REWIND:
|
||||
case KEYCODE_MEDIA_FAST_FORWARD:
|
||||
return true;
|
||||
default:
|
||||
// We need to pass all keys to the policy in the following cases:
|
||||
// - screen is off
|
||||
// - keyguard is visible
|
||||
// - policy is performing key chording
|
||||
//return ! isScreenOn || keyguardVisible || chording;
|
||||
return true; // XXX stubbed out for now
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
@ -546,39 +562,22 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId,
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenOn() {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenOn);
|
||||
if (checkAndClearExceptionFromCallback(env, "isScreenOn")) {
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
return android_server_PowerManagerService_isScreenOn();
|
||||
}
|
||||
|
||||
bool NativeInputManager::isScreenBright() {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenBright);
|
||||
if (checkAndClearExceptionFromCallback(env, "isScreenBright")) {
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
return android_server_PowerManagerService_isScreenBright();
|
||||
}
|
||||
|
||||
void NativeInputManager::virtualKeyFeedback(nsecs_t when, int32_t deviceId,
|
||||
int32_t action, int32_t flags, int32_t keyCode,
|
||||
int32_t scanCode, int32_t metaState, nsecs_t downTime) {
|
||||
void NativeInputManager::virtualKeyDownFeedback() {
|
||||
#if DEBUG_INPUT_READER_POLICY
|
||||
LOGD("virtualKeyFeedback - when=%lld, deviceId=%d, action=%d, flags=%d, keyCode=%d, "
|
||||
"scanCode=%d, metaState=%d, downTime=%lld",
|
||||
when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
|
||||
LOGD("virtualKeyDownFeedback");
|
||||
#endif
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyFeedback,
|
||||
when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
|
||||
checkAndClearExceptionFromCallback(env, "virtualKeyFeedback");
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
|
||||
checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
@ -593,16 +592,21 @@ int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
|
||||
const int32_t WM_ACTION_GO_TO_SLEEP = 4;
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
bool isScreenOn = this->isScreenOn();
|
||||
bool isScreenBright = this->isScreenBright();
|
||||
|
||||
jint wmActions = env->CallIntMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.interceptKeyBeforeQueueing,
|
||||
deviceId, EV_KEY, scanCode, keyCode, policyFlags, down ? 1 : 0, when, isScreenOn);
|
||||
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
|
||||
wmActions = 0;
|
||||
jint wmActions = 0;
|
||||
if (isPolicyKey(keyCode, isScreenOn)) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
wmActions = env->CallIntMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.interceptKeyBeforeQueueing,
|
||||
when, keyCode, down, policyFlags, isScreenOn);
|
||||
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
|
||||
wmActions = 0;
|
||||
}
|
||||
} else {
|
||||
wmActions = WM_ACTION_PASS_TO_USER;
|
||||
}
|
||||
|
||||
int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
|
||||
@ -617,8 +621,7 @@ int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.goToSleep, when);
|
||||
checkAndClearExceptionFromCallback(env, "goToSleep");
|
||||
android_server_PowerManagerService_goToSleep(when);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
|
||||
@ -629,6 +632,8 @@ int32_t NativeInputManager::interceptKey(nsecs_t when,
|
||||
actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
|
||||
|
||||
if (down && isAppSwitchKey(keyCode)) {
|
||||
JNIEnv* env = jniEnv();
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
|
||||
checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
|
||||
|
||||
@ -1531,11 +1536,13 @@ int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t
|
||||
windowType = focusedWindow->layoutParamsType;
|
||||
} // release lock
|
||||
|
||||
const InputTarget& target = outTargets.top();
|
||||
bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
|
||||
if (consumed) {
|
||||
outTargets.clear();
|
||||
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
||||
if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
|
||||
const InputTarget& target = outTargets.top();
|
||||
bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
|
||||
if (consumed) {
|
||||
outTargets.clear();
|
||||
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
||||
}
|
||||
}
|
||||
|
||||
pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
|
||||
@ -1552,11 +1559,11 @@ int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
|
||||
|
||||
switch (motionEvent->getNature()) {
|
||||
case INPUT_EVENT_NATURE_TRACKBALL:
|
||||
return identifyTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
||||
return waitForTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
||||
outTargets);
|
||||
|
||||
case INPUT_EVENT_NATURE_TOUCH:
|
||||
return identifyTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
||||
return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
|
||||
outTargets);
|
||||
|
||||
default:
|
||||
@ -1565,11 +1572,11 @@ int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
|
||||
}
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEvent,
|
||||
int32_t NativeInputManager::waitForTrackballEventTargets(MotionEvent* motionEvent,
|
||||
uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
||||
Vector<InputTarget>& outTargets) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("identifyTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
||||
LOGD("waitForTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
||||
policyFlags, injectorPid, injectorUid);
|
||||
#endif
|
||||
|
||||
@ -1591,11 +1598,11 @@ int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEve
|
||||
return INPUT_EVENT_INJECTION_SUCCEEDED;
|
||||
}
|
||||
|
||||
int32_t NativeInputManager::identifyTouchEventTargets(MotionEvent* motionEvent,
|
||||
int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
|
||||
uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
|
||||
Vector<InputTarget>& outTargets) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
LOGD("identifyTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
||||
LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
|
||||
policyFlags, injectorPid, injectorUid);
|
||||
#endif
|
||||
|
||||
@ -1642,8 +1649,8 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target
|
||||
if (inputChannelObj) {
|
||||
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
|
||||
gCallbacksClassInfo.interceptKeyBeforeDispatching,
|
||||
inputChannelObj, keyEvent->getKeyCode(), keyEvent->getMetaState(),
|
||||
keyEvent->getAction() == KEY_EVENT_ACTION_DOWN,
|
||||
inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
|
||||
keyEvent->getKeyCode(), keyEvent->getMetaState(),
|
||||
keyEvent->getRepeatCount(), policyFlags);
|
||||
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
|
||||
|
||||
@ -1665,10 +1672,7 @@ void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t ev
|
||||
}
|
||||
|
||||
void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
|
||||
JNIEnv* env = jniEnv();
|
||||
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.pokeUserActivity,
|
||||
eventTime, eventType);
|
||||
checkAndClearExceptionFromCallback(env, "pokeUserActivity");
|
||||
android_server_PowerManagerService_userActivity(eventTime, eventType);
|
||||
}
|
||||
|
||||
void NativeInputManager::dumpDispatchStateLd() {
|
||||
@ -2082,12 +2086,6 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
|
||||
FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.isScreenOn, gCallbacksClassInfo.clazz,
|
||||
"isScreenOn", "()Z");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.isScreenBright, gCallbacksClassInfo.clazz,
|
||||
"isScreenBright", "()Z");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
|
||||
"notifyConfigurationChanged", "(JIII)V");
|
||||
|
||||
@ -2106,24 +2104,18 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
|
||||
"notifyANR", "(Ljava/lang/Object;)J");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.virtualKeyFeedback, gCallbacksClassInfo.clazz,
|
||||
"virtualKeyFeedback", "(JIIIIIIJ)V");
|
||||
GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
|
||||
"virtualKeyDownFeedback", "()V");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
|
||||
"interceptKeyBeforeQueueing", "(IIIIIIJZ)I");
|
||||
"interceptKeyBeforeQueueing", "(JIZIZ)I");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
|
||||
"interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIZII)Z");
|
||||
"interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
|
||||
"checkInjectEventsPermission", "(II)Z");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.goToSleep, gCallbacksClassInfo.clazz,
|
||||
"goToSleep", "(J)V");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.pokeUserActivity, gCallbacksClassInfo.clazz,
|
||||
"pokeUserActivity", "(JI)V");
|
||||
|
||||
GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
|
||||
"notifyAppSwitchComing", "()V");
|
||||
|
||||
|
@ -1,358 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "Input"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include <utils/misc.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/EventHub.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static struct input_offsets_t
|
||||
{
|
||||
jfieldID mMinValue;
|
||||
jfieldID mMaxValue;
|
||||
jfieldID mFlat;
|
||||
jfieldID mFuzz;
|
||||
|
||||
jfieldID mDeviceId;
|
||||
jfieldID mType;
|
||||
jfieldID mScancode;
|
||||
jfieldID mKeycode;
|
||||
jfieldID mFlags;
|
||||
jfieldID mValue;
|
||||
jfieldID mWhen;
|
||||
} gInputOffsets;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static Mutex gLock;
|
||||
static sp<EventHub> gHub;
|
||||
|
||||
static jboolean
|
||||
android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz,
|
||||
jobject event)
|
||||
{
|
||||
gLock.lock();
|
||||
sp<EventHub> hub = gHub;
|
||||
if (hub == NULL) {
|
||||
hub = new EventHub;
|
||||
gHub = hub;
|
||||
}
|
||||
gLock.unlock();
|
||||
|
||||
int32_t deviceId;
|
||||
int32_t type;
|
||||
int32_t scancode, keycode;
|
||||
uint32_t flags;
|
||||
int32_t value;
|
||||
nsecs_t when;
|
||||
bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode,
|
||||
&flags, &value, &when);
|
||||
|
||||
env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId);
|
||||
env->SetIntField(event, gInputOffsets.mType, (jint)type);
|
||||
env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode);
|
||||
env->SetIntField(event, gInputOffsets.mKeycode, (jint)keycode);
|
||||
env->SetIntField(event, gInputOffsets.mFlags, (jint)flags);
|
||||
env->SetIntField(event, gInputOffsets.mValue, value);
|
||||
env->SetLongField(event, gInputOffsets.mWhen,
|
||||
(jlong)(nanoseconds_to_milliseconds(when)));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getDeviceClasses(JNIEnv* env, jobject clazz,
|
||||
jint deviceId)
|
||||
{
|
||||
jint classes = 0;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) classes = gHub->getDeviceClasses(deviceId);
|
||||
gLock.unlock();
|
||||
return classes;
|
||||
}
|
||||
|
||||
static jstring
|
||||
android_server_KeyInputQueue_getDeviceName(JNIEnv* env, jobject clazz,
|
||||
jint deviceId)
|
||||
{
|
||||
String8 name;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) name = gHub->getDeviceName(deviceId);
|
||||
gLock.unlock();
|
||||
|
||||
if (name.size() > 0) {
|
||||
return env->NewStringUTF(name.string());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
android_server_KeyInputQueue_addExcludedDevice(JNIEnv* env, jobject clazz,
|
||||
jstring deviceName)
|
||||
{
|
||||
gLock.lock();
|
||||
sp<EventHub> hub = gHub;
|
||||
if (hub == NULL) {
|
||||
hub = new EventHub;
|
||||
gHub = hub;
|
||||
}
|
||||
gLock.unlock();
|
||||
|
||||
const char* nameStr = env->GetStringUTFChars(deviceName, NULL);
|
||||
gHub->addExcludedDevice(nameStr);
|
||||
env->ReleaseStringUTFChars(deviceName, nameStr);
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_server_KeyInputQueue_getAbsoluteInfo(JNIEnv* env, jobject clazz,
|
||||
jint deviceId, jint axis,
|
||||
jobject info)
|
||||
{
|
||||
int32_t minValue, maxValue, flat, fuzz;
|
||||
int res = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) {
|
||||
res = gHub->getAbsoluteInfo(deviceId, axis,
|
||||
&minValue, &maxValue, &flat, &fuzz);
|
||||
}
|
||||
gLock.unlock();
|
||||
|
||||
if (res < 0) return JNI_FALSE;
|
||||
|
||||
env->SetIntField(info, gInputOffsets.mMinValue, (jint)minValue);
|
||||
env->SetIntField(info, gInputOffsets.mMaxValue, (jint)maxValue);
|
||||
env->SetIntField(info, gInputOffsets.mFlat, (jint)flat);
|
||||
env->SetIntField(info, gInputOffsets.mFuzz, (jint)fuzz);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getSwitchState(JNIEnv* env, jobject clazz,
|
||||
jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getSwitchState(-1, -1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getSwitchStateDevice(JNIEnv* env, jobject clazz,
|
||||
jint deviceId, jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getSwitchState(deviceId, -1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getScancodeState(JNIEnv* env, jobject clazz,
|
||||
jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getScanCodeState(0, -1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getScancodeStateDevice(JNIEnv* env, jobject clazz,
|
||||
jint deviceId, jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getScanCodeState(deviceId, -1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getKeycodeState(JNIEnv* env, jobject clazz,
|
||||
jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getKeyCodeState(0, -1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz,
|
||||
jint deviceId, jint sw)
|
||||
{
|
||||
jint st = -1;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) st = gHub->getKeyCodeState(deviceId,-1, sw);
|
||||
gLock.unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_server_KeyInputQueue_scancodeToKeycode(JNIEnv* env, jobject clazz,
|
||||
jint deviceId, jint scancode)
|
||||
{
|
||||
jint res = 0;
|
||||
gLock.lock();
|
||||
if (gHub != NULL) {
|
||||
int32_t keycode;
|
||||
uint32_t flags;
|
||||
gHub->scancodeToKeycode(deviceId, scancode, &keycode, &flags);
|
||||
res = keycode;
|
||||
}
|
||||
gLock.unlock();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_server_KeyInputQueue_hasKeys(JNIEnv* env, jobject clazz,
|
||||
jintArray keyCodes, jbooleanArray outFlags)
|
||||
{
|
||||
jboolean ret = JNI_FALSE;
|
||||
|
||||
int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
|
||||
uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
|
||||
jsize numCodes = env->GetArrayLength(keyCodes);
|
||||
if (numCodes == env->GetArrayLength(outFlags)) {
|
||||
gLock.lock();
|
||||
if (gHub != NULL) ret = gHub->hasKeys(numCodes, codes, flags);
|
||||
gLock.unlock();
|
||||
}
|
||||
|
||||
env->ReleaseBooleanArrayElements(outFlags, flags, 0);
|
||||
env->ReleaseIntArrayElements(keyCodes, codes, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* JNI registration.
|
||||
*/
|
||||
static JNINativeMethod gInputMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "readEvent", "(Landroid/view/RawInputEvent;)Z",
|
||||
(void*) android_server_KeyInputQueue_readEvent },
|
||||
{ "getDeviceClasses", "(I)I",
|
||||
(void*) android_server_KeyInputQueue_getDeviceClasses },
|
||||
{ "getDeviceName", "(I)Ljava/lang/String;",
|
||||
(void*) android_server_KeyInputQueue_getDeviceName },
|
||||
{ "addExcludedDevice", "(Ljava/lang/String;)V",
|
||||
(void*) android_server_KeyInputQueue_addExcludedDevice },
|
||||
{ "getAbsoluteInfo", "(IILcom/android/server/InputDevice$AbsoluteInfo;)Z",
|
||||
(void*) android_server_KeyInputQueue_getAbsoluteInfo },
|
||||
{ "getSwitchState", "(I)I",
|
||||
(void*) android_server_KeyInputQueue_getSwitchState },
|
||||
{ "getSwitchState", "(II)I",
|
||||
(void*) android_server_KeyInputQueue_getSwitchStateDevice },
|
||||
{ "nativeGetScancodeState", "(I)I",
|
||||
(void*) android_server_KeyInputQueue_getScancodeState },
|
||||
{ "nativeGetScancodeState", "(II)I",
|
||||
(void*) android_server_KeyInputQueue_getScancodeStateDevice },
|
||||
{ "nativeGetKeycodeState", "(I)I",
|
||||
(void*) android_server_KeyInputQueue_getKeycodeState },
|
||||
{ "nativeGetKeycodeState", "(II)I",
|
||||
(void*) android_server_KeyInputQueue_getKeycodeStateDevice },
|
||||
{ "hasKeys", "([I[Z)Z",
|
||||
(void*) android_server_KeyInputQueue_hasKeys },
|
||||
{ "scancodeToKeycode", "(II)I",
|
||||
(void*) android_server_KeyInputQueue_scancodeToKeycode },
|
||||
};
|
||||
|
||||
int register_android_server_KeyInputQueue(JNIEnv* env)
|
||||
{
|
||||
jclass input = env->FindClass("com/android/server/KeyInputQueue");
|
||||
LOG_FATAL_IF(input == NULL, "Unable to find class com/android/server/KeyInputQueue");
|
||||
int res = jniRegisterNativeMethods(env, "com/android/server/KeyInputQueue",
|
||||
gInputMethods, NELEM(gInputMethods));
|
||||
|
||||
jclass absoluteInfo = env->FindClass("com/android/server/InputDevice$AbsoluteInfo");
|
||||
LOG_FATAL_IF(absoluteInfo == NULL, "Unable to find class com/android/server/InputDevice$AbsoluteInfo");
|
||||
|
||||
gInputOffsets.mMinValue
|
||||
= env->GetFieldID(absoluteInfo, "minValue", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mMinValue == NULL, "Unable to find InputDevice.AbsoluteInfo.minValue");
|
||||
|
||||
gInputOffsets.mMaxValue
|
||||
= env->GetFieldID(absoluteInfo, "maxValue", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mMaxValue == NULL, "Unable to find InputDevice.AbsoluteInfo.maxValue");
|
||||
|
||||
gInputOffsets.mFlat
|
||||
= env->GetFieldID(absoluteInfo, "flat", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mFlat == NULL, "Unable to find InputDevice.AbsoluteInfo.flat");
|
||||
|
||||
gInputOffsets.mFuzz
|
||||
= env->GetFieldID(absoluteInfo, "fuzz", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mFuzz == NULL, "Unable to find InputDevice.AbsoluteInfo.fuzz");
|
||||
|
||||
jclass inputEvent = env->FindClass("android/view/RawInputEvent");
|
||||
LOG_FATAL_IF(inputEvent == NULL, "Unable to find class android/view/RawInputEvent");
|
||||
|
||||
gInputOffsets.mDeviceId
|
||||
= env->GetFieldID(inputEvent, "deviceId", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mDeviceId == NULL, "Unable to find RawInputEvent.deviceId");
|
||||
|
||||
gInputOffsets.mType
|
||||
= env->GetFieldID(inputEvent, "type", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mType == NULL, "Unable to find RawInputEvent.type");
|
||||
|
||||
gInputOffsets.mScancode
|
||||
= env->GetFieldID(inputEvent, "scancode", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mScancode == NULL, "Unable to find RawInputEvent.scancode");
|
||||
|
||||
gInputOffsets.mKeycode
|
||||
= env->GetFieldID(inputEvent, "keycode", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mKeycode == NULL, "Unable to find RawInputEvent.keycode");
|
||||
|
||||
gInputOffsets.mFlags
|
||||
= env->GetFieldID(inputEvent, "flags", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mFlags == NULL, "Unable to find RawInputEvent.flags");
|
||||
|
||||
gInputOffsets.mValue
|
||||
= env->GetFieldID(inputEvent, "value", "I");
|
||||
LOG_FATAL_IF(gInputOffsets.mValue == NULL, "Unable to find RawInputEvent.value");
|
||||
|
||||
gInputOffsets.mWhen
|
||||
= env->GetFieldID(inputEvent, "when", "J");
|
||||
LOG_FATAL_IF(gInputOffsets.mWhen == NULL, "Unable to find RawInputEvent.when");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
142
services/jni/com_android_server_PowerManagerService.cpp
Normal file
142
services/jni/com_android_server_PowerManagerService.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PowerManagerService-JNI"
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include "jni.h"
|
||||
#include <limits.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include "com_android_server_PowerManagerService.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
|
||||
jmethodID goToSleep;
|
||||
jmethodID userActivity;
|
||||
} gPowerManagerServiceClassInfo;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jobject gPowerManagerServiceObj;
|
||||
|
||||
static Mutex gPowerManagerLock;
|
||||
static bool gScreenOn;
|
||||
static bool gScreenBright;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool android_server_PowerManagerService_isScreenOn() {
|
||||
AutoMutex _l(gPowerManagerLock);
|
||||
return gScreenOn;
|
||||
}
|
||||
|
||||
bool android_server_PowerManagerService_isScreenBright() {
|
||||
AutoMutex _l(gPowerManagerLock);
|
||||
return gScreenBright;
|
||||
}
|
||||
|
||||
void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
|
||||
if (gPowerManagerServiceObj) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity,
|
||||
nanoseconds_to_milliseconds(eventTime), false, eventType, false);
|
||||
checkAndClearExceptionFromCallback(env, "userActivity");
|
||||
}
|
||||
}
|
||||
|
||||
void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
|
||||
if (gPowerManagerServiceObj) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep,
|
||||
nanoseconds_to_milliseconds(eventTime));
|
||||
checkAndClearExceptionFromCallback(env, "goToSleep");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_server_PowerManagerService_nativeInit(JNIEnv* env, jobject obj) {
|
||||
gPowerManagerServiceObj = env->NewGlobalRef(obj);
|
||||
}
|
||||
|
||||
static void android_server_PowerManagerService_nativeSetPowerState(JNIEnv* env,
|
||||
jobject serviceObj, jboolean screenOn, jboolean screenBright) {
|
||||
AutoMutex _l(gPowerManagerLock);
|
||||
gScreenOn = screenOn;
|
||||
gScreenBright = screenBright;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static JNINativeMethod gPowerManagerServiceMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeInit", "()V",
|
||||
(void*) android_server_PowerManagerService_nativeInit },
|
||||
{ "nativeSetPowerState", "(ZZ)V",
|
||||
(void*) android_server_PowerManagerService_nativeSetPowerState },
|
||||
};
|
||||
|
||||
#define FIND_CLASS(var, className) \
|
||||
var = env->FindClass(className); \
|
||||
LOG_FATAL_IF(! var, "Unable to find class " className); \
|
||||
var = jclass(env->NewGlobalRef(var));
|
||||
|
||||
#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
|
||||
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
|
||||
LOG_FATAL_IF(! var, "Unable to find method " methodName);
|
||||
|
||||
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
|
||||
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
|
||||
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
|
||||
|
||||
int register_android_server_PowerManagerService(JNIEnv* env) {
|
||||
int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService",
|
||||
gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
|
||||
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
|
||||
|
||||
// Callbacks
|
||||
|
||||
FIND_CLASS(gPowerManagerServiceClassInfo.clazz, "com/android/server/PowerManagerService");
|
||||
|
||||
GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, gPowerManagerServiceClassInfo.clazz,
|
||||
"goToSleep", "(J)V");
|
||||
|
||||
GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, gPowerManagerServiceClassInfo.clazz,
|
||||
"userActivity", "(JZIZ)V");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* namespace android */
|
42
services/jni/com_android_server_PowerManagerService.h
Normal file
42
services/jni/com_android_server_PowerManagerService.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
|
||||
#define _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include "jni.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
enum {
|
||||
POWER_MANAGER_OTHER_EVENT = 0,
|
||||
POWER_MANAGER_CHEEK_EVENT = 1,
|
||||
POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
|
||||
// up events or LONG_TOUCH events.
|
||||
POWER_MANAGER_LONG_TOUCH_EVENT = 3,
|
||||
POWER_MANAGER_TOUCH_UP_EVENT = 4,
|
||||
POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.
|
||||
};
|
||||
|
||||
extern bool android_server_PowerManagerService_isScreenOn();
|
||||
extern bool android_server_PowerManagerService_isScreenBright();
|
||||
extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
|
||||
extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
|
@ -6,9 +6,9 @@
|
||||
namespace android {
|
||||
int register_android_server_AlarmManagerService(JNIEnv* env);
|
||||
int register_android_server_BatteryService(JNIEnv* env);
|
||||
int register_android_server_KeyInputQueue(JNIEnv* env);
|
||||
int register_android_server_InputManager(JNIEnv* env);
|
||||
int register_android_server_LightsService(JNIEnv* env);
|
||||
int register_android_server_PowerManagerService(JNIEnv* env);
|
||||
int register_android_server_SensorService(JNIEnv* env);
|
||||
int register_android_server_VibratorService(JNIEnv* env);
|
||||
int register_android_server_SystemServer(JNIEnv* env);
|
||||
@ -28,7 +28,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
}
|
||||
LOG_ASSERT(env, "Could not retrieve the env!");
|
||||
|
||||
register_android_server_KeyInputQueue(env);
|
||||
register_android_server_PowerManagerService(env);
|
||||
register_android_server_InputManager(env);
|
||||
register_android_server_LightsService(env);
|
||||
register_android_server_AlarmManagerService(env);
|
||||
|
Reference in New Issue
Block a user