{"content":"Command: cd /Users/nickchen/WorkBuddy/2026-10-23-15-17-57/cleanyourtv && sed -n '2790,3010p' launcher/app/src/main/java/com/gathin/tvhome/MainActivity.java\nStdout:                 : new Intent(Intent.ACTION_VIEW, uri.buildUpon().scheme(inputUriScheme).build()))\r\n                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\r\n        try {\r\n            startActivity(view);\r\n            return;\r\n        } catch (ActivityNotFoundException | SecurityException e) {\r\n            if (inputAction.isEmpty()) {\r\n                Toast.makeText(this, R.string.not_available, Toast.LENGTH_SHORT).show();\r\n                return;\r\n            }\r\n        }\r\n        open(new Intent(inputAction).setDataAndType(uri, \"vnd.android.cursor.item/channel\"));\r\n    }\r\n\r\n    /** Dropdown menu under the Inputs pill: HDMI ports (with connection state), AV and Live TV. */\r\n    private void showInputs() {\r\n        // A configured source panel and no Live TV row to offer next to it: the panel is the whole menu.\r\n        // The BYINTEK U4 needs this, as its TvInputManager lists three HDMI ports and an AV input it doesn't have.\r\n        List<CoocaaSources.Source> coocaa = coocaaSources ? CoocaaSources.list(this) : Collections.emptyList();\r\n        if (coocaa.isEmpty() && !sourcePanelService.isEmpty() && liveTvIntent() == null) {\r\n            openSourcePanel();\r\n            return;\r\n        }\r\n        // top_menu: the pill is gone, so the list hangs under the gear, growing inward from the right.\r\n        // Read the switch, not the pill: show_inputs_pill=false hides the pill too, and there the list\r\n        // keeps its usual place.\r\n        boolean underGear = topMenu;\r\n        View anchor = findViewById(underGear ? R.id.btnSettings : R.id.btnInputs);\r\n        View panel = getLayoutInflater().inflate(R.layout.popup_inputs, root, false);\r\n        LinearLayout rows = panel.findViewById(R.id.rows);\r\n\r\n        // Compact: as wide as the Inputs pill (a touch wider so \"HDMI 1\" fits), hanging right below it.\r\n        int width = Math.max(anchor.getWidth(), (int) (150 * density));\r\n        final PopupWindow popup = glassPopup(panel, width);\r\n\r\n        TvInputManager tim = (TvInputManager) getSystemService(TV_INPUT_SERVICE);\r\n        // Rows are collected first and added in port order: on MiTV4-ANSM0 the firmware registers only the\r\n        // empty port (HDMI3) and not HDMI1, whose row is synthesized at the end of the loop, so adding rows\r\n        // as they come would put HDMI3 on top and the port with the set-top box last.\r\n        List<InputRow> pending = new ArrayList<>();\r\n        String tunerId = null;\r\n        boolean tunerIsHw = false;\r\n        boolean tunerIsAnalog = false;\r\n        if (tim != null) {\r\n            List<TvInputInfo> inputs = new ArrayList<>(tim.getTvInputList());\r\n            // HDMI ports first in port order, then AV and the rest.\r\n            Collections.sort(inputs, (a, b) -> {\r\n                boolean ha = a.getType() == TvInputInfo.TYPE_HDMI, hb = b.getType() == TvInputInfo.TYPE_HDMI;\r\n                if (ha != hb) return ha ? -1 : 1;\r\n                return String.valueOf(a.loadLabel(this)).compareToIgnoreCase(String.valueOf(b.loadLabel(this)));\r\n            });\r\n            // An HDMI-CEC device (an Apple TV, a soundbar) gets an input of its own whose parent is the\r\n            // port it sits on, so the port and the device would each get a row (Vestel MT7332: \"HDMI 1\"\r\n            // and \"HDMI Apple TV\"). The device takes its port's row instead, and a bare port is listed\r\n            // only when nothing on it speaks CEC.\r\n            Set<String> inputIds = new HashSet<>();\r\n            for (TvInputInfo info : inputs) inputIds.add(info.getId());\r\n            Map<String, List<TvInputInfo>> cecDevices = new HashMap<>();\r\n            for (TvInputInfo info : inputs) {\r\n                String parent = info.getParentId();\r\n                if (parent == null || !inputIds.contains(parent)) continue;\r\n                if (!info.isPassthroughInput() || inputHidden(info)) continue;\r\n                List<TvInputInfo> onPort = cecDevices.get(parent);\r\n                if (onPort == null) cecDevices.put(parent, onPort = new ArrayList<>());\r\n                onPort.add(info);\r\n            }\r\n            // Some TVs (Sony) report every HDMI port as connected whether or not anything is plugged in,\r\n            // so drop the HDMI status then. A TV with every port really in use loses it too.\r\n            int hdmiPorts = 0, hdmiConnected = 0;\r\n            for (TvInputInfo info : inputs) {\r\n                if (!info.isPassthroughInput() || info.getType() != TvInputInfo.TYPE_HDMI) continue;\r\n                if (info.getParentId() != null && inputIds.contains(info.getParentId())) continue;\r\n                hdmiPorts++;\r\n                if (tim.getInputState(info.getId()) == TvInputManager.INPUT_STATE_CONNECTED) hdmiConnected++;\r\n            }\r\n            boolean hdmiStateBogus = hdmiPorts > 1 && hdmiConnected == hdmiPorts;\r\n            // A mapped port the firmware never registers while another one claims to be connected means the\r\n            // state is invented: MiTV4-ANSM0 reports HDMI3 \"connected\" with nothing on it and never registers\r\n            // HDMI1, which has the set-top box. No row shows a status then, instead of a green dot on a dead port.\r\n            if (!inputAction.isEmpty() && hdmiConnected > 0) {\r\n                for (String m : getResources().getStringArray(R.array.input_sources)) {\r\n                    int eq = m.indexOf('=');\r\n                    if (eq <= 0 || m.substring(eq + 1).trim().startsWith(\"-\")) continue;\r\n                    String hw = m.substring(0, eq).trim();\r\n                    boolean registered = false;\r\n                    for (TvInputInfo info : inputs) {\r\n                        if (info.getId().endsWith(\"/\" + hw)) { registered = true; break; }\r\n                    }\r\n                    if (!registered) { hdmiStateBogus = true; break; }\r\n                }\r\n            }\r\n            for (TvInputInfo info : inputs) {\r\n                if (info.getType() == TvInputInfo.TYPE_TUNER\r\n                        && (info.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0\r\n                        && (liveTvInputId.isEmpty() || liveTvInputId.equals(info.getId()))) {\r\n                    // Prefer a hardware tuner: the framework names those \".../HW<n>\". System apps such as\r\n                    // AirPlay also register software inputs of type TUNER and may sort first (seen on TCL G05).\r\n                    // Among tuners of the same kind, skip an analog input when another is present.\r\n                    // MediaTek names them AnalogInputService and TunerInputService; alphabetical order\r\n                    // would pick the analog one, and Live TV then opens a dead ATV source.\r\n                    boolean hw = info.getId().matches(\".*/HW\\\\d+$\");\r\n                    boolean analog = info.getId().toLowerCase(Locale.ROOT).contains(\"analog\");\r\n                    boolean better = tunerId == null\r\n                            || (hw && !tunerIsHw)\r\n                            || (hw == tunerIsHw && tunerIsAnalog && !analog)\r\n                            || (hw == tunerIsHw && analog == tunerIsAnalog\r\n                                    && info.getId().compareTo(tunerId) < 0);\r\n                    if (better) {\r\n                        tunerId = info.getId();\r\n                        tunerIsHw = hw;\r\n                        tunerIsAnalog = analog;\r\n                    }\r\n                }\r\n                // Inputs hidden in the TV's Settings > Inputs stay out of the menu too.\r\n                if (!info.isPassthroughInput() || inputHidden(info)) continue;\r\n                // input_sources can leave out ports the board reports but the set does not have (\"HW8=-\").\r\n                if (Integer.valueOf(-1).equals(mappedSource(info.getId()))) continue;\r\n                // A CEC device's row is added with its port, below.\r\n                if (info.getParentId() != null && inputIds.contains(info.getParentId())) continue;\r\n                CharSequence l = info.loadLabel(this);\r\n                String label = l == null ? info.getId() : l.toString();\r\n                boolean hdmi = info.getType() == TvInputInfo.TYPE_HDMI;\r\n                if (hdmi) {\r\n                    if (!label.toUpperCase(Locale.ROOT).contains(\"HDMI\")) {\r\n                        label = \"HDMI \" + label;\r\n                    } else {\r\n                        // The firmware names the port \"HDMI3\" while the mapped rows read \"HDMI 3\": one style.\r\n                        java.util.regex.Matcher hm =\r\n                                java.util.regex.Pattern.compile(\"(?i)HDMI\\\\s*(\\\\d+)\").matcher(label);\r\n                        if (hm.matches()) label = \"HDMI \" + hm.group(1);\r\n                    }\r\n                }\r\n                CharSequence custom = inputCustomLabel(info);\r\n                boolean named = custom != null && custom.length() > 0 && !custom.toString().equals(label);\r\n                List<TvInputInfo> devices = cecDevices.get(info.getId());\r\n                if (devices != null) {\r\n                    // \"Apple TV · HDMI 1\": the device's own name (or the one given to it or to its port in\r\n                    // Settings > Inputs), then the port. Opening the device's input also makes it the CEC\r\n                    // active source, which wakes it.\r\n                    for (TvInputInfo device : devices) {\r\n                        CharSequence name = inputCustomLabel(device);\r\n                        if (name == null || name.length() == 0) name = named ? custom : device.loadLabel(this);\r\n                        String deviceLabel = name == null || name.length() == 0 ? label : name + \" \\u00B7 \" + label;\r\n                        final String deviceId = device.getId();\r\n                        int state = hdmiStateBogus ? -1 : tim.getInputState(deviceId);\r\n                        pending.add(new InputRow(R.drawable.ic_input, deviceLabel, state,\r\n                                () -> openInput(deviceId), hdmiOrder(label)));\r\n                    }\r\n                    continue;\r\n                }\r\n                // The name given in Settings > Inputs (e.g. \"MacBook Pro\") goes first, the port after it.\r\n                if (named) label = custom + \" \\u00B7 \" + label;\r\n                final String id = info.getId();\r\n                // Analog AV jacks have no hotplug detection, and some TVs report them as always connected\r\n                // (TCL Smart TV Pro G03 says \"Connected\" with nothing plugged in), so AV rows show no state.\r\n                int state = !hdmi || hdmiStateBogus ? -1 : tim.getInputState(id);\r\n                pending.add(new InputRow(hdmi ? R.drawable.ic_input : R.drawable.ic_av, label, state,\r\n                        () -> openInput(id), hdmi ? hdmiOrder(label) : InputRow.AV));\r\n            }\r\n            // Local fork for MiTV4-ANSM0: this firmware never registers the HDMI port that actually has a\r\n            // device on it (HDMI1/HW5 with the IPTV box), while ports with nothing plugged in do get\r\n            // registered. List every input_sources entry whose framework input is missing, so the port is\r\n            // still one click away. Needs input_action, which is how a mapped input opens anyway.\r\n            if (!inputAction.isEmpty()) {\r\n                for (String m : getResources().getStringArray(R.array.input_sources)) {\r\n                    int eq = m.indexOf('=');\r\n                    if (eq <= 0) continue;\r\n                    String hw = m.substring(0, eq).trim();\r\n                    if (!hw.matches(\"HW\\\\d+\")) continue;\r\n                    boolean registered = false;\r\n                    for (TvInputInfo info : inputs) {\r\n                        if (info.getId().endsWith(\"/\" + hw)) { registered = true; break; }\r\n                    }\r\n                    if (registered) continue;\r\n                    String rest = m.substring(eq + 1).trim();\r\n                    int colon = rest.indexOf(':');\r\n                    String name = colon >= 0 ? rest.substring(colon + 1).trim() : \"\";\r\n                    int source;\r\n                    try { source = Integer.parseInt(colon >= 0 ? rest.substring(0, colon).trim() : rest); }\r\n                    catch (NumberFormatException e) { continue; }\r\n                    if (source < 0) continue;\r\n                    final String syntheticId = \"unregistered/\" + hw;\r\n                    boolean av = name.toUpperCase(Locale.ROOT).contains(\"AV\");\r\n                    pending.add(new InputRow(av ? R.drawable.ic_av : R.drawable.ic_input,\r\n                            name.isEmpty() ? hw : name, -1, () -> openInput(syntheticId),\r\n                            av ? InputRow.AV : hdmiOrder(name)));\r\n                }\r\n            }\r\n        }\r\n        // Port order: HDMI 1, 2, 3 …, then AV and the rest, with a separator before them.\r\n        Collections.sort(pending, (a, b) -> a.order != b.order\r\n                ? Integer.compare(a.order, b.order) : a.title.compareToIgnoreCase(b.title));\r\n        boolean separated = false;\r\n        for (InputRow row : pending) {\r\n            if (!separated && row.order >= InputRow.AV) {\r\n                if (rows.getChildCount() > 0) addSeparator(rows);\r\n                separated = true;\r\n            }\r\n            addInputRow(rows, popup, row.icon, row.title, row.state, row.action);\r\n        }\r\n        // Coocaa OS registers nothing with TvInputManager; com.skyworth.tv lists its sources instead.\r\n        if (rows.getChildCount() == 0) {\r\n            for (CoocaaSources.Source s : coocaa) {\r\n                int icon = \"HDMI\".equals(s.name) ? R.drawable.ic_input\r\n                        : \"VOD\".equals(s.name) ? R.drawable.ic_livetv : R.drawable.ic_av;\r\n                addInputRow(rows, popup, icon, s.label, -1, () -> {\r\n                    if (!CoocaaSources.open(this, s)) {\r\n                        Toast.makeText(this, R.string.not_available, Toast.LENGTH_SHORT).show();\r\n                    }\r\n                });\r\n            }\r\n        }\r\n        // Nothing to list where there is no TvInputManager: the TV's own source panel switches inputs.\r\n        if (rows.getChildCount() == 0 && !sourcePanelService.isEmpty()) {\r\n            addInputRow(rows, popup, R.drawable.ic_input, getString(R.string.inputs), -1, this::openSourcePanel);\r\n        }\r\n        Intent liveTv = liveTvIntent();\r\n        if (liveTv != null && tunerId != null) {\r\n            // Tune that input only when the Live TV package itself handles the URI.\r\n            // The unrestricted input player also resolves it (that is how HDMI opens), but on the\r\n            // AIWA AI PONT SA that player stays black, and the Live TV package does not handle the\r\n\nStderr: (empty)\nExit Code: 0\nSignal: (none)","renderer":{"type":"text","value":"                : new Intent(Intent.ACTION_VIEW, uri.buildUpon().scheme(inputUriScheme).build()))\r\n                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\r\n        try {\r\n            startActivity(view);\r\n            return;\r\n        } catch (ActivityNotFoundException | SecurityException e) {\r\n            if (inputAction.isEmpty()) {\r\n                Toast.makeText(this, R.string.not_available, Toast.LENGTH_SHORT).show();\r\n                return;\r\n            }\r\n        }\r\n        open(new Intent(inputAction).setDataAndType(uri, \"vnd.android.cursor.item/channel\"));\r\n    }\r\n\r\n    /** Dropdown menu under the Inputs pill: HDMI ports (with connection state), AV and Live TV. */\r\n    private void showInputs() {\r\n        // A configured source panel and no Live TV row to offer next to it: the panel is the whole menu.\r\n        // The BYINTEK U4 needs this, as its TvInputManager lists three HDMI ports and an AV input it doesn't have.\r\n        List<CoocaaSources.Source> coocaa = coocaaSources ? CoocaaSources.list(this) : Collections.emptyList();\r\n        if (coocaa.isEmpty() && !sourcePanelService.isEmpty() && liveTvIntent() == null) {\r\n            openSourcePanel();\r\n            return;\r\n        }\r\n        // top_menu: the pill is gone, so the list hangs under the gear, growing inward from the right.\r\n        // Read the switch, not the pill: show_inputs_pill=false hides the pill too, and there the list\r\n        // keeps its usual place.\r\n        boolean underGear = topMenu;\r\n        View anchor = findViewById(underGear ? R.id.btnSettings : R.id.btnInputs);\r\n        View panel = getLayoutInflater().inflate(R.layout.popup_inputs, root, false);\r\n        LinearLayout rows = panel.findViewById(R.id.rows);\r\n\r\n        // Compact: as wide as the Inputs pill (a touch wider so \"HDMI 1\" fits), hanging right below it.\r\n        int width = Math.max(anchor.getWidth(), (int) (150 * density));\r\n        final PopupWindow popup = glassPopup(panel, width);\r\n\r\n        TvInputManager tim = (TvInputManager) getSystemService(TV_INPUT_SERVICE);\r\n        // Rows are collected first and added in port order: on MiTV4-ANSM0 the firmware registers only the\r\n        // empty port (HDMI3) and not HDMI1, whose row is synthesized at the end of the loop, so adding rows\r\n        // as they come would put HDMI3 on top and the port with the set-top box last.\r\n        List<InputRow> pending = new ArrayList<>();\r\n        String tunerId = null;\r\n        boolean tunerIsHw = false;\r\n        boolean tunerIsAnalog = false;\r\n        if (tim != null) {\r\n            List<TvInputInfo> inputs = new ArrayList<>(tim.getTvInputList());\r\n            // HDMI ports first in port order, then AV and the rest.\r\n            Collections.sort(inputs, (a, b) -> {\r\n                boolean ha = a.getType() == TvInputInfo.TYPE_HDMI, hb = b.getType() == TvInputInfo.TYPE_HDMI;\r\n                if (ha != hb) return ha ? -1 : 1;\r\n                return String.valueOf(a.loadLabel(this)).compareToIgnoreCase(String.valueOf(b.loadLabel(this)));\r\n            });\r\n            // An HDMI-CEC device (an Apple TV, a soundbar) gets an input of its own whose parent is the\r\n            // port it sits on, so the port and the device would each get a row (Vestel MT7332: \"HDMI 1\"\r\n            // and \"HDMI Apple TV\"). The device takes its port's row instead, and a bare port is listed\r\n            // only when nothing on it speaks CEC.\r\n            Set<String> inputIds = new HashSet<>();\r\n            for (TvInputInfo info : inputs) inputIds.add(info.getId());\r\n            Map<String, List<TvInputInfo>> cecDevices = new HashMap<>();\r\n            for (TvInputInfo info : inputs) {\r\n                String parent = info.getParentId();\r\n                if (parent == null || !inputIds.contains(parent)) continue;\r\n                if (!info.isPassthroughInput() || inputHidden(info)) continue;\r\n                List<TvInputInfo> onPort = cecDevices.get(parent);\r\n                if (onPort == null) cecDevices.put(parent, onPort = new ArrayList<>());\r\n                onPort.add(info);\r\n            }\r\n            // Some TVs (Sony) report every HDMI port as connected whether or not anything is plugged in,\r\n            // so drop the HDMI status then. A TV with every port really in use loses it too.\r\n            int hdmiPorts = 0, hdmiConnected = 0;\r\n            for (TvInputInfo info : inputs) {\r\n                if (!info.isPassthroughInput() || info.getType() != TvInputInfo.TYPE_HDMI) continue;\r\n                if (info.getParentId() != null && inputIds.contains(info.getParentId())) continue;\r\n                hdmiPorts++;\r\n                if (tim.getInputState(info.getId()) == TvInputManager.INPUT_STATE_CONNECTED) hdmiConnected++;\r\n            }\r\n            boolean hdmiStateBogus = hdmiPorts > 1 && hdmiConnected == hdmiPorts;\r\n            // A mapped port the firmware never registers while another one claims to be connected means the\r\n            // state is invented: MiTV4-ANSM0 reports HDMI3 \"connected\" with nothing on it and never registers\r\n            // HDMI1, which has the set-top box. No row shows a status then, instead of a green dot on a dead port.\r\n            if (!inputAction.isEmpty() && hdmiConnected > 0) {\r\n                for (String m : getResources().getStringArray(R.array.input_sources)) {\r\n                    int eq = m.indexOf('=');\r\n                    if (eq <= 0 || m.substring(eq + 1).trim().startsWith(\"-\")) continue;\r\n                    String hw = m.substring(0, eq).trim();\r\n                    boolean registered = false;\r\n                    for (TvInputInfo info : inputs) {\r\n                        if (info.getId().endsWith(\"/\" + hw)) { registered = true; break; }\r\n                    }\r\n                    if (!registered) { hdmiStateBogus = true; break; }\r\n                }\r\n            }\r\n            for (TvInputInfo info : inputs) {\r\n                if (info.getType() == TvInputInfo.TYPE_TUNER\r\n                        && (info.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0\r\n                        && (liveTvInputId.isEmpty() || liveTvInputId.equals(info.getId()))) {\r\n                    // Prefer a hardware tuner: the framework names those \".../HW<n>\". System apps such as\r\n                    // AirPlay also register software inputs of type TUNER and may sort first (seen on TCL G05).\r\n                    // Among tuners of the same kind, skip an analog input when another is present.\r\n                    // MediaTek names them AnalogInputService and TunerInputService; alphabetical order\r\n                    // would pick the analog one, and Live TV then opens a dead ATV source.\r\n                    boolean hw = info.getId().matches(\".*/HW\\\\d+$\");\r\n                    boolean analog = info.getId().toLowerCase(Locale.ROOT).contains(\"analog\");\r\n                    boolean better = tunerId == null\r\n                            || (hw && !tunerIsHw)\r\n                            || (hw == tunerIsHw && tunerIsAnalog && !analog)\r\n                            || (hw == tunerIsHw && analog == tunerIsAnalog\r\n                                    && info.getId().compareTo(tunerId) < 0);\r\n                    if (better) {\r\n                        tunerId = info.getId();\r\n                        tunerIsHw = hw;\r\n                        tunerIsAnalog = analog;\r\n                    }\r\n                }\r\n                // Inputs hidden in the TV's Settings > Inputs stay out of the menu too.\r\n                if (!info.isPassthroughInput() || inputHidden(info)) continue;\r\n                // input_sources can leave out ports the board reports but the set does not have (\"HW8=-\").\r\n                if (Integer.valueOf(-1).equals(mappedSource(info.getId()))) continue;\r\n                // A CEC device's row is added with its port, below.\r\n                if (info.getParentId() != null && inputIds.contains(info.getParentId())) continue;\r\n                CharSequence l = info.loadLabel(this);\r\n                String label = l == null ? info.getId() : l.toString();\r\n                boolean hdmi = info.getType() == TvInputInfo.TYPE_HDMI;\r\n                if (hdmi) {\r\n                    if (!label.toUpperCase(Locale.ROOT).contains(\"HDMI\")) {\r\n                        label = \"HDMI \" + label;\r\n                    } else {\r\n                        // The firmware names the port \"HDMI3\" while the mapped rows read \"HDMI 3\": one style.\r\n                        java.util.regex.Matcher hm =\r\n                                java.util.regex.Pattern.compile(\"(?i)HDMI\\\\s*(\\\\d+)\").matcher(label);\r\n                        if (hm.matches()) label = \"HDMI \" + hm.group(1);\r\n                    }\r\n                }\r\n                CharSequence custom = inputCustomLabel(info);\r\n                boolean named = custom != null && custom.length() > 0 && !custom.toString().equals(label);\r\n                List<TvInputInfo> devices = cecDevices.get(info.getId());\r\n                if (devices != null) {\r\n                    // \"Apple TV · HDMI 1\": the device's own name (or the one given to it or to its port in\r\n                    // Settings > Inputs), then the port. Opening the device's input also makes it the CEC\r\n                    // active source, which wakes it.\r\n                    for (TvInputInfo device : devices) {\r\n                        CharSequence name = inputCustomLabel(device);\r\n                        if (name == null || name.length() == 0) name = named ? custom : device.loadLabel(this);\r\n                        String deviceLabel = name == null || name.length() == 0 ? label : name + \" \\u00B7 \" + label;\r\n                        final String deviceId = device.getId();\r\n                        int state = hdmiStateBogus ? -1 : tim.getInputState(deviceId);\r\n                        pending.add(new InputRow(R.drawable.ic_input, deviceLabel, state,\r\n                                () -> openInput(deviceId), hdmiOrder(label)));\r\n                    }\r\n                    continue;\r\n                }\r\n                // The name given in Settings > Inputs (e.g. \"MacBook Pro\") goes first, the port after it.\r\n                if (named) label = custom + \" \\u00B7 \" + label;\r\n                final String id = info.getId();\r\n                // Analog AV jacks have no hotplug detection, and some TVs report them as always connected\r\n                // (TCL Smart TV Pro G03 says \"Connected\" with nothing plugged in), so AV rows show no state.\r\n                int state = !hdmi || hdmiStateBogus ? -1 : tim.getInputState(id);\r\n                pending.add(new InputRow(hdmi ? R.drawable.ic_input : R.drawable.ic_av, label, state,\r\n                        () -> openInput(id), hdmi ? hdmiOrder(label) : InputRow.AV));\r\n            }\r\n            // Local fork for MiTV4-ANSM0: this firmware never registers the HDMI port that actually has a\r\n            // device on it (HDMI1/HW5 with the IPTV box), while ports with nothing plugged in do get\r\n            // registered. List every input_sources entry whose framework input is missing, so the port is\r\n            // still one click away. Needs input_action, which is how a mapped input opens anyway.\r\n            if (!inputAction.isEmpty()) {\r\n                for (String m : getResources().getStringArray(R.array.input_sources)) {\r\n                    int eq = m.indexOf('=');\r\n                    if (eq <= 0) continue;\r\n                    String hw = m.substring(0, eq).trim();\r\n                    if (!hw.matches(\"HW\\\\d+\")) continue;\r\n                    boolean registered = false;\r\n                    for (TvInputInfo info : inputs) {\r\n                        if (info.getId().endsWith(\"/\" + hw)) { registered = true; break; }\r\n                    }\r\n                    if (registered) continue;\r\n                    String rest = m.substring(eq + 1).trim();\r\n                    int colon = rest.indexOf(':');\r\n                    String name = colon >= 0 ? rest.substring(colon + 1).trim() : \"\";\r\n                    int source;\r\n                    try { source = Integer.parseInt(colon >= 0 ? rest.substring(0, colon).trim() : rest); }\r\n                    catch (NumberFormatException e) { continue; }\r\n                    if (source < 0) continue;\r\n                    final String syntheticId = \"unregistered/\" + hw;\r\n                    boolean av = name.toUpperCase(Locale.ROOT).contains(\"AV\");\r\n                    pending.add(new InputRow(av ? R.drawable.ic_av : R.drawable.ic_input,\r\n                            name.isEmpty() ? hw : name, -1, () -> openInput(syntheticId),\r\n                            av ? InputRow.AV : hdmiOrder(name)));\r\n                }\r\n            }\r\n        }\r\n        // Port order: HDMI 1, 2, 3 …, then AV and the rest, with a separator before them.\r\n        Collections.sort(pending, (a, b) -> a.order != b.order\r\n                ? Integer.compare(a.order, b.order) : a.title.compareToIgnoreCase(b.title));\r\n        boolean separated = false;\r\n        for (InputRow row : pending) {\r\n            if (!separated && row.order >= InputRow.AV) {\r\n                if (rows.getChildCount() > 0) addSeparator(rows);\r\n                separated = true;\r\n            }\r\n            addInputRow(rows, popup, row.icon, row.title, row.state, row.action);\r\n        }\r\n        // Coocaa OS registers nothing with TvInputManager; com.skyworth.tv lists its sources instead.\r\n        if (rows.getChildCount() == 0) {\r\n            for (CoocaaSources.Source s : coocaa) {\r\n                int icon = \"HDMI\".equals(s.name) ? R.drawable.ic_input\r\n                        : \"VOD\".equals(s.name) ? R.drawable.ic_livetv : R.drawable.ic_av;\r\n                addInputRow(rows, popup, icon, s.label, -1, () -> {\r\n                    if (!CoocaaSources.open(this, s)) {\r\n                        Toast.makeText(this, R.string.not_available, Toast.LENGTH_SHORT).show();\r\n                    }\r\n                });\r\n            }\r\n        }\r\n        // Nothing to list where there is no TvInputManager: the TV's own source panel switches inputs.\r\n        if (rows.getChildCount() == 0 && !sourcePanelService.isEmpty()) {\r\n            addInputRow(rows, popup, R.drawable.ic_input, getString(R.string.inputs), -1, this::openSourcePanel);\r\n        }\r\n        Intent liveTv = liveTvIntent();\r\n        if (liveTv != null && tunerId != null) {\r\n            // Tune that input only when the Live TV package itself handles the URI.\r\n            // The unrestricted input player also resolves it (that is how HDMI opens), but on the\r\n            // AIWA AI PONT SA that player stays black, and the Live TV package does not handle the"}}