Hand in hand to teach you Android global touch event monitoring

  • 2021-12-19 06:47:08
  • OfStack

Android System Global Touch Event Monitoring

Android touch global monitoring means that touch events can be obtained in any interface after monitoring is called.

To achieve this function, you must modify the source code to add a new interface, because the system does not expose this method by default.

Source code

Classes and related codes that listen for system global touch events:


frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
    @Override
    public void registerPointerEventListener(PointerEventListener listener, int displayId) {
        Slog.i(TAG, "registerPointerEventListener PointerEventListener = " + listener);
        synchronized (mGlobalLock) {
            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            if (displayContent != null) {
                displayContent.registerPointerEventListener(listener);
            }
        }
    }

    @Override
    public void unregisterPointerEventListener(PointerEventListener listener, int displayId) {
        synchronized (mGlobalLock) {
            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            if (displayContent != null) {
                displayContent.unregisterPointerEventListener(listener);
            }
        }
    }

The first parameter is the PointerEventListener interface in,

There are MotionEvent Object contains click events, such as DOWN、UP、MOVING And other information.


    package android.view;
    public interface WindowManagerPolicyConstants {
        interface PointerEventListener {
            void onPointerEvent(MotionEvent motionEvent);
        }
    }

The second parameter, screen id, normally uses 0 to indicate the main screen id. Some devices need to pay attention to this only when they have a projection screen or a second screen.

Here's how to register this service

1. Bind this system service, this method will not work

Because the service's aidl interface IWindowManager does not expose this method
The registerPointerEventListener method is defined in another internal interface, WindowManagerFuncs


public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
    public interface WindowManagerFuncs {
            /** Register a system listener for touch events */
            void registerPointerEventListener(PointerEventListener listener, int displayId);

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

2. Obtain WindowManagerFuncs object. There are many ways to obtain this object in the source code

Reference:


frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
public PhoneWindowManager extends AbsPhoneWindowManager implements WindowManagerPolicy, IHwPhoneWindowManagerInner{
    public WindowManagerFuncs getWindowManagerFuncs(){
        return mWindowManagerFuncs; 
    }
}

WindowManagerFuncs in the source code can be directly new, using the following:


PhoneWindowManager phoneWindowManager = new PhoneWindowManager();
WindowManagerFuncs windowManagerFuncs = phoneWindowManager.getWindowManagerFuncs();
windowManagerFuncsEx.registerPointerEventListener(listener, Display.DEFAULT_DISPLAY);

3. Add aidl callback to Huawei Emui source code

WindowManagerEx has a channel to send data directly to WindowManagerService and can monitor data

(1) Add aidl interface


vendor\huawei\Emui\frameworks\hwCommInterface\base\core\java\com\huawei\android\app\IHwPointEventCallback.aidl
package com.huawei.android.app;
    import android.view.MotionEvent;
    oneway interface IHwPointEventCallback {
        void onPointerEvent(in MotionEvent motionEvent);
    }

(2) Modification of WindowManagerEx


vendor\huawei\Emui\frameworks\hwext\hwext\framework\src\com\huawei\android\app\WindowManagerEx.java
    private final int TRANSACTION_SET_POINTER_EVENT_LISTENER = android.os.IBinder.FIRST_CALL_TRANSACTION + 2100;
    // To WindowManagerService Pass the listening object 
    public static void setPointerEventListener(IHwPointEventCallback listener) {
        Log.i(LOG_TAG, "setPointerEventListener listener = " + listener);
        IBinder windowManagerBinder = WindowManagerGlobal.getWindowManagerService().asBinder();
        if (windowManagerBinder != null) {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            try {
                data.writeInterfaceToken("android.view.IWindowManager");
                // Transfer aidl Monitor object 
                data.writeStrongBinder(listener != null ? listener.asBinder() : null);
               // Send 
                windowManagerBinder.transact(TRANSACTION_SET_POINTER_EVENT_LISTENER, data, reply, 0);
            } catch (RemoteException e){
                Log.e(LOG_TAG, "setPointerEventListener exception is " + e.getMessage());
            } finally {
                data.recycle();
                reply.recycle();
            }
        } else {
            Log.w(LOG_TAG, "setPointerEventListener windowManagerBinder is null");
        }
    }

(3) Receive data in WindowManagerService and do actual monitoring

Based on the idea of not modifying the source code as much as possible, Emui has a subclass HwWindowManagerService of WindowManagerService, and the code can be modified in the subclass.


vendor\huawei\Emui\frameworks\base\services\java\huawei\com\android\server\wm\HwWindowManagerService.java
    HwWindowManagerService extends WindowManagerService
    private final int TRANSACTION_SET_POINTER_EVENT_LISTENER = android.os.IBinder.FIRST_CALL_TRANSACTION + 2100;
    private IHwPointEventCallback mIHwPointEventCallback = null;
    
    // Receive WindowManagerEx Transmitted data 
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
            switch (code) {
                case TRANSACTION_SET_POINTER_EVENT_LISTENER:
                    data.enforceInterface("android.view.IWindowManager");
                    IHwPointEventCallback observer = IHwPointEventCallback.Stub.asInterface(data.readStrongBinder());
                    setPointerEventListener(observer);
                    reply.writeNoException();
                    return true;

        }
    }
    
    // In Service Create only in the 1 Listening object of 
    private PointerEventListener mPointerEventListener = new PointerEventListener() {
        @Override
        public void onPointerEvent(MotionEvent motionEvent) {
            if(mIHwPointEventCallback != null) {
                try {
                    mIHwPointEventCallback.onPointerEvent(motionEvent);
                } catch (RemoteException e) {
                    Slog.e(TAG, "mIHwPointEventCallback error = " + e.getMessage());
                }
            }
        }
    };

    // Add a method for setting touch listening 
    private void setPointerEventListener(IHwPointEventCallback listener) {
        Slog.i(TAG, "setPointerEventListener PointerEventListener = " + listener);
        int uid = Binder.getCallingUid();
        if(uid != Process.SYSTEM_UID){
            Slog.e(TAG, "setPointerEventListener uid must be "+ Process.SYSTEM_UID +",but now uid = " + uid);
            return;
        }
        mIHwPointEventCallback = listener;
        if(listener != null) {
            // The method that actually calls to the registered touch event of the parent class 
            registerPointerEventListener(mPointerEventListener, Display.DEFAULT_DISPLAY);
        }
        else {
            // Method that actually calls to the parent class's de-register touch event 
            unregisterPointerEventListener(mPointerEventListener, Display.DEFAULT_DISPLAY);
        }
    }

Method 3 can monitor the global touch events of the system in the common app,

Because app can rely on emui_addons. jar of Emui,
Calling some classes inside, such as WindowManagerEx, can listen for global touch events.

Other system environments can refer to the above implementation according to the actual situation.

Sharing encouragement: Only when you read more can you know that there are still more that you haven't seen yet.


Related articles: