HdmiUtils.java revision 92b77cf9cbf512e7141cad6fef5a38d0682dde43
163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo/* 263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Copyright (C) 2014 The Android Open Source Project 363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Licensed under the Apache License, Version 2.0 (the "License"); 563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * you may not use this file except in compliance with the License. 663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * You may obtain a copy of the License at 763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * http://www.apache.org/licenses/LICENSE-2.0 963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 1063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Unless required by applicable law or agreed to in writing, software 1163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * distributed under the License is distributed on an "AS IS" BASIS, 1263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * See the License for the specific language governing permissions and 1463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * limitations under the License. 1563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo */ 1663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 1763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heopackage com.android.server.hdmi; 1863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 1963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heoimport android.hardware.hdmi.HdmiCec; 2063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heoimport android.hardware.hdmi.HdmiCecMessage; 2163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heoimport android.util.Slog; 2279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport android.util.SparseArray; 2363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 240340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport java.util.ArrayList; 250340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport java.util.Collections; 260340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport java.util.List; 270340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 2863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo/** 2963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Various utilities to handle HDMI CEC messages. 3063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo */ 3163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heofinal class HdmiUtils { 3263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 3363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo private HdmiUtils() { /* cannot be instantiated */ } 3463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 3563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo /** 3663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Verify if the given address is for the given device type. If not it will throw 3763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * {@link IllegalArgumentException}. 3863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 3963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param logicalAddress the logical address to verify 4063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param deviceType the device type to check 4163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @throw IllegalArgumentException 4263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo */ 4363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo static void verifyAddressType(int logicalAddress, int deviceType) { 4463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress); 4563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo if (actualDeviceType != deviceType) { 4663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType 4763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo + ", Actual:" + actualDeviceType); 4863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo } 4963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo } 5063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 5163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo /** 5263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Check if the given CEC message come from the given address. 5363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 5463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param cmd the CEC message to check 5563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param expectedAddress the expected source address of the given message 5663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param tag the tag of caller module (for log message) 5763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @return true if the CEC message comes from the given address 5863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo */ 5963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo static boolean checkCommandSource(HdmiCecMessage cmd, int expectedAddress, String tag) { 6063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo int src = cmd.getSource(); 6163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo if (src != expectedAddress) { 6263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo Slog.w(tag, "Invalid source [Expected:" + expectedAddress + ", Actual:" + src + "]"); 6363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo return false; 6463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo } 6563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo return true; 6663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo } 6763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo 6863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo /** 6963a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * Parse the parameter block of CEC message as [System Audio Status]. 7063a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * 7163a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @param cmd the CEC message to parse 7263a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo * @return true if the given parameter has [ON] value 7363a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo */ 7463a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo static boolean parseCommandParamSystemAudioStatus(HdmiCecMessage cmd) { 7563a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo // TODO: Handle the exception when the length is wrong. 7663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo return cmd.getParams().length > 0 7763a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo && cmd.getParams()[0] == HdmiConstants.SYSTEM_AUDIO_STATUS_ON; 7863a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo } 79092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 80092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang /** 810340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * Convert integer array to list of {@link Integer}. 820340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 830340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <p>The result is immutable. 840340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 850340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * @param is integer array 860340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * @return {@link List} instance containing the elements in the given array 870340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim */ 880340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim static List<Integer> asImmutableList(final int[] is) { 890340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim ArrayList<Integer> list = new ArrayList<>(is.length); 900340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim for (int type : is) { 910340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim list.add(type); 920340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 930340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return Collections.unmodifiableList(list); 940340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 950340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 960340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim /** 97092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * Assemble two bytes into single integer value. 98092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * 99092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @param data to be assembled 100092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @return assembled value 101092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang */ 102092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang static int twoBytesToInt(byte[] data) { 103092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF); 104092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 105092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 106092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang /** 10792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * Assemble two bytes into single integer value. 10892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * 10992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param data to be assembled 11092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param offset offset to the data to convert in the array 11192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @return assembled value 11292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim */ 11392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim static int twoBytesToInt(byte[] data, int offset) { 11492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF); 11592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 11692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 11792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim /** 118092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * Assemble three bytes into single integer value. 119092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * 120092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @param data to be assembled 121092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @return assembled value 122092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang */ 123092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang static int threeBytesToInt(byte[] data) { 124092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF); 125092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 12679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 12779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang static <T> List<T> sparseArrayToList(SparseArray<T> array) { 12879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang ArrayList<T> list = new ArrayList<>(); 12979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (int i = 0; i < array.size(); ++i) { 13079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang list.add(array.valueAt(i)); 13179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 13279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return list; 13379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 13479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 13592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim /** 13692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * See if the new path is affecting the active path. 13792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * 13892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param activePath current active path 13992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param newPath new path 14092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @return true if the new path changes the current active path 14192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim */ 14292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim static boolean isAffectingActiveRoutingPath(int activePath, int newPath) { 14392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // The new path affects the current active path if the parent of the new path 14492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // is an ancestor of the active path. 14592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.1.0.0, 2.0.0.0) -> true, new path alters the parent 14692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.1.0.0, 1.2.0.0) -> true, new path is a sibling 14792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.1.0.0, 1.2.1.0) -> false, new path is a descendant of a sibling 14892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.0.0.0, 3.2.0.0) -> false, in a completely different path 14992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 15092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // Get the parent of the new path by clearing the least significant 15192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // non-zero nibble. 15292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim for (int i = 0; i <= 12; i += 4) { 15392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim int nibble = (newPath >> i) & 0xF; 15492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim if (nibble != 0) { 15592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim int mask = 0xFFF0 << i; 15692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim newPath &= mask; 15792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim break; 15892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 15992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 16092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim if (newPath == 0x0000) { 16192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return true; // Top path always affects the active path 16292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 16392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return isInActiveRoutingPath(activePath, newPath); 16492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 16592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 16692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim /** 16792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * See if the new path is in the active path. 16892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * 16992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param activePath current active path 17092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @param newPath new path 17192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim * @return true if the new path in the active routing path 17292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim */ 17392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim static boolean isInActiveRoutingPath(int activePath, int newPath) { 17492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // Check each nibble of the currently active path and the new path till the position 17592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // where the active nibble is not zero. For (activePath, newPath), 17692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.1.0.0, 1.0.0.0) -> true, new path is a parent 17792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.2.1.0, 1.2.1.2) -> true, new path is a descendant 17892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.1.0.0, 1.2.0.0) -> false, new path is a sibling 17992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim // (1.0.0.0, 2.0.0.0) -> false, in a completely different path 18092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim for (int i = 12; i >= 0; i -= 4) { 18192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim int nibbleActive = (activePath >> i) & 0xF; 18292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim if (nibbleActive == 0) { 18392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim break; 18492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 18592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim int nibbleNew = (newPath >> i) & 0xF; 18692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim if (nibbleNew == 0) { 18792b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim break; 18892b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 18992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim if (nibbleActive != nibbleNew) { 19092b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return false; 19192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 19292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 19392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return true; 19492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 19592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 19663a2e0696ce2a04fbe0f1f00cfe9c93189f944daYuncheol Heo} 197