Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 037aa8d4 authored by Craig Mautner's avatar Craig Mautner
Browse files

Centralize all system InputEventReceiver monitors.

Implement all system level InputEvent monitors as new
InputEventListeners. Only one InputChannel required and monitoring
can be enabled or disabled by registering with WindowManagerService.

Change-Id: I64714ab858342ed183c62b421098478ffb6637bc
parent 97f41383
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -407,11 +407,6 @@ public interface WindowManagerPolicy {
         */
        public int getLidState();

        /**
         * Creates an input channel that will receive all input from the input dispatcher.
         */
        public InputChannel monitorInput(String name);

        /**
         * Switch the keyboard layout for the given device.
         * Direction should be +1 or -1 to go to the next or previous keyboard layout.
@@ -425,6 +420,21 @@ public interface WindowManagerPolicy {
         * Return the window manager lock needed to correctly call "Lw" methods.
         */
        public Object getWindowManagerLock();

        /** Register a system listener for touch events */
        void registerPointerEventListener(PointerEventListener listener);

        /** Unregister a system listener for touch events */
        void unregisterPointerEventListener(PointerEventListener listener);
    }

    public interface PointerEventListener {
        /**
         * 1. onPointerEvent will be called on the service.UiThread.
         * 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
         * copy() must be made and the copy must be recycled.
         **/
        public void onPointerEvent(MotionEvent motionEvent);
    }

    /** Window has been added to the screen. */
