android下實現framebuffer獨佔的原理

來源:互聯網
上載者:User

1.android下獨佔framebuffer的代碼(tslib)

int open_framebuffer(void)
{
struct vt_stat vts;
char vtname[128];
int fd, nr;
unsigned y, addr;
struct vt_mode vm;

if ((fbdevice = getenv ("TSLIB_FBDEVICE")) == NULL)
fbdevice = defaultfbdevice;

if ((consoledevice = getenv ("TSLIB_CONSOLEDEVICE")) == NULL)
consoledevice = defaultconsoledevice;

if (strcmp (consoledevice, "none") != 0) {
sprintf (vtname,"%s%d", consoledevice, 1);
        fd = open (vtname, O_WRONLY);
        if (fd < 0) {
               perror("open consoledevice");
               return -1;
        }

if (ioctl(fd, VT_OPENQRY, &nr) < 0) {
               perror("ioctl VT_OPENQRY");
               return -1;
        }
        close(fd);
printf("We get tty num:%d\n", nr);

        sprintf(vtname, "%s%d", consoledevice, nr);

        con_fd = open(vtname, O_RDWR | O_NDELAY);
        if (con_fd < 0) {
               perror("open tty");
               return -1;
        }

        if (ioctl(con_fd, VT_GETSTATE, &vts) == 0)
               last_vt = vts.v_active;

        if (ioctl(con_fd, VT_ACTIVATE, nr) < 0) {
               perror("VT_ACTIVATE");
               close(con_fd);
               return -1;
        }

        if (ioctl(con_fd, VT_WAITACTIVE, nr) < 0) {
               perror("VT_WAITACTIVE");
               close(con_fd);
               return -1;
        }

        if (ioctl(con_fd, KDSETMODE, KD_GRAPHICS) < 0) {
               perror("KDSETMODE");
               close(con_fd);
               return -1;
        }

}

fb_fd = open(fbdevice, O_RDWR);
if (fb_fd == -1) {
perror("open fbdevice");
return -1;
}

if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) {
perror("ioctl FBIOGET_FSCREENINFO");
close(fb_fd);
return -1;
}

if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) {
perror("ioctl FBIOGET_VSCREENINFO");
close(fb_fd);
return -1;
}
xres = var.xres;
yres = var.yres;

fbuffer = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0);
if (fbuffer == (unsigned char *)-1) {
perror("mmap framebuffer");
close(fb_fd);
return -1;
}
memset(fbuffer,0,fix.smem_len);
ioctl(fb_fd, FBIOBLANK, 0);
bytes_per_pixel = (var.bits_per_pixel + 7) / 8;
line_addr = malloc (sizeof (__u32) * var.yres_virtual);
addr = 0;
for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length)
line_addr [y] = fbuffer + addr;

return 0;
}


2. android下的console管理

DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread(
        const sp<SurfaceFlinger>& flinger)
    : DisplayEventThreadBase(flinger), consoleFd(-1)
{   
  
   。。。
    // set up signals so we're notified when the console changes
    // we can't use SIGUSR1 because it's used by the java-vm
    vm.mode = VT_PROCESS;  //設定為VT_PROCESS模式,可以console切換
    vm.waitv = 0;
    vm.relsig = SIGUSR2;
    vm.acqsig = SIGUNUSED;
    vm.frsig = 0;

    struct sigaction act;
    sigemptyset(&act.sa_mask);
    act.sa_handler = sigHandler;
    act.sa_flags = 0;
    sigaction(vm.relsig, &act, NULL);

    sigemptyset(&act.sa_mask);
    act.sa_handler = sigHandler;
    act.sa_flags = 0;
    sigaction(vm.acqsig, &act, NULL);

    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, vm.relsig);
    sigaddset(&mask, vm.acqsig);
    sigprocmask(SIG_BLOCK, &mask, NULL);

    // switch to graphic mode
    res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
    LOGW_IF(res<0,
            "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res);

    this->prev_vt_num = vs.v_active;
    this->vt_num = vtnum;
    this->consoleFd = fd;
}


bool DisplayHardwareBase::ConsoleManagerThread::threadLoop()
{
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, vm.relsig);
    sigaddset(&mask, vm.acqsig);
    int sig = 0;
    sigwait(&mask, &sig);

    if (sig == vm.relsig) {   //收到relsig訊號
        sp<SurfaceFlinger> flinger = mFlinger.promote();
        LOGD("About to give-up screen, flinger = %p", flinger.get());
        if (flinger != 0)
            flinger->screenReleased(0);
    } else if (sig == vm.acqsig) {  //收到acqsig訊號
        sp<SurfaceFlinger> flinger = mFlinger.promote();
        LOGD("Screen about to return, flinger = %p", flinger.get());
        if (flinger != 0) 
            flinger->screenAcquired(0);
    }
    
    return true;
}


總結:

bool SurfaceFlinger::threadLoop()利用handleConsoleEvents()判斷當前進程是否有console的控制權。

當除了surfaceFlinger之外的進程使用VT_ACTIVATE啟用了console後,surfaceFlinger失去了console的控制權

mCanDraw返回false,因而不再向framebuffer更新資料。


3.kernel(2.6.29)中的代碼調用:

(1). driver/char/vt_ioctl.c +821

case VT_ACTIVATE:
if (!perm)
goto eperm;
if (arg == 0 || arg > MAX_NR_CONSOLES)
ret =  -ENXIO;
else {
arg--;
acquire_console_sem();
ret = vc_allocate(arg);
release_console_sem();
printk("We want active tty%d\n", arg);
if (ret)
break;
set_console(arg); //設定該tty成為當前的console
}


(2). driver/char/vt.c +2406

int set_console(int nr)
{
struct vc_data *vc = vc_cons[fg_console].d;

if (!vc_cons_allocated(nr) || vt_dont_switch ||
(vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) { 

//android設定當前console為VT_PROCESS KD_GRAPHICS模式,因而可以切換console

。。。
}


(3).切換新的console

void change_console(struct vc_data *new_vc)
{
struct vc_data *vc;

if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
return;

vc = vc_cons[fg_console].d;
if (vc->vt_mode.mode == VT_PROCESS) {

vc->vt_newvt = new_vc->vc_num;
if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {  //發送signal給surfaceflinger

return;
}

。。。

}


(4).恢複老的console

static void complete_change_console(struct vc_data *vc)
{

。。。

if (vc->vt_mode.mode == VT_PROCESS) {
/*
* Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {  //發送acqsig訊號

。。。

}


---

南京


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.