本文基于lxc容器在安卓系统中运行linux两个同时运行不须要重启切换
android运行linux有好多方案
1.chroot须要root
2.proot不须要root
3.lxc须要改建内核须要而且须要root
三种方案网上都好多,像我之前在手机上编译deepin就是用到了linuxdeploy,编译deepinarmhf的时侯也用了华为公测的鲲鹏917那速率爽到爆linux常用命令,可惜真正销售的时侯华为发布了鲲鹏920,920支持硬件浮点不支持软浮点linux学习论坛,我没办法使用chroot来建立一个armhf环境linux 启动android模拟器,所以直接用手机安装了linuxdeploy来实现,手机现今的配置都是6G8g显存这个配置买个服务器要好多钱,主要还是钱的问题有钱直接让华为单独给你开个917服务器,回归题外话,大部份方案要显示界面都是通过vnc远程或则xdsl方法,比较简单安装个apk才能解决。
本文使用lxc方案natvice直接勾画到java层使用的案例安卓版本为7.1.2linux版本debianbuster其他版本长治小异
阅读这篇文章的前提你必须有android源码内核源码能自己编译安卓系统,熟悉建立chrootlinux
建立lxclinuxdebian在ubuntu上
安装也很简单aptinstalllxc
lxc-create -t download -n debian10 -- --dist debian --release "buster"
让你选择版本我使用的是rk328832位安卓所以选择了armhf
之后就通过chroot大法安装x11桌面环境
3288是一个极其强大的cpu我直接安装了deepin桌面其实他很大我早已努力精简到了1.5G,怎样将deepin移植到armhf请看我其他博客我还为他写了一个专栏,须要的是耐心,deepin使用的kde容积缩小很难,谁让他漂亮呢,也支持一下国产桌面,精简的完全可以使用xfce或则lxdelxqt等桌面也是特别的稳定。
也有在linux上运行android的anbox方案linux 启动android模拟器,也是采用lxc技术实现lxc运行android我也尝试过并且没有成功运行在armhf上,我在其他文章也写过,在ubuntuamd64上能运行上去并且bug成吨的伤害让你无从下手让其有希望成为商用产品
项目的起因是由于linux上资源的短缺,好多软件没办法使用要么使用winne并且这个我没发觉如何在arm32位或则arm64位系统上使用,没想到deepin居然采用这些方案来运行windows程序
在安卓上运行lxc我们可以通过mmap将x11的界面输出到安卓,尽管代码很简单,而且我为他阅读了大量的知识来了解安卓图形界面显示的整个原理,及阅读androidsurfacesurfacecontrolsurfaceflinger关系的源码,网上资料好多而且大部份都是写android4一下的,只能通过介绍对比源码查看改变
我们创建一个安卓surfaceview程序
SurfaceView surfaceview = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = surfaceview.getHolder();
holder.addCallback(new SurfaceHolder.Callback(){
@Override
public void surfaceCreated(SurfaceHolder holder) {
linuxinit(holder.getSurface());
linuxinit是将下层surfaceview创建的surface通过so传递到底层
下层与natvice层交互通过binder
我们传递surface的时侯通过binder实质是传递一个IGraphicBufferProducer下边是so中的bidner顾客端将收到的surface继续往下传递
Parcel data, reply;
int transCode = 0;
int writeInt = 0;
int replyInt = 0;
data.writeStrongBinder(IInterface::asBinder(surface->getIGraphicBufferProducer()));
binder->transact(transCode, data, &reply);
编撰一个binder服务器
用于接收
status_t onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
{
//从parcel读出一个binder对象
sp binder(data.readStrongBinder());
//Binder对象就是IGraphicBufferProducer类型的
sp gbp(interface_cast(binder));
//new了一个Surface,构造函数的参数会带上这个binder对象
zwsurface = new Surface(gbp, true);
}
为了验证疗效我直接在natvice层直接操作surface
ANativeWindow_Buffer outBuffer;
zwsurface->lock(&outBuffer, NULL);
ssize_t bpr = outBuffer.stride * 2;
android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
zwsurface->unlockAndPost();
这是时侯安卓层apk中的surfaceview就显示一个黑色的颜色
类似于java下层用canvas画
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.BLUE); //随便设置背景颜色
holder.unlockCanvasAndPost(canvas);
如今natvice层早已领到了surface那我们就通过mmap将x11界面截图传递或则直接socket传递
我们在回顾一下刚刚的natvice操作
ANativeWindow_BufferoutBuffer;申请显存空间
zwsurface->lock(&outBuffer,NULL);锁定显存空间
android_memset16((uint16_t*)outBuffer.bits,0xF800,bpr*outBuffer.height);显存复制
zwsurface->unlockAndPost();释放进行显示
那我们就须要将x11的图形信息传递到ANativeWindow_Buffer中即可
具体的可以取查阅maruos实现
这么我们就可以很便捷的将x11界面数据传递过来
关于怎么获取x11下的图形数据我们又要熟悉xorg框架
这儿国外的知识很少对这一块我也是学习各大美国源码的操作一知半解,要学习xlib
主要是XOpenDisplay联接联接xserver
XShmGetImage获取图片数据然后传递下来
最后上两张完成的图