Android 屏蔽Power键 Home键
16lz
2021-01-23
-
- 在PhoneWindowManagerjava中处理
- 在InputDispatchercpp中处理
在Android开发中,我们通常需要对发往工厂的Android软件进行工厂测试;这其中就要去测试各个按键的功能,例如:测试HOME/BACK/MENU/POWER。但是问题在于:这些按键基本上都是有系统负责处理的,或者在系统处理了之后在向上分发的。也就是说,不论怎样系统都会对此类按键进行处理。
这里给出如下方法:
在PhoneWindowManager.java中处理
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
// First we always handle the home key here, so applications// can never break it, although if keyguard is on, we do let// it handle it, because that gives us the correct 5 second// timeout.if (keyCode == KeyEvent.KEYCODE_HOME) { // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! if (!down) { cancelPreloadRecentApps(); mHomePressed = false; if (mHomeConsumed) { mHomeConsumed = false; return -1; } if (canceled) { Log.i(TAG, "Ignoring HOME; event canceled."); return -1; } // If an incoming call is ringing, HOME is totally disabled. // (The user is already on the InCallUI at this point, // and his ONLY options are to answer or reject the call.) TelecomManager telecomManager = getTelecommService(); if (telecomManager != null && telecomManager.isRinging()) { Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); return -1; } // Delay handling home if a double-tap is possible. if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { // just in case mHomeDoubleTapPending = true; mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, ViewConfiguration.getDoubleTapTimeout()); return -1; } // deal with key.... before if (isTopActivityFactoryTool(win)) { Log.d(TAG,"factory tool return"); return 0; } // deal with key.... end handleShortPressOnHome(); return -1; } // If a system window has focus, then it doesn't make sense // right now to interact with applications. WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; if (attrs != null) { final int type = attrs.type; if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { // the "app" is keyguard, so give it the key return 0; } final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; for (int i=0; iif (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { // don't do anything, but also don't pass it to the app return -1; } } } // Remember that home is pressed and handle special actions. if (repeatCount == 0) { mHomePressed = true; if (mHomeDoubleTapPending) { mHomeDoubleTapPending = false; mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); handleDoubleTapOnHome(); } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { preloadRecentApps(); } } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { handleLongPressOnHome(event.getDeviceId()); } } return -1;}
其中
isTopActivityFactoryTool函数的实现方式
public boolean isTopActivityFactoryTool(WindowState win) { if(win != null){ String topPackageName = win.getOwningPackage(); if(("com.cp.packagename1".equals(topPackageName) || "com.cp.packagename2".equals(topPackageName))){ Log.d(TAG,"top activity is " + topPackageName); return true; } } return false;}
在InputDispatcher.cpp中处理
frameworks/base/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {#if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld", args->eventTime, args->deviceId, args->source, args->policyFlags, args->action, args->flags, args->keyCode, args->scanCode, args->metaState, args->downTime);#endif if (!validateKeyEvent(args->action)) { return; } uint32_t policyFlags = args->policyFlags; int32_t flags = args->flags; int32_t metaState = args->metaState; if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { policyFlags |= POLICY_FLAG_VIRTUAL; flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; } if (policyFlags & POLICY_FLAG_FUNCTION) { metaState |= AMETA_FUNCTION_ON; } policyFlags |= POLICY_FLAG_TRUSTED; int32_t keyCode = args->keyCode; if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) { int32_t newKeyCode = AKEYCODE_UNKNOWN; if (keyCode == AKEYCODE_DEL) { newKeyCode = AKEYCODE_BACK; } else if (keyCode == AKEYCODE_ENTER) { newKeyCode = AKEYCODE_HOME; } if (newKeyCode != AKEYCODE_UNKNOWN) { AutoMutex _l(mLock); struct KeyReplacement replacement = {keyCode, args->deviceId}; mReplacedKeys.add(replacement, newKeyCode); keyCode = newKeyCode; metaState &= ~AMETA_META_ON; } } else if (args->action == AKEY_EVENT_ACTION_UP) { // In order to maintain a consistent stream of up and down events, check to see if the key // going up is one we've replaced in a down event and haven't yet replaced in an up event, // even if the modifier was released between the down and the up events. AutoMutex _l(mLock); struct KeyReplacement replacement = {keyCode, args->deviceId}; ssize_t index = mReplacedKeys.indexOfKey(replacement); if (index >= 0) { keyCode = mReplacedKeys.valueAt(index); mReplacedKeys.removeItemsAt(index); metaState &= ~AMETA_META_ON; } } KeyEvent event; event.initialize(args->deviceId, args->source, args->action, flags, keyCode, args->scanCode, metaState, 0, args->downTime, args->eventTime); mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); bool needWake; { // acquire lock mLock.lock(); if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); policyFlags |= POLICY_FLAG_FILTERED; if (!mPolicy->filterInputEvent(&event, policyFlags)) { return; // event was consumed by the filter } mLock.lock(); } int32_t repeatCount = 0; //add your control code here if(false){ //origin source code }else{ //your self source code } #ifdef CONTROL_KEY_CODE //your self source code #else //origin source doce #endif KeyEntry* newEntry = new KeyEntry(args->eventTime, args->deviceId, args->source, policyFlags, args->action, flags, keyCode, args->scanCode, metaState, repeatCount, args->downTime); needWake = enqueueInboundEventLocked(newEntry); mLock.unlock(); } // release lock if (needWake) { mLooper->wake(); }}
详细的添加规则可以根据自己需求,伪代码如下所示
//add your control code here if(false){ //origin source code }else{ //your self source code } #ifdef CONTROL_KEY_CODE //your self source code #else //origin source doce #endif
有关InputDispatch的处理参见 Android 中处理POWER/HOME流程
更多相关文章
- 深入理解:Android 编译系统
- 基于Android的校园快递系统_移动端设计_后台管理_MySQL数据库设
- 【生态】特斯拉的中控系统为什么是Linux而不是Android?
- 用U盘安装Android系统在PC x86平台上运行Android
- Android的内存泄露测试 mat
- Android中系统触摸相关辅助类总结