+15 −41
Original line number Diff line number Diff line
@@ -296,35 +296,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    WindowState mFocusedWindow;
    IApplicationToken mFocusedApp;

    private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
        private final PointerLocationView mView;

        public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
                PointerLocationView view) {
            super(inputChannel, looper);
            mView = view;
        }

    private final class PointerLocationPointerEventListener implements PointerEventListener {
        @Override
        public void onInputEvent(InputEvent event) {
            boolean handled = false;
            try {
                if (event instanceof MotionEvent
                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                    final MotionEvent motionEvent = (MotionEvent)event;
                    mView.addPointerEvent(motionEvent);
                    handled = true;
                }
            } finally {
                finishInputEvent(event, handled);
        public void onPointerEvent(MotionEvent motionEvent) {
            if (mPointerLocationView != null) {
                mPointerLocationView.addPointerEvent(motionEvent);
            }
        }
    }

    // Pointer location view state, only modified on the mHandler Looper.
    PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
    PointerLocationPointerEventListener mPointerLocationPointerEventListener;
    PointerLocationView mPointerLocationView;
    InputChannel mPointerLocationInputChannel;

    // The current size of the screen; really; extends into the overscan area of
    // the screen and doesn't account for any system elements like the status bar.
@@ -568,8 +551,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    private int mStatusHideybar;
    private int mNavigationHideybar;

    private InputChannel mSystemGestureInputChannel;
    private SystemGestures mSystemGestures;
    private SystemGesturesPointerEventListener mSystemGestures;

    IStatusBarService getStatusBarService() {
        synchronized (mServiceAquireLock) {
@@ -925,10 +907,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        context.registerReceiver(mMultiuserReceiver, filter);

        // monitor for system gestures
        mSystemGestureInputChannel = mWindowManagerFuncs.monitorInput("SystemGestures");
        mSystemGestures = new SystemGestures(mSystemGestureInputChannel,
                mHandler.getLooper(), context,
                new SystemGestures.Callbacks() {
        mSystemGestures = new SystemGesturesPointerEventListener(context,
                new SystemGesturesPointerEventListener.Callbacks() {
                    @Override
                    public void onSwipeFromTop() {
                        if (mStatusBar != null) {
@@ -954,6 +934,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                        }
                    }
                });
        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);

        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
@@ -1212,23 +1193,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
            wm.addView(mPointerLocationView, lp);

            mPointerLocationInputChannel =
                    mWindowManagerFuncs.monitorInput("PointerLocationView");
            mPointerLocationInputEventReceiver =
                    new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
                            Looper.myLooper(), mPointerLocationView);
            mPointerLocationPointerEventListener = new PointerLocationPointerEventListener();
            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationPointerEventListener);
        }
    }

    private void disablePointerLocation() {
        if (mPointerLocationInputEventReceiver != null) {
            mPointerLocationInputEventReceiver.dispose();
            mPointerLocationInputEventReceiver = null;
        }

        if (mPointerLocationInputChannel != null) {
            mPointerLocationInputChannel.dispose();
            mPointerLocationInputChannel = null;
        if (mPointerLocationPointerEventListener != null) {
            mWindowManagerFuncs.unregisterPointerEventListener(
                    mPointerLocationPointerEventListener);
            mPointerLocationPointerEventListener = null;
        }

        if (mPointerLocationView != null) {
+4 −17
Original line number Diff line number Diff line
@@ -17,19 +17,15 @@
package com.android.internal.policy.impl;

import android.content.Context;
import android.os.Looper;
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy.PointerEventListener;

/*
 * Listens for system-wide input gestures, firing callbacks when detected.
 * @hide
 */
public class SystemGestures extends InputEventReceiver {
public class SystemGesturesPointerEventListener implements PointerEventListener {
    private static final String TAG = "SystemGestures";
    private static final boolean DEBUG = false;
    private static final long SWIPE_TIMEOUT_MS = 500;
@@ -55,9 +51,7 @@ public class SystemGestures extends InputEventReceiver {
    private boolean mSwipeFireable;
    private boolean mDebugFireable;

    public SystemGestures(InputChannel inputChannel, Looper looper,
            Context context, Callbacks callbacks) {
        super(inputChannel, looper);
    public SystemGesturesPointerEventListener(Context context, Callbacks callbacks) {
        mCallbacks = checkNull("callbacks", callbacks);
        mSwipeStartThreshold = checkNull("context", context).getResources()
                .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
@@ -72,14 +66,7 @@ public class SystemGestures extends InputEventReceiver {
    }

    @Override
    public void onInputEvent(InputEvent event) {
        if (event instanceof MotionEvent && event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
            onPointerMotionEvent((MotionEvent) event);
        }
        finishInputEvent(event, false /*handled*/);
    }

    private void onPointerMotionEvent(MotionEvent event) {
    public void onPointerEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mSwipeFireable = true;
+1 −5
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.InputChannel;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -101,11 +100,8 @@ class DisplayContent {
    /** Sorted most recent at top, oldest at [0]. */
    ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();

    /** Forward motion events to mTapDetector. */
    InputChannel mTapInputChannel;

    /** Detect user tapping outside of current focused stack bounds .*/
    StackTapDetector mTapDetector;
    StackTapPointerEventListener mTapDetector;

    /** Detect user tapping outside of current focused stack bounds .*/
    Region mTouchExcludeRegion = new Region();
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 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.wm;

import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy.PointerEventListener;

import com.android.server.UiThread;

import java.util.ArrayList;

public class PointerEventDispatcher extends InputEventReceiver {
    ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
    PointerEventListener[] mListenersArray = new PointerEventListener[0];

    public PointerEventDispatcher(InputChannel inputChannel) {
        super(inputChannel, UiThread.getHandler().getLooper());
    }

    @Override
    public void onInputEvent(InputEvent event) {
        try {
            if (event instanceof MotionEvent
                    && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                final MotionEvent motionEvent = (MotionEvent)event;
                PointerEventListener[] listeners;
                synchronized (mListeners) {
                    if (mListenersArray == null) {
                        mListenersArray = new PointerEventListener[mListeners.size()];
                        mListeners.toArray(mListenersArray);
                    }
                    listeners = mListenersArray;
                }
                for (int i = 0; i < listeners.length; ++i) {
                    listeners[i].onPointerEvent(motionEvent);
                }
            }
        } finally {
            finishInputEvent(event, false);
        }
    }

    /**
     * Add the specified listener to the list.
     * @param listener The listener to add.
     */
    public void registerInputEventListener(PointerEventListener listener) {
        synchronized (mListeners) {
            if (mListeners.contains(listener)) {
                throw new IllegalStateException("registerInputEventListener: trying to register" +
                        listener + " twice.");
            }
            mListeners.add(listener);
            mListenersArray = null;
        }
    }

    /**
     * Remove the specified listener from the list.
     * @param listener The listener to remove.
     */
    public void unregisterInputEventListener(PointerEventListener listener) {
        synchronized (mListeners) {
            if (!mListeners.contains(listener)) {
                throw new IllegalStateException("registerInputEventListener: " + listener +
                        " not registered.");
            }
            mListeners.remove(listener);
            mListenersArray = null;
        }
    }
}
Loading