KeyCode及KeyCode分发机制


需求场景

纯KeyCode 快捷操作

  • 经常在代码中实现返回、Home 、音量加减、截屏 等功能实现,代码中硬编码 shell 脚本 模拟 KeyCode事件
  • 物理按键调试,模拟物理按键测试用:按键功能,物理按键驱动层已经调试完成,但有没有完整的硬件方便调试,应用层模拟物理按键功能来调试。比如:Android方案中,电视产品、音箱产品、带屏的Android各种方案
    都是有物理按键的,如果自己测试验证物理按键的功能呢,那就需要自己来模拟KeyEventCode 来模拟按键,先自测。
  • 遥控器功能【投影产品】:一般根据蓝牙方案、红外方案实现遥控功能,传递给系统的都是Key的键值,系统自带标准的键值,这样就形成一套标准的流程了,系统根据键值做出反馈或者系统收到对应的键值反馈给上层,上层来处理业务逻辑。
  • 游戏类产品,手柄的控制。手柄上面的功能按钮其实就是一些物理按键,点击物理按键,系统或者应用监听后给出反馈。那么在实际测试的时候,就需要模拟按键来测试验证
  • 如果Android平板作为电脑使用,插上USB,那么Android平板作为电脑来时候,就必须响应键盘上面的所有按键,这些物理按键也是通过KeyCode
    来传递给系统,准确来说是系统来响应这些KeyCode,进而再处理响应的逻辑。

总的来讲:系统响应KeyCode,这些KeyCode是外设作为输入源,KeyCode 键值就是Android一套标准的协议

KeyCode 按键响应操作、拦截

比如物理按键操作之后,系统是如何分发、响应、处理、拦截呢? 比如我们需要客制化一些物理按键功能,如何实现呢?


一、工作中常用KeyCode

枚举值键值功能说明
KEYCODE_HOME3主屏幕键
KEYCODE_BACK4返回键
KEYCODE_DPAD_UP19向上方向键
KEYCODE_DPAD_DOWN20向下方向键
KEYCODE_DPAD_LEFT21向左方向键
KEYCODE_DPAD_RIGHT22向右方向键
KEYCODE_DPAD_CENTER23中心键
KEYCODE_VOLUME_UP24手机音量+
KEYCODE_VOLUME_DOWN25手机音量-
KEYCODE_POWER26电源键
KEYCODE_EXPLORER64启动浏览器程序
KEYCODE_MEDIA_PLAY_PAUSE85多媒体播放、暂停键
KEYCODE_MEDIA_STOP86停止键
KEYCODE_MEDIA_NEXT87下一首键
KEYCODE_MEDIA_PREVIOUS88上一首键
KEYCODE_MEDIA_REWIND89快退键
KEYCODE_MEDIA_FAST_FORWARD90快进键
KEYCODE_MEDIA_PLAY126播放键
KEYCODE_MEDIA_PAUSE127暂停键
KEYCODE_VOLUME_MUTE164手机扬声器静音
KEYCODE_APP_SWITCH187任务管理 最近历史任务
KEYCODE_MUSIC209启动音乐
KEYCODE_BRIGHTNESS_DOWN220亮度减少
KEYCODE_BRIGHTNESS_UP221亮度增加
KEYCODE_DPAD_DOWN_LEFT269向左下方向键
KEYCODE_DPAD_DOWN_RIGHT271向右下方向键
KEYCODE_DPAD_UP_LEFT268向左上方向键
KEYCODE_DPAD_UP_RIGHT270向右上方向键

备注:如何用命令来模拟执行按键操作
枚举方式:adb shell input keyevent KEYCODE_HOME

code方式:adb shell input keyevent 3

二、KeyCode大全

这里给出谷歌官方KeyEvent 事件,里面总结了所有的KeyCode
官方KeyCode


三、KeyCode 响应事件

事件输入流程

从大的方向将,物理按键始于外部输入,在Kernel 响应,再传递到Service或者View层消费,对于Kernel层、系统层暂不研究。
输入设备键值从底层到应用层的映射流程
在这里插入图片描述

事件响应

源码分析

