Android 屏蔽Power键 Home键

    • 在PhoneWindowManagerjava中处理
    • 在InputDispatchercpp中处理

在Android开发中,我们通常需要对发往工厂的Android软件进行工厂测试;这其中就要去测试各个按键的功能,例如:测试HOME/BACK/MENU/POWER。但是问题在于:这些按键基本上都是有系统负责处理的,或者在系统处理了之后在向上分发的。也就是说,不论怎样系统都会对此类按键进行处理。
这里给出如下方法:

PhoneWindowManager.java中处理

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

Android 屏蔽Power键 Home键_第1张图片


// 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)