Android显示Surface


Surface创建

在ViewRootImpl,创建一个final的Surface对象,任何线程可访问它,内部mLock锁。ViewRootImpl类中的Surface定义。

final Surface mSurface = new Surface();

第一次performTraversals方法或窗体发生改变时,Surface的#isValid方法判断是否有效,relayoutWindow方法,初始化Surface。

之前无效,现在有效
1:设置newSurface标志,下次再绘制。
2:初始化硬件渲染,mHardwareRenderer#initinitialize方法

之前有效,现在无效
各种destroy停止

一直有效
硬件渲染更新,mHardwareRenderer#updateSurface方法

Surface的#isValid方法。

public boolean isValid() {
    synchronized (mLock) {
        if (mNativeObject == 0) return false;
        return nativeIsValid(mNativeObject);
    }
}

当Surface内部底层指针mNativeObject不空,且底层JNI方法#nativeIsValid判断有效时,认定Java层Surface有效。
通过IWindowSession的#relayout方法访问Wms服务。

public int relayout(IWindow window, int seq, ...,Surface outSurface) {
    int res = mService.relayoutWindow(this, window, ..., outSurface);
    return res;
}

Wms服务的#relayoutWindow方法,初始化App进程传过来的Surface。

public int relayoutWindow(Session session, IWindow client, ...,Surface outSurface) {
    ..
    if (viewVisibility == View.VISIBLE &&
                    (win.mAppToken == null || !win.mAppToken.clientHidden)) {
        try {
            ...
            SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
            //创建surfaceControl
            if (surfaceControl != null) {
                outSurface.copyFrom(surfaceControl);
            } else {
                outSurface.release();
            }
        } catch (Exception e) {
        }
    }
    ...
}

创建一个SurfaceControl对象,调用它的copyFrom方法,初始化底层Surface,该对象是Surface控制类。


创建SurfaceControl

SurfaceControl底层结构图。

SurfaceControl结构图.jpg

WindowStateAnimator的createSurfaceLocked方法。

SurfaceControl createSurfaceLocked() {
    if (mSurfaceControl == null) {
        mDrawState = DRAW_PENDING;//状态变更为待绘制
        ...
        try {
            mSurfaceW = width;//设置surface的宽高
            mSurfaceH = height;
            ...
            mSurfaceFormat = format;//设置surface格式
            mSurfaceControl = new SurfaceControl(
                        mSession.mSurfaceSession,
                        attrs.getTitle().toString(),
                        width, height, format, flags);
            w.mHasSurface = true;//winstate有了surface
            try {
                mSurfaceX = left;
                mSurfaceY = top;
                try {
                    mSurfaceControl.setPosition(left, top);
                    mSurfaceLayer = mAnimLayer;
                    ...
                    mSurfaceControl.setLayer(mAnimLayer);
                    mSurfaceControl.setAlpha(0);
                    mSurfaceShown = false;
                } catch (RuntimeException e) {
                    ...
                }
                mLastHidden = true;//刚创建的设为隐藏
            }
    }
}

在Java层,SurfaceControl#构造方法,JNI#方法,创建底层SurfaceControl,参数是SurfaceSession、宽高、格式等,返回指针。

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    //创建底层surfaceControl。
    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags);
    ...
    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}

底层SurfaceComposerClient,它在SurfaceSession构造方法创建。创建底层SurfaceControl。

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags) {
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

在Wms服务进程,此方法本质是调用Client#createSurface实现与SF进程通信,SF进程初始化handle与gbp,最后,构建一个底层SurfaceControl用于封装关键的handle与gdp。
ISurfaceComposerClient是Wms服务进程与SF进程通信业务接口,SurfaceComposerClient#onFirstRef方法在构造方法前调用。

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;//初始化mClient。
            mStatus = NO_ERROR;
        }
    }
}

通过createConnection方法,调用端得到的业务接口的实现BpSurfaceComposerClient。SF进程服务端创建Client对象,继承BnSurfaceComposerClient。


SF进程createSurface方法

Wms进程发起访问后,SF进程启动binder线程处理业务,向SF主线程发送一个MessageCreateLayer消息。
Client#createSurface方法。