源码位置:
PhoneWindowManager
这里涉及到 源码中的PhoneWindowManager 来响应物理按键事件并进行分发:


    // You can only start consuming the key gesture if ACTION_DOWN and repeat count
    // is 0. If you start intercepting the key halfway, then key will not be consumed
    // and will be sent to apps for processing too.
    // e.g. If a certain combination is only handled on ACTION_UP (i.e.
    // interceptShortcut() returns true only for ACTION_UP), then since we already
    // sent the ACTION_DOWN events to the application, we MUST also send the
    // ACTION_UP to the application.
    // So, to ensure that your intercept logic works properly, and we don't send any
    // conflicting events to application, make sure to consume the event on
    // ACTION_DOWN even if you want to do something on ACTION_UP. This is essential
    // to maintain event parity and to not have incomplete key gestures.
    @SuppressLint("MissingPermission")
    private boolean interceptSystemKeysAndShortcuts(IBinder focusedToken, KeyEvent event) {
        final boolean keyguardOn = keyguardOn();
        final int keyCode = event.getKeyCode();
        final int repeatCount = event.getRepeatCount();
        final int metaState = event.getMetaState();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean canceled = event.isCanceled();
        final int displayId = event.getDisplayId();
        final int deviceId = event.getDeviceId();
        final boolean firstDown = down && repeatCount == 0;

        // Cancel any pending meta actions if we see any other keys being pressed between the
        // down of the meta key and its corresponding up.
        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
            mPendingMetaAction = false;
        }
        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
            mPendingCapsLockToggle = false;
        }

        if (isUserSetupComplete() && !keyguardOn) {
            if (mModifierShortcutManager.interceptKey(event)) {
                dismissKeyboardShortcutsMenu();
                mPendingMetaAction = false;
                mPendingCapsLockToggle = false;
                return true;
            }
        }

        switch (keyCode) {
            case KeyEvent.KEYCODE_HOME:
                return handleHomeShortcuts(focusedToken, event);
            case KeyEvent.KEYCODE_MENU:
                // Hijack modified menu keys for debugging features
                final int chordBug = KeyEvent.META_SHIFT_ON;

                if (mEnableShiftMenuBugReports && firstDown
                        && (metaState & chordBug) == chordBug) {
                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
                            null, null, null, 0, null, null);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_RECENT_APPS:
                if (firstDown) {
                    showRecentApps(false /* triggeredFromAltTab */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                }
                return true;
            case KeyEvent.KEYCODE_APP_SWITCH:
                if (!keyguardOn) {
                    if (firstDown) {
                        preloadRecentApps();
                    } else if (!down) {
                        toggleRecentApps();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);
                    }
                }
                return true;
            case KeyEvent.KEYCODE_A:
                if (firstDown && event.isMetaPressed()) {
                    launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
                            deviceId, event.getEventTime(),
                            AssistUtils.INVOCATION_TYPE_UNKNOWN);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_H:
            case KeyEvent.KEYCODE_ENTER:
                if (event.isMetaPressed()) {
                    return handleHomeShortcuts(focusedToken, event);
                }
                break;
            case KeyEvent.KEYCODE_I:
                if (firstDown && event.isMetaPressed()) {
                    showSystemSettings();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_L:
                if (firstDown && event.isMetaPressed()) {
                    lockNow(null /* options */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LOCK_SCREEN);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_N:
                if (firstDown && event.isMetaPressed()) {
                    if (event.isCtrlPressed()) {
                        sendSystemKeyToStatusBarAsync(event);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_NOTES);
                    } else {
                        toggleNotificationPanel();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_S:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TAKE_SCREENSHOT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_DEL:
            case KeyEvent.KEYCODE_ESCAPE:
                if (firstDown && event.isMetaPressed()) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
                    injectBackGesture(event.getDownTime());
                    return true;
                }
            case KeyEvent.KEYCODE_DPAD_UP:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
                    if (statusbar != null) {
                        statusbar.moveFocusedTaskToFullscreen(getTargetDisplayIdForKeyEvent(event));
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.MULTI_WINDOW_NAVIGATION);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
                    if (statusbar != null) {
                        statusbar.enterDesktop(getTargetDisplayIdForKeyEvent(event));
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.DESKTOP_MODE);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                if (firstDown && event.isMetaPressed()) {
                    if (event.isCtrlPressed()) {
                        enterStageSplitFromRunningApp(true /* leftOrTop */);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
                    } else {
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
                        injectBackGesture(event.getDownTime());
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    enterStageSplitFromRunningApp(false /* leftOrTop */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_SLASH:
                if (firstDown && event.isMetaPressed() && !keyguardOn) {
                    toggleKeyboardShortcutsMenu(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_SHORTCUT_HELPER);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_ASSIST:
                Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_VOICE_ASSIST:
                Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
                        + " interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_VIDEO_APP_1:
            case KeyEvent.KEYCODE_VIDEO_APP_2:
            case KeyEvent.KEYCODE_VIDEO_APP_3:
            case KeyEvent.KEYCODE_VIDEO_APP_4:
            case KeyEvent.KEYCODE_VIDEO_APP_5:
            case KeyEvent.KEYCODE_VIDEO_APP_6:
            case KeyEvent.KEYCODE_VIDEO_APP_7:
            case KeyEvent.KEYCODE_VIDEO_APP_8:
            case KeyEvent.KEYCODE_FEATURED_APP_1:
            case KeyEvent.KEYCODE_FEATURED_APP_2:
            case KeyEvent.KEYCODE_FEATURED_APP_3:
            case KeyEvent.KEYCODE_FEATURED_APP_4:
            case KeyEvent.KEYCODE_DEMO_APP_1:
            case KeyEvent.KEYCODE_DEMO_APP_2:
            case KeyEvent.KEYCODE_DEMO_APP_3:
            case KeyEvent.KEYCODE_DEMO_APP_4:
                Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_BRIGHTNESS_UP:
            case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
                if (down) {
                    int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;

                    // Disable autobrightness if it's on
                    int auto = Settings.System.getIntForUser(
                            mContext.getContentResolver(),
                            Settings.System.SCREEN_BRIGHTNESS_MODE,
                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                            UserHandle.USER_CURRENT_OR_SELF);
                    if (auto != 0) {
                        Settings.System.putIntForUser(mContext.getContentResolver(),
                                Settings.System.SCREEN_BRIGHTNESS_MODE,
                                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                                UserHandle.USER_CURRENT_OR_SELF);
                    }
                    int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;

                    float minLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
                    float maxLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
                    float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);

                    float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);
                    float adjustedGammaBrightness =
                            gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;
                    adjustedGammaBrightness = MathUtils.constrain(adjustedGammaBrightness, 0f,
                            1f);
                    float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(
                            adjustedGammaBrightness);
                    adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness,
                            minLinearBrightness, maxLinearBrightness);
                    mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);

                    Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION
                            | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
                    intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
                if (down) {
                    mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_DOWN);
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:
                if (down) {
                    mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_UP);
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:
                // TODO: Add logic
                if (!down) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_TOGGLE);
                }
                return true;
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                if (mUseTvRouting || mHandleVolumeKeysInWM) {
                    // On TVs or when the configuration is enabled, volume keys never
                    // go to the foreground app.
                    dispatchDirectAudioEvent(event);
                    return true;
                }

                // If the device is in VR mode and keys are "internal" (e.g. on the side of the
                // device), then drop the volume keys and don't forward it to the
                // application/dispatch the audio event.
                if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
                    final InputDevice d = event.getDevice();
                    if (d != null && !d.isExternal()) {
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_TAB:
                if (firstDown && !keyguardOn && isUserSetupComplete()) {
                    if (event.isMetaPressed()) {
                        showRecentApps(false);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                        return true;
                    } else if (mRecentAppsHeldModifiers == 0) {
                        final int shiftlessModifiers =
                                event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
                        if (KeyEvent.metaStateHasModifiers(
                                shiftlessModifiers, KeyEvent.META_ALT_ON)) {
                            mRecentAppsHeldModifiers = shiftlessModifiers;
                            showRecentApps(true);
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                            return true;
                        }
                    }
                }
                break;
            case KeyEvent.KEYCODE_ALL_APPS:
                if (!down) {
                    mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
                    Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
                    msg.setAsynchronous(true);
                    msg.sendToTarget();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);
                }
                return true;
            case KeyEvent.KEYCODE_NOTIFICATION:
                if (!down) {
                    toggleNotificationPanel();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                }
                return true;
            case KeyEvent.KEYCODE_SEARCH:
                if (firstDown && !keyguardOn) {
                    switch (mSearchKeyBehavior) {
                        case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
                            launchTargetSearchActivity();
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SEARCH);
                            return true;
                        }
                        case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
                        default:
                            break;
                    }
                }
                break;
            case KeyEvent.KEYCODE_LANGUAGE_SWITCH:
                if (firstDown) {
                    int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                    sendSwitchKeyboardLayout(event, focusedToken, direction);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_META_LEFT:
            case KeyEvent.KEYCODE_META_RIGHT:
                if (down) {
                    if (event.isAltPressed()) {
                        mPendingCapsLockToggle = true;
                        mPendingMetaAction = false;
                    } else {
                        mPendingCapsLockToggle = false;
                        mPendingMetaAction = true;
                    }
                } else {
                    // Toggle Caps Lock on META-ALT.
                    if (mPendingCapsLockToggle) {
                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
                        mPendingCapsLockToggle = false;
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                    } else if (mPendingMetaAction) {
                        if (!canceled) {
                            launchAllAppsViaA11y();
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);
                        }
                        mPendingMetaAction = false;
                    }
                }
                return true;
            case KeyEvent.KEYCODE_ALT_LEFT:
            case KeyEvent.KEYCODE_ALT_RIGHT:
                if (down) {
                    if (event.isMetaPressed()) {
                        mPendingCapsLockToggle = true;
                        mPendingMetaAction = false;
                    } else {
                        mPendingCapsLockToggle = false;
                    }
                } else {
                    // hide recent if triggered by ALT-TAB.
                    if (mRecentAppsHeldModifiers != 0
                            && (metaState & mRecentAppsHeldModifiers) == 0) {
                        mRecentAppsHeldModifiers = 0;
                        hideRecentApps(true, false);
                        return true;
                    }

                    // Toggle Caps Lock on META-ALT.
                    if (mPendingCapsLockToggle) {
                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
                        mPendingCapsLockToggle = false;
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_CAPS_LOCK:
                if (!down) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                }
                break;
            case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL:
                Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in"
                        + " interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_SETTINGS:
                if (mShortPressOnSettingsBehavior == SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL) {
                    if (!down) {
                        toggleNotificationPanel();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_STEM_PRIMARY:
                if (prepareToSendSystemKeyToApplication(focusedToken, event)) {
                    // Send to app.
                    return false;
                } else {
                    // Intercepted.
                    sendSystemKeyToStatusBarAsync(event);
                    return true;
                }
            case KeyEvent.KEYCODE_SCREENSHOT:
                if (emojiAndScreenshotKeycodesAvailable() && down && repeatCount == 0) {
                    interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
                }
                return true;
        }
        if (isValidGlobalKey(keyCode)
                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
            return true;
        }

        // Reserve all the META modifier combos for system behavior
        return (metaState & KeyEvent.META_META_ON) != 0;
    }

源码举例说明

控制中,如下:

   case KeyEvent.KEYCODE_BRIGHTNESS_UP:
            case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
                if (down) {
                    int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;

                    // Disable autobrightness if it's on
                    int auto = Settings.System.getIntForUser(
                            mContext.getContentResolver(),
                            Settings.System.SCREEN_BRIGHTNESS_MODE,
                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                            UserHandle.USER_CURRENT_OR_SELF);
                    if (auto != 0) {
                        Settings.System.putIntForUser(mContext.getContentResolver(),
                                Settings.System.SCREEN_BRIGHTNESS_MODE,
                                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                                UserHandle.USER_CURRENT_OR_SELF);
                    }
                    int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;

                    float minLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
                    float maxLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
                    float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);

                    float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);
                    float adjustedGammaBrightness =
                            gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;
                    adjustedGammaBrightness = MathUtils.constrain(adjustedGammaBrightness, 0f,
                            1f);
                    float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(
                            adjustedGammaBrightness);
                    adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness,
                            minLinearBrightness, maxLinearBrightness);
                    mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);

                    Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION
                            | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
                    intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));
                }
                return true;

这里消费亮度

业务逻辑如下:

  • 获取当前亮度模式
  • 获取当前亮度、最大亮度、最小亮度
  • 调节亮度【用到了亮度曲线 从伽马曲线】
  • 发送亮度控制的Intent
    的接受者【实际为BrightnessDialog

声音音量也是一样的,在这个方法中进行了处理一次,再响应给View来处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ItJavawfc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值