Nexus 7 Tablet 安装多系统


Multi-Booting the Nexus 7 Tablet

Jul 29, 2013 By Bill Childers

Anyone who knows me well enough knows I love mobile devices. Phones, tablets and other shiny glowing gadgets are almost an addiction for me. I’ve talked about my addiction in other articles and columns, and Kyle Rankin even made fun of me once in a Point/Counterpoint column because my household has a bunch of iOS devices in it. Well, I was fortunate enough to add an Android device to the mix recently—a Nexus 7 tablet. I actually won this device at the Southern California Linux Expo as part of the Rackspace Break/Fix Contest, but that’s a different story.

If you’ve not seen a Nexus 7, it’s a nice little device. Like all “Nexus”-branded Android devices, it’s a “reference” device for Google’s base Android implementation, so it’s got a well-supported set of hardware. I’m not trying to make this article sound like a full-fledged review of the device, but here’s a few tech specs in case you’re not familiar with it:

  • 7″ screen with 1280×800 resolution.
  • 7.81″ x 4.72″ x 0.41″ (198.5mm x 120mm x 10.45mm).
  • 16 or 32GB of Flash storage (mine is the 16GB model).
  • 1GB of RAM.
  • NVIDIA Tegra 3 Quad-Core Processor.
  • Wi-Fi, Bluetooth and optional 3G radios.
  • Android 4.2 Jelly Bean.

The Nexus line of Android devices makes up the reference implementation for Android, so that tends to be the series of device that sees the fastest movement in terms of new builds of the OS, and in unique OS derivatives like CyanogenMod. Right about the time I received the Nexus 7, Canonical released the developer beta of Ubuntu Touch, which targeted the Nexus 7 as its deployment platform.

Because I can’t leave nice things well enough alone, I decided to start trying alternate OS ROMs on my shiny new Nexus 7. Ordinarily, each new OS would require you to reflash the device, losing all your configuration, apps and saved data. However, I found a neat hack called MultiROM that lets you sideload multiple ROMs on your device. How does it work? Well, let’s walk through the installation.

Prep for MultiROM Installation

First, and I can’t stress this enough, back up your device. I really, really mean it. Back up your device. You’re messing around with lots of low-level stuff when you’re installing MultiROM, so you’ll want to have copies of your data. Also, one of the first steps is to wipe the device and return it to an “out-of-the-box” configuration, so you’ll want your stuff safe.

Second, grab copies of the “stock” Nexus 7 ROMs as they shipped from the factory. You will want these in the event something goes wrong, or if you decide you don’t like this MultiROM hackery and want to roll your device back to a stock configuration.

Third, check the links in the Resources section of this article for up-to-date documentation on MultiROM. It’s possible for things to change between this writing and press time, so follow any instructions you see there. Those instructions will supersede anything I type here, as this kind of hack can be a rapidly moving target. Also, do your own homework—lots of great YouTube videos describe this process, and a video sometimes can be worth several thousand words.

*Notice:* please make sure you follow these three steps, then follow the MultiROM documentation exactly. I’m not responsible if your tablet gets bricked or turns itself into SkyNet and goes on a rampage against humanity. Though I have to say, if that happened, it’d be kind of neat, in a geeky sort of way.

Unlocking Your Bootloader

Your device should be on the latest available factory ROM supported by MultiROM before you begin the installation. At the time of this writing, on my Nexus 7 (Wi-Fi-only) model, that was 4.2.2. The Nexus 7 comes from the factory with a “locked” bootloader. The first thing you’ve got to do is unlock the bootloader before you can proceed.

To unlock the bootloader, you need the Android SDK tools installed on your computer (see the Resources section for a download link). Specifically, you’ll need the fastboot and adb tools for this, so make sure they’re on your system and in your shell’s PATH environment variable.

Next, hook up your tablet to your computer via the USB-to-MicroUSB cable, and then run:

adb reboot bootloader

Your tablet then will reboot, and you’ll be in the Android bootloader. Once you’re in the bootloader, run the following command:

sudo fastboot oem unlock

Next, you’ll be prompted to confirm the command and accept that all data on your device will be erased. The tablet then will reboot, winding up in the setup wizard where you’ll be prompted for all your setup information as if it were fresh out of the box once more.

