Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afc85425 authored by Arun Kumar K.R's avatar Arun Kumar K.R Committed by Steve Kondik
Browse files

HDMI: changes to notify audio on hdmi connect.

- When DVI monitor is connected, audio service should not be notified
- remove the redundant changes to check HDCP during boot up
- On connect, check for HDCP/DVI mode and handle audio accordingly

Change-Id: I2af352570eddd4820a9d5ee232f4e2f351c0c524
CRs-fixed: 324931

Update HDMI Notification mechanism and minor cleanup

-- Update HDMI notification mechanism to be based on switch
node, /devices/virtual/switch/hdmi
-- Remove unused SurfaceComposerClient object.
-- Use path /sys/devices/virtual/graphics instead of symlink
/sys/class/graphics
-- Remove support for intents HDMI_CABLE_CONNECTED,
HDMI_CABLE_DISCONNECTED, HDMI_CONNECTED, HDMI_DISCONNECTED.
-- Add support in AudioPolicyManager to handle non HDMI modes.

CRs-fixed: 325697
(cherry picked from commit dd1ef209a42794415b1a06ff947028b26f028fa9)

Change-Id: I07dc58c700b8a2f4c7e086c688e277ce66b3e4c3

HDMIService: Minor fixes in the HDMI Service

- When the cable is connected, set the best mode for HDMI,
  no need to store the current best mode, as this can cause
  issues when a different TV is connected.
- start the HDMIDaemon from the Service, this will help ensure
  HDMI Mirroring works after framework reboot

CRs-fixed: 333941 333497
(cherry picked from commit eb4ade6e6908c49a2e624a71ff1265e14c0b4ec7)

Conflicts:

	services/java/com/android/server/HDMIService.java

Change-Id: Ic87d1703065a284878e7e9c8adac3afb6def56ec

HDMIService: getModeOrder to return order based on resolution

- getModeOrder function used to return order based on the resolution,
  modified that to be based on the best resolution
  This fixes the problem where the HDMI TV used to support 1080p@30Hz
  but still it was picking 1080p@24Hz
- mCurrentMode stores the current display mode on HDMI, reset it when
  the cable is disconnected

(cherry picked from commit 91cb5160ca2b4aaee7cc8c01f6d7162e9c55d67a)

Change-Id: I3efbe385603560330600eab3adeb0da1f1e102aa
parent 28fa43d1
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ LOCAL_SHARED_LIBRARIES := \
    libutils \
    libbinder \
    libgui \
    libmedia \

LOCAL_C_INCLUDES := \
	$(call include-path-for, corecg graphics)
