Android 11 关于按键拦截/按键事件处理分享
创始人
2024-11-15 02:03:17

系统在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java处理按键事件,不管是物理按键还是
SystemUI的nav_bar上的虚拟按键(使用了KeyEvent类中的,比如:KeyEvent.KEYCODE_VOLUME_UP).

主要注意的有两个函数:
interceptKeyBeforeDispatching 分发之前拦截事件

interceptKeyBeforeQueueing 加入队列之前拦截事件

长按物理音量上键弹出重启Dialog,去除Dialog界面部分选项
    @Override     public long interceptKeyBeforeDispatching(IBinder focusedToken, 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();         final int displayId = event.getDisplayId();          if (true) {             Log.d("tag", "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="                     + repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled);         }          //add text         Log.d("tag", "policyFlags:" + policyFlags);//长按和短按会产生不同的policyFlags         //短按流程 按下 down=true repeatCount=0 2次  抬起 down=false repeatCount=0         //长按流程 按下 down=true repeatCount++ 不断自增  抬起 down=false repeatCount=0         if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {//1107296256  long  //1644167168 short             if (policyFlags == 1107296256 || policyFlags == 1644167168) {                 if (repeatCount == 20) {                     mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);                     mHandler.sendEmptyMessageDelayed(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS, 2000 * 1);                 }                 return -1;             }         }         //add text          //infrare simulate mouse         boolean isBox = "box".equals(SystemProperties.get("ro.target.product"));         if(isBox){         ...     }  // Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg,ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); -> powerLongPress();                           || showGlobalActions();  frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java //dialog所有菜单选项              emergency         lockdown         power         restart         logout         screenshot         bugreport            @VisibleForTesting     protected void createActionItems() {         // Simple toggle style if there's no vibrator, otherwise use a tri-state         if (!mHasVibrator) {             mSilentModeAction = new SilentModeToggleAction();         } else {             mSilentModeAction = new SilentModeTriStateAction(mAudioManager, mHandler);         }         mAirplaneModeOn = new AirplaneModeAction();         onAirplaneModeChanged();          mItems.clear();         mOverflowItems.clear();         mPowerItems.clear();         String[] defaultActions = {"restart"};//getDefaultActions();//add text          ShutDownAction shutdownAction = new ShutDownAction();         RestartAction restartAction = new RestartAction();         ArraySet addedKeys = new ArraySet();         List tempActions = new ArrayList<>();         CurrentUserProvider currentUser = new CurrentUserProvider();          //add text         // make sure emergency affordance action is first, if needed         /*if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {             addIfShouldShowAction(tempActions, new EmergencyAffordanceAction());             addedKeys.add(GLOBAL_ACTION_KEY_EMERGENCY);         }*/         //add text          for (int i = 0; i < defaultActions.length; i++) {             String actionKey = defaultActions[i];             if (addedKeys.contains(actionKey)) {                 // If we already have added this, don't add it again.                 continue;             }     ... }          //点击dialog外,让它消失     protected static ActionsDialog mDialog;//add static           private void initializeLayout() {             setContentView(com.android.systemui.R.layout.global_actions_grid_v2);             fixNavBarClipping();             mControlsView = findViewById(com.android.systemui.R.id.global_actions_controls);             mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);             mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {                 @Override                 public boolean dispatchPopulateAccessibilityEvent(                         View host, AccessibilityEvent event) {                     // Populate the title here, just as Activity does                     event.getText().add(mContext.getString(R.string.global_actions));                     return true;                 }             });             //add text             ViewGroup black_view = findViewById(com.android.systemui.R.id.global_actions_grid_root);             black_view.setClickable(true);             black_view.setOnClickListener(v -> {                 if (mDialog != null) mDialog.dismiss();                 //dismissDialog();             });             //add text             mGlobalActionsLayout.setRotationListener(this::onRotate);             mGlobalActionsLayout.setAdapter(mAdapter);    //衍生案例1: 长按电源键直接关机不弹出dialog     void showGlobalActionsInternal() {         //add text         /*if (mGlobalActions == null) {             mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);         }         final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());         // since it took two seconds of long press to bring this up,         // poke the wake lock so they have some time to see the dialog.         mPowerManager.userActivity(SystemClock.uptimeMillis(), false);*/                  mPowerManager.shutdown(false,null,false);//add text         //add text     } //也可以修改属性实现 ./frameworks/base/core/res/res/values/config.xml          1         //衍生案例2: 长按power键按住三秒即可自动关机     3   //先去掉dialog           @Override     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {             ...             case KeyEvent.KEYCODE_POWER: {                 //add text 长按3s关机,达不到3s取消                 if (down) {                         Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);                         msg.setAsynchronous(true);                         mHandler.sendMessageDelayed(msg,3000);                 } else {                         mHandler.removeMessages(MSG_POWER_LONG_PRESS);                 }                 //add text                 break;             }                          //注释掉原来的逻辑             /*case KeyEvent.KEYCODE_POWER: {                 EventLogTags.writeInterceptPower(                         KeyEvent.actionToString(event.getAction()),                         mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter);                 // Any activity on the power button stops the accessibility shortcut                 cancelPendingAccessibilityShortcutAction();                 result &= ~ACTION_PASS_TO_USER;                 isWakeKey = false; // wake-up will be handled separately                 if (down) {                     interceptPowerKeyDown(event, interactive);                 } else {                     interceptPowerKeyUp(event, interactive, canceled);                 }                 break;             }*/ }  

Adroid11.0长按power键关机流程分析
Android 设备按键处理

一些按键模拟案例
    @Override     public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,             int policyFlags) {             ...            } else if (keyCode == KeyEvent.KEYCODE_MENU) {             // Hijack modified menu keys for debugging features             final int chordBug = KeyEvent.META_SHIFT_ON;              //add text 模拟长按             if (event.getAction() == KeyEvent.ACTION_UP && (event.getEventTime() - event.getDownTime() > 800)) {                 Log.d(TAG,"this is a KEYCODE_MENU's long press");                 //to do                 return -1;             }             //add text              ...                  } 

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...