Installing MultiROM

Now that your bootloader is unlocked, you can proceed to the trickiest part of this process—installing MultiROM. Grab a copy of it from the XDA-Developers MultiROM thread (the link is in the Resources section of this article; currently the filename is You’ll also need to get the modified TWRP install file (TWRP_multirom_n7_20130404.img) and a patched kernel ( Rename the TWRP install file to recovery.img, then hook your tablet back up to your computer, and place these files in the root of its filesystem (keep the .zip files zipped—don’t unzip them).

Next, from your computer’s command line, you’ll need to run the adb utility from the Android SDK again, but this time, with the proper argument to get the system to boot to “recovery” mode:

adb reboot recovery

This will bring the device to “Clockwork Recovery” mode. From the Recovery menu on the device, choose “Install zip from sdcard”, followed by “choose zip from sdcard”, then specify the MultiROM zip file you moved to the root of your tablet’s filesystem earlier. When it’s done flashing, select “reboot system now”, and your Nexus 7 will reboot.

Once the device boots normally, issue the following command from your computer to get the system back in the bootloader:

adb reboot bootloader

The device will reboot in bootloader mode. Select the fastboot option on the screen, then type the following on your computer:

sudo fastboot flash recovery recovery.img

That’ll flash the modified recovery image that MultiROM requires to your tablet. Next, just tell the tablet to reboot by issuing the following command to it:

sudo fastboot reboot

Your Nexus 7 now is ready to install alternate ROMs.

Adding ROMs to MultiROM

Adding ROMs to MultiROM is fairly straightforward from here. Just hook your tablet up to your computer, drop the .zip file for the ROM you want to install onto the root of the filesystem, and then shut down the tablet. Restart your Nexus 7 in MultiROM by holding the “Volume Down” button while pushing the power switch. You’ll see a screen with what appears to be the Android logo lying on its back (Figure 1). This is the bootloader. Push the “Volume Down” button until the red arrow at the top of the screen indicates “Recovery Mode”, then push the Power button. This will boot the Nexus 7 into MultiROM. Alt none

Figure 1. Android Bootloader Screen

Now that your Nexus 7 is actually in MultiROM, select the “Advanced” button in the lower-left corner, then select “MultiROM” in the lower-right corner. Now, to install a ROM, touch “Add ROM” in the upper-left corner (Figure 2).

Alt none

Figure 2. MultiROM “Add ROM” Screen

Accept the defaults (unless you’re trying the Ubuntu Touch developer release), and just press Next. The next screen will ask you to select a ROM source. Touch the Zip file button, then pick the .zip file of whatever ROM you want to install. The system will go ahead and install it, and it’ll let you know when it’s complete. Push the Reboot button when the install is complete, and your tablet will reboot into the MultiROM selection screen (Figure 3).

Alt none

Figure 3. MultiROM Boot Menu

Looking at my boot menu, you’ll see I’ve got cm-10.0.0-grouper installed, otherwise known as CyanogenMod. To boot that, I simply touch it, then press the large blue Boot button at the bottom of the screen. It’s as simple as that—the Nexus 7 will just start booting CyanogenMod. At one point, I had the stock ROM, CyanogenMod, AKOP and Ubuntu Touch on my Nexus 7, all coexisting nicely (but they took too much of my limited 16GB storage space, so I pruned back some).

If you decide a particular ROM isn’t for you, you can get rid of it quite easily. Just go back to the MultiROM install by booting with the Power and Volume Down buttons depressed, then select Recovery, and press the Power button again. Dive back into the MultiROM menus, just like you’re installing a ROM, but instead of pressing Add ROM, press List ROMs. Touch the ROM you want to delete, and then just select Delete from the buttons that pop up. This will let you keep your MultiROM install clean, with only the ROMs you want to test active at any given time.

Getting Ubuntu Touch Running

Ubuntu Touch is something I’ve been watching closely, particularly because I spent a little time with an Ubuntu Touch-equipped Nexus 7 at the Southern California Linux Expo. The Ubuntu Touch developer builds can be a little finicky, although they’ve stabilized in recent weeks. The key to getting them going in MultiROM is to select the “Don’t Share” radio button when adding the ROM (Figure 2). The Ubuntu Touch builds come in two parts. Add the smaller hardware-specific zip file first (on my Wi-Fi Nexus 7, it’s, but do not reboot—go back, list the ROM again, then push Flash Zip, and select the larger ROM file ( After that completes, you can reboot your tablet into Ubuntu Touch. Be advised, though, that Ubuntu Touch is under very heavy development, and sometimes the daily builds exhibit issues—and may not work at all. Your mileage may vary. If you do get Ubuntu Touch going, but it seems unresponsive to touch, try sliding from the left bezel toward the center. That’ll bring up a Unity-style launcher, and things should work from there. It took me a few tries to figure this out. I thought my Ubuntu Touch installation was broken or that I had a bad build. It turns out, it’s just a different operating paradigm.

Alt none

Figure 4. Ubuntu Touch on the Nexus 7!


The Nexus 7 by itself is a great, low-cost, high-power tablet. However, thanks to its status as a reference device, there’s a lot of alternate OSes out there for it. MultiROM lets you try them all without requiring you to wipe your device each time you want to try a new OS or ROM build. Check it out, but back up your data, and read the documentation thoroughly.


The programmer who wrote the MultiROM program has a great sense of humor, and he left a “Pong” easter egg in the software. From the main MultiROM boot screen, just touch the MultiROM logo, and you’ll get a proper portrait-orientation port of Pong (say that three times fast!)

Alt none



XDA-Developers MultiROM Install Thread:

Nexus 7 Factory ROM Images:

Android SDK Tools Download Page:

CyanogenMod Home Page:

AKOP Home Page:

Ubuntu Touch Installation:

Ubuntu Touch Download Page:

Using libavformat and libavcodec

ref :

Using libavformat and libavcodec

Martin Böhme ([email protected])

February 18, 2004

Update (January 23 2009): By now, these articles are quite out of date… unfortunately, I haven’t found the time to update them, but thankfully, others have jumped in. Stephen Dranger has a more recent tutorial, ryanfb of has an updated version of the code, and David Hoerl has a more recent update.

Update (July 22 2004): I discovered that the code I originally presented contained a memory leak (av_free_packet() wasn’t being called). My apologies – I’ve updated the demo program and the code in the article to eliminate the leak.

Update (July 21 2004): There’s a new prerelease of ffmpeg (0.4.9-pre1). I describe the changes to the libavformat / libavcodec API in this article.

The libavformat and libavcodec libraries that come with ffmpeg are a great way of accessing a large variety of video file formats. Unfortunately, there is no real documentation on using these libraries in your own programs (at least I couldn’t find any), and the example programs aren’t really very helpful either.

This situation meant that, when I used libavformat/libavcodec on a recent project, it took quite a lot of experimentation to find out how to use them. Here’s what I learned – hopefully I’ll be able to save others from having to go through the same trial-and-error process. There’s also a small demo program that you can download. The code I’ll present works with libavformat/libavcodec as included in version 0.4.8 of ffmpeg (the most recent version as I’m writing this). If you find that later versions break the code, please let me know.

In this document, I’ll only cover how to read video streams from a file; audio streams work pretty much the same way, but I haven’t actually used them, so I can’t present any example code.

In case you’re wondering why there are two libraries, libavformat and libavcodec: Many video file formats (AVI being a prime example) don’t actually specify which codec(s) should be used to encode audio and video data; they merely define how an audio and a video stream (or, potentially, several audio/video streams) should be combined into a single file. This is why sometimes, when you open an AVI file, you get only sound, but no picture – because the right video codec isn’t installed on your system. Thus, libavformat deals with parsing video files and separating the streams contained in them, and libavcodec deals with decoding raw audio and video streams.

Opening a Video File

First things first – let’s look at how to open a video file and get at the streams contained in it. The first thing we need to do is to initialize libavformat/libavcodec:


This registers all available file formats and codecs with the library so they will be used automatically when a file with the corresponding format/codec is opened. Note that you only need to call av_register_all() once, so it’s probably best to do this somewhere in your startup code. If you like, it’s possible to register only certain individual file formats and codecs, but there’s usually no reason why you would have to do that.

Next off, opening the file:

AVFormatContext *pFormatCtx;
const char      *filename="myvideo.mpg";

// Open video file
if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0)
    handle_error(); // Couldn't open file

The last three parameters specify the file format, buffer size and format parameters; by simply specifying NULL or 0 we ask libavformat to auto-detect the format and use a default buffer size. Replace handle_error() with appropriate error handling code for your application.

Next, we need to retrieve information about the streams contained in the file:

// Retrieve stream information
    handle_error(); // Couldn't find stream information

This fills the streams field of the AVFormatContext with valid information. As a debugging aid, we’ll dump this information onto standard error, but of course you don’t have to do this in a production application:

dump_format(pFormatCtx, 0, filename, false);

As mentioned in the introduction, we’ll handle only video streams, not audio streams. To make things nice and easy, we simply use the first video stream we find:

int            i, videoStream;
AVCodecContext *pCodecCtx;

// Find the first video stream
for(i=0; i<pFormatCtx->nb_streams; i++)
    handle_error(); // Didn't find a video stream

// Get a pointer to the codec context for the video stream

OK, so now we’ve got a pointer to the so-called codec context for our video stream, but we still have to find the actual codec and open it:

AVCodec *pCodec;

// Find the decoder for the video stream
    handle_error(); // Codec not found

// Inform the codec that we can handle truncated bitstreams -- i.e.,
// bitstreams where frame boundaries can fall in the middle of packets
if(pCodec->capabilities & CODEC_CAP_TRUNCATED)

// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0)
    handle_error(); // Could not open codec

(So what’s up with those “truncated bitstreams”? Well, as we’ll see in a moment, the data in a video stream is split up into packets. Since the amount of data per video frame can vary, the boundary between two video frames need not coincide with a packet boundary. Here, we’re telling the codec that we can handle this situation.)

One important piece of information that is stored in the AVCodecContext structure is the frame rate of the video. To allow for non-integer frame rates (like NTSC’s 29.97 fps), the rate is stored as a fraction, with the numerator in pCodecCtx->frame_rate and the denominator in pCodecCtx->frame_rate_base. While testing the library with different video files, I noticed that some codecs (notably ASF) seem to fill these fields incorrectly (frame_rate_base contains 1 instead of 1000). The following hack fixes this:

// Hack to correct wrong frame rates that seem to be generated by some 
// codecs
if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)

Note that it shouldn’t be a problem to leave this fix in place even if the bug is corrected some day – it’s unlikely that a video would have a frame rate of more than 1000 fps.

One more thing left to do: Allocate a video frame to store the decoded images in:

AVFrame *pFrame;


That’s it! Now let’s start decoding some video.

Decoding Video Frames

As I’ve already mentioned, a video file can contain several audio and video streams, and each of those streams is split up into packets of a particular size. Our job is to read these packets one by one using libavformat, filter out all those that aren’t part of the video stream we’re interested in, and hand them on to libavcodec for decoding. In doing this, we’ll have to take care of the fact that the boundary between two frames can occur in the middle of a packet.

Sound complicated? Lucikly, we can encapsulate this whole process in a routine that simply returns the next video frame:

bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, 
    int videoStream, AVFrame *pFrame)
    static AVPacket packet;
    static int      bytesRemaining=0;
    static uint8_t  *rawData;
    static bool     fFirstTime=true;
    int             bytesDecoded;
    int             frameFinished;

    // First time we're called, set to NULL to indicate it
    // doesn't have to be freed

    // Decode packets until we have decoded a complete frame
        // Work on the current packet until we have decoded all of it
        while(bytesRemaining > 0)
            // Decode the next chunk of data
            bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame,
                &frameFinished, rawData, bytesRemaining);

            // Was there an error?
            if(bytesDecoded < 0)
                fprintf(stderr, "Error while decoding frame\n");
                return false;


            // Did we finish the current frame? Then we can return
                return true;

        // Read the next packet, skipping all packets that aren't for this
        // stream
            // Free old packet

            // Read new packet
            if(av_read_packet(pFormatCtx, &packet)<0)
                goto loop_exit;
        } while(packet.stream_index!=videoStream);



    // Decode the rest of the last frame
    bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, 
        rawData, bytesRemaining);

    // Free last packet

    return frameFinished!=0;

