diff options
| -rw-r--r-- | cmds/keystore/keystore.cpp | 2 | ||||
| -rwxr-xr-x | cmds/keystore/test-keystore | 9 | ||||
| -rw-r--r-- | include/binder/IMemory.h | 1 | ||||
| -rw-r--r-- | include/binder/MemoryHeapBase.h | 14 | ||||
| -rw-r--r-- | include/binder/Permission.h | 68 | ||||
| -rw-r--r-- | include/binder/PermissionCache.h | 79 | ||||
| -rw-r--r-- | include/gui/SurfaceTexture.h | 23 | ||||
| -rw-r--r-- | include/pim/EventRecurrence.h | 82 | ||||
| -rw-r--r-- | include/surfaceflinger/Surface.h | 2 | ||||
| -rw-r--r-- | libs/binder/Android.mk | 2 | ||||
| -rw-r--r-- | libs/binder/IMemory.cpp | 53 | ||||
| -rw-r--r-- | libs/binder/MemoryHeapBase.cpp | 15 | ||||
| -rw-r--r-- | libs/binder/Permission.cpp | 88 | ||||
| -rw-r--r-- | libs/binder/PermissionCache.cpp | 113 | ||||
| -rw-r--r-- | libs/gui/Surface.cpp | 4 | ||||
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 53 | ||||
| -rw-r--r-- | libs/gui/tests/SurfaceTexture_test.cpp | 176 | ||||
| -rw-r--r-- | libs/ui/Android.mk | 1 | ||||
| -rw-r--r-- | libs/ui/EventRecurrence.cpp | 484 | ||||
| -rw-r--r-- | libs/utils/BackupData.cpp | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 19 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 26 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 17 |
23 files changed, 502 insertions, 832 deletions
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp index bbd1a1bfd6..1c1f37a34c 100644 --- a/cmds/keystore/keystore.cpp +++ b/cmds/keystore/keystore.cpp @@ -708,7 +708,7 @@ static struct user { uid_t euid; uint32_t perms; } users[] = { - {AID_SYSTEM, ~0, ~GET}, + {AID_SYSTEM, ~0, ~0}, {AID_VPN, AID_SYSTEM, GET}, {AID_WIFI, AID_SYSTEM, GET}, {AID_ROOT, AID_SYSTEM, GET}, diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore index 82b276fe76..3be51b3e7b 100755 --- a/cmds/keystore/test-keystore +++ b/cmds/keystore/test-keystore @@ -116,11 +116,12 @@ function test_basic() { expect "1 No error" expect "baz" - log "system does not have access to read any keys" + log "get baz" keystore system g baz - expect "6 Permission denied" - - log "however, root can read system user keys (as can wifi or vpn users)" + expect "1 No error" + expect "quux" + + log "root can read system user keys (as can wifi or vpn users)" keystore root g baz expect "1 No error" expect "quux" diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h index 74d2cc7816..2d0db001c6 100644 --- a/include/binder/IMemory.h +++ b/include/binder/IMemory.h @@ -43,6 +43,7 @@ public: virtual void* getBase() const = 0; virtual size_t getSize() const = 0; virtual uint32_t getFlags() const = 0; + virtual uint32_t getOffset() const = 0; // these are there just for backward source compatibility int32_t heapID() const { return getHeapID(); } diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h index 2f2e31b380..bbbda9c164 100644 --- a/include/binder/MemoryHeapBase.h +++ b/include/binder/MemoryHeapBase.h @@ -27,7 +27,7 @@ namespace android { // --------------------------------------------------------------------------- -class MemoryHeapBase : public virtual BnMemoryHeap +class MemoryHeapBase : public virtual BnMemoryHeap { public: enum { @@ -38,12 +38,12 @@ public: NO_CACHING = 0x00000200 }; - /* + /* * maps the memory referenced by fd. but DOESN'T take ownership * of the filedescriptor (it makes a copy with dup() */ MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0); - + /* * maps memory from the given device */ @@ -61,9 +61,10 @@ public: virtual void* getBase() const; virtual size_t getSize() const; virtual uint32_t getFlags() const; + virtual uint32_t getOffset() const; const char* getDevice() const; - + /* this closes this heap -- use carefully */ void dispose(); @@ -74,12 +75,12 @@ public: mDevice = device; return mDevice ? NO_ERROR : ALREADY_EXISTS; } - + protected: MemoryHeapBase(); // init() takes ownership of fd status_t init(int fd, void *base, int size, - int flags = 0, const char* device = NULL); + int flags = 0, const char* device = NULL); private: status_t mapfd(int fd, size_t size, uint32_t offset = 0); @@ -90,6 +91,7 @@ private: uint32_t mFlags; const char* mDevice; bool mNeedUnmap; + uint32_t mOffset; }; // --------------------------------------------------------------------------- diff --git a/include/binder/Permission.h b/include/binder/Permission.h deleted file mode 100644 index 9542d50663..0000000000 --- a/include/binder/Permission.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BINDER_PERMISSION_H -#define BINDER_PERMISSION_H - -#include <stdint.h> -#include <unistd.h> - -#include <utils/SortedVector.h> -#include <utils/String16.h> -#include <utils/threads.h> - -namespace android { -// --------------------------------------------------------------------------- - -/* - * Permission caches the result of the permission check for the given - * permission name and the provided uid/pid. It also handles a few - * known cases efficiently (caller is in the same process or is root). - * The package manager does something similar but lives in dalvik world - * and is therefore extremely slow to access. - */ - -class Permission -{ -public: - Permission(char const* name); - Permission(const String16& name); - Permission(const Permission& rhs); - virtual ~Permission(); - - bool operator < (const Permission& rhs) const; - - // checks the current binder call's caller has access to this permission - bool checkCalling() const; - - // checks the specified pid/uid has access to this permission - bool check(pid_t pid, uid_t uid) const; - -protected: - virtual bool doCheckPermission(pid_t pid, uid_t uid) const; - -private: - Permission& operator = (const Permission& rhs) const; - const String16 mPermissionName; - mutable SortedVector<uid_t> mGranted; - const pid_t mPid; - mutable Mutex mLock; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif /* BINDER_PERMISSION_H */ diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h new file mode 100644 index 0000000000..1171d48bad --- /dev/null +++ b/include/binder/PermissionCache.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BINDER_PERMISSION_H +#define BINDER_PERMISSION_H + +#include <stdint.h> +#include <unistd.h> + +#include <utils/String16.h> +#include <utils/Singleton.h> + +namespace android { +// --------------------------------------------------------------------------- + +/* + * PermissionCache caches permission checks for a given uid. + * + * Currently the cache is not updated when there is a permission change, + * for instance when an application is uninstalled. + * + * IMPORTANT: for the reason stated above, only system permissions are safe + * to cache. This restriction may be lifted at a later time. + * + */ + +class PermissionCache : Singleton<PermissionCache> { + struct Entry { + String16 name; + uid_t uid; + bool granted; + inline bool operator < (const Entry& e) const { + return (uid == e.uid) ? (name < e.name) : (uid < e.uid); + } + }; + mutable Mutex mLock; + // we pool all the permission names we see, as many permissions checks + // will have identical names + SortedVector< String16 > mPermissionNamesPool; + // this is our cache per say. it stores pooled names. + SortedVector< Entry > mCache; + + // free the whole cache, but keep the permission name pool + void purge(); + + status_t check(bool* granted, + const String16& permission, uid_t uid) const; + + void cache(const String16& permission, uid_t uid, bool granted); + +public: + PermissionCache(); + + static bool checkCallingPermission(const String16& permission); + + static bool checkCallingPermission(const String16& permission, + int32_t* outPid, int32_t* outUid); + + static bool checkPermission(const String16& permission, + pid_t pid, uid_t uid); +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif /* BINDER_PERMISSION_H */ diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 9294df6743..c82fb9b77e 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -46,17 +46,20 @@ public: enum { NUM_BUFFER_SLOTS = 32 }; struct FrameAvailableListener : public virtual RefBase { - // onFrameAvailable() is called from queueBuffer() is the FIFO is - // empty. You can use SurfaceTexture::getQueuedCount() to - // figure out if there are more frames waiting. - // This is called without any lock held can be called concurrently by - // multiple threads. + // onFrameAvailable() is called from queueBuffer() each time an + // additional frame becomes available for consumption. This means that + // frames that are queued while in asynchronous mode only trigger the + // callback if no previous frames are pending. Frames queued while in + // synchronous mode always trigger the callback. + // + // This is called without any lock held and can be called concurrently + // by multiple threads. virtual void onFrameAvailable() = 0; }; // tex indicates the name OpenGL texture to which images are to be streamed. // This texture name cannot be changed once the SurfaceTexture is created. - SurfaceTexture(GLuint tex); + SurfaceTexture(GLuint tex, bool allowSynchronousMode = true); virtual ~SurfaceTexture(); @@ -101,11 +104,6 @@ public: // target texture belongs is bound to the calling thread. status_t updateTexImage(); - // getqueuedCount returns the number of queued frames waiting in the - // FIFO. In asynchronous mode, this always returns 0 or 1 since - // frames are not accumulating in the FIFO. - size_t getQueuedCount() const; - // setBufferCountServer set the buffer count. If the client has requested // a buffer count using setBufferCount, the server-buffer count will // take effect once the client sets the count back to zero. @@ -361,6 +359,9 @@ private: // mSynchronousMode whether we're in synchronous mode or not bool mSynchronousMode; + // mAllowSynchronousMode whether we allow synchronous mode or not + const bool mAllowSynchronousMode; + // mDequeueCondition condition used for dequeueBuffer in synchronous mode mutable Condition mDequeueCondition; diff --git a/include/pim/EventRecurrence.h b/include/pim/EventRecurrence.h deleted file mode 100644 index 1ceda41e27..0000000000 --- a/include/pim/EventRecurrence.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -#ifndef _PIM_EVENT_RECURRENCE_H -#define _PIM_EVENT_RECURRENCE_H - -#include <utils/String16.h> - -namespace android { - -struct EventRecurrence -{ -public: - EventRecurrence(); - ~EventRecurrence(); - - status_t parse(const String16&); - - - enum freq_t { - SECONDLY = 1, - MINUTELY = 2, - HOURLY = 3, - DAILY = 4, - WEEKLY = 5, - MONTHLY = 6, - YEARLY = 7 - }; - - enum { - SU = 0x00010000, - MO = 0x00020000, - TU = 0x00040000, - WE = 0x00080000, - TH = 0x00100000, - FR = 0x00200000, - SA = 0x00400000 - }; - - freq_t freq; - String16 until; - int count; - int interval; - int* bysecond; - int bysecondCount; - int* byminute; - int byminuteCount; - int* byhour; - int byhourCount; - int* byday; - int* bydayNum; - int bydayCount; - int* bymonthday; - int bymonthdayCount; - int* byyearday; - int byyeardayCount; - int* byweekno; - int byweeknoCount; - int* bymonth; - int bymonthCount; - int* bysetpos; - int bysetposCount; - int wkst; -}; - -}; // namespace android - -#endif // _PIM_EVENT_RECURRENCE_H diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 8845dc9e1c..dc2a845620 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -40,6 +40,7 @@ namespace android { class GraphicBuffer; class GraphicBufferMapper; class IOMX; +class ISurfaceTexture; class Rect; class Surface; class SurfaceComposerClient; @@ -154,6 +155,7 @@ public: bool isValid(); uint32_t getFlags() const { return mFlags; } uint32_t getIdentity() const { return mIdentity; } + sp<ISurfaceTexture> getSurfaceTexture(); // the lock/unlock APIs must be used from the same thread status_t lock(SurfaceInfo* info, bool blocking = true); diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index f9d9f25922..3a12e96c04 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -27,7 +27,7 @@ sources := \ MemoryHeapBase.cpp \ MemoryHeapPmem.cpp \ Parcel.cpp \ - Permission.cpp \ + PermissionCache.cpp \ ProcessState.cpp \ Static.cpp diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp index bc8c412fb0..1ace8f8291 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -42,11 +42,11 @@ class HeapCache : public IBinder::DeathRecipient public: HeapCache(); virtual ~HeapCache(); - + virtual void binderDied(const wp<IBinder>& who); - sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); - void free_heap(const sp<IBinder>& binder); + sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); + void free_heap(const sp<IBinder>& binder); sp<IMemoryHeap> get_heap(const sp<IBinder>& binder); void dump_heaps(); @@ -57,7 +57,7 @@ private: int32_t count; }; - void free_heap(const wp<IBinder>& binder); + void free_heap(const wp<IBinder>& binder); Mutex mHeapCacheLock; KeyedVector< wp<IBinder>, heap_info_t > mHeapCache; @@ -81,11 +81,12 @@ public: virtual void* getBase() const; virtual size_t getSize() const; virtual uint32_t getFlags() const; + virtual uint32_t getOffset() const; private: friend class IMemory; friend class HeapCache; - + // for debugging in this module static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) { return gHeapCache->find_heap(binder); @@ -97,7 +98,7 @@ private: return gHeapCache->get_heap(binder); } static inline void dump_heaps() { - gHeapCache->dump_heaps(); + gHeapCache->dump_heaps(); } void assertMapped() const; @@ -107,6 +108,7 @@ private: mutable void* mBase; mutable size_t mSize; mutable uint32_t mFlags; + mutable uint32_t mOffset; mutable bool mRealHeap; mutable Mutex mLock; }; @@ -123,7 +125,7 @@ public: BpMemory(const sp<IBinder>& impl); virtual ~BpMemory(); virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const; - + private: mutable sp<IMemoryHeap> mHeap; mutable ssize_t mOffset; @@ -203,7 +205,7 @@ IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory"); BnMemory::BnMemory() { } -BnMemory::~BnMemory() { +BnMemory::~BnMemory() { } status_t BnMemory::onTransact( @@ -229,7 +231,7 @@ status_t BnMemory::onTransact( BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl) : BpInterface<IMemoryHeap>(impl), - mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false) + mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false) { } @@ -242,7 +244,7 @@ BpMemoryHeap::~BpMemoryHeap() { sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder(); if (VERBOSE) { - LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d", + LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d", binder.get(), this, mSize, mHeapId); CallStack stack; stack.update(); @@ -270,6 +272,7 @@ void BpMemoryHeap::assertMapped() const if (mHeapId == -1) { mBase = heap->mBase; mSize = heap->mSize; + mOffset = heap->mOffset; android_atomic_write( dup( heap->mHeapId ), &mHeapId ); } } else { @@ -286,13 +289,14 @@ void BpMemoryHeap::assertReallyMapped() const // remote call without mLock held, worse case scenario, we end up // calling transact() from multiple threads, but that's not a problem, // only mmap below must be in the critical section. - + Parcel data, reply; data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor()); status_t err = remote()->transact(HEAP_ID, data, &reply); int parcel_fd = reply.readFileDescriptor(); ssize_t size = reply.readInt32(); uint32_t flags = reply.readInt32(); + uint32_t offset = reply.readInt32(); LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)", asBinder().get(), parcel_fd, size, err, strerror(-err)); @@ -309,7 +313,7 @@ void BpMemoryHeap::assertReallyMapped() const Mutex::Autolock _l(mLock); if (mHeapId == -1) { mRealHeap = true; - mBase = mmap(0, size, access, MAP_SHARED, fd, 0); + mBase = mmap(0, size, access, MAP_SHARED, fd, offset); if (mBase == MAP_FAILED) { LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)", asBinder().get(), size, fd, strerror(errno)); @@ -317,6 +321,7 @@ void BpMemoryHeap::assertReallyMapped() const } else { mSize = size; mFlags = flags; + mOffset = offset; android_atomic_write(fd, &mHeapId); } } @@ -343,14 +348,19 @@ uint32_t BpMemoryHeap::getFlags() const { return mFlags; } +uint32_t BpMemoryHeap::getOffset() const { + assertMapped(); + return mOffset; +} + // --------------------------------------------------------------------------- IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap"); -BnMemoryHeap::BnMemoryHeap() { +BnMemoryHeap::BnMemoryHeap() { } -BnMemoryHeap::~BnMemoryHeap() { +BnMemoryHeap::~BnMemoryHeap() { } status_t BnMemoryHeap::onTransact( @@ -362,6 +372,7 @@ status_t BnMemoryHeap::onTransact( reply->writeFileDescriptor(getHeapID()); reply->writeInt32(getSize()); reply->writeInt32(getFlags()); + reply->writeInt32(getOffset()); return NO_ERROR; } break; default: @@ -383,17 +394,17 @@ HeapCache::~HeapCache() void HeapCache::binderDied(const wp<IBinder>& binder) { //LOGD("binderDied binder=%p", binder.unsafe_get()); - free_heap(binder); + free_heap(binder); } -sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) +sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) { Mutex::Autolock _l(mHeapCacheLock); ssize_t i = mHeapCache.indexOfKey(binder); if (i>=0) { heap_info_t& info = mHeapCache.editValueAt(i); LOGD_IF(VERBOSE, - "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", + "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", binder.get(), info.heap.get(), static_cast<BpMemoryHeap*>(info.heap.get())->mSize, static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, @@ -415,7 +426,7 @@ void HeapCache::free_heap(const sp<IBinder>& binder) { free_heap( wp<IBinder>(binder) ); } -void HeapCache::free_heap(const wp<IBinder>& binder) +void HeapCache::free_heap(const wp<IBinder>& binder) { sp<IMemoryHeap> rel; { @@ -426,7 +437,7 @@ void HeapCache::free_heap(const wp<IBinder>& binder) int32_t c = android_atomic_dec(&info.count); if (c == 1) { LOGD_IF(VERBOSE, - "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", + "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", binder.unsafe_get(), info.heap.get(), static_cast<BpMemoryHeap*>(info.heap.get())->mSize, static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId, @@ -450,7 +461,7 @@ sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder) return realHeap; } -void HeapCache::dump_heaps() +void HeapCache::dump_heaps() { Mutex::Autolock _l(mHeapCacheLock); int c = mHeapCache.size(); @@ -459,7 +470,7 @@ void HeapCache::dump_heaps() BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get())); LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)", mHeapCache.keyAt(i).unsafe_get(), - info.heap.get(), info.count, + info.heap.get(), info.count, h->mHeapId, h->mBase, h->mSize); } } diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp index 9f501e277c..bf4a73f389 100644 --- a/libs/binder/MemoryHeapBase.cpp +++ b/libs/binder/MemoryHeapBase.cpp @@ -40,15 +40,15 @@ namespace android { // --------------------------------------------------------------------------- -MemoryHeapBase::MemoryHeapBase() +MemoryHeapBase::MemoryHeapBase() : mFD(-1), mSize(0), mBase(MAP_FAILED), - mDevice(NULL), mNeedUnmap(false) + mDevice(NULL), mNeedUnmap(false), mOffset(0) { } MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) + mDevice(0), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); @@ -65,7 +65,7 @@ MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) + mDevice(0), mNeedUnmap(false), mOffset(0) { int open_flags = O_RDWR; if (flags & NO_CACHING) @@ -84,7 +84,7 @@ MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), - mDevice(0), mNeedUnmap(false) + mDevice(0), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); @@ -141,6 +141,7 @@ status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset) } mFD = fd; mSize = size; + mOffset = offset; return NO_ERROR; } @@ -183,5 +184,9 @@ const char* MemoryHeapBase::getDevice() const { return mDevice; } +uint32_t MemoryHeapBase::getOffset() const { + return mOffset; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp deleted file mode 100644 index fd8fe6983d..0000000000 --- a/libs/binder/Permission.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <utils/Log.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> -#include <binder/Permission.h> - -namespace android { -// --------------------------------------------------------------------------- - -Permission::Permission(char const* name) - : mPermissionName(name), mPid(getpid()) -{ -} - -Permission::Permission(const String16& name) - : mPermissionName(name), mPid(getpid()) -{ -} - -Permission::Permission(const Permission& rhs) - : mPermissionName(rhs.mPermissionName), - mGranted(rhs.mGranted), - mPid(rhs.mPid) -{ -} - -Permission::~Permission() -{ -} - -bool Permission::operator < (const Permission& rhs) const -{ - return mPermissionName < rhs.mPermissionName; -} - -bool Permission::checkCalling() const -{ - IPCThreadState* ipcState = IPCThreadState::self(); - pid_t pid = ipcState->getCallingPid(); - uid_t uid = ipcState->getCallingUid(); - return doCheckPermission(pid, uid); -} - -bool Permission::check(pid_t pid, uid_t uid) const -{ - return doCheckPermission(pid, uid); -} - -bool Permission::doCheckPermission(pid_t pid, uid_t uid) const -{ - if ((uid == 0) || (pid == mPid)) { - // root and ourselves is always okay - return true; - } else { - // see if we already granted this permission for this uid - Mutex::Autolock _l(mLock); - if (mGranted.indexOf(uid) >= 0) - return true; - } - - bool granted = checkPermission(mPermissionName, pid, uid); - if (granted) { - Mutex::Autolock _l(mLock); - // no need to check again, the old item will be replaced if it is - // already there. - mGranted.add(uid); - } - return granted; -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp new file mode 100644 index 0000000000..7278187b08 --- /dev/null +++ b/libs/binder/PermissionCache.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "PermissionCache" + +#include <stdint.h> +#include <utils/Log.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/PermissionCache.h> +#include <utils/String8.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ; + +// ---------------------------------------------------------------------------- + +PermissionCache::PermissionCache() { +} + +status_t PermissionCache::check(bool* granted, + const String16& permission, uid_t uid) const { + Mutex::Autolock _l(mLock); + Entry e; + e.name = permission; + e.uid = uid; + ssize_t index = mCache.indexOf(e); + if (index >= 0) { + *granted = mCache.itemAt(index).granted; + return NO_ERROR; + } + return NAME_NOT_FOUND; +} + +void PermissionCache::cache(const String16& permission, + uid_t uid, bool granted) { + Mutex::Autolock _l(mLock); + Entry e; + ssize_t index = mPermissionNamesPool.indexOf(permission); + if (index > 0) { + e.name = mPermissionNamesPool.itemAt(index); + } else { + mPermissionNamesPool.add(permission); + e.name = permission; + } + // note, we don't need to store the pid, which is not actually used in + // permission checks + e.uid = uid; + e.granted = granted; + index = mCache.indexOf(e); + if (index < 0) { + mCache.add(e); + } +} + +void PermissionCache::purge() { + Mutex::Autolock _l(mLock); + mCache.clear(); +} + +bool PermissionCache::checkCallingPermission(const String16& permission) { + return PermissionCache::checkCallingPermission(permission, NULL, NULL); +} + +bool PermissionCache::checkCallingPermission( + const String16& permission, int32_t* outPid, int32_t* outUid) { + IPCThreadState* ipcState = IPCThreadState::self(); + pid_t pid = ipcState->getCallingPid(); + uid_t uid = ipcState->getCallingUid(); + if (outPid) *outPid = pid; + if (outUid) *outUid = uid; + return PermissionCache::checkPermission(permission, pid, uid); +} + +bool PermissionCache::checkPermission( + const String16& permission, pid_t pid, uid_t uid) { + if ((uid == 0) || (pid == getpid())) { + // root and ourselves is always okay + return true; + } + + PermissionCache& pc(PermissionCache::getInstance()); + bool granted = false; + if (pc.check(&granted, permission, uid) != NO_ERROR) { + nsecs_t t = -systemTime(); + granted = android::checkPermission(permission, pid, uid); + t += systemTime(); + LOGD("checking %s for uid=%d => %s (%d us)", + String8(permission).string(), uid, + granted?"granted":"denied", (int)ns2us(t)); + pc.cache(permission, uid, granted); + } + return granted; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 4d1d923a42..9185e1e993 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -421,6 +421,10 @@ status_t Surface::validate(bool inCancelBuffer) const return NO_ERROR; } +sp<ISurfaceTexture> Surface::getSurfaceTexture() { + return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL; +} + sp<IBinder> Surface::asBinder() const { return mSurface!=0 ? mSurface->asBinder() : 0; } diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 3cecdb401a..0925001965 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -78,7 +78,7 @@ static float mtxRot270[16] = { static void mtxMul(float out[16], const float a[16], const float b[16]); -SurfaceTexture::SurfaceTexture(GLuint tex) : +SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mDefaultWidth(1), mDefaultHeight(1), mPixelFormat(PIXEL_FORMAT_RGBA_8888), @@ -91,7 +91,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex) : mCurrentTimestamp(0), mNextTransform(0), mTexName(tex), - mSynchronousMode(false) { + mSynchronousMode(false), + mAllowSynchronousMode(allowSynchronousMode) { LOGV("SurfaceTexture::SurfaceTexture"); sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); @@ -371,6 +372,9 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { Mutex::Autolock lock(mMutex); status_t err = OK; + if (!mAllowSynchronousMode && enabled) + return err; + if (!enabled) { // going to asynchronous mode, drain the queue while (mSynchronousMode != enabled && !mQueue.isEmpty()) { @@ -413,17 +417,22 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { return -EINVAL; } - if (mQueue.empty()) { - listener = mFrameAvailableListener; - } - if (mSynchronousMode) { - // in synchronous mode we queue all buffers in a FIFO + // In synchronous mode we queue all buffers in a FIFO. mQueue.push_back(buf); + + // Synchronous mode always signals that an additional frame should + // be consumed. + listener = mFrameAvailableListener; } else { - // in asynchronous mode we only keep the most recent buffer + // In asynchronous mode we only keep the most recent buffer. if (mQueue.empty()) { mQueue.push_back(buf); + + // Asynchronous mode only signals that a frame should be + // consumed if no previous frame was pending. If a frame were + // pending then the consumer would have already been notified. + listener = mFrameAvailableListener; } else { Fifo::iterator front(mQueue.begin()); // buffer currently queued is freed @@ -479,24 +488,14 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); - Mutex::Autolock lock(mMutex); - int buf = mCurrentTexture; + // In asynchronous mode the list is guaranteed to be one buffer + // deep, while in synchronous mode we use the oldest buffer. if (!mQueue.empty()) { - // in asynchronous mode the list is guaranteed to be one buffer deep, - // while in synchronous mode we use the oldest buffer Fifo::iterator front(mQueue.begin()); - buf = *front; - mQueue.erase(front); - if (mQueue.isEmpty()) { - mDequeueCondition.signal(); - } - } + int buf = *front; - // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT, - // so this check will fail until a buffer gets queued. - if (mCurrentTexture != buf) { // Update the GL texture object. EGLImageKHR image = mSlots[buf].mEglImage; if (image == EGL_NO_IMAGE_KHR) { @@ -534,7 +533,7 @@ status_t SurfaceTexture::updateTexImage() { } if (mCurrentTexture != INVALID_BUFFER_SLOT) { - // the current buffer becomes FREE if it was still in the queued + // The current buffer becomes FREE if it was still in the queued // state. If it has already been given to the client // (synchronous mode), then it stays in DEQUEUED state. if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) @@ -549,17 +548,17 @@ status_t SurfaceTexture::updateTexImage() { mCurrentTransform = mSlots[buf].mTransform; mCurrentTimestamp = mSlots[buf].mTimestamp; computeCurrentTransformMatrix(); + + // Now that we've passed the point at which failures can happen, + // it's safe to remove the buffer from the front of the queue. + mQueue.erase(front); mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. glBindTexture(mCurrentTextureTarget, mTexName); } - return OK; -} -size_t SurfaceTexture::getQueuedCount() const { - Mutex::Autolock lock(mMutex); - return mQueue.size(); + return OK; } bool SurfaceTexture::isExternalFormat(uint32_t format) diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index f219639a06..dfa9211afa 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -419,6 +419,31 @@ protected: ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); } + class FrameWaiter : public SurfaceTexture::FrameAvailableListener { + public: + FrameWaiter(): + mPendingFrames(0) { + } + + void waitForFrame() { + Mutex::Autolock lock(mMutex); + while (mPendingFrames == 0) { + mCondition.wait(mMutex); + } + mPendingFrames--; + } + + virtual void onFrameAvailable() { + Mutex::Autolock lock(mMutex); + mPendingFrames++; + mCondition.signal(); + } + + int mPendingFrames; + Mutex mMutex; + Condition mCondition; + }; + sp<SurfaceTexture> mST; sp<SurfaceTextureClient> mSTC; sp<ANativeWindow> mANW; @@ -648,6 +673,157 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { } } +// This test is intended to catch synchronization bugs between the CPU-written +// and GPU-read buffers. +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { + enum { texWidth = 16 }; + enum { texHeight = 16 }; + enum { numFrames = 1024 }; + + ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); + ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2)); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_WRITE_OFTEN)); + + struct TestPixel { + int x; + int y; + }; + const TestPixel testPixels[] = { + { 4, 11 }, + { 12, 14 }, + { 7, 2 }, + }; + enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])}; + + class ProducerThread : public Thread { + public: + ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels): + mANW(anw), + mTestPixels(testPixels) { + } + + virtual ~ProducerThread() { + } + + virtual bool threadLoop() { + for (int i = 0; i < numFrames; i++) { + ANativeWindowBuffer* anb; + if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + return false; + } + if (anb == NULL) { + return false; + } + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()) + != NO_ERROR) { + return false; + } + + const int yuvTexOffsetY = 0; + int stride = buf->getStride(); + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * texHeight; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; + int yuvTexStrideU = yuvTexStrideV; + + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + + // Gray out all the test pixels first, so we're more likely to + // see a failure if GL is still texturing from the buffer we + // just dequeued. + for (int j = 0; j < numTestPixels; j++) { + int x = mTestPixels[j].x; + int y = mTestPixels[j].y; + uint8_t value = 128; + img[y*stride + x] = value; + } + + // Fill the buffer with gray. + for (int y = 0; y < texHeight; y++) { + for (int x = 0; x < texWidth; x++) { + img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128; + img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128; + img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128; + } + } + + // Set the test pixels to either white or black. + for (int j = 0; j < numTestPixels; j++) { + int x = mTestPixels[j].x; + int y = mTestPixels[j].y; + uint8_t value = 0; + if (j == (i % numTestPixels)) { + value = 255; + } + img[y*stride + x] = value; + } + + buf->unlock(); + if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()) + != NO_ERROR) { + return false; + } + } + return false; + } + + sp<ANativeWindow> mANW; + const TestPixel* mTestPixels; + }; + + sp<FrameWaiter> fw(new FrameWaiter); + mST->setFrameAvailableListener(fw); + + sp<Thread> pt(new ProducerThread(mANW, testPixels)); + pt->run(); + + glViewport(0, 0, texWidth, texHeight); + + glClearColor(0.2, 0.2, 0.2, 0.2); + glClear(GL_COLOR_BUFFER_BIT); + + // We wait for the first two frames up front so that the producer will be + // likely to dequeue the buffer that's currently being textured from. + fw->waitForFrame(); + fw->waitForFrame(); + + for (int i = 0; i < numFrames; i++) { + SCOPED_TRACE(String8::format("frame %d", i).string()); + + // We must wait for each frame to come in because if we ever do an + // updateTexImage call that doesn't consume a newly available buffer + // then the producer and consumer will get out of sync, which will cause + // a deadlock. + if (i > 1) { + fw->waitForFrame(); + } + mST->updateTexImage(); + drawTexture(); + + for (int j = 0; j < numTestPixels; j++) { + int x = testPixels[j].x; + int y = testPixels[j].y; + uint8_t value = 0; + if (j == (i % numTestPixels)) { + // We must y-invert the texture coords + EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255)); + } else { + // We must y-invert the texture coords + EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255)); + } + } + } + + pt->requestExitAndWait(); +} + // XXX: This test is disabled because there are currently no drivers that can // handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target. TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) { diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index f9990bb7d9..427bbba896 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -43,7 +43,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ $(commonSources) \ EGLUtils.cpp \ - EventRecurrence.cpp \ FramebufferNativeWindow.cpp \ GraphicBuffer.cpp \ GraphicBufferAllocator.cpp \ diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp deleted file mode 100644 index b436b506f3..0000000000 --- a/libs/ui/EventRecurrence.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - */ - -#include <pim/EventRecurrence.h> -#include <utils/String8.h> -#include <stdio.h> -#include <limits.h> - -namespace android { - -#define FAIL_HERE() do { \ - printf("Parsing failed at line %d\n", __LINE__); \ - return UNKNOWN_ERROR; \ - } while(0) - -EventRecurrence::EventRecurrence() - :freq((freq_t)0), - until(), - count(0), - interval(0), - bysecond(0), - bysecondCount(0), - byminute(0), - byminuteCount(0), - byhour(0), - byhourCount(0), - byday(0), - bydayNum(0), - bydayCount(0), - bymonthday(0), - bymonthdayCount(0), - byyearday(0), - byyeardayCount(0), - byweekno(0), - byweeknoCount(0), - bymonth(0), - bymonthCount(0), - bysetpos(0), - bysetposCount(0), - wkst(0) -{ -} - -EventRecurrence::~EventRecurrence() -{ - delete[] bysecond; - delete[] byminute; - delete[] byhour; - delete[] byday; - delete[] bydayNum; - delete[] byyearday; - delete[] bymonthday; - delete[] byweekno; - delete[] bymonth; - delete[] bysetpos; -} - -enum LHS { - NONE_LHS = 0, - FREQ, - UNTIL, - COUNT, - INTERVAL, - BYSECOND, - BYMINUTE, - BYHOUR, - BYDAY, - BYMONTHDAY, - BYYEARDAY, - BYWEEKNO, - BYMONTH, - BYSETPOS, - WKST -}; - -struct LHSProc -{ - const char16_t* text; - size_t textSize; - uint32_t value; -}; - -const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' }; -const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' }; -const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' }; -const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'}; -const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' }; -const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' }; -const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' }; -const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' }; -const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' }; -const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' }; -const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' }; -const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' }; -const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' }; -const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' }; - -#define SIZ(x) (sizeof(x)/sizeof(x[0])) - -const LHSProc LHSPROC[] = { - { FREQ_text, SIZ(FREQ_text), FREQ }, - { UNTIL_text, SIZ(UNTIL_text), UNTIL }, - { COUNT_text, SIZ(COUNT_text), COUNT }, - { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL }, - { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND }, - { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE }, - { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR }, - { BYDAY_text, SIZ(BYDAY_text), BYDAY }, - { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY }, - { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY }, - { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO }, - { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH }, - { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS }, - { WKST_text, SIZ(WKST_text), WKST }, - { NULL, 0, NONE_LHS }, -}; - -const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' }; -const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' }; -const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' }; -const char16_t DAILY_text[] = { 'D','A','I','L','Y' }; -const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' }; -const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' }; -const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' }; - -typedef LHSProc FreqProc; - -const FreqProc FREQPROC[] = { - { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY }, - { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY }, - { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY }, - { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY }, - { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY }, - { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY }, - { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY }, - { NULL, 0, NONE_LHS }, -}; - -const char16_t SU_text[] = { 'S','U' }; -const char16_t MO_text[] = { 'M','O' }; -const char16_t TU_text[] = { 'T','U' }; -const char16_t WE_text[] = { 'W','E' }; -const char16_t TH_text[] = { 'T','H' }; -const char16_t FR_text[] = { 'F','R' }; -const char16_t SA_text[] = { 'S','A' }; - -const FreqProc WEEKDAYPROC[] = { - { SU_text, SIZ(SU_text), EventRecurrence::SU }, - { MO_text, SIZ(MO_text), EventRecurrence::MO }, - { TU_text, SIZ(TU_text), EventRecurrence::TU }, - { WE_text, SIZ(WE_text), EventRecurrence::WE }, - { TH_text, SIZ(TH_text), EventRecurrence::TH }, - { FR_text, SIZ(FR_text), EventRecurrence::FR }, - { SA_text, SIZ(SA_text), EventRecurrence::SA }, - { NULL, 0, NONE_LHS }, -}; - -// returns the index into LHSPROC for the match or -1 if not found -inline static int -match_proc(const LHSProc* p, const char16_t* str, size_t len) -{ - int i = 0; - while (p->text != NULL) { - if (p->textSize == len) { - if (0 == memcmp(p->text, str, len*sizeof(char16_t))) { - return i; - } - } - p++; - i++; - } - return -1; -} - -// rangeMin and rangeMax are inclusive -static status_t -parse_int(const char16_t* str, size_t len, int* out, - int rangeMin, int rangeMax, bool zeroOK) -{ - char16_t c; - size_t i=0; - - if (len == 0) { - FAIL_HERE(); - } - bool negative = false; - c = str[0]; - if (c == '-' ) { - negative = true; - i++; - } - else if (c == '+') { - i++; - } - int n = 0; - for (; i<len; i++) { - c = str[i]; - if (c < '0' || c > '9') { - FAIL_HERE(); - } - int prev = n; - n *= 10; - // the spec doesn't address how big these numbers can be, - // so we're not going to worry about not being able to represent - // INT_MIN, and if we're going to wrap, we'll just clamp to - // INT_MAX instead - if (n < prev) { - n = INT_MAX; - } else { - n += c - '0'; - } - } - if (negative) { - n = -n; - } - if (n < rangeMin || n > rangeMax) { - FAIL_HERE(); - } - if (!zeroOK && n == 0) { - FAIL_HERE(); - } - *out = n; - return NO_ERROR; -} - -static status_t -parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut, - int rangeMin, int rangeMax, bool zeroOK, - status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int) -{ - status_t err; - - if (len == 0) { - *countOut = 0; - *listOut = NULL; - return NO_ERROR; - } - - // make one pass through looking for commas so we know how big to make our - // out array. - int count = 1; - for (size_t i=0; i<len; i++) { - if (str[i] == ',') { - count++; - } - } - - int* list = new int[count]; - const char16_t* p = str; - int commaIndex = 0; - size_t i; - - for (i=0; i<len; i++) { - if (str[i] == ',') { - err = func(p, (str+i-p), list+commaIndex, rangeMin, - rangeMax, zeroOK); - if (err != NO_ERROR) { - goto bail; - } - commaIndex++; - p = str+i+1; - } - } - - err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK); - if (err != NO_ERROR) { - goto bail; - } - commaIndex++; - - *countOut = count; - *listOut = list; - - return NO_ERROR; - -bail: - delete[] list; - FAIL_HERE(); -} - -// the numbers here are small, so we pack them both into one value, and then -// split it out later. it lets us reuse all the comma separated list code. -static status_t -parse_byday(const char16_t* s, size_t len, int* out, - int rangeMin, int rangeMax, bool zeroOK) -{ - status_t err; - int n = 0; - const char16_t* p = s; - size_t plen = len; - - if (len > 0) { - char16_t c = s[0]; - if (c == '-' || c == '+' || (c >= '0' && c <= '9')) { - if (len > 1) { - size_t nlen = 0; - c = s[nlen]; - while (nlen < len - && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) { - c = s[nlen]; - nlen++; - } - if (nlen > 0) { - nlen--; - err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK); - if (err != NO_ERROR) { - FAIL_HERE(); - } - p += nlen; - plen -= nlen; - } - } - } - - int index = match_proc(WEEKDAYPROC, p, plen); - if (index >= 0) { - *out = (0xffff0000 & WEEKDAYPROC[index].value) - | (0x0000ffff & n); - return NO_ERROR; - } - } - return UNKNOWN_ERROR; -} - -static void -postprocess_byday(int count, int* byday, int** bydayNum) -{ - int* bdn = new int[count]; - *bydayNum = bdn; - for (int i=0; i<count; i++) { - uint32_t v = byday[i]; - int16_t num = v & 0x0000ffff; - byday[i] = v & 0xffff0000; - // will sign extend: - bdn[i] = num; - } -} - -#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \ - if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \ - &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \ - FAIL_HERE(); \ - } -status_t -EventRecurrence::parse(const String16& str) -{ - char16_t const* work = str.string(); - size_t len = str.size(); - - int lhsIndex = NONE_LHS; - int index; - - size_t start = 0; - for (size_t i=0; i<len; i++) { - char16_t c = work[i]; - if (c != ';' && i == len-1) { - c = ';'; - i++; - } - if (c == ';' || c == '=') { - if (i != start) { - const char16_t* s = work+start; - const size_t slen = i-start; - - String8 thestring(String16(s, slen)); - - switch (c) - { - case '=': - if (lhsIndex == NONE_LHS) { - lhsIndex = match_proc(LHSPROC, s, slen); - if (lhsIndex >= 0) { - break; - } - } - FAIL_HERE(); - case ';': - { - switch (LHSPROC[lhsIndex].value) - { - case FREQ: - if (this->freq != 0) { - FAIL_HERE(); - } - index = match_proc(FREQPROC, s, slen); - if (index >= 0) { - this->freq = (freq_t)FREQPROC[index].value; - } - break; - case UNTIL: - // XXX should check that this is a valid time - until.setTo(String16(s, slen)); - break; - case COUNT: - if (count != 0 - || NO_ERROR != parse_int(s, slen, - &count, INT_MIN, INT_MAX, true)) { - FAIL_HERE(); - } - break; - case INTERVAL: - if (interval != 0 - || NO_ERROR != parse_int(s, slen, - &interval, INT_MIN, INT_MAX, false)) { - FAIL_HERE(); - } - break; - case BYSECOND: - PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true) - break; - case BYMINUTE: - PARSE_INT_LIST_CHECKED(byminute, 0, 59, true) - break; - case BYHOUR: - PARSE_INT_LIST_CHECKED(byhour, 0, 23, true) - break; - case BYDAY: - if (bydayCount != 0 || NO_ERROR != - parse_int_list(s, slen, &bydayCount, - &byday, -53, 53, false, - parse_byday)) { - FAIL_HERE(); - } - postprocess_byday(bydayCount, byday, &bydayNum); - break; - case BYMONTHDAY: - PARSE_INT_LIST_CHECKED(bymonthday, -31, 31, - false) - break; - case BYYEARDAY: - PARSE_INT_LIST_CHECKED(byyearday, -366, 366, - false) - break; - case BYWEEKNO: - PARSE_INT_LIST_CHECKED(byweekno, -53, 53, - false) - break; - case BYMONTH: - PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false) - break; - case BYSETPOS: - PARSE_INT_LIST_CHECKED(bysetpos, - INT_MIN, INT_MAX, true) - break; - case WKST: - if (this->wkst != 0) { - FAIL_HERE(); - } - index = match_proc(WEEKDAYPROC, s, slen); - if (index >= 0) { - this->wkst = (int)WEEKDAYPROC[index].value; - } - break; - default: - FAIL_HERE(); - } - lhsIndex = NONE_LHS; - break; - } - } - - start = i+1; - } - } - } - - // enforce that there was a FREQ - if (freq == 0) { - FAIL_HERE(); - } - - // default wkst to MO if it wasn't specified - if (wkst == 0) { - wkst = MO; - } - - return NO_ERROR; -} - - -}; // namespace android - - diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp index f963058fab..8791263933 100644 --- a/libs/utils/BackupData.cpp +++ b/libs/utils/BackupData.cpp @@ -285,7 +285,8 @@ BackupDataReader::ReadNextHeader(bool* done, int* type) break; } default: - LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); + LOGD("Chunk header at %d has invalid type: 0x%08x", + (int)(m_pos - sizeof(m_header)), (int)m_header.type); m_status = EINVAL; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2bab6a8fe1..35e29a6315 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -101,9 +101,8 @@ Layer::~Layer() } void Layer::onFrameQueued() { - if (android_atomic_or(1, &mQueuedFrames) == 0) { - mFlinger->signalEvent(); - } + android_atomic_inc(&mQueuedFrames); + mFlinger->signalEvent(); } // called with SurfaceFlinger::mStateLock as soon as the layer is entered @@ -406,20 +405,18 @@ bool Layer::isCropped() const { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { - if (android_atomic_and(0, &mQueuedFrames)) { + if (mQueuedFrames > 0) { + // signal another event if we have more frames pending + if (android_atomic_dec(&mQueuedFrames) > 1) { + mFlinger->signalEvent(); + } + if (mSurfaceTexture->updateTexImage() < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return; } - // signal another event if we have more frames waiting - if (mSurfaceTexture->getQueuedCount()) { - if (android_atomic_or(1, &mQueuedFrames) == 0) { - mFlinger->signalEvent(); - } - } - mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); mSurfaceTexture->getTransformMatrix(mTextureMatrix); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97edfeef50..f0b19f26e9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -32,6 +32,7 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/MemoryHeapBase.h> +#include <binder/PermissionCache.h> #include <utils/String8.h> #include <utils/String16.h> @@ -67,6 +68,13 @@ namespace android { // --------------------------------------------------------------------------- +const String16 sHardwareTest("android.permission.HARDWARE_TEST"); +const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"); +const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); +const String16 sDump("android.permission.DUMP"); + +// --------------------------------------------------------------------------- + SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), @@ -74,10 +82,6 @@ SurfaceFlinger::SurfaceFlinger() mResizeTransationPending(false), mLayersRemoved(false), mBootTime(systemTime()), - mHardwareTest("android.permission.HARDWARE_TEST"), - mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"), - mReadFramebuffer("android.permission.READ_FRAME_BUFFER"), - mDump("android.permission.DUMP"), mVisibleRegionsDirty(false), mHwWorkListDirty(false), mDeferReleaseConsole(false), @@ -1464,7 +1468,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) const size_t SIZE = 4096; char buffer[SIZE]; String8 result; - if (!mDump.checkCalling()) { + + if (!PermissionCache::checkCallingPermission(sDump)) { snprintf(buffer, SIZE, "Permission Denial: " "can't dump SurfaceFlinger from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), @@ -1596,7 +1601,8 @@ status_t SurfaceFlinger::onTransact( IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) { + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) { LOGE("Permission Denial: " "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; @@ -1609,7 +1615,8 @@ status_t SurfaceFlinger::onTransact( IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) { + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { LOGE("Permission Denial: " "can't read framebuffer pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; @@ -1621,7 +1628,7 @@ status_t SurfaceFlinger::onTransact( status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { CHECK_INTERFACE(ISurfaceComposer, data, reply); - if (UNLIKELY(!mHardwareTest.checkCalling())) { + if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) { IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); @@ -2404,8 +2411,7 @@ status_t Client::onTransact( const int self_pid = getpid(); if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) { // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) + if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger)) { LOGE("Permission Denial: " "can't openGlobalTransaction pid=%d, uid=%d", pid, uid); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index af1ef04dc2..45f80aedc2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -20,21 +20,20 @@ #include <stdint.h> #include <sys/types.h> -#include <utils/SortedVector.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> #include <utils/Atomic.h> #include <utils/Errors.h> +#include <utils/KeyedVector.h> #include <utils/RefBase.h> +#include <utils/SortedVector.h> +#include <utils/threads.h> -#include <binder/IMemory.h> -#include <binder/Permission.h> #include <binder/BinderService.h> +#include <binder/IMemory.h> #include <ui/PixelFormat.h> +#include <surfaceflinger/IGraphicBufferAlloc.h> #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/ISurfaceComposerClient.h> -#include <surfaceflinger/IGraphicBufferAlloc.h> #include "Barrier.h" #include "Layer.h" @@ -353,11 +352,7 @@ private: surface_flinger_cblk_t* mServerCblk; GLuint mWormholeTexName; nsecs_t mBootTime; - Permission mHardwareTest; - Permission mAccessSurfaceFlinger; - Permission mReadFramebuffer; - Permission mDump; - + // Can only accessed from the main thread, these members // don't need synchronization State mDrawingState; |