diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/input/InputDispatcher.cpp | 2 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 16 | ||||
-rw-r--r-- | services/input/InputReader.h | 12 | ||||
-rw-r--r-- | services/java/com/android/server/RotationSwitchObserver.java | 163 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 20 | ||||
-rw-r--r-- | services/java/com/android/server/wm/ScreenRotationAnimation.java | 32 |
6 files changed, 242 insertions, 3 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 652166d..0dad55a 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -265,7 +265,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { // Reset the key repeat timer whenever we disallow key events, even if the next event // is not a key. This is to ensure that we abort a key repeat if the device is just coming // out of sleep. - if (!mPolicy->isKeyRepeatEnabled()) { + if (!mPolicy->isKeyRepeatEnabled() || !mDispatchEnabled) { resetKeyRepeatLocked(); } diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index c66e7a1..d9290f4 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -4991,6 +4991,7 @@ void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) mPointerSimple.currentProperties.id = 0; mPointerSimple.currentProperties.toolType = mCurrentCookedPointerData.pointerProperties[index].toolType; + mLastStylusTime = when; } else { down = false; hovering = false; @@ -5073,6 +5074,11 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } } + if (rejectPalm(when)) { // stylus is currently active + mPointerSimple.reset(); + return; + } + if (mPointerSimple.down && !down) { mPointerSimple.down = false; @@ -5183,6 +5189,9 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { + + if (rejectPalm(when)) return; + PointerCoords pointerCoords[MAX_POINTERS]; PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0; @@ -5262,6 +5271,13 @@ void TouchInputMapper::unfadePointer(PointerControllerInterface::Transition tran } } +nsecs_t TouchInputMapper::mLastStylusTime = 0; + +bool TouchInputMapper::rejectPalm(nsecs_t when) { + return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) && + mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS; +} + bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 379229f..6167508 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -152,6 +152,9 @@ struct InputReaderConfiguration { // True to show the pointer icon when a stylus is used. bool stylusIconEnabled; + // Ignore finger touches this long after the stylus has been used (including hover) + nsecs_t stylusPalmRejectionTime; + InputReaderConfiguration() : virtualKeyQuietTime(0), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), @@ -169,7 +172,9 @@ struct InputReaderConfiguration { pointerGestureMovementSpeedRatio(0.8f), pointerGestureZoomSpeedRatio(0.3f), showTouches(false), - stylusIconEnabled(false) { } + stylusIconEnabled(false), + stylusPalmRejectionTime(50 * 10000000LL) // 50 ms + { } bool getDisplayInfo(int32_t displayId, bool external, int32_t* width, int32_t* height, int32_t* orientation) const; @@ -1480,6 +1485,9 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + // The time the stylus event was processed by any TouchInputMapper + static nsecs_t mLastStylusTime; + void sync(nsecs_t when); bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); @@ -1534,6 +1542,8 @@ private: void assignPointerIds(); void unfadePointer(PointerControllerInterface::Transition transition); + + bool rejectPalm(nsecs_t when); }; diff --git a/services/java/com/android/server/RotationSwitchObserver.java b/services/java/com/android/server/RotationSwitchObserver.java new file mode 100644 index 0000000..a191433 --- /dev/null +++ b/services/java/com/android/server/RotationSwitchObserver.java @@ -0,0 +1,163 @@ +/* + * 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 com.android.server; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.os.UEventObserver; +import android.provider.Settings; +import android.util.Log; +import android.util.Slog; + +import android.widget.Toast; +import android.view.IWindowManager; +import android.os.ServiceManager; +import android.os.RemoteException; +import android.os.AsyncTask; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +/** + * <p>RotationLockObserver monitors for rotation lock switch state + */ +class RotationSwitchObserver extends UEventObserver { + private static final String TAG = RotationSwitchObserver.class + .getSimpleName(); + private static final boolean LOG = true; + + private static final String LOCK_UEVENT_MATCH = + "DEVPATH=/devices/virtual/switch/rotationlock"; + private static final String LOCK_STATE_PATH = + "/sys/class/switch/rotationlock/state"; + + private static final int MSG_LOCK_STATE = 0; + + private int mLockState; + private int mPreviousLockState; + + private boolean mSystemReady; + + private final Context mContext; + + private boolean mAutoRotation; + + public RotationSwitchObserver(Context context) { + mContext = context; + init(); // set initial status + + startObserving(LOCK_UEVENT_MATCH); + } + + @Override + public void onUEvent(UEventObserver.UEvent event) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Slog.v(TAG, "Switch UEVENT: " + event.toString()); + } + + synchronized (this) { + try { + int newState = Integer.parseInt(event.get("SWITCH_STATE")); + if (newState != mLockState) { + mPreviousLockState = mLockState; + mLockState = newState; + if (mSystemReady) { + update(); + } + } + } catch (NumberFormatException e) { + Slog.e(TAG, "Could not parse switch state from event " + + event); + } + } + } + + private final void init() { + char[] buffer = new char[1024]; + + try { + FileReader file = new FileReader(LOCK_STATE_PATH); + int len = file.read(buffer, 0, 1024); + file.close(); + mPreviousLockState = mLockState = + Integer.valueOf((new String(buffer, 0, len)).trim()); + } catch (FileNotFoundException e) { + Slog.w(TAG, "This kernel does not have rotation switch support"); + } catch (NumberFormatException e) { + Slog.e(TAG, "" , e); + } catch (IOException e) { + Slog.e(TAG, "" , e); + } + } + + void systemReady() { + synchronized (this) { + mSystemReady = true; + } + } + + private final void update() { + mHandler.sendEmptyMessage(MSG_LOCK_STATE); + } + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_LOCK_STATE: + synchronized (this) { + boolean autoRotate = mLockState == 0; + int toastId = autoRotate + ? com.android.internal.R.string.toast_rotation_unlocked + : com.android.internal.R.string.toast_rotation_locked; + + setAutoRotation(autoRotate); + + Toast.makeText(mContext, mContext.getString(toastId), + Toast.LENGTH_SHORT).show(); + break; + } + } + } + }; + + private void setAutoRotation(final boolean autorotate) { + mAutoRotation = autorotate; + AsyncTask.execute(new Runnable() { + public void run() { + try { + IWindowManager wm = IWindowManager.Stub.asInterface( + ServiceManager + .getService(Context.WINDOW_SERVICE)); + if (autorotate) { + wm.thawRotation(); + } else { + wm.freezeRotation(-1); + } + } catch (RemoteException exc) { + Log.w(TAG, "Unable to save auto-rotate setting"); + } + } + }); + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 17a4b5d..c13a3e2 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -144,6 +144,7 @@ class ServerThread extends Thread { BluetoothService bluetooth = null; BluetoothA2dpService bluetoothA2dp = null; DockObserver dock = null; + RotationSwitchObserver rotateSwitch = null; UsbService usb = null; UiModeManagerService uiMode = null; RecognitionManagerService recognition = null; @@ -282,6 +283,9 @@ class ServerThread extends Thread { Slog.e("System", "************ Failure starting core service", e); } + boolean hasRotationLock = context.getResources().getBoolean(com.android + .internal.R.bool.config_hasRotationLockSwitch); + DevicePolicyManagerService devicePolicy = null; StatusBarManagerService statusBar = null; InputMethodManagerService imm = null; @@ -531,6 +535,16 @@ class ServerThread extends Thread { } try { + if (hasRotationLock) { + Slog.i(TAG, "Rotation Switch Observer"); + // Listen for switch changes + rotateSwitch = new RotationSwitchObserver(context); + } + } catch (Throwable e) { + reportWtf("starting RotationSwitchObserver", e); + } + + try { Slog.i(TAG, "Wired Accessory Observer"); // Listen for wired headset changes new WiredAccessoryObserver(context); @@ -696,6 +710,7 @@ class ServerThread extends Thread { final NetworkPolicyManagerService networkPolicyF = networkPolicy; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; + final RotationSwitchObserver rotateSwitchF = rotateSwitch; final UsbService usbF = usb; final ThrottleService throttleF = throttle; final UiModeManagerService uiModeF = uiMode; @@ -750,6 +765,11 @@ class ServerThread extends Thread { reportWtf("making Dock Service ready", e); } try { + if (rotateSwitchF != null) rotateSwitchF.systemReady(); + } catch (Throwable e) { + reportWtf("making Rotation Switch Service ready", e); + } + try { if (usbF != null) usbF.systemReady(); } catch (Throwable e) { reportWtf("making USB Service ready", e); diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index 35503d3..4e4f851 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -62,6 +62,7 @@ class ScreenRotationAnimation { public ScreenRotationAnimation(Context context, SurfaceSession session, boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) { + boolean isTegra = android.os.SystemProperties.get("ro.board.platform","").equals("tegra"); mContext = context; // Screenshot does NOT include rotation! @@ -99,7 +100,7 @@ class ScreenRotationAnimation { try { try { mSurface = new Surface(session, 0, "FreezeSurface", - -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); + -1, mWidth, mHeight, PixelFormat.OPAQUE, isTegra ? 0 : (Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN)); if (mSurface == null || !mSurface.isValid()) { // Screenshot failed, punt. mSurface = null; @@ -116,6 +117,35 @@ class ScreenRotationAnimation { " FREEZE " + mSurface + ": CREATE"); setRotation(originalRotation); + + if (isTegra) { + Rect rect = new Rect(0, 0, mWidth, mHeight); + Canvas canvas = null; + + try { + canvas = mSurface.lockCanvas(rect); + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Unable to lock surface", e); + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to lock surface", e); + } + + Bitmap screenshot = Surface.screenshot(0, 0); + if (canvas == null || screenshot == null) { + Slog.w(TAG, "Null surface canvas"); + mSurface.destroy(); + mSurface = null; + return; + } + + Paint paint = new Paint(0); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + + canvas.drawBitmap(screenshot, 0, 0, paint); + mSurface.unlockCanvasAndPost(canvas); + + } + } finally { if (!inTransaction) { Surface.closeTransaction(); |