11a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis/* 21a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * Copyright (C) 2010 The Android Open Source Project 31a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * 41a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 51a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * you may not use this file except in compliance with the License. 61a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * You may obtain a copy of the License at 71a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * 81a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 91a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * 101a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * Unless required by applicable law or agreed to in writing, software 111a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 121a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * See the License for the specific language governing permissions and 141a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis * limitations under the License. 151a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis */ 161a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 171a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#ifndef ANDROID_GUI_CONSUMERBASE_H 181a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#define ANDROID_GUI_CONSUMERBASE_H 191a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 201a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#include <gui/BufferQueue.h> 211a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 221a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#include <ui/GraphicBuffer.h> 231a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 241a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#include <utils/String8.h> 251a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#include <utils/Vector.h> 261a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#include <utils/threads.h> 271a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 281a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennisnamespace android { 291a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis// ---------------------------------------------------------------------------- 301a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 311a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennisclass String8; 321a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 331a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis// ConsumerBase is a base class for BufferQueue consumer end-points. It 341a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis// handles common tasks like management of the connection to the BufferQueue 351a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis// and the buffer pool. 361a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennisclass ConsumerBase : public virtual RefBase, 371a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis protected BufferQueue::ConsumerListener { 381a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennispublic: 391a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis struct FrameAvailableListener : public virtual RefBase { 401a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // onFrameAvailable() is called each time an additional frame becomes 411a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // available for consumption. This means that frames that are queued 421a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // while in asynchronous mode only trigger the callback if no previous 431a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // frames are pending. Frames queued while in synchronous mode always 441a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // trigger the callback. 451a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // 461a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // This is called without any lock held and can be called concurrently 471a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // by multiple threads. 481a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void onFrameAvailable() = 0; 491a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis }; 501a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 511a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual ~ConsumerBase(); 521a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 531a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // abandon frees all the buffers and puts the ConsumerBase into the 541a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // 'abandoned' state. Once put in this state the ConsumerBase can never 551a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // leave it. When in the 'abandoned' state, all methods of the 561a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // ISurfaceTexture interface will fail with the NO_INIT error. 571a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // 581a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // Note that while calling this method causes all the buffers to be freed 591a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // from the perspective of the the ConsumerBase, if there are additional 601a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // references on the buffers (e.g. if a buffer is referenced by a client 611a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // or by OpenGL ES as a texture) then those buffer will remain allocated. 621a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void abandon(); 631a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 641a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // set the name of the ConsumerBase that will be used to identify it in 651a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // log messages. 661a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void setName(const String8& name); 671a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 681a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // getBufferQueue returns the BufferQueue object to which this 691a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // ConsumerBase is connected. 701a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis sp<BufferQueue> getBufferQueue() const; 711a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 721a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // dump writes the current state to a string. These methods should NOT be 731a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // overridden by child classes. Instead they should override the 741a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // dumpLocked method, which is called by these methods after locking the 751a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mutex. 761a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void dump(String8& result) const; 771a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; 781a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 791a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // setFrameAvailableListener sets the listener object that will be notified 801a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // when a new frame becomes available. 811a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); 821a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 831a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennisprivate: 841a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis ConsumerBase(const ConsumerBase&); 851a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis void operator=(const ConsumerBase&); 861a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 871a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennisprotected: 881a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 899fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // ConsumerBase constructs a new ConsumerBase object to consume image 909fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // buffers from the given BufferQueue. 911a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis ConsumerBase(const sp<BufferQueue> &bufferQueue); 921a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 931a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // Implementation of the BufferQueue::ConsumerListener interface. These 941a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // calls are used to notify the ConsumerBase of asynchronous events in the 959fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // BufferQueue. These methods should not need to be overridden by derived 969fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // classes, but if they are overridden the ConsumerBase implementation 979fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // must be called from the derived class. 981a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void onFrameAvailable(); 991a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void onBuffersReleased(); 1001a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1011a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // freeBufferLocked frees up the given buffer slot. If the slot has been 1021a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // initialized this will release the reference to the GraphicBuffer in that 1039fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // slot. Otherwise it has no effect. 1049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1059fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // Derived classes should override this method to clean up any state they 1069fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // keep per slot. If it is overridden, the derived class's implementation 1079fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // must call ConsumerBase::freeBufferLocked. 1081a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // 1091a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // This method must be called with mMutex locked. 1101a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void freeBufferLocked(int slotIndex); 1111a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1121a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // abandonLocked puts the BufferQueue into the abandoned state, causing 1131a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // all future operations on it to fail. This method rather than the public 1141a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // abandon method should be overridden by child classes to add abandon- 1151a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // time behavior. 1161a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // 1179fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // Derived classes should override this method to clean up any object 1189fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // state they keep (as opposed to per-slot state). If it is overridden, 1199fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // the derived class's implementation must call ConsumerBase::abandonLocked. 1209fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1211a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // This method must be called with mMutex locked. 1221a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void abandonLocked(); 1231a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1249fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // dumpLocked dumps the current state of the ConsumerBase object to the 1259fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // result string. Each line is prefixed with the string pointed to by the 1269fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // prefix argument. The buffer argument points to a buffer that may be 1279fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // used for intermediate formatting data, and the size of that buffer is 1289fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // indicated by the size argument. 1299fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1309fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // Derived classes should override this method to dump their internal 1319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // state. If this method is overridden the derived class's implementation 1329fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // should call ConsumerBase::dumpLocked. 1339fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1349fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // This method must be called with mMutex locked. 1351a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual void dumpLocked(String8& result, const char* prefix, char* buffer, 1369fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis size_t size) const; 1371a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1381a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // acquireBufferLocked fetches the next buffer from the BufferQueue and 1391a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // updates the buffer slot for the buffer returned. 1409fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1419fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // Derived classes should override this method to perform any 1429fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // initialization that must take place the first time a buffer is assigned 1439fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // to a slot. If it is overridden the derived class's implementation must 1449fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // call ConsumerBase::acquireBufferLocked. 1451a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item); 1461a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1471a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // releaseBufferLocked relinquishes control over a buffer, returning that 1481a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // control to the BufferQueue. 1499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 1509fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // Derived classes should override this method to perform any cleanup that 1519fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // must take place when a buffer is released back to the BufferQueue. If 1529fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // it is overridden the derived class's implementation must call 1539504eb915c9628e130f45019bdefda0168089886Jesse Hall // ConsumerBase::releaseBufferLocked. 1541a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis virtual status_t releaseBufferLocked(int buf, EGLDisplay display, 155b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis EGLSyncKHR eglFence); 156b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis 1579504eb915c9628e130f45019bdefda0168089886Jesse Hall // addReleaseFence* adds the sync points associated with a fence to the set 158b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis // of sync points that must be reached before the buffer in the given slot 159b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis // may be used after the slot has been released. This should be called by 160b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis // derived classes each time some asynchronous work is kicked off that 161b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis // references the buffer. 162b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis status_t addReleaseFence(int slot, const sp<Fence>& fence); 1639504eb915c9628e130f45019bdefda0168089886Jesse Hall status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence); 1641a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1651a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // Slot contains the information and object references that 1661a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // ConsumerBase maintains about a BufferQueue buffer slot. 1671a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis struct Slot { 1681a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mGraphicBuffer is the Gralloc buffer store in the slot or NULL if 1691a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // no Gralloc buffer is in the slot. 1701a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis sp<GraphicBuffer> mGraphicBuffer; 1711a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1721a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mFence is a fence which will signal when the buffer associated with 1731a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // this buffer slot is no longer being used by the consumer and can be 1741a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // overwritten. The buffer can be dequeued before the fence signals; 1751a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // the producer is responsible for delaying writes until it signals. 1761a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis sp<Fence> mFence; 1771a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis }; 1781a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1791a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mSlots stores the buffers that have been allocated by the BufferQueue 1801a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // for each buffer slot. It is initialized to null pointers, and gets 1811a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // filled in with the result of BufferQueue::acquire when the 1821a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // client dequeues a buffer from a 1831a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // slot that has not yet been used. The buffer allocated to a slot will also 1841a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // be replaced if the requested buffer usage or geometry differs from that 1851a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // of the buffer allocated to a slot. 1861a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis Slot mSlots[BufferQueue::NUM_BUFFER_SLOTS]; 1871a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1881a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mAbandoned indicates that the BufferQueue will no longer be used to 1891a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // consume images buffers pushed to it using the ISurfaceTexture 1901a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // interface. It is initialized to false, and set to true in the abandon 1911a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // method. A BufferQueue that has been abandoned will return the NO_INIT 1921a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // error from all IConsumerBase methods capable of returning an error. 1931a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis bool mAbandoned; 1941a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1951a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mName is a string used to identify the ConsumerBase in log messages. 1961a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // It can be set by the setName method. 1971a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis String8 mName; 1981a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 1991a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mFrameAvailableListener is the listener object that will be called when a 2001a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // new frame becomes available. If it is not NULL it will be called from 2011a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // queueBuffer. 2021a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis sp<FrameAvailableListener> mFrameAvailableListener; 2031a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 2041a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // The ConsumerBase has-a BufferQueue and is responsible for creating this object 2051a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // if none is supplied 2061a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis sp<BufferQueue> mBufferQueue; 2071a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 2081a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // mMutex is the mutex used to prevent concurrent access to the member 2091a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis // variables of ConsumerBase objects. It must be locked whenever the 2109fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // member variables are accessed or when any of the *Locked methods are 2119fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // called. 2129fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // 2139fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis // This mutex is intended to be locked by derived classes. 2141a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis mutable Mutex mMutex; 2151a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis}; 2161a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 2171a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis// ---------------------------------------------------------------------------- 2181a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis}; // namespace android 2191a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis 2201a4d883dcc1725892bfb5c28dec255a233186524Jamie Gennis#endif // ANDROID_GUI_CONSUMERBASE_H 221