hwc_uevents.cpp revision 56f610dd235b577725198e9341caae92379fdf23
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are
6 * retained for attribution purposes only.
7
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#define DEBUG 0
21#ifndef HWC_OBSERVER_H
22#define HWC_OBSERVER_H
23#include <hardware_legacy/uevent.h>
24#include <utils/Log.h>
25#include <sys/resource.h>
26#include <string.h>
27#include <stdlib.h>
28#include "hwc_utils.h"
29#include "external.h"
30
31namespace qhwc {
32
33const char* MSMFB_DEVICE_FB0 = "change@/devices/virtual/graphics/fb0";
34const char* MSMFB_DEVICE_FB1 = "change@/devices/virtual/graphics/fb1";
35const char* MSMFB_HDMI_NODE = "fb1";
36
37static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
38{
39    int vsync = 0;
40    char* hdmi;
41    int64_t timestamp = 0;
42    const char *str = udata;
43    int hdmiconnected = ctx->mExtDisplay->getExternalDisplay();
44
45    if(!strcasestr(str, "@/devices/virtual/graphics/fb")) {
46        ALOGD_IF(DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
47        return;
48    }
49
50    if(hdmiconnected)
51        vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1));
52    else
53        vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
54
55    hdmi = strcasestr(str, MSMFB_HDMI_NODE);
56    if(vsync) {
57        str += strlen(str) + 1;
58        while(*str) {
59            if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
60                timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
61                //XXX: Handle vsync from multiple displays
62                ctx->proc->vsync(ctx->proc, (int)ctx->dpys[0], timestamp);
63            }
64            str += strlen(str) + 1;
65            if(str - udata >= len)
66                break;
67        }
68        return;
69    }
70
71    if(hdmi) {
72        // parse HDMI events
73        // The event will be of the form:
74        // change@/devices/virtual/graphics/fb1 ACTION=change
75        // DEVPATH=/devices/virtual/graphics/fb1
76        // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
77        // for now just parsing onlin/offline info is enough
78        str = udata;
79        int connected = 0;
80        if(!(strncmp(str,"online@",strlen("online@")))) {
81            connected = 1;
82            ctx->mExtDisplay->setExternalDisplay(connected);
83        } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
84            connected = 0;
85            ctx->mExtDisplay->setExternalDisplay(connected);
86        }
87    }
88
89}
90
91static void *uevent_loop(void *param)
92{
93    int len = 0;
94    static char udata[4096];
95    memset(udata, 0, sizeof(udata));
96    hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
97
98    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
99    uevent_init();
100
101    while(1) {
102        len = uevent_next_event(udata, sizeof(udata) - 2);
103        handle_uevent(ctx, udata, len);
104    }
105
106    return NULL;
107}
108
109void init_uevent_thread(hwc_context_t* ctx)
110{
111    pthread_t uevent_thread;
112    pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx);
113}
114
115}; //namespace
116#endif //HWC_OBSERVER_H
117