Merge "Fix 4691563: Don't show lock before unlock screen"
diff --git a/include/binder/Permission.h b/include/binder/Permission.h
deleted file mode 100644
index 9542d50..0000000
--- 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 0000000..1171d48
--- /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 e558dfd..c82fb9b 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -46,11 +46,14 @@
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;
};
@@ -101,11 +104,6 @@
// 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.
diff --git a/include/pim/EventRecurrence.h b/include/pim/EventRecurrence.h
deleted file mode 100644
index 1ceda41..0000000
--- 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/libs/binder/Android.mk b/libs/binder/Android.mk
index f9d9f25..3a12e96 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,7 +27,7 @@
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
- Permission.cpp \
+ PermissionCache.cpp \
ProcessState.cpp \
Static.cpp
diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp
deleted file mode 100644
index fd8fe69..0000000
--- 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 0000000..7278187
--- /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/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 37e6d11..0925001 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -417,17 +417,22 @@
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
@@ -483,24 +488,14 @@
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) {
@@ -538,7 +533,7 @@
}
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)
@@ -553,17 +548,17 @@
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/ui/Android.mk b/libs/ui/Android.mk
index f9990bb..427bbba 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,7 +43,6 @@
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 b436b50..0000000
--- 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/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2bab6a8..35e29a6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,9 +101,8 @@
}
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 @@
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 97edfee..f0b19f2 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 af1ef04..45f80ae 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 @@
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;