Now, all we have to do is sit in a loop, calling GetNextFrame() until it returns false. Just one more thing to take care of: Most codecs return images in YUV 420 format (one luminance and two chrominance channels, with the chrominance channels samples at half the spatial resolution of the luminance channel). Depending on what you want to do with the video data, you may want to convert this to RGB. (Note, though, that this is not necessary if all you want to do is display the video data; take a look at the X11 Xvideo extension, which does YUV-to-RGB and scaling in hardware.) Fortunately, libavcodec provides a conversion routine called img_convert, which does conversion between YUV and RGB as well as a variety of other image formats. The loop that decodes the video thus becomes:

while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame))
    img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, 
        pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

    // Process the video frame (save to disk etc.)

The RGB image pFrameRGB (of type AVFrame *) is allocated like this:

AVFrame *pFrameRGB;
int     numBytes;
uint8_t *buffer;

// Allocate an AVFrame structure

// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
buffer=new uint8_t[numBytes];

// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
    pCodecCtx->width, pCodecCtx->height);

Cleaning up

OK, we’ve read and processed our video, now all that’s left for us to do is clean up after ourselves:

// Free the RGB image
delete [] buffer;

// Free the YUV frame

// Close the codec

// Close the video file


Sample Code

A sample app that wraps all of this code up in compilable form is here. If you have any additional comments, please contact me at[email protected]. Standard disclaimer: I assume no liability for the correct functioning of the code and techniques presented in this article.

