Home | History | Annotate | Download | only in hdmi
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.hdmi;
     18 
     19 import android.view.KeyEvent;
     20 
     21 import libcore.util.EmptyArray;
     22 
     23 import java.util.Arrays;
     24 
     25 /**
     26  * Helper class to translate android keycode to hdmi cec keycode and vice versa.
     27  */
     28 final class HdmiCecKeycode {
     29     public static final int UNSUPPORTED_KEYCODE = -1;
     30     public static final int NO_PARAM = -1;
     31 
     32     // =========================================================================
     33     // Hdmi CEC keycodes
     34     public static final int CEC_KEYCODE_SELECT = 0x00;
     35     public static final int CEC_KEYCODE_UP = 0x01;
     36     public static final int CEC_KEYCODE_DOWN = 0x02;
     37     public static final int CEC_KEYCODE_LEFT = 0x03;
     38     public static final int CEC_KEYCODE_RIGHT = 0x04;
     39     public static final int CEC_KEYCODE_RIGHT_UP = 0x05;
     40     public static final int CEC_KEYCODE_RIGHT_DOWN = 0x06;
     41     public static final int CEC_KEYCODE_LEFT_UP = 0x07;
     42     public static final int CEC_KEYCODE_LEFT_DOWN = 0x08;
     43     public static final int CEC_KEYCODE_ROOT_MENU = 0x09;
     44     public static final int CEC_KEYCODE_SETUP_MENU = 0x0A;
     45     public static final int CEC_KEYCODE_CONTENTS_MENU = 0x0B;
     46     public static final int CEC_KEYCODE_FAVORITE_MENU = 0x0C;
     47     public static final int CEC_KEYCODE_EXIT = 0x0D;
     48     // RESERVED = 0x0E - 0x0F
     49     public static final int CEC_KEYCODE_MEDIA_TOP_MENU = 0x10;
     50     public static final int CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU = 0x11;
     51     // RESERVED = 0x12  0x1C
     52     public static final int CEC_KEYCODE_NUMBER_ENTRY_MODE = 0x1D;
     53     public static final int CEC_KEYCODE_NUMBER_11 = 0x1E;
     54     public static final int CEC_KEYCODE_NUMBER_12 = 0x1F;
     55     public static final int CEC_KEYCODE_NUMBER_0_OR_NUMBER_10 = 0x20;
     56     public static final int CEC_KEYCODE_NUMBERS_1 = 0x21;
     57     public static final int CEC_KEYCODE_NUMBERS_2 = 0x22;
     58     public static final int CEC_KEYCODE_NUMBERS_3 = 0x23;
     59     public static final int CEC_KEYCODE_NUMBERS_4 = 0x24;
     60     public static final int CEC_KEYCODE_NUMBERS_5 = 0x25;
     61     public static final int CEC_KEYCODE_NUMBERS_6 = 0x26;
     62     public static final int CEC_KEYCODE_NUMBERS_7 = 0x27;
     63     public static final int CEC_KEYCODE_NUMBERS_8 = 0x28;
     64     public static final int CEC_KEYCODE_NUMBERS_9 = 0x29;
     65     public static final int CEC_KEYCODE_DOT = 0x2A;
     66     public static final int CEC_KEYCODE_ENTER = 0x2B;
     67     public static final int CEC_KEYCODE_CLEAR = 0x2C;
     68     // RESERVED = 0x2D - 0x2E
     69     public static final int CEC_KEYCODE_NEXT_FAVORITE = 0x2F;
     70     public static final int CEC_KEYCODE_CHANNEL_UP = 0x30;
     71     public static final int CEC_KEYCODE_CHANNEL_DOWN = 0x31;
     72     public static final int CEC_KEYCODE_PREVIOUS_CHANNEL = 0x32;
     73     public static final int CEC_KEYCODE_SOUND_SELECT = 0x33;
     74     public static final int CEC_KEYCODE_INPUT_SELECT = 0x34;
     75     public static final int CEC_KEYCODE_DISPLAY_INFORMATION = 0x35;
     76     public static final int CEC_KEYCODE_HELP = 0x36;
     77     public static final int CEC_KEYCODE_PAGE_UP = 0x37;
     78     public static final int CEC_KEYCODE_PAGE_DOWN = 0x38;
     79     // RESERVED = 0x39 - 0x3F
     80     public static final int CEC_KEYCODE_POWER = 0x40;
     81     public static final int CEC_KEYCODE_VOLUME_UP = 0x41;
     82     public static final int CEC_KEYCODE_VOLUME_DOWN = 0x42;
     83     public static final int CEC_KEYCODE_MUTE = 0x43;
     84     public static final int CEC_KEYCODE_PLAY = 0x44;
     85     public static final int CEC_KEYCODE_STOP = 0x45;
     86     public static final int CEC_KEYCODE_PAUSE = 0x46;
     87     public static final int CEC_KEYCODE_RECORD = 0x47;
     88     public static final int CEC_KEYCODE_REWIND = 0x48;
     89     public static final int CEC_KEYCODE_FAST_FORWARD = 0x49;
     90     public static final int CEC_KEYCODE_EJECT = 0x4A;
     91     public static final int CEC_KEYCODE_FORWARD = 0x4B;
     92     public static final int CEC_KEYCODE_BACKWARD = 0x4C;
     93     public static final int CEC_KEYCODE_STOP_RECORD = 0x4D;
     94     public static final int CEC_KEYCODE_PAUSE_RECORD = 0x4E;
     95     public static final int CEC_KEYCODE_RESERVED = 0x4F;
     96     public static final int CEC_KEYCODE_ANGLE = 0x50;
     97     public static final int CEC_KEYCODE_SUB_PICTURE = 0x51;
     98     public static final int CEC_KEYCODE_VIDEO_ON_DEMAND = 0x52;
     99     public static final int CEC_KEYCODE_ELECTRONIC_PROGRAM_GUIDE = 0x53;
    100     public static final int CEC_KEYCODE_TIMER_PROGRAMMING = 0x54;
    101     public static final int CEC_KEYCODE_INITIAL_CONFIGURATION = 0x55;
    102     public static final int CEC_KEYCODE_SELECT_BROADCAST_TYPE = 0x56;
    103     public static final int CEC_KEYCODE_SELECT_SOUND_PRESENTATION = 0x57;
    104     // RESERVED = 0x58-0x5F
    105     public static final int CEC_KEYCODE_PLAY_FUNCTION = 0x60;
    106     public static final int CEC_KEYCODE_PAUSE_PLAY_FUNCTION = 0x61;
    107     public static final int CEC_KEYCODE_RECORD_FUNCTION = 0x62;
    108     public static final int CEC_KEYCODE_PAUSE_RECORD_FUNCTION = 0x63;
    109     public static final int CEC_KEYCODE_STOP_FUNCTION = 0x64;
    110     public static final int CEC_KEYCODE_MUTE_FUNCTION = 0x65;
    111     public static final int CEC_KEYCODE_RESTORE_VOLUME_FUNCTION = 0x66;
    112     public static final int CEC_KEYCODE_TUNE_FUNCTION = 0x67;
    113     public static final int CEC_KEYCODE_SELECT_MEDIA_FUNCTION = 0x68;
    114     public static final int CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION = 0x69;
    115     public static final int CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A;
    116     public static final int CEC_KEYCODE_POWER_TOGGLE_FUNCTION = 0x6B;
    117     public static final int CEC_KEYCODE_POWER_OFF_FUNCTION = 0x6C;
    118     public static final int CEC_KEYCODE_POWER_ON_FUNCTION = 0x6D;
    119     // RESERVED = 0x6E-0x70
    120     public static final int CEC_KEYCODE_F1_BLUE = 0x71;
    121     public static final int CEC_KEYCODE_F2_RED = 0x72;
    122     public static final int CEC_KEYCODE_F3_GREEN = 0x73;
    123     public static final int CEC_KEYCODE_F4_YELLOW = 0x74;
    124     public static final int CEC_KEYCODE_F5 = 0x75;
    125     public static final int CEC_KEYCODE_DATA = 0x76;
    126     // RESERVED = 0x77-0xFF
    127 
    128     // =========================================================================
    129     // UI Broadcast Type
    130     public static final int UI_BROADCAST_TOGGLE_ALL = 0x00;
    131     public static final int UI_BROADCAST_TOGGLE_ANALOGUE_DIGITAL = 0x01;
    132     public static final int UI_BROADCAST_ANALOGUE = 0x10;
    133     public static final int UI_BROADCAST_ANALOGUE_TERRESTRIAL = 0x20;
    134     public static final int UI_BROADCAST_ANALOGUE_CABLE = 0x30;
    135     public static final int UI_BROADCAST_ANALOGUE_SATELLITE = 0x40;
    136     public static final int UI_BROADCAST_DIGITAL = 0x50;
    137     public static final int UI_BROADCAST_DIGITAL_TERRESTRIAL = 0x60;
    138     public static final int UI_BROADCAST_DIGITAL_CABLE = 0x70;
    139     public static final int UI_BROADCAST_DIGITAL_SATELLITE = 0x80;
    140     public static final int UI_BROADCAST_DIGITAL_COMMNICATIONS_SATELLITE = 0x90;
    141     public static final int UI_BROADCAST_DIGITAL_COMMNICATIONS_SATELLITE_2 = 0x91;
    142     public static final int UI_BROADCAST_IP = 0xA0;
    143 
    144     // =========================================================================
    145     // UI Sound Presentation Control
    146     public static final int UI_SOUND_PRESENTATION_SOUND_MIX_DUAL_MONO = 0x20;
    147     public static final int UI_SOUND_PRESENTATION_SOUND_MIX_KARAOKE = 0x30;
    148     public static final int UI_SOUND_PRESENTATION_SELECT_AUDIO_DOWN_MIX = 0x80;
    149     public static final int UI_SOUND_PRESENTATION_SELECT_AUDIO_AUTO_REVERBERATION = 0x90;
    150     public static final int UI_SOUND_PRESENTATION_SELECT_AUDIO_AUTO_EQUALIZER = 0xA0;
    151     public static final int UI_SOUND_PRESENTATION_BASS_STEP_PLUS = 0xB1;
    152     public static final int UI_SOUND_PRESENTATION_BASS_NEUTRAL = 0xB2;
    153     public static final int UI_SOUND_PRESENTATION_BASS_STEP_MINUS = 0xB3;
    154     public static final int UI_SOUND_PRESENTATION_TREBLE_STEP_PLUS = 0xC1;
    155     public static final int UI_SOUND_PRESENTATION_TREBLE_NEUTRAL = 0xC2;
    156     public static final int UI_SOUND_PRESENTATION_TREBLE_STEP_MINUS = 0xC3;
    157 
    158     private HdmiCecKeycode() {
    159     }
    160 
    161     /**
    162      * A mapping between Android and CEC keycode.
    163      * <p>
    164      * Normal implementation of this looks like
    165      *
    166      * <pre>
    167      * new KeycodeEntry(KeyEvent.KEYCODE_DPAD_CENTER, CEC_KEYCODE_SELECT);
    168      * </pre>
    169      * <p>
    170      * However, some keys in CEC requires additional parameter. In order to use parameterized cec
    171      * key, add unique android keycode (existing or custom) corresponding to a pair of cec keycode
    172      * and and its param.
    173      *
    174      * <pre>
    175      * new KeycodeEntry(CUSTOME_ANDORID_KEY_1, CEC_KEYCODE_SELECT_BROADCAST_TYPE,
    176      *         UI_BROADCAST_TOGGLE_ALL);
    177      * new KeycodeEntry(CUSTOME_ANDORID_KEY_2, CEC_KEYCODE_SELECT_BROADCAST_TYPE,
    178      *         UI_BROADCAST_ANALOGUE);
    179      * </pre>
    180      */
    181     private static class KeycodeEntry {
    182         private final int mAndroidKeycode;
    183         private final boolean mIsRepeatable;
    184         private final byte[] mCecKeycodeAndParams;
    185 
    186         private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable,
    187                 byte[] cecParams) {
    188             mAndroidKeycode = androidKeycode;
    189             mIsRepeatable = isRepeatable;
    190             mCecKeycodeAndParams = new byte[cecParams.length + 1];
    191             System.arraycopy(cecParams, 0, mCecKeycodeAndParams, 1, cecParams.length);
    192             mCecKeycodeAndParams[0] = (byte) (cecKeycode & 0xFF);
    193         }
    194 
    195         private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) {
    196             this(androidKeycode, cecKeycode, isRepeatable, EmptyArray.BYTE);
    197         }
    198 
    199         private KeycodeEntry(int androidKeycode, int cecKeycode, byte[] cecParams) {
    200             this(androidKeycode, cecKeycode, true, cecParams);
    201         }
    202 
    203         private KeycodeEntry(int androidKeycode, int cecKeycode) {
    204             this(androidKeycode, cecKeycode, true, EmptyArray.BYTE);
    205         }
    206 
    207         private byte[] toCecKeycodeAndParamIfMatched(int androidKeycode) {
    208             if (mAndroidKeycode == androidKeycode) {
    209                 return mCecKeycodeAndParams;
    210             } else {
    211                 return null;
    212             }
    213         }
    214 
    215         private int toAndroidKeycodeIfMatched(byte[] cecKeycodeAndParams) {
    216             if (Arrays.equals(mCecKeycodeAndParams, cecKeycodeAndParams)) {
    217                 return mAndroidKeycode;
    218             } else {
    219                 return UNSUPPORTED_KEYCODE;
    220             }
    221         }
    222 
    223         private Boolean isRepeatableIfMatched(int androidKeycode) {
    224             if (mAndroidKeycode == androidKeycode) {
    225                 return mIsRepeatable;
    226             } else {
    227                 return null;
    228             }
    229         }
    230     }
    231 
    232     private static byte[] intToSingleByteArray(int value) {
    233         return new byte[] {
    234                 (byte) (value & 0xFF) };
    235     }
    236 
    237     // Keycode entry container for all mappings.
    238     // Note that order of entry is the same as above cec keycode definition.
    239     private static final KeycodeEntry[] KEYCODE_ENTRIES = new KeycodeEntry[] {
    240             new KeycodeEntry(KeyEvent.KEYCODE_DPAD_CENTER, CEC_KEYCODE_SELECT),
    241             new KeycodeEntry(KeyEvent.KEYCODE_DPAD_UP, CEC_KEYCODE_UP),
    242             new KeycodeEntry(KeyEvent.KEYCODE_DPAD_DOWN, CEC_KEYCODE_DOWN),
    243             new KeycodeEntry(KeyEvent.KEYCODE_DPAD_LEFT, CEC_KEYCODE_LEFT),
    244             new KeycodeEntry(KeyEvent.KEYCODE_DPAD_RIGHT, CEC_KEYCODE_RIGHT),
    245             // No Android keycode defined for CEC_KEYCODE_RIGHT_UP
    246             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RIGHT_UP),
    247             // No Android keycode defined for CEC_KEYCODE_RIGHT_DOWN
    248             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RIGHT_DOWN),
    249             // No Android keycode defined for CEC_KEYCODE_LEFT_UP
    250             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_UP),
    251             // No Android keycode defined for CEC_KEYCODE_LEFT_DOWN
    252             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_DOWN),
    253             new KeycodeEntry(KeyEvent.KEYCODE_HOME, CEC_KEYCODE_ROOT_MENU),
    254             new KeycodeEntry(KeyEvent.KEYCODE_SETTINGS, CEC_KEYCODE_SETUP_MENU),
    255             new KeycodeEntry(KeyEvent.KEYCODE_TV_CONTENTS_MENU, CEC_KEYCODE_CONTENTS_MENU, false),
    256             // No Android keycode defined for CEC_KEYCODE_FAVORITE_MENU
    257             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_FAVORITE_MENU),
    258             // Note that both BACK and ESCAPE are mapped to EXIT of CEC keycode.
    259             // This would be problematic when translates CEC keycode to Android keycode.
    260             // In current implementation, we pick BACK as mapping of EXIT key.
    261             // If you'd like to map CEC EXIT to Android EXIT key, change order of
    262             // the following two definition.
    263             new KeycodeEntry(KeyEvent.KEYCODE_BACK, CEC_KEYCODE_EXIT),
    264             new KeycodeEntry(KeyEvent.KEYCODE_ESCAPE, CEC_KEYCODE_EXIT),
    265             // RESERVED
    266             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_TOP_MENU, CEC_KEYCODE_MEDIA_TOP_MENU),
    267             new KeycodeEntry(KeyEvent.KEYCODE_TV_MEDIA_CONTEXT_MENU,
    268                     CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU),
    269             // RESERVED
    270             // No Android keycode defined for CEC_KEYCODE_NUMBER_ENTRY_MODE
    271             new KeycodeEntry(KeyEvent.KEYCODE_TV_NUMBER_ENTRY, CEC_KEYCODE_NUMBER_ENTRY_MODE),
    272             new KeycodeEntry(KeyEvent.KEYCODE_11, CEC_KEYCODE_NUMBER_11),
    273             new KeycodeEntry(KeyEvent.KEYCODE_12, CEC_KEYCODE_NUMBER_12),
    274             new KeycodeEntry(KeyEvent.KEYCODE_0, CEC_KEYCODE_NUMBER_0_OR_NUMBER_10),
    275             new KeycodeEntry(KeyEvent.KEYCODE_1, CEC_KEYCODE_NUMBERS_1),
    276             new KeycodeEntry(KeyEvent.KEYCODE_2, CEC_KEYCODE_NUMBERS_2),
    277             new KeycodeEntry(KeyEvent.KEYCODE_3, CEC_KEYCODE_NUMBERS_3),
    278             new KeycodeEntry(KeyEvent.KEYCODE_4, CEC_KEYCODE_NUMBERS_4),
    279             new KeycodeEntry(KeyEvent.KEYCODE_5, CEC_KEYCODE_NUMBERS_5),
    280             new KeycodeEntry(KeyEvent.KEYCODE_6, CEC_KEYCODE_NUMBERS_6),
    281             new KeycodeEntry(KeyEvent.KEYCODE_7, CEC_KEYCODE_NUMBERS_7),
    282             new KeycodeEntry(KeyEvent.KEYCODE_8, CEC_KEYCODE_NUMBERS_8),
    283             new KeycodeEntry(KeyEvent.KEYCODE_9, CEC_KEYCODE_NUMBERS_9),
    284             new KeycodeEntry(KeyEvent.KEYCODE_PERIOD, CEC_KEYCODE_DOT),
    285             new KeycodeEntry(KeyEvent.KEYCODE_NUMPAD_ENTER, CEC_KEYCODE_ENTER),
    286             new KeycodeEntry(KeyEvent.KEYCODE_CLEAR, CEC_KEYCODE_CLEAR),
    287             // RESERVED
    288             // No Android keycode defined for CEC_KEYCODE_NEXT_FAVORITE
    289             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_NEXT_FAVORITE),
    290             new KeycodeEntry(KeyEvent.KEYCODE_CHANNEL_UP, CEC_KEYCODE_CHANNEL_UP),
    291             new KeycodeEntry(KeyEvent.KEYCODE_CHANNEL_DOWN, CEC_KEYCODE_CHANNEL_DOWN),
    292             new KeycodeEntry(KeyEvent.KEYCODE_LAST_CHANNEL, CEC_KEYCODE_PREVIOUS_CHANNEL),
    293             // No Android keycode defined for CEC_KEYCODE_SOUND_SELECT
    294             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SOUND_SELECT),
    295             new KeycodeEntry(KeyEvent.KEYCODE_TV_INPUT, CEC_KEYCODE_INPUT_SELECT),
    296             new KeycodeEntry(KeyEvent.KEYCODE_INFO, CEC_KEYCODE_DISPLAY_INFORMATION),
    297             // No Android keycode defined for CEC_KEYCODE_HELP
    298             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_HELP),
    299             new KeycodeEntry(KeyEvent.KEYCODE_PAGE_UP, CEC_KEYCODE_PAGE_UP),
    300             new KeycodeEntry(KeyEvent.KEYCODE_PAGE_DOWN, CEC_KEYCODE_PAGE_DOWN),
    301             // RESERVED
    302             new KeycodeEntry(KeyEvent.KEYCODE_POWER, CEC_KEYCODE_POWER, false),
    303             new KeycodeEntry(KeyEvent.KEYCODE_VOLUME_UP, CEC_KEYCODE_VOLUME_UP),
    304             new KeycodeEntry(KeyEvent.KEYCODE_VOLUME_DOWN, CEC_KEYCODE_VOLUME_DOWN),
    305             new KeycodeEntry(KeyEvent.KEYCODE_VOLUME_MUTE, CEC_KEYCODE_MUTE, false),
    306             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PLAY, CEC_KEYCODE_PLAY),
    307             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_STOP, CEC_KEYCODE_STOP),
    308             // Note that we map both MEDIA_PAUSE and MEDIA_PLAY_PAUSE to CEC PAUSE key.
    309             // When it translates CEC PAUSE key, it picks Android MEDIA_PAUSE key as a mapping of
    310             // it. If you'd like to choose MEDIA_PLAY_PAUSE, please change order of the following
    311             // two lines.
    312             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PAUSE, CEC_KEYCODE_PAUSE),
    313             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, CEC_KEYCODE_PAUSE),
    314             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_RECORD, CEC_KEYCODE_RECORD),
    315             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_REWIND, CEC_KEYCODE_REWIND),
    316             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, CEC_KEYCODE_FAST_FORWARD),
    317             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_EJECT, CEC_KEYCODE_EJECT),
    318             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_NEXT, CEC_KEYCODE_FORWARD),
    319             new KeycodeEntry(KeyEvent.KEYCODE_MEDIA_PREVIOUS, CEC_KEYCODE_BACKWARD),
    320             // No Android keycode defined for CEC_KEYCODE_STOP_RECORD
    321             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_STOP_RECORD),
    322             // No Android keycode defined for CEC_KEYCODE_PAUSE_RECORD
    323             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_RECORD),
    324             // No Android keycode defined for CEC_KEYCODE_RESERVED
    325             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RESERVED),
    326             // No Android keycode defined for CEC_KEYCODE_ANGLE
    327             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_ANGLE),
    328             new KeycodeEntry(KeyEvent.KEYCODE_CAPTIONS, CEC_KEYCODE_SUB_PICTURE),
    329             // No Android keycode defined for CEC_KEYCODE_VIDEO_ON_DEMAND
    330             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_VIDEO_ON_DEMAND),
    331             new KeycodeEntry(KeyEvent.KEYCODE_GUIDE, CEC_KEYCODE_ELECTRONIC_PROGRAM_GUIDE),
    332             new KeycodeEntry(KeyEvent.KEYCODE_TV_TIMER_PROGRAMMING, CEC_KEYCODE_TIMER_PROGRAMMING),
    333             // No Android keycode defined for CEC_KEYCODE_INITIAL_CONFIGURATION
    334             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_INITIAL_CONFIGURATION),
    335             // No Android keycode defined for CEC_KEYCODE_SELECT_BROADCAST_TYPE
    336             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_BROADCAST_TYPE),
    337             new KeycodeEntry(KeyEvent.KEYCODE_TV_TERRESTRIAL_ANALOG,
    338                     CEC_KEYCODE_SELECT_BROADCAST_TYPE, true,
    339                     intToSingleByteArray(UI_BROADCAST_ANALOGUE)),
    340             new KeycodeEntry(KeyEvent.KEYCODE_TV_TERRESTRIAL_DIGITAL,
    341                     CEC_KEYCODE_SELECT_BROADCAST_TYPE, true,
    342                     intToSingleByteArray(UI_BROADCAST_DIGITAL_TERRESTRIAL)),
    343             new KeycodeEntry(KeyEvent.KEYCODE_TV_SATELLITE_BS,
    344                     CEC_KEYCODE_SELECT_BROADCAST_TYPE, true,
    345                     intToSingleByteArray(UI_BROADCAST_DIGITAL_SATELLITE)),
    346             new KeycodeEntry(KeyEvent.KEYCODE_TV_SATELLITE_CS,
    347                     CEC_KEYCODE_SELECT_BROADCAST_TYPE, true,
    348                     intToSingleByteArray(UI_BROADCAST_DIGITAL_COMMNICATIONS_SATELLITE)),
    349             new KeycodeEntry(KeyEvent.KEYCODE_TV_NETWORK,
    350                     CEC_KEYCODE_SELECT_BROADCAST_TYPE, true,
    351                     intToSingleByteArray(UI_BROADCAST_TOGGLE_ANALOGUE_DIGITAL)),
    352             // No Android keycode defined for CEC_KEYCODE_SELECT_SOUND_PRESENTATION
    353             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_SOUND_PRESENTATION),
    354             // RESERVED
    355             // The following deterministic key definitions do not need key mapping
    356             // since they are supposed to be generated programmatically only.
    357             // No Android keycode defined for CEC_KEYCODE_PLAY_FUNCTION
    358             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PLAY_FUNCTION, false),
    359             // No Android keycode defined for CEC_KEYCODE_PAUSE_PLAY_FUNCTION
    360             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_PLAY_FUNCTION, false),
    361             // No Android keycode defined for CEC_KEYCODE_RECORD_FUNCTION
    362             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RECORD_FUNCTION, false),
    363             // No Android keycode defined for CEC_KEYCODE_PAUSE_RECORD_FUNCTION
    364             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_PAUSE_RECORD_FUNCTION, false),
    365             // No Android keycode defined for CEC_KEYCODE_STOP_FUNCTION
    366             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_STOP_FUNCTION, false),
    367             // No Android keycode defined for CEC_KEYCODE_MUTE_FUNCTION
    368             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_MUTE_FUNCTION, false),
    369             // No Android keycode defined for CEC_KEYCODE_RESTORE_VOLUME_FUNCTION
    370             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_RESTORE_VOLUME_FUNCTION, false),
    371             // No Android keycode defined for CEC_KEYCODE_TUNE_FUNCTION
    372             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_TUNE_FUNCTION, false),
    373             // No Android keycode defined for CEC_KEYCODE_SELECT_MEDIA_FUNCTION
    374             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_MEDIA_FUNCTION, false),
    375             // No Android keycode defined for CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION
    376             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION, false),
    377             // No Android keycode defined for CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION
    378             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION, false),
    379             // No Android keycode defined for CEC_KEYCODE_POWER_TOGGLE_FUNCTION
    380             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_TOGGLE_FUNCTION, false),
    381             // No Android keycode defined for CEC_KEYCODE_POWER_OFF_FUNCTION
    382             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_OFF_FUNCTION, false),
    383             // No Android keycode defined for CEC_KEYCODE_POWER_ON_FUNCTION
    384             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_POWER_ON_FUNCTION, false),
    385             // RESERVED
    386             new KeycodeEntry(KeyEvent.KEYCODE_PROG_BLUE, CEC_KEYCODE_F1_BLUE),
    387             new KeycodeEntry(KeyEvent.KEYCODE_PROG_RED, CEC_KEYCODE_F2_RED),
    388             new KeycodeEntry(KeyEvent.KEYCODE_PROG_GREEN, CEC_KEYCODE_F3_GREEN),
    389             new KeycodeEntry(KeyEvent.KEYCODE_PROG_YELLOW, CEC_KEYCODE_F4_YELLOW),
    390             new KeycodeEntry(KeyEvent.KEYCODE_F5, CEC_KEYCODE_F5),
    391             new KeycodeEntry(KeyEvent.KEYCODE_TV_DATA_SERVICE, CEC_KEYCODE_DATA),
    392             // RESERVED
    393             // Add a new key mapping here if new keycode is introduced.
    394     };
    395 
    396     /**
    397      * Translate Android keycode to Hdmi Cec keycode and params.
    398      *
    399      * @param keycode Android keycode. For details, refer {@link KeyEvent}
    400      * @return byte array of CEC keycode and params if matched. Otherwise, return null.
    401      */
    402     static byte[] androidKeyToCecKey(int keycode) {
    403         for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
    404             byte[] cecKeycodeAndParams = KEYCODE_ENTRIES[i].toCecKeycodeAndParamIfMatched(keycode);
    405             if (cecKeycodeAndParams != null) {
    406                 return cecKeycodeAndParams;
    407             }
    408         }
    409         return null;
    410     }
    411 
    412     /**
    413      * Translate Hdmi CEC keycode with params to Android keycode.
    414      *
    415      * @param cecKeycodeAndParams CEC keycode and params
    416      * @return cec keycode corresponding to the given android keycode. If finds no matched keycode,
    417      *         return {@link #UNSUPPORTED_KEYCODE}
    418      */
    419     static int cecKeycodeAndParamsToAndroidKey(byte[] cecKeycodeAndParams) {
    420         for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
    421             int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(cecKeycodeAndParams);
    422             if (androidKey != UNSUPPORTED_KEYCODE) {
    423                 return androidKey;
    424             }
    425         }
    426         return UNSUPPORTED_KEYCODE;
    427     }
    428 
    429     /**
    430      * Whether the given {@code androidKeycode} is repeatable key or not.
    431      *
    432      * @param androidKeycode keycode of android
    433      * @return false if the given {@code androidKeycode} is not supported key code
    434      */
    435     static boolean isRepeatableKey(int androidKeycode) {
    436         for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
    437             Boolean isRepeatable = KEYCODE_ENTRIES[i].isRepeatableIfMatched(androidKeycode);
    438             if (isRepeatable != null) {
    439                 return isRepeatable;
    440             }
    441         }
    442         return false;
    443     }
    444 
    445     /**
    446      * Returns {@code true} if given Android keycode is supported, otherwise {@code false}.
    447      */
    448     static boolean isSupportedKeycode(int androidKeycode) {
    449         return HdmiCecKeycode.androidKeyToCecKey(androidKeycode) != null;
    450     }
    451 
    452     /**
    453      * Returns CEC keycode to control audio mute status.
    454      *
    455      * @param muting {@code true} if audio is being muted
    456      */
    457     public static int getMuteKey(boolean muting) {
    458         // CEC_KEYCODE_MUTE_FUNCTION, CEC_KEYCODE_RESTORE_VOLUME_FUNCTION are deterministic
    459         // commands that ensures the status changes to what we want, while CEC_KEYCODE_MUTE
    460         // simply toggles the status.
    461         // The former is a better choice in this regard, but there are compatibility issues
    462         // observed - many audio receivers don't recognize the commands. We fall back on
    463         // CEC_KEYCODE_MUTE for now.
    464         // return muting ? CEC_KEYCODE_MUTE_FUNCTION : CEC_KEYCODE_RESTORE_VOLUME_FUNCTION;
    465         return CEC_KEYCODE_MUTE;
    466     }
    467 }
    468