lxp 发表于 2017-8-9 16:14:57

Android7.1下显示/隐藏鼠标

本帖最后由 lxp 于 2017-8-9 16:16 编辑

功能:长按遥控的search键后,切换为飞鼠模式。问题:1.切换飞鼠模式鼠标没有显示出来(要按其他上下左右按钮才开始显示)2.切换回按键模式后,鼠标是自动等待一段时间消失,而不是立即消失
从下面这个博客得到启示http://blog.csdn.net/myarrow/article/details/12708185画鼠标流程
鼠标由PointerController.cpp控制。文件在framework/base/libs/input/PointerController.cpp鼠标隐藏的方法
void PointerController::fade(Transition transition) {
    AutoMutex _l(mLock);

    // Remove the inactivity timeout, since we are fading now.
    removeInactivityTimeoutLocked();

    // Start fading.
    if (transition == TRANSITION_IMMEDIATE) {
      mLocked.pointerFadeDirection = 0;
      mLocked.pointerAlpha = 0.0f;
      updatePointerLocked();
    } else {
      mLocked.pointerFadeDirection = -1;
      startAnimationLocked();
    }
}



本次补丁是framework/base/services/core/java/com/android/server/policy/PhoneWindowManaer.java+    Runnable HPHRunable = new Runnable(){
+            public void run(){
+                mEscPressd = true;
+               Log.e(TAG,"linjc:HPHRunable");
+               mstate=SystemProperties.get("sys.KeyMouse.mKeyMouseState");
+               if(mstate.equals("on"))
+               {
+                     SystemProperties.set("sys.KeyMouse.mKeyMouseState","off");
+                              Toast.makeText(mContext, "Restore the default button mode", Toast.LENGTH_LONG).show();
+               //             Toast.makeText(getActivity(), "Restore the default button mode", Toast.LENGTH_LONG).show();
+                      }
+                      else
+                      {
+                              SystemProperties.set("sys.KeyMouse.mKeyMouseState","on");
+                              Toast.makeText(mContext, "Into Mouse mode,click this key again out of this mode", Toast.LENGTH_LONG).show();
+               //             Toast.makeText(getActivity(), "Into Mouse mode,click this key again out of this mode", Toast.LENGTH_LONG).show();
+               }
+            }
+    };
+

他主要是设置sys.KeyMouse.mKeyMouseState这个全局属性。
sys.KeyMouse.mKeyMouseState在interceptKeyBeforeDispatching函数里
@Override
    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
      final boolean keyguardOn = keyguardOn();
      final int keyCode = event.getKeyCode();
      final int repeatCount = event.getRepeatCount();
      final int metaState = event.getMetaState();
      final int flags = event.getFlags();
      final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
      final boolean canceled = event.isCanceled();

      if (DEBUG_INPUT) {
            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
                  + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
                  + " canceled=" + canceled);
      }

      mstate = SystemProperties.get("sys.KeyMouse.mKeyMouseState");
      if (mstate.equals("on") && ((keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_LEFT)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_RIGHT)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_UP)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_DOWN)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_MODE_SWITCH))) {
            keydown = down;
            mKeyMouseHandler.sendEmptyMessage(keyCode);            
            //return -1;
      }

      if (mstate.equals("on") && ((keyCode == KeyEvent.KEYCODE_ENTER)
                ||(keyCode == KeyEvent.KEYCODE_DPAD_CENTER))) {
            return -1;
      }
      
      ...
      当sys.KeyMouse.mKeyMouseState为on的时候,截取一些keycode交给mKeyMouseHandler处理
public Handler mKeyMouseHandler = new Handler() {
      public void handleMessage(Message msg) {
            switch(msg.what){
            case KeyEvent.KEYCODE_TV_KEYMOUSE_LEFT:
                mdeltax = -1.0f;
                mdeltay = 0;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_RIGHT:
                mdeltax = 1.0f;
                mdeltay = 0;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_UP:
                mdeltax = 0;
                mdeltay = -1.0f;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_DOWN:
                mdeltax = 0;
                mdeltay = 1.0f;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_MODE_SWITCH:
                mdeltax = 0;
                mdeltay = 0;
                break;
            default:
                break;
            }

            try {
                mWindowManager.dispatchMouse(mdeltax,mdeltay,screenWidth,screenHeight);
            } catch (Exception e){
                e.printStackTrace();
            }

            if (keydown) {
                mKeyMouseHandler.sendEmptyMessageDelayed(msg.what,30);
            }
      }
    };mWindowManager.dispatchMouse(mdeltax,mdeltay,screenWidth,screenHeight);
