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

Commit 7b5b624b authored by Steve Kondik's avatar Steve Kondik Committed by Gerrit Code Review
Browse files

Merge "HDMI: changes to notify audio on hdmi connect." into ics

parents 5c422333 afc85425
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