Power长按、组合键分析

原创 2016年02月29日 18:43:48

1.Power长按功能原理

 当按下power时

                    Log.i(TAG, "PowerKey down, isScreenOn = " + isScreenOn);
                    interceptPowerKeyDown(!isScreenOn || hungUp
                            || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
    private void interceptPowerKeyDown(boolean handled) {
        mPowerKeyHandled = handled;
        if (!handled || mChangeLongPressPowerKey) {
            if(mChangeLongPressPowerKey) {
                Log.d(TAG,"fast boot acquire cpu wakelock for timeout :"+(ViewConfiguration.getGlobalActionKeyTimeout()+100));
                PowerManager.WakeLock fastBootWake = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FastBootWake");
                fastBootWake.acquire(ViewConfiguration.getGlobalActionKeyTimeout()+100);
             }
            mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
        }
    }

抬起手时
                    Log.i(TAG, "PowerKey up");
                    mPowerKeyTriggered = false;
                    cancelPendingScreenshotChordAction();
                    if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
                        result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
                    }
                    mPendingPowerKeyUpCanceled = false;
    private boolean interceptPowerKeyUp(boolean canceled) {
        if (!mPowerKeyHandled) {
            mHandler.removeCallbacks(mPowerLongPress);
            return !canceled;
        }
        if (mChangeLongPressPowerKey) {
            mHandler.removeCallbacks(mPowerLongPress);
        }
        return false;
    }

根据以上代码分析知,在亮屏、音量键没触发、power键没进行挂电话行为时,按下power会进入mPowerLongPress启动的倒计时,当抬起手时会判断power键的事件是否被消耗,如果没被消耗则移除mPowerLongPress事件,并返回传进来的boolean的相反值。

mPendingPowerKeyUpCanceled的值控制如下

    private void cancelPendingPowerKeyAction() {
        if (!mPowerKeyHandled) {
            mHandler.removeCallbacks(mPowerLongPress);
        }
        if (mPowerKeyTriggered) {
            mPendingPowerKeyUpCanceled = true;
        }
    }

总结来说:要想实现长按,需要1.一个boolean值用于判断按下的事件是否消费,如mPowerKeyHandled。2.handler延迟执行长按的事件,并且在长按事件的执行代码中把事件boolean设置为消费状态。3.up事件中判断这次按下事件是否被消耗,如果没则处理单点流程。

长按实现:记录下第一次按下的时间,记录此次事件是否被消费,在down事件中判断是否达到了长按时间,在up事件中把事件归零并判断事件是否消费并重置。

2.组合键原理

长按power+音量下可以截图,以此为例分析

在power键的down事件中有如下代码

                    if (isScreenOn && !mPowerKeyTriggered
                            && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                        mPowerKeyTriggered = true;
                        mPowerKeyTime = event.getDownTime();
                        interceptScreenshotChord();
                    }

    private void interceptScreenshotChord() {
        if (mScreenshotChordEnabled
                && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
            final long now = SystemClock.uptimeMillis();
            if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
                    && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
                mVolumeDownKeyConsumedByScreenshotChord = true;
                cancelPendingPowerKeyAction();

                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
            }
        }
    }

音量-按键down事件
                        if (isScreenOn && !mVolumeDownKeyTriggered
                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                            mVolumeDownKeyTriggered = true;
                            mVolumeDownKeyTime = event.getDownTime();
                            mVolumeDownKeyConsumedByScreenshotChord = false;
                            cancelPendingPowerKeyAction();
                            interceptScreenshotChord();
                        }
根据以上代码可以分析出;power键按下时记下按下的时间并且mPowerKeyTriggered设为true,音量键同样如此,两个都调用了interceptScreenshotChord()方法,也就是说先按下哪个键不影响。在interceptScreenshotChord()方法中,如果power被触发、音量down被触发,音量up没被触发则继续判断两个按键按下的间隔是否在一定时间内,如果是则开始进入截屏流程,并把mVolumeDownKeyConsumedByScreenshotChord设为true,mVolumeDownKeyConsumedByScreenshotChord值用于阻止音量按键事件往下传递用,在interceptKeyBeforeDispatching方法内
        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
            if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
                final long now = SystemClock.uptimeMillis();
                final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
                if (now < timeoutTime) {
                    return timeoutTime - now;
                }
            }
            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
                    && mVolumeDownKeyConsumedByScreenshotChord) {
                if (!down) {
                    mVolumeDownKeyConsumedByScreenshotChord = false;
                }
                return -1;
            }
        }
可以看出,如果先按的是音量-键,那么在一定时间内事件是没有被传递下去,当抬手时则mVolumeDownKeyConsumedByScreenshotChord=true.不过mVolumeDownKeyConsumedByScreenshotChord好像没什么用。

总结:要想实现组合键,1、记录两个按键的按下时间。2、记录两个按键是否按下触发。3、每个按键按下时触发同一个方法并在此方法内判读两个按键按下的时间差是否在一定时间内,如果是则组合按键生效。

注意:power按键之所以在组合按键起效时不响应点击或者长按事件,因为处理时判断了音量键是否按下去了,如果按下了则不起效。而如果power键先按,则在音量键按下时调用了mVolumeDownKeyConsumedByScreenshotChord

    private void cancelPendingPowerKeyAction() {
        if (!mPowerKeyHandled) {
            mHandler.removeCallbacks(mPowerLongPress);
        }
        if (mPowerKeyTriggered) {
            mPendingPowerKeyUpCanceled = true;
        }
    }
mPendingPowerKeyUpCanceled的用途是阻止power松开时灭屏


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android之ActivityManager简介(一)

本文主要内容是讲解一下关于Android中的ActivityManager,这个类可以得到“设备配置的属性”,"进程信息","任务信息",“服务”,“正在运行的程序” 因此通过这个类,我们可...

触摸屏驱动学习笔记 一

第一:四线式电阻式触摸屏原理   S3C2440而言:在直接试用触摸屏的是时,引脚XP、XM、XP和YM被用于和触摸屏直接相连。只剩下AIN[3:0]共4个引脚用于一般的ADC输入;当不使用的时候,X...

Android 性能优化 二 TraceView工具的使用

一、 选择跟踪范围 在想要根据的代码片段之间使用以下两句代码 Debug.startMethodTracing("love_world_"); Debug.stopMethodTracing(); ...

手机灭屏之后,来短信或者信息亮屏5s之后再黑屏

Android N上验证:   这个修改为客制化的需求,可以在BaseStatusBar.java定义一个wakelock,并初始化: import android.os.PowerMa...

ActivityManager

android.app.ActivityManager 这个类主要用来管理所有设备上的Activities。 权限:android.permission.GET_TASKS 方法:| 返回类型    ...

JAVA调用svnkit获取svn树节点

SVNKit (JavaSVN) 是一个纯 Java 的 SVN 客户端库,使用 SVNKit 无需安装任何 SVN 的客户端,支持各种操作系统。 这是一款商业软件,非商业可免费使用。 ...

Android中获取正在运行的应用程序-----ActivityManager.RunningAppProcessInfo类详解

转载请注明出处:http://blog.csdn.net/qinjuning                    ...

Android源码学习之六——ActivityManager框架解析

本文从静态类结构和动态类结构两个角度分析了ActivityManager的框架,兼顾了Binder机制和代理模式在进程间通信的机理,对帮助开发人员深化操作系统的结构和框架具有一定的指导作用。
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)