发现鼠标事件由这个方法处理。
mWindowManager是WindowManagerService
跟进dispatchMouse这个方法


framework/base/services/core/java/com/android/server/wm/WindowManagerService.java
   public class WindowManagerService extends IWindowManager.Stub
      implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    ...
      }

    ...

   public void dispatchMouse(float x, float y, int w, int h) {
            mInputManager.dispatchMouse(x,y,w,h);
    }mInputManager是InputManagerService类的实例

framework/base/services/core/java/com/android/server/input/InputManagerService.java
   public void dispatchMouse(float x, float y, int w, int h){
      nativedispatchMouse(x, y, w, h, mPtr);
    }   private static native void nativedispatchMouse(float x, float y, int w, int h, long ptr);nativedispatchMouse是一个jni方法

查找framework/base/services/core/jni下
发现一个com_android_server_input_InputManagerService.cpp
framework/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static const JNINativeMethod gInputManagerMethods[] = {
    /* name, signature, funcPtr */

...nativedispatchMouse的原型是android_server_InputManager_nativedispatchMouse

static void android_server_InputManager_nativedispatchMouse(JNIEnv* env,
                jclass clazz,jfloat x,jfloat y,jint w,jint h,jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    int mID;
    float mx, my;
    float screenWidth,screenHeight;
    char *mgetID=new char;
    char *mkeyMouseState=new char;
    screenWidth=(float)w;
    screenHeight=(float)h;

    property_get("sys.ID.mID",mgetID,0);
    mID=atoi(mgetID);

    mPointerController=im->obtainPointerController(mID);

    //start to dispatchMouse
    mPointerController->setPresentation(
                  PointerControllerInterface::PRESENTATION_POINTER);
    mPointerController->move(x,y);
    mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
    mPointerController->getPosition(&mx, &my);

    //if((mx<=0)||((mx>=(screenWidth-10.0f))||(my<=0)||(my>=(screenHeight-10.0f)))
    //      x=0;y=0;

    if (mx == 0) {
            strcpy(mkeyMouseState, "left");
    } else if (mx>=(screenWidth-5.0f)) {
            strcpy(mkeyMouseState, "right");
    } else if (my == 0) {
            strcpy(mkeyMouseState, "up");
    } else if (my >= (screenHeight-5.0f)) {
            strcpy(mkeyMouseState, "down");
    } else {
            strcpy(mkeyMouseState, "Non-boundary");
    }

    property_set("sys.keymouselimitstate",mkeyMouseState);
}终于在这里发现了PointerController的实例了
隐藏鼠标只要模仿dispatchMouse写一个方法就可以了


static void android_server_InputManager_nativefadeMouse(JNIEnv* env,
jclass clazz,jlong ptr){
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   int mID;
   char *mgetID=new char;

   property_get("sys.ID.mID",mgetID,0);
   mID=atoi(mgetID);

   mPointerController=im->obtainPointerController(mID);

   //start to dispatchMouse
    mPointerController->setPresentation(
                  PointerControllerInterface::PRESENTATION_POINTER);   
    mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
}gInputManagerMethods[] 数组加上我们新加的方法
{ "nativefadeMouse", "(J)V",
                (void*) android_server_InputManager_nativefadeMouse},第二个参数括号里面代表的是函数参数类型,括号外的表示返回类型,一定要对应。具体值百度。

这里要注意的是WindowManagerService是继承了IWindowManager.Stub
要找到IWindowManager.aidl加上对应的方法。
最后,找到文件在
framework/base/core/java/android/view/IWindowManager.aidl
其他中间调用就不写了。

-----------------------------------
鼠标显示的方法
比较简单,看到上面的mKeyMouseHandler。
当sys.KeyMouse.mKeyMouseState设为on的同时,将keydown设为true(为了让鼠标一直显示,直到模式切换回去或者有人按键),mKeyMouseHandler.sendEmptyMessage(KeyEvent.KEYCODE_TV_KEYMOUSE_MODE_SWITCH)。








页: [1]
查看完整版本: Android7.1下显示/隐藏鼠标