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_PROCESSKD_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信号

。。。

}


---

南京


更多相关文章

  1. Android(安卓)视频播放器 应用层设计 考虑事项 (二)
  2. Android源码学习之五-Android的IPC机制
  3. Android程序全屏方法
  4. Android采用Linux内核的原因:
  5. Android(安卓)AIDL实现跨进程Activity与Service的通信
  6. 【Android话题-2.3系统服务】你知道怎么添加一个系统服务吗
  7. Android之判断当前指定App是否在前台
  8. Android(安卓)Service小记
  9. Android(安卓)一些指令

随机推荐

  1. Edittext失去焦点
  2. ScrollView里面放入多个子控件
  3. Android 沿着线绘制文字
  4. ubuntu连接android设备(附最简单方法)(转载
  5. Android JSON Parsing Tutorial
  6. Android 背光流程小结
  7. android实现电话录音
  8. android 获得屏幕宽和高
  9. android NFC
  10. Android 短信备份完整版