Merge "More native input dispatch work." into gingerbread

This commit is contained in:
Chris Tate
2010-07-07 17:43:12 -07:00
committed by Android (Google) Code Review
23 changed files with 892 additions and 6092 deletions

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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.

View File

@ -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) {
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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");

View File

@ -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

View 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 */

View 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

View File

@ -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);