+87 −32
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
#include <signal.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <media/IAudioPolicyService.h>
#include <media/AudioSystem.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
@@ -46,7 +49,7 @@ namespace android {

// ---------------------------------------------------------------------------

#define DEVICE_ROOT "/sys/class/graphics"
#define DEVICE_ROOT "/sys/devices/virtual/graphics"
#define DEVICE_NODE "fb1"

#define HDMI_SOCKET_NAME        "hdmid"
@@ -55,7 +58,6 @@ namespace android {
#define HDMI_EVT_DISCONNECTED   "hdmi_disconnected"
#define HDMI_EVT_AUDIO_ON       "hdmi_audio_on"
#define HDMI_EVT_AUDIO_OFF      "hdmi_audio_off"
#define HDMI_EVT_NO_BROADCAST_ONLINE "hdmi_no_broadcast_online"

#define HDMI_CMD_ENABLE_HDMI    "enable_hdmi"
#define HDMI_CMD_DISABLE_HDMI   "disable_hdmi"
@@ -68,6 +70,7 @@ namespace android {
#define SYSFS_EDID_MODES        DEVICE_ROOT "/" DEVICE_NODE "/edid_modes"
#define SYSFS_HPD               DEVICE_ROOT "/" DEVICE_NODE "/hpd"
#define SYSFS_HDCP_PRESENT      DEVICE_ROOT "/" DEVICE_NODE "/hdcp_present"
#define SYSFS_HDMI_MODE         DEVICE_ROOT "/" DEVICE_NODE "/hdmi_mode"

#ifdef QCOM_HARDWARE
//Should match to the external_display_type HDMI in QComUI
@@ -96,11 +99,6 @@ void HDMIDaemon::onFirstRef() {
    run("HDMIDaemon", PRIORITY_AUDIO);
}

sp<SurfaceComposerClient> HDMIDaemon::session() const {
    return mSession;
}


void HDMIDaemon::binderDied(const wp<IBinder>& who)
{
    requestExit();
@@ -133,7 +131,7 @@ status_t HDMIDaemon::readyToRun() {
    }

    int uevent_sz = 64 * 1024;
    if (setsockopt(mUeventSock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
    if (setsockopt(mUeventSock, SOL_SOCKET, SO_RCVBUF, &uevent_sz,
                   sizeof(uevent_sz)) < 0) {
        LOGE("Unable to set uevent socket options: %s", strerror(errno));
        return -1;
@@ -204,13 +202,6 @@ bool HDMIDaemon::threadLoop()
                strerror(errno));
        }
        else {
            // Check if HDCP Keys are present
            if(checkHDCPPresent()) {
                LOGD("threadLoop: HDCP keys are present, delay Broadcast.");
                sendCommandToFramework(action_no_broadcast_online);
            }

            mSession = new SurfaceComposerClient();
            processUeventQueue();

            if (!mDriverOnline) {
@@ -232,7 +223,7 @@ bool HDMIDaemon::threadLoop()
    return true;
}

bool HDMIDaemon::checkHDCPPresent() {
bool HDMIDaemon::isHDCPPresent() {
    char present = '0';
    //Open the hdcp file - to know if HDCP is supported
    int hdcpFile = open(SYSFS_HDCP_PRESENT, O_RDONLY, 0);
@@ -248,6 +239,63 @@ bool HDMIDaemon::checkHDCPPresent() {
    close(hdcpFile);
    return (present == '1') ? true : false;
}

bool HDMIDaemon::isHDMIMode() {
    bool ret = false;
    char mode = '0';
    int modeFile = open (SYSFS_HDMI_MODE, O_RDONLY, 0);
    if(modeFile < 0) {
        LOGE("%s:hdmi_mode_file '%s' not found", __func__, SYSFS_HDMI_MODE);
    } else {
        //Read from the hdmi_mode file
        int r = read(modeFile, &mode, 1);
        if (r <= 0) {
            LOGE("%s: hdmi_mode file empty '%s'", __func__, SYSFS_HDMI_MODE);
        }
    }
    close(modeFile);
    return (mode == '1') ? true : false;
}

void HDMIDaemon::enableAudio() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IAudioPolicyService> binder;
    binder = interface_cast<IAudioPolicyService>(
            sm->getService(String16("media.audio_policy")));
    if(binder != 0) {
        binder->setDeviceConnectionState(AUDIO_DEVICE_OUT_AUX_DIGITAL,
            AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "");
    } else {
        LOGE("%s: Failed to contact audio service", __FUNCTION__);
    }
}

void HDMIDaemon::disableAudio() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IAudioPolicyService> binder;
    binder = interface_cast<IAudioPolicyService>(
            sm->getService(String16("media.audio_policy")));
    if(binder != 0) {
        binder->setDeviceConnectionState(AUDIO_DEVICE_OUT_AUX_DIGITAL,
            AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
    } else {
        LOGE("%s: Failed to contact audio service", __FUNCTION__);
    }
}

bool isAudioEnabled() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IAudioPolicyService> binder;
    binder = interface_cast<IAudioPolicyService>(
            sm->getService(String16("media.audio_policy")));
    if(binder != 0) {
        if(binder->getDeviceConnectionState(AUDIO_DEVICE_OUT_AUX_DIGITAL, "")
                == AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
            return true;
    }
    return false;
}

bool HDMIDaemon::cableConnected(bool defaultValue) const
{
    int hdmiStateFile = open(SYSFS_CONNECTED, O_RDONLY, 0);
@@ -587,8 +635,17 @@ int HDMIDaemon::processFrameworkCommand()
        LOGD(HDMI_CMD_ENABLE_HDMI);
        if(mNxtMode != -1) {
            LOGD("processFrameworkCommand: setResolution with =%d", mNxtMode);
            if(isAudioEnabled()) {
                //If Audio is enabled, turn it off because setResolution() will
                //call power off. Also treat the following as a single
                //transaction
                disableAudio();
                setResolution(mNxtMode);
                enableAudio();
            } else {
                setResolution(mNxtMode);
            }
        }
    } else if (!strcmp(buffer, HDMI_CMD_DISABLE_HDMI)) {
        LOGD(HDMI_CMD_DISABLE_HDMI);

@@ -661,7 +718,16 @@ int HDMIDaemon::processFrameworkCommand()
            }
            // If we have a valid fd1 - setresolution
            if(fd1 > 0) {
                if(isAudioEnabled()) {
                    // Disable audio before changing resolution, since that calls
                    // a poweroff, which could time out audio output.
                    disableAudio();
                    setResolution(mode);
                    // Enable audio once we are done with resolution change.
                    enableAudio();
                } else {
                    setResolution(mode);
                }
            } else {
            // Store the mode
                mNxtMode = mode;
@@ -678,30 +744,19 @@ bool HDMIDaemon::sendCommandToFramework(uevent_action action)

    switch (action)
    {
    //Disconnect
    case action_offline:
        strncpy(message, HDMI_EVT_DISCONNECTED, sizeof(message));
        break;
    //Connect
    case action_online:
        readResolution();
        snprintf(message, sizeof(message), "%s: %s", HDMI_EVT_CONNECTED, mEDIDs);
        break;
    //action_audio_on
    case action_audio_on:
        strncpy(message, HDMI_EVT_AUDIO_ON, sizeof(message));
        break;
    //action_audio_off
    case action_audio_off:
        strncpy(message, HDMI_EVT_AUDIO_OFF, sizeof(message));
        break;
    //action_no_broadcast_online
    case action_no_broadcast_online:
        strncpy(message, HDMI_EVT_NO_BROADCAST_ONLINE, sizeof(message));
        break;
        return true;
    default:
        LOGE("sendCommandToFramework: Unknown event received");
        break;
        return false;
    }
    int result = write(mAcceptedConnection, message, strlen(message) + 1);
    LOGD("sendCommandToFramework: '%s' %s", message, result >= 0 ? "successful" : "failed");
+12 −9
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 The Android Open Source Project
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@
namespace android {

enum uevent_action { action_add, action_remove, action_change,
                                  action_online, action_offline, action_audio_on, action_audio_off, action_no_broadcast_online };
                                  action_online, action_offline, action_audio_on, action_audio_off };
const int ueventParamMax = 32;
struct uevent {
    char *path;
@@ -83,10 +83,12 @@ struct HDMIUeventQueue {

class HDMIDaemon : public Thread, public IBinder::DeathRecipient
{
    /*Overrides*/
    virtual bool        threadLoop();
    virtual status_t    readyToRun();
    virtual void        onFirstRef();
    virtual void        binderDied(const wp<IBinder>& who);

    bool processUeventMessage(uevent& event);
    void queueUevent();
    void processUeventQueue();
@@ -98,14 +100,17 @@ class HDMIDaemon : public Thread, public IBinder::DeathRecipient
    void setResolution(int ID);
    bool openFramebuffer();
    bool writeHPDOption(int userOption) const;
    inline bool isValidMode(int ID);
    bool checkHDCPPresent();
    bool isValidMode(int ID);

    static bool isHDCPPresent();
    static bool isHDMIMode();
    static void enableAudio();
    static void disableAudio();

    int mFrameworkSock;
    int mAcceptedConnection;
    int mUeventSock;
    HDMIUeventQueue* mHDMIUeventQueueHead;
    sp<SurfaceComposerClient> mSession;
    int fd1;
    bool mDriverOnline;
    int mCurrentID;
@@ -115,8 +120,6 @@ class HDMIDaemon : public Thread, public IBinder::DeathRecipient
public:
    HDMIDaemon();
    virtual ~HDMIDaemon();

    sp<SurfaceComposerClient> session() const;
};

// ---------------------------------------------------------------------------
+30 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <stdint.h>

#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <cutils/properties.h>
@@ -57,6 +59,27 @@ static bool checkPermission() {
    return ok;
}

/* Returns true if HDMI mode, false if DVI or on errors */
#ifdef QCOM_HARDWARE
static bool isHDMIMode() {
    char mode = '0';
    const char* SYSFS_HDMI_MODE =
        "/sys/devices/virtual/graphics/fb1/hdmi_mode";
    int modeFile = open (SYSFS_HDMI_MODE, O_RDONLY, 0);
    if(modeFile < 0) {
        LOGE("%s: Node %s not found", __func__, SYSFS_HDMI_MODE);
    } else {
        //Read from the hdmi_mode file
        int r = read(modeFile, &mode, 1);
        if (r <= 0) {
            LOGE("%s: hdmi_mode file empty '%s'", __func__, SYSFS_HDMI_MODE);
        }
    }
    close(modeFile);
    return (mode == '1') ? true : false;
}
#endif

namespace {
    extern struct audio_policy_service_ops aps_ops;
};
@@ -168,7 +191,12 @@ status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
            state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
        return BAD_VALUE;
    }

#ifdef QCOM_HARDWARE
    /* On HDMI connection, return if we are not in HDMI mode */
    if(device == AUDIO_DEVICE_OUT_AUX_DIGITAL && !isHDMIMode()) {
        return NO_ERROR;
    }
#endif
    LOGV("setDeviceConnectionState() tid %d", gettid());
    Mutex::Autolock _l(mLock);
    return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
@@ -182,6 +210,7 @@ audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
    if (mpAudioPolicy == NULL) {
        return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
    }
    Mutex::Autolock _l(mLock);
    return mpAudioPolicy->get_device_connection_state(mpAudioPolicy, device,
                                                      device_address);
}
+1 −11
Original line number Diff line number Diff line
/*
 * Copyright 2007, The Android Open Source Project
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -54,7 +54,6 @@ final class HDMIListener implements Runnable {
    private static final String HDMI_EVT_CONNECTED = "hdmi_connected";
    private static final String HDMI_EVT_DISCONNECTED = "hdmi_disconnected";
    private static final String HDMI_EVT_START = "hdmi_listner_started";
    private static final String HDMI_EVT_NO_BROADCAST_ONLINE = "hdmi_no_broadcast_online";
    private static final String HDMI_EVT_AUDIO_ON = "hdmi_audio_on";
    private static final String HDMI_EVT_AUDIO_OFF = "hdmi_audio_off";

@@ -62,8 +61,6 @@ final class HDMIListener implements Runnable {
    private DataOutputStream mOutputStream;
    private boolean mHDMIConnected = false;
    private boolean mHDMIEnabled = false;
    // Broadcast on HDMI connected
    private boolean mOnlineBroadCast = true;
    private int[] mEDIDs = new int[0];

    HDMIListener(HDMIService service) {
@@ -94,9 +91,6 @@ final class HDMIListener implements Runnable {
        } else if (event.startsWith(HDMI_EVT_AUDIO_OFF)) {
            // Notify HDMIAudio off
            mService.notifyHDMIAudioOff();
        } else if (event.startsWith(HDMI_EVT_NO_BROADCAST_ONLINE)) {
            // do not broadcast on connect event
            mOnlineBroadCast = false;
        }
    }

@@ -202,10 +196,6 @@ final class HDMIListener implements Runnable {
    boolean isHDMIConnected() {
        return mHDMIConnected;
    }
    // returns true if we need to broadcast for Audio on cable connect
    boolean getOnlineBroadcast() {
        return mOnlineBroadCast;
    }

    public void enableHDMIOutput(boolean hdmiEnable) {
        if (mHDMIEnabled == hdmiEnable) {
Loading