ubuntu 搭建 vpn

OS : ubuntu 12.10

install pptpd

apt-get install pptpd

configure pptpd

vi /etc/pptpd.conf

localip   #主机的ip地址
remoteip   #分配给客户端的ip地址
vi /etc/ppp/pptpd-options

vi /etc/ppp/chap-secrets 

user1 pptpd password *    #适用所有ip, "pptpd"需要跟/etc/ppp/pptpd-options中的name相同
user2 pptpd password    #适用指定ip
/etc/init.d/pptpd restart #重启pptpd服务


vi /etc/sysctl.conf 
net.ipv4.ip_forward=1  #开启ip转发

sysctl -p #使ip转发生效
apt-get install iptables #安装iptables
iptables -A FORWARD -s -j ACCEPT  #对应remote ip段
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE  #把192.168.1.0/24的请求转到eth0,eth0是主机的外网网卡
iptables-save  > /etc/iptables-rules
vi /etc/network/if-up.d/iptables : 内容有如下两行: 

iptables-restore < /etc/iptables-rules

chmod +x /etc/network/if-up.d/iptables


#include <stdio.h>
#include <usb.h>

int main(void)
      struct usb_bus *busses;
      busses = usb_get_busses();
      struct usb_bus *bus;
      int c, i, a;
      /* ... */
      for (bus = busses; bus; bus = bus->next) {
        struct usb_device *dev;
        int val;
        usb_dev_handle *junk;
        for (dev = bus->devices; dev; dev = dev->next) {
          char buf[1024];
          junk = usb_open ( dev );
          if ( junk == NULL ){
            printf("Can't open %p (%s)\n", dev, buf );
          } else {
            val = usb_reset(junk);
            printf( "reset %p %d (%s)\n", dev, val, buf );
gcc -o outputname resetusb.c -lusb


Android 触摸和鼠标模式切换

Android os : > 4.0

Android 4.0以后,触摸屏的触摸模式和鼠标模式使用idc文件来做切换。 需要把触摸屏设备的相应idc文件放到 /system/usr/idc/ 目录下。 如下是IRTOUCH Vendor_6615_Product_0085.idc文件的内容:

 # Copyright (C) 2012 Beijing IRTOUCH SYSTEMS Co.,Ltd
    # Input Device Configuration File for the IRTOUCH touch screen.

    device.internal = 1 

    # Basic Parameters
    touch.deviceType = touchScreen
    touch.orientationAware = 1 

    # Size
    touch.size.calibration = diameter
    touch.size.scale = 10
    touch.size.bias = 0 
    touch.size.isSummed = 0 

    # Pressure
    touch.pressure.calibration = amplitude
    touch.pressure.scale = 0.005

    # Orientation
    touch.orientetion.calibration = none