Client.cpp revision 161410b01a37bcc5522d8e91fe0a743989c86e70
1db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian/*
2db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * Copyright (C) 2012 The Android Open Source Project
3db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian *
4db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
5db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * you may not use this file except in compliance with the License.
6db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * You may obtain a copy of the License at
7db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian *
8db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
9db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian *
10db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * Unless required by applicable law or agreed to in writing, software
11db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
12db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * See the License for the specific language governing permissions and
14db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian * limitations under the License.
15db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian */
16db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
17db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include <stdint.h>
18db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include <sys/types.h>
19db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
20db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include <binder/PermissionCache.h>
214f4f0943489d9113c66ac22b58cfba8c21dfa879Mathias Agopian#include <binder/IPCThreadState.h>
22db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
23db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include <private/android_filesystem_config.h>
24db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
25db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include "Client.h"
26921e6ac4b7610a178285898d191eb0e3afe906c0Mathias Agopian#include "Layer.h"
27db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian#include "SurfaceFlinger.h"
28db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
29db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopiannamespace android {
30db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
31db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian// ---------------------------------------------------------------------------
32db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
33db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopianconst String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
34db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
35db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian// ---------------------------------------------------------------------------
36db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
37db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias AgopianClient::Client(const sp<SurfaceFlinger>& flinger)
381db73f66624e7d151710483dd58e03eed672f064Robert Carr    : Client(flinger, nullptr)
391db73f66624e7d151710483dd58e03eed672f064Robert Carr{
401db73f66624e7d151710483dd58e03eed672f064Robert Carr}
411db73f66624e7d151710483dd58e03eed672f064Robert Carr
421db73f66624e7d151710483dd58e03eed672f064Robert CarrClient::Client(const sp<SurfaceFlinger>& flinger, const sp<Layer>& parentLayer)
431db73f66624e7d151710483dd58e03eed672f064Robert Carr    : mFlinger(flinger),
441db73f66624e7d151710483dd58e03eed672f064Robert Carr      mParentLayer(parentLayer)
45db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
46db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
47db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
48db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias AgopianClient::~Client()
49db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
50db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    const size_t count = mLayers.size();
51db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    for (size_t i=0 ; i<count ; i++) {
529524cb3b37a91b5741790c77ff24fd825b02bca7Robert Carr        sp<Layer> l = mLayers.valueAt(i).promote();
539524cb3b37a91b5741790c77ff24fd825b02bca7Robert Carr        if (l != nullptr) {
549524cb3b37a91b5741790c77ff24fd825b02bca7Robert Carr            mFlinger->removeLayer(l);
559524cb3b37a91b5741790c77ff24fd825b02bca7Robert Carr        }
56db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    }
57db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
58db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
591db73f66624e7d151710483dd58e03eed672f064Robert Carrvoid Client::setParentLayer(const sp<Layer>& parentLayer) {
60f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    Mutex::Autolock _l(mLock);
611db73f66624e7d151710483dd58e03eed672f064Robert Carr    mParentLayer = parentLayer;
621db73f66624e7d151710483dd58e03eed672f064Robert Carr}
631db73f66624e7d151710483dd58e03eed672f064Robert Carr
64f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wusp<Layer> Client::getParentLayer(bool* outParentDied) const {
65f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    Mutex::Autolock _l(mLock);
66f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    sp<Layer> parent = mParentLayer.promote();
67f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    if (outParentDied != nullptr) {
68f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu        *outParentDied = (mParentLayer != nullptr && parent == nullptr);
69f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    }
70f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    return parent;
71f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu}
72f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu
73db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopianstatus_t Client::initCheck() const {
74db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    return NO_ERROR;
75db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
76db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
7713127d8921356dff794250e04208c3ed60b3a3dfMathias Agopianvoid Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer)
78db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
79db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    Mutex::Autolock _l(mLock);
80ac9fa427d4a86745e60a5f7fd8e3ea340c4db907Mathias Agopian    mLayers.add(handle, layer);
81db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
82db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
8313127d8921356dff794250e04208c3ed60b3a3dfMathias Agopianvoid Client::detachLayer(const Layer* layer)
84db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
85db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    Mutex::Autolock _l(mLock);
86db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    // we do a linear search here, because this doesn't happen often
87db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    const size_t count = mLayers.size();
88db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    for (size_t i=0 ; i<count ; i++) {
89db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        if (mLayers.valueAt(i) == layer) {
90db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian            mLayers.removeItemsAt(i, 1);
91db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian            break;
92db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        }
93db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    }
94db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
9513127d8921356dff794250e04208c3ed60b3a3dfMathias Agopiansp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const
96db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
97db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    Mutex::Autolock _l(mLock);
9813127d8921356dff794250e04208c3ed60b3a3dfMathias Agopian    sp<Layer> lbc;
9913127d8921356dff794250e04208c3ed60b3a3dfMathias Agopian    wp<Layer> layer(mLayers.valueFor(handle));
100db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    if (layer != 0) {
101db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        lbc = layer.promote();
102ac9fa427d4a86745e60a5f7fd8e3ea340c4db907Mathias Agopian        ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get());
103db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    }
104db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    return lbc;
105db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
106db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
107db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
108db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopianstatus_t Client::onTransact(
109db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
110db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
111db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    // these must be checked
112db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     IPCThreadState* ipc = IPCThreadState::self();
113db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     const int pid = ipc->getCallingPid();
114db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     const int uid = ipc->getCallingUid();
115db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     const int self_pid = getpid();
1161db73f66624e7d151710483dd58e03eed672f064Robert Carr     // If we are called from another non root process without the GRAPHICS, SYSTEM, or ROOT
1171db73f66624e7d151710483dd58e03eed672f064Robert Carr     // uid we require the sAccessSurfaceFlinger permission.
1181db73f66624e7d151710483dd58e03eed672f064Robert Carr     // We grant an exception in the case that the Client has a "parent layer", as its
1191db73f66624e7d151710483dd58e03eed672f064Robert Carr     // effects will be scoped to that layer.
1201db73f66624e7d151710483dd58e03eed672f064Robert Carr     if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != AID_SYSTEM && uid != 0)
121f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu             && (getParentLayer() == nullptr)) {
122db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian         // we're called from a different process, do the real check
123db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian         if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
124db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian         {
125db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian             ALOGE("Permission Denial: "
1261db73f66624e7d151710483dd58e03eed672f064Robert Carr                     "can't openGlobalTransaction pid=%d, uid<=%d", pid, uid);
127db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian             return PERMISSION_DENIED;
128db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian         }
129db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     }
130db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
131db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
132db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
133db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
1344d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopianstatus_t Client::createSurface(
135db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        const String8& name,
1364d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
137479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk        const sp<IBinder>& parentHandle, uint32_t windowType, uint32_t ownerUid,
1384d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        sp<IBinder>* handle,
1394d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        sp<IGraphicBufferProducer>* gbp)
140db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian{
1411f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr    sp<Layer> parent = nullptr;
1421f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr    if (parentHandle != nullptr) {
143161410b01a37bcc5522d8e91fe0a743989c86e70chaviw        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
144161410b01a37bcc5522d8e91fe0a743989c86e70chaviw        parent = layerHandle->owner.promote();
1451f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr        if (parent == nullptr) {
1461f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr            return NAME_NOT_FOUND;
1471f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr        }
1481f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr    }
149f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu    if (parent == nullptr) {
150f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu        bool parentDied;
151f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu        parent = getParentLayer(&parentDied);
1521db73f66624e7d151710483dd58e03eed672f064Robert Carr        // If we had a parent, but it died, we've lost all
1531db73f66624e7d151710483dd58e03eed672f064Robert Carr        // our capabilities.
154f456f32e0f9292d71b57b3255cde416b677faac2Chia-I Wu        if (parentDied) {
1551db73f66624e7d151710483dd58e03eed672f064Robert Carr            return NAME_NOT_FOUND;
1561db73f66624e7d151710483dd58e03eed672f064Robert Carr        }
1571db73f66624e7d151710483dd58e03eed672f064Robert Carr    }
1581f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr
159db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    /*
160db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     * createSurface must be called from the GL thread so that it can
161db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     * have access to the GL context.
162db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian     */
163921e6ac4b7610a178285898d191eb0e3afe906c0Mathias Agopian    class MessageCreateLayer : public MessageBase {
164db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        SurfaceFlinger* flinger;
165db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        Client* client;
1664d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        sp<IBinder>* handle;
1674d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        sp<IGraphicBufferProducer>* gbp;
1684d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        status_t result;
169db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        const String8& name;
170db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        uint32_t w, h;
171db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        PixelFormat format;
172db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        uint32_t flags;
1731f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr        sp<Layer>* parent;
174479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk        uint32_t windowType;
175479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk        uint32_t ownerUid;
176db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    public:
177921e6ac4b7610a178285898d191eb0e3afe906c0Mathias Agopian        MessageCreateLayer(SurfaceFlinger* flinger,
178db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian                const String8& name, Client* client,
1794d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
180479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk                sp<IBinder>* handle, uint32_t windowType, uint32_t ownerUid,
1811f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr                sp<IGraphicBufferProducer>* gbp,
1821f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr                sp<Layer>* parent)
1834d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian            : flinger(flinger), client(client),
18453390e1e8c33ebee5bb8100e846f5263ba05ff73Pablo Ceballos              handle(handle), gbp(gbp), result(NO_ERROR),
1851f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9Robert Carr              name(name), w(w), h(h), format(format), flags(flags),
186479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk              parent(parent), windowType(windowType), ownerUid(ownerUid) {
187db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        }
1884d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian        status_t getResult() const { return result; }
189db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        virtual bool handler() {
1904d9b822e2c18142e55fe2611aa6cd7dc7d4a62c6Mathias Agopian            result = flinger->createLayer(name, client, w, h, format, flags,
191479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk                    windowType, ownerUid, handle, gbp, parent);
192db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian            return true;
193db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian        }
194db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    };
195db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
196921e6ac4b7610a178285898d191eb0e3afe906c0Mathias Agopian    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
197479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk            name, this, w, h, format, flags, handle,
198479c60c85c40fd3536b0c88036e838dc1a4c56a0Albert Chaulk            windowType, ownerUid, gbp, &parent);
199db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian    mFlinger->postMessageSync(msg);
200921e6ac4b7610a178285898d191eb0e3afe906c0Mathias Agopian    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
201db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
202ac9fa427d4a86745e60a5f7fd8e3ea340c4db907Mathias Agopian
203ac9fa427d4a86745e60a5f7fd8e3ea340c4db907Mathias Agopianstatus_t Client::destroySurface(const sp<IBinder>& handle) {
204ac9fa427d4a86745e60a5f7fd8e3ea340c4db907Mathias Agopian    return mFlinger->onLayerRemoved(this, handle);
205db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}
206db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian
207d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslavstatus_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
208d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    sp<Layer> layer = getLayerUser(handle);
209d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    if (layer == NULL) {
210d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav        return NAME_NOT_FOUND;
211d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    }
212d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    layer->clearFrameStats();
213d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    return NO_ERROR;
214d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav}
215d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav
216d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslavstatus_t Client::getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
217d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    sp<Layer> layer = getLayerUser(handle);
218d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    if (layer == NULL) {
219d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav        return NAME_NOT_FOUND;
220d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    }
221d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    layer->getFrameStats(outStats);
222d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    return NO_ERROR;
223d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav}
224d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav
225db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian// ---------------------------------------------------------------------------
226db403e8ff0d7727015e1a5009bab20eb7ec205bcMathias Agopian}; // namespace android
227