1. Code that exclusively occupies framebuffer in Android (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 = defafbfbdevice;
If (consoledevice = getenv ("tslib_consoledevice") = NULL)
Leledevice = defaconsoconsoledevice;
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. Console Management in Android
Displayhardwarebase: consolemanagerthread (
Const sp <surfaceflinger> & flinger)
: Displayeventthreadbase (flinger), consolefd (-1)
{
...
// Set up signals so we're re notified when the console changes
// We can't use SIGUSR1 because it's used by the Java-VM
VM. mode = vt_process;// Set it to vt_process mode, which can be switched to 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-> lelefd = 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 ){// Receives the relsig Signal
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 ){// Receives the acqsig Signal
Sp <surfaceflinger> flinger = mflinger. Promote ();
Logd ("screen about to return, flinger = % P", flinger. Get ());
If (flinger! = 0)
Flinger-> screenacquired (0 );
}
Return true;
}
Summary:
Bool surfaceflinger: threadloop () uses handleconsoleevents () to determine whether the current process has control over the console.
When a process except surfaceflinger uses vt_activate to activate the console, surfaceflinger loses control of the console.
Mcandraw returns false, so data is no longer updated to framebuffer.
3. Code call in kernel (2.6.29:
(1). Driver/Char/vt_ioctl.c ++ 821
Case vt_activate:
If (! Perm)
Goto eperm;
If (ARG = 0 | arg> max_nr_les les)
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 );// Set this tty to the current 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 )){
// Set the current console to vt_process kd_graphics mode for Android, so you can switch the Console
...
}
(3) switch to the new 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 ){// Send signal to surfaceflinger
Return;
}
...
}
(4) restore the old 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 ){// Send the acqsig Signal
...
}
---
Nanjing