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.util.SparseArray;
     20 
     21 /**
     22  * This class handles the incoming messages when HdmiCecService is in the standby mode.
     23  */
     24 public final class HdmiCecStandbyModeHandler {
     25 
     26     private interface CecMessageHandler {
     27         boolean handle(HdmiCecMessage message);
     28     }
     29 
     30     private static final class Bystander implements CecMessageHandler {
     31         @Override
     32         public boolean handle(HdmiCecMessage message) {
     33             return true;
     34         }
     35     }
     36 
     37     private static final class Bypasser implements CecMessageHandler {
     38         @Override
     39         public boolean handle(HdmiCecMessage message) {
     40             return false;
     41         }
     42     }
     43 
     44     private final class Aborter implements CecMessageHandler {
     45         private final int mReason;
     46         public Aborter(int reason) {
     47             mReason = reason;
     48         }
     49         @Override
     50         public boolean handle(HdmiCecMessage message) {
     51             mService.maySendFeatureAbortCommand(message, mReason);
     52             return true;
     53         }
     54     }
     55 
     56     private final class AutoOnHandler implements CecMessageHandler {
     57         @Override
     58         public boolean handle(HdmiCecMessage message) {
     59             if (!mTv.getAutoWakeup()) {
     60                 mAborterRefused.handle(message);
     61                 return true;
     62             }
     63             return false;
     64         }
     65     }
     66 
     67     private final class UserControlProcessedHandler implements CecMessageHandler {
     68         @Override
     69         public boolean handle(HdmiCecMessage message) {
     70             // The power status here is always standby.
     71             if (HdmiCecLocalDevice.isPowerOnOrToggleCommand(message)) {
     72                 return false;
     73             } else if (HdmiCecLocalDevice.isPowerOffOrToggleCommand(message)) {
     74                 return true;
     75             }
     76             return mAborterIncorrectMode.handle(message);
     77         }
     78     }
     79 
     80     private final HdmiControlService mService;
     81     private final HdmiCecLocalDeviceTv mTv;
     82 
     83     private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
     84     private final CecMessageHandler mDefaultHandler = new Aborter(
     85             Constants.ABORT_UNRECOGNIZED_OPCODE);
     86     private final CecMessageHandler mAborterIncorrectMode = new Aborter(
     87             Constants.ABORT_NOT_IN_CORRECT_MODE);
     88     private final CecMessageHandler mAborterRefused = new Aborter(Constants.ABORT_REFUSED);
     89     private final CecMessageHandler mAutoOnHandler = new AutoOnHandler();
     90     private final CecMessageHandler mBypasser = new Bypasser();
     91     private final CecMessageHandler mBystander = new Bystander();
     92     private final UserControlProcessedHandler
     93             mUserControlProcessedHandler = new UserControlProcessedHandler();
     94 
     95     public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) {
     96         mService = service;
     97         mTv = tv;
     98 
     99         addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
    100         addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
    101 
    102         addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
    103         addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
    104         addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
    105         addHandler(Constants.MESSAGE_ROUTING_INFORMATION, mBystander);
    106         addHandler(Constants.MESSAGE_SET_STREAM_PATH, mBystander);
    107         addHandler(Constants.MESSAGE_STANDBY, mBystander);
    108         addHandler(Constants.MESSAGE_SET_MENU_LANGUAGE, mBystander);
    109         addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBystander);
    110         addHandler(Constants.MESSAGE_USER_CONTROL_RELEASED, mBystander);
    111         addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBystander);
    112         addHandler(Constants.MESSAGE_FEATURE_ABORT, mBystander);
    113         addHandler(Constants.MESSAGE_INACTIVE_SOURCE, mBystander);
    114         addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
    115         addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
    116 
    117         // If TV supports the following messages during power-on, ignore them and do nothing,
    118         // else reply with <Feature Abort>["Unrecognized Opcode"]
    119         // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
    120         addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander);
    121 
    122         // If TV supports the following messages during power-on, reply with <Feature Abort>["Not
    123         // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"]
    124         // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>,
    125         // <Tuner Stem Increment>, <Menu Status>.
    126         addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
    127         addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
    128         addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
    129 
    130         addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
    131         addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
    132         addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
    133         addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
    134         addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
    135         addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
    136 
    137         addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
    138 
    139         addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
    140         addHandler(Constants.MESSAGE_ABORT, mBypasser);
    141         addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
    142 
    143         addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
    144         addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
    145     }
    146 
    147     private void addHandler(int opcode, CecMessageHandler handler) {
    148         mCecMessageHandlers.put(opcode, handler);
    149     }
    150 
    151     /**
    152      * Handles the CEC message in the standby mode.
    153      *
    154      * @param message {@link HdmiCecMessage} to be processed
    155      * @return true if the message is handled in the handler, false means that the message is need
    156      *         to be dispatched to the local device.
    157      */
    158     boolean handleCommand(HdmiCecMessage message) {
    159         CecMessageHandler handler = mCecMessageHandlers.get(message.getOpcode());
    160         if (handler != null) {
    161             return handler.handle(message);
    162         }
    163         return mDefaultHandler.handle(message);
    164     }
    165 }
    166