HdmiCecController.java revision 7d9a843af83dbc75b1d170c743603198ede5a10f
10792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang/* 20792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Copyright (C) 2014 The Android Open Source Project 30792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 40792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Licensed under the Apache License, Version 2.0 (the "License"); 50792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * you may not use this file except in compliance with the License. 60792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * You may obtain a copy of the License at 70792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 80792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * http://www.apache.org/licenses/LICENSE-2.0 90792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 100792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Unless required by applicable law or agreed to in writing, software 110792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * distributed under the License is distributed on an "AS IS" BASIS, 120792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * See the License for the specific language governing permissions and 140792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * limitations under the License. 150792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang */ 160792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 170792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangpackage com.android.server.hdmi; 180792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 19e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangimport android.hardware.hdmi.HdmiCec; 207d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jangimport android.hardware.hdmi.HdmiCecDeviceInfo; 21e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangimport android.hardware.hdmi.HdmiCecMessage; 220792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangimport android.os.Handler; 230792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangimport android.os.Looper; 240792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangimport android.os.Message; 25e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangimport android.util.Slog; 267d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jangimport android.util.SparseArray; 27e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 287d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jangimport java.util.ArrayList; 29e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangimport java.util.Arrays; 307d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jangimport java.util.List; 310792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 320792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang/** 330792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command 340792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * and pass it to CEC HAL so that it sends message to other device. For incoming 350792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * message it translates the message and delegates it to proper module. 360792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 370792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * <p>It can be created only by {@link HdmiCecController#create} 380792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 390792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * <p>Declared as package-private, accessed by {@link HdmiControlService} only. 400792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang */ 410792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangclass HdmiCecController { 420792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang private static final String TAG = "HdmiCecController"; 430792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 44e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // A message to pass cec send command to IO looper. 45e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int MSG_SEND_CEC_COMMAND = 1; 46e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 47e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // Message types to handle incoming message in main service looper. 48e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private final static int MSG_RECEIVE_CEC_COMMAND = 1; 49e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 50e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: move these values to HdmiCec.java once make it internal constant class. 51e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // CEC's ABORT reason values. 52e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_UNRECOGNIZED_MODE = 0; 53e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_NOT_IN_CORRECT_MODE = 1; 54e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_CANNOT_PROVIDE_SOURCE = 2; 55e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_INVALID_OPERAND = 3; 56e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_REFUSED = 4; 57e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static final int ABORT_UNABLE_TO_DETERMINE = 5; 58e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 590792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // Handler instance to process synchronous I/O (mainly send) message. 600792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang private Handler mIoHandler; 610792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 620792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // Handler instance to process various messages coming from other CEC 630792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // device or issued by internal state change. 64e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private Handler mControlHandler; 650792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 660792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // Stores the pointer to the native implementation of the service that 670792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // interacts with HAL. 680792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang private long mNativePtr; 690792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 707d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang // Map-like container of all cec devices. A logical address of device is 717d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang // used as key of container. 727d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos = 737d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang new SparseArray<HdmiCecDeviceInfo>(); 747d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang 750792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang // Private constructor. Use HdmiCecController.create(). 760792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang private HdmiCecController() { 770792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 780792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 790792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang /** 800792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * A factory method to get {@link HdmiCecController}. If it fails to initialize 810792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * inner device or has no device it will return {@code null}. 820792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 830792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * <p>Declared as package-private, accessed by {@link HdmiControlService} only. 84e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang * @param service {@link HdmiControlService} instance used to create internal handler 85e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang * and to pass callback for incoming message or event. 860792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * @return {@link HdmiCecController} if device is initialized successfully. Otherwise, 870792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * returns {@code null}. 880792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang */ 89e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang static HdmiCecController create(HdmiControlService service) { 900792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang HdmiCecController handler = new HdmiCecController(); 910792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang long nativePtr = nativeInit(handler); 920792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang if (nativePtr == 0L) { 930792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang handler = null; 940792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang return null; 950792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 960792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 97e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang handler.init(service, nativePtr); 980792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang return handler; 990792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 1000792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 101e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static byte[] buildBody(int opcode, byte[] params) { 102e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang byte[] body = new byte[params.length + 1]; 103e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang body[0] = (byte) opcode; 104e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang System.arraycopy(params, 0, body, 1, params.length); 105e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang return body; 106e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 107e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 108e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private final class IoHandler extends Handler { 109e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private IoHandler(Looper looper) { 110e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang super(looper); 111e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 112e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 113e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang @Override 114e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang public void handleMessage(Message msg) { 115e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang switch (msg.what) { 116e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang case MSG_SEND_CEC_COMMAND: 117e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCecMessage cecMessage = (HdmiCecMessage) msg.obj; 118e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams()); 119e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang nativeSendCecCommand(mNativePtr, cecMessage.getSource(), 120e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang cecMessage.getDestination(), body); 121e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang break; 122e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang default: 123e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang Slog.w(TAG, "Unsupported CEC Io request:" + msg.what); 124e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang break; 125e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 126e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 127e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 128e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 129e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private final class ControlHandler extends Handler { 130e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private ControlHandler(Looper looper) { 131e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang super(looper); 132e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 133e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 134e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang @Override 135e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang public void handleMessage(Message msg) { 136e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang switch (msg.what) { 137e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang case MSG_RECEIVE_CEC_COMMAND: 138e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: delegate it to HdmiControl service. 139e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang onReceiveCommand((HdmiCecMessage) msg.obj); 140e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang break; 141e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang default: 142e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang Slog.i(TAG, "Unsupported message type:" + msg.what); 143e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang break; 1440792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 145e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 146e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 1470792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 1487d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang /** 1497d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * Add a new {@link HdmiCecDeviceInfo}. It returns old device info which has the same 1507d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * logical address as new device info's. 1517d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 1527d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * <p>Declared as package-private. accessed by {@link HdmiControlService} only. 1537d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 1547d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @param deviceInfo a new {@link HdmiCecDeviceInfo} to be added. 1557d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @return {@code null} if it is new device. Otherwise, returns old {@HdmiCecDeviceInfo} 1567d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * that has the same logical address as new one has. 1577d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang */ 1587d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang HdmiCecDeviceInfo addDeviceInfo(HdmiCecDeviceInfo deviceInfo) { 1597d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang HdmiCecDeviceInfo oldDeviceInfo = getDeviceInfo(deviceInfo.getLogicalAddress()); 1607d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang if (oldDeviceInfo != null) { 1617d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang removeDeviceInfo(deviceInfo.getLogicalAddress()); 1627d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1637d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang mDeviceInfos.append(deviceInfo.getLogicalAddress(), deviceInfo); 1647d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang return oldDeviceInfo; 1657d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1667d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang 1677d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang /** 1687d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * Remove a device info corresponding to the given {@code logicalAddress}. 1697d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * It returns removed {@link HdmiCecDeviceInfo} if exists. 1707d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 1717d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * <p>Declared as package-private. accessed by {@link HdmiControlService} only. 1727d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 1737d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @param logicalAddress logical address of device to be removed 1747d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @return removed {@link HdmiCecDeviceInfo} it exists. Otherwise, returns {@code null} 1757d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang */ 1767d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang HdmiCecDeviceInfo removeDeviceInfo(int logicalAddress) { 1777d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang HdmiCecDeviceInfo deviceInfo = mDeviceInfos.get(logicalAddress); 1787d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang if (deviceInfo != null) { 1797d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang mDeviceInfos.remove(logicalAddress); 1807d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1817d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang return deviceInfo; 1827d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1837d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang 1847d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang /** 1857d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * Return a list of all {@HdmiCecDeviceInfo}. 1867d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 1877d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * <p>Declared as package-private. accessed by {@link HdmiControlService} only. 1887d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang */ 1897d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang List<HdmiCecDeviceInfo> getDeviceInfoList() { 1907d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang List<HdmiCecDeviceInfo> deviceInfoList = new ArrayList<HdmiCecDeviceInfo>( 1917d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang mDeviceInfos.size()); 1927d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang for (int i = 0; i < mDeviceInfos.size(); ++i) { 1937d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang deviceInfoList.add(mDeviceInfos.valueAt(i)); 1947d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1957d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang return deviceInfoList; 1967d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 1977d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang 1987d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang /** 1997d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * Return a {@link HdmiCecDeviceInfo} corresponding to the given {@code logicalAddress}. 2007d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 2017d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * <p>Declared as package-private. accessed by {@link HdmiControlService} only. 2027d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * 2037d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @param logicalAddress logical address to be retrieved 2047d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * @return {@link HdmiCecDeviceInfo} matched with the given {@code logicalAddress}. 2057d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang * Returns null if no logical address matched 2067d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang */ 2077d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) { 2087d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang return mDeviceInfos.get(logicalAddress); 2097d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang } 2107d9a843af83dbc75b1d170c743603198ede5a10fJungshik Jang 211e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private void init(HdmiControlService service, long nativePtr) { 212e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang mIoHandler = new IoHandler(service.getServiceLooper()); 213e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang mControlHandler = new ControlHandler(service.getServiceLooper()); 2140792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang mNativePtr = nativePtr; 2150792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 2160792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 217e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private void onReceiveCommand(HdmiCecMessage message) { 218e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: Handle message according to opcode type. 219e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 220e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: Use device's source address for broadcast message. 221e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang int sourceAddress = message.getDestination() != HdmiCec.ADDR_BROADCAST ? 222e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang message.getDestination() : 0; 223e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // Reply <Feature Abort> to initiator (source) for all requests. 224e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang sendFeatureAbort(sourceAddress, message.getSource(), message.getOpcode(), 225e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang ABORT_REFUSED); 226e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 227e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 228e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private void sendFeatureAbort(int srcAddress, int destAddress, int originalOpcode, 229e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang int reason) { 230e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang byte[] params = new byte[2]; 231e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang params[0] = (byte) originalOpcode; 232e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang params[1] = (byte) reason; 233e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 234e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCecMessage cecMessage = new HdmiCecMessage(srcAddress, destAddress, 235e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCec.MESSAGE_FEATURE_ABORT, params); 236e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang Message message = mIoHandler.obtainMessage(MSG_SEND_CEC_COMMAND, cecMessage); 237e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang mIoHandler.sendMessage(message); 238e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 239e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 240e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang /** 241e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang * Called by native when incoming CEC message arrived. 242e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang */ 243e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) { 244e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang byte opcode = body[0]; 245e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang byte params[] = Arrays.copyOfRange(body, 1, body.length); 246e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCecMessage cecMessage = new HdmiCecMessage(srcAddress, dstAddress, opcode, params); 247e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 248e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // Delegate message to main handler so that it handles in main thread. 249e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang Message message = mControlHandler.obtainMessage( 250e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang MSG_RECEIVE_CEC_COMMAND, cecMessage); 251e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang mControlHandler.sendMessage(message); 252e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 253e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 2540792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang /** 255e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang * Called by native when a hotplug event issues. 2560792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang */ 257e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private void handleHotplug(boolean connected) { 258e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: Delegate event to main message handler. 2590792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 2600792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 2610792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang private static native long nativeInit(HdmiCecController handler); 262e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang private static native int nativeSendCecCommand(long contollerPtr, int srcAddress, 263e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang int dstAddress, byte[] body); 2640792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} 265