status_t Client::createSurface(...) {
    //先定义一个消息类MessageCreateLayer 
    class MessageCreateLayer : public MessageBase {
        SurfaceFlinger* flinger;
        Client* client;
        sp<IBinder>* handle;
        sp<IGraphicBufferProducer>* gbp;
        status_t result;
        ..
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle,
                sp<IGraphicBufferProducer>* gbp)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp),
              name(name), w(w), h(h), format(format), flags(flags) {
        }
        status_t getResult() const { return result; }
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);//
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle, gbp);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

创建一个MessageCreateLayer消息,postMessageSync发送给SF主线程。

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
        nsecs_t reltime, uint32_t /* flags */) {
    status_t res = mEventQueue.postMessage(msg, reltime);
    if (res == NO_ERROR) {
        msg->wait();//栅栏等待
    }
    return res;
}

向EventQueue消息队列发送同步消息,然后通过栅栏使binder线程陷入wait,最后由主线程唤醒。MessageCreateLayer继承MessageBase,当主线程handleMessage方法处理时,触发子类MessageCreateLayer重写的handler方法,最后打开栅栏,唤醒等待的binder线程。

void MessageBase::handleMessage(const Message&) {
    //走到MessageCreateLayer重写的handler方法
    this->handler();
    barrier.open();
};
//MessageCreateLayer重写的handler方法
virtual bool handler() {
    result = flinger->createLayer(name, client, w, h, format, flags,handle, gbp);
    return true;
}

handler处理时,触发主线程SF#createLayer方法,真正初始化handle与gbp,返回result,SF#binder线程被唤醒后,createSurface继续执行,此时,result已初始化赋值。

总结
binder线程被栅栏阻挡,进入等待,当主线程handler方法执行后,有了result,打开栅栏,放行>binder线程,被唤醒拿到result。


SF主线程createLayer方法

status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp<Client>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) {
    sp<Layer> layer;
    result = createNormalLayer(client,
                    name, w, h, flags, format,//format是java层传过来的
                    handle, gbp, &layer);//创建Layer对象,指针在layer中。
    ...
    result = addClientLayer(client, *handle, *gbp, layer);//将layer增加到list中
    ...
    setTransactionFlags(eTransactionNeeded);//0x01 创建Layer,触发eTransactionNeeded
    return result;
}

SurfaceFlinger#createNormalLayer方法。

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,//普通Layer
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) {
    ...
    *outLayer = new Layer(this, client, name, w, h, flags);//创建Layer
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();//初始化handle和gbp
        *gbp = (*outLayer)->getProducer();
    }
    return err;
}

创建普通层级Layer对象,Layer#getHandle与Layer#getProducer方法初始化handle、gbp指针,将Layer加入到Client中的map保存,

每个Layer对应一个handle。

  • Layer#getHandle:handle是IBinder类型,创建服务进程端Handle对象,在内核为其创建服务节点,客户端拿到的handle是BpXxx,handle是一个远程进程连接到SF进程的句柄。
  • Layer#getProducer:返回Layer的IGraphicBufferProducer。IGraphicBufferProducer也是跨进程通信的业务接口,远程进程拿到的是BpGraphicBufferProducer,通过它操作图形内存区的。
  • SF进程通过reply的writeStrongBinder方法写入,远程进程通过readStrongBinder读取。

底层Surface

Surface#copyFrom方法。

public void copyFrom(SurfaceControl other) {
    ...
    //底层SurfaceControl指针
    long surfaceControlPtr = other.mNativeObject;
    ...
    long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
    synchronized (mLock) {
        if (mNativeObject != 0) {
            nativeRelease(mNativeObject);//释放原底层Surface指针
        }
        setNativeObjectLocked(newNativeObject);
    }
}

JNI#方法利用底层SurfaceControl创建底层Surface。
底层SurfaceControl#getSurface方法。

sp<Surface> SurfaceControl::getSurface() const {
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) { 
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}

底层Surface创建,封装GraphicBufferProducer指针。

Wms服务初始化Surface,App进程通过Surface操作图形缓冲区。
GraphicBufferProducer是生产者。


任重而道远

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容