summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/keystore/keystore.cpp3
-rwxr-xr-xcmds/keystore/test-keystore9
-rw-r--r--include/binder/IMemory.h1
-rw-r--r--include/binder/MemoryHeapBase.h14
-rw-r--r--include/binder/Permission.h68
-rw-r--r--include/binder/PermissionCache.h79
-rw-r--r--include/gui/SurfaceTexture.h27
-rw-r--r--include/pim/EventRecurrence.h82
-rw-r--r--include/private/surfaceflinger/LayerState.h8
-rw-r--r--include/surfaceflinger/IGraphicBufferAlloc.h2
-rw-r--r--include/surfaceflinger/ISurfaceComposer.h7
-rw-r--r--include/surfaceflinger/ISurfaceComposerClient.h7
-rw-r--r--include/surfaceflinger/Surface.h2
-rw-r--r--include/surfaceflinger/SurfaceComposerClient.h26
-rw-r--r--include/utils/BitSet.h3
-rw-r--r--include/utils/LinearTransform.h64
-rw-r--r--include/utils/SortedVector.h2
-rw-r--r--include/utils/Vector.h26
-rw-r--r--include/utils/threads.h4
-rw-r--r--libs/binder/Android.mk2
-rw-r--r--libs/binder/IMemory.cpp53
-rw-r--r--libs/binder/MemoryHeapBase.cpp15
-rw-r--r--libs/binder/Permission.cpp88
-rw-r--r--libs/binder/PermissionCache.cpp113
-rw-r--r--libs/gui/IGraphicBufferAlloc.cpp13
-rw-r--r--libs/gui/ISurfaceComposer.cpp35
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp25
-rw-r--r--libs/gui/LayerState.cpp11
-rw-r--r--libs/gui/Surface.cpp4
-rw-r--r--libs/gui/SurfaceComposerClient.cpp593
-rw-r--r--libs/gui/SurfaceTexture.cpp70
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp180
-rw-r--r--libs/gui/tests/Surface_test.cpp26
-rw-r--r--libs/ui/Android.mk1
-rw-r--r--libs/ui/EventRecurrence.cpp484
-rw-r--r--libs/ui/InputTransport.cpp3
-rw-r--r--libs/utils/Android.mk1
-rw-r--r--libs/utils/BackupData.cpp3
-rw-r--r--libs/utils/LinearTransform.cpp262
-rw-r--r--libs/utils/Threads.cpp4
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp5
-rw-r--r--services/surfaceflinger/Layer.cpp19
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp224
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h33
-rw-r--r--services/surfaceflinger/tests/resize/resize.cpp8
-rw-r--r--services/surfaceflinger/tests/surface/surface.cpp4
-rw-r--r--vpn/java/android/net/vpn/IVpnService.aidl50
-rw-r--r--vpn/java/android/net/vpn/L2tpIpsecProfile.java65
-rw-r--r--vpn/java/android/net/vpn/L2tpIpsecPskProfile.java54
-rw-r--r--vpn/java/android/net/vpn/L2tpProfile.java68
-rw-r--r--vpn/java/android/net/vpn/PptpProfile.java56
-rw-r--r--vpn/java/android/net/vpn/VpnManager.java242
-rw-r--r--vpn/java/android/net/vpn/VpnProfile.aidl19
-rw-r--r--vpn/java/android/net/vpn/VpnProfile.java177
-rw-r--r--vpn/java/android/net/vpn/VpnState.java38
-rw-r--r--vpn/java/android/net/vpn/VpnType.java55
-rw-r--r--vpn/java/com/android/server/vpn/DaemonProxy.java199
-rw-r--r--vpn/java/com/android/server/vpn/L2tpIpsecPskService.java47
-rw-r--r--vpn/java/com/android/server/vpn/L2tpIpsecService.java50
-rw-r--r--vpn/java/com/android/server/vpn/L2tpService.java35
-rw-r--r--vpn/java/com/android/server/vpn/PptpService.java34
-rw-r--r--vpn/java/com/android/server/vpn/VpnConnectingError.java35
-rw-r--r--vpn/java/com/android/server/vpn/VpnDaemons.java147
-rw-r--r--vpn/java/com/android/server/vpn/VpnService.java477
-rw-r--r--vpn/java/com/android/server/vpn/VpnServiceBinder.java117
-rw-r--r--vpn/tests/vpntests/Android.mk14
-rw-r--r--vpn/tests/vpntests/AndroidManifest.xml36
-rwxr-xr-xvpn/tests/vpntests/src/android/net/vpn/VpnTest.java157
68 files changed, 1369 insertions, 3516 deletions
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index bbd1a1b..4b4b9b9 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -708,11 +708,10 @@ 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},
- {AID_KEYCHAIN, AID_SYSTEM, TEST | GET | SAW},
{~0, ~0, TEST | GET | INSERT | DELETE | EXIST | SAW},
};
diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore
index 82b276f..3be51b3 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 74d2cc7..2d0db00 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 2f2e31b..bbbda9c 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 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 9294df6..e36360c 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.
@@ -141,7 +139,7 @@ public:
// setFrameAvailableListener sets the listener object that will be notified
// when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+ void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
// getAllocator retrieves the binder object that must be referenced as long
// as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
@@ -345,7 +343,7 @@ private:
uint32_t mNextTransform;
// mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
+ // be bound when updateTexImage is called. It is set at construction time
// changed with a call to setTexName.
const GLuint mTexName;
@@ -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 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/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h
index d7fe572..d2fed41 100644
--- a/include/private/surfaceflinger/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -29,6 +29,7 @@
namespace android {
class Parcel;
+class ISurfaceComposerClient;
struct layer_state_t {
@@ -68,6 +69,13 @@ struct layer_state_t {
Region transparentRegion;
};
+struct ComposerState {
+ sp<ISurfaceComposerClient> client;
+ layer_state_t state;
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+};
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
index e1b6b57..d3b2062 100644
--- a/include/surfaceflinger/IGraphicBufferAlloc.h
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -37,7 +37,7 @@ public:
/* Create a new GraphicBuffer for the client to use.
*/
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage) = 0;
+ PixelFormat format, uint32_t usage, status_t* error) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 03fd01b..dba98a3 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -34,6 +34,7 @@ namespace android {
// ----------------------------------------------------------------------------
class IMemoryHeap;
+class ComposerState;
class ISurfaceComposer : public IInterface
{
@@ -105,8 +106,7 @@ public:
virtual sp<IMemoryHeap> getCblk() const = 0;
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
- virtual void openGlobalTransaction() = 0;
- virtual void closeGlobalTransaction() = 0;
+ virtual void setTransactionState(const Vector<ComposerState>& state) = 0;
/* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
@@ -149,8 +149,7 @@ public:
CREATE_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
GET_CBLK,
- OPEN_GLOBAL_TRANSACTION,
- CLOSE_GLOBAL_TRANSACTION,
+ SET_TRANSACTION_STATE,
SET_ORIENTATION,
FREEZE_DISPLAY,
UNFREEZE_DISPLAY,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 2e75a0e..6e9a654 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -37,8 +37,6 @@ typedef int32_t DisplayID;
// ----------------------------------------------------------------------------
-class layer_state_t;
-
class ISurfaceComposerClient : public IInterface
{
public:
@@ -69,11 +67,6 @@ public:
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t destroySurface(SurfaceID sid) = 0;
-
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t setState(int32_t count, const layer_state_t* states) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 8845dc9..dc2a845 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/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 140b9f8..7fbbfb2 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -37,10 +37,12 @@ namespace android {
// ---------------------------------------------------------------------------
class DisplayInfo;
+class Composer;
class IMemoryHeap;
class ISurfaceComposer;
class Region;
class surface_flinger_cblk_t;
+struct layer_state_t;
// ---------------------------------------------------------------------------
@@ -59,8 +61,11 @@ public:
// ---------------------------------------------------------------------------
+class Composer;
+
class SurfaceComposerClient : public RefBase
{
+ friend class Composer;
public:
SurfaceComposerClient();
virtual ~SurfaceComposerClient();
@@ -101,13 +106,7 @@ public:
// All composer parameters must be changed within a transaction
// several surfaces can be updated in one transaction, all changes are
// committed at once when the transaction is closed.
- // CloseTransaction() usually requires an IPC with the server.
-
- //! Open a composer transaction
- status_t openTransaction();
-
- //! commit the transaction
- status_t closeTransaction();
+ // closeGlobalTransaction() usually requires an IPC with the server.
//! Open a composer transaction on all active SurfaceComposerClients.
static void openGlobalTransaction();
@@ -152,19 +151,12 @@ public:
private:
virtual void onFirstRef();
- inline layer_state_t* get_state_l(SurfaceID id);
- layer_state_t* lockLayerState(SurfaceID id);
- inline void unlockLayerState();
-
- mutable Mutex mLock;
- SortedVector<layer_state_t> mStates;
- int32_t mTransactionOpen;
- layer_state_t* mPrebuiltLayerState;
+ Composer& getComposer();
- // these don't need to be protected because they never change
- // after assignment
+ mutable Mutex mLock;
status_t mStatus;
sp<ISurfaceComposerClient> mClient;
+ Composer& mComposer;
};
// ---------------------------------------------------------------------------
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
index de748b5..600017e 100644
--- a/include/utils/BitSet.h
+++ b/include/utils/BitSet.h
@@ -44,6 +44,9 @@ struct BitSet32 {
// Returns true if the bit set does not contain any marked bits.
inline bool isEmpty() const { return ! value; }
+ // Returns true if the bit set does not contain any unmarked bits.
+ inline bool isFull() const { return value == 0xffffffff; }
+
// Returns true if the specified bit is marked.
inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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 _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again). Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+ int64_t a_zero;
+ int64_t b_zero;
+ int32_t a_to_b_numer;
+ uint32_t a_to_b_denom;
+
+ // Transform from A->B
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+ // Transform from B->A
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+ // Helpers which will reduce the fraction N/D using Euclid's method.
+ template <class T> static void reduce(T* N, T* D);
+ static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 8beec57..0e98aeb 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -32,6 +32,8 @@ namespace android {
template <class TYPE>
class SortedVector : private SortedVectorImpl
{
+ friend class Vector<TYPE>;
+
public:
typedef TYPE value_type;
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index f1e87e6..b908e2a 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -29,6 +29,9 @@
namespace android {
+template <typename TYPE>
+class SortedVector;
+
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
@@ -47,13 +50,17 @@ public:
Vector();
Vector(const Vector<TYPE>& rhs);
+ explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
- /*
+ const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+
+ /*
* empty the vector
*/
@@ -215,6 +222,11 @@ Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
}
template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+ : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
Vector<TYPE>::~Vector() {
finish_vector();
}
@@ -227,6 +239,18 @@ Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
template<class TYPE> inline
const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
VectorImpl::operator = (rhs);
return *this;
}
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 432805e..c8e9c04 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -133,13 +133,13 @@ extern pid_t androidGetTid();
// Change the scheduling group of a particular thread. The group
// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
// grp is out of range, else another non-zero value with errno set if
-// the operation failed.
+// the operation failed. Thread ID zero means current thread.
extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
// Change the priority AND scheduling group of a particular thread. The priority
// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
// if the priority set failed, else another value if just the group set failed;
-// in either case errno is set.
+// in either case errno is set. Thread ID zero means current thread.
extern int androidSetThreadPriority(pid_t tid, int prio);
#ifdef __cplusplus
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 @@ 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 bc8c412..1ace8f8 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 9f501e2..bf4a73f 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 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/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 0cd51da..30f8d00 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -43,7 +43,7 @@ public:
}
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint32_t usage, status_t* error) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
data.writeInt32(w);
@@ -52,14 +52,15 @@ public:
data.writeInt32(usage);
remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
sp<GraphicBuffer> graphicBuffer;
- bool nonNull = (bool)reply.readInt32();
- if (nonNull) {
+ status_t result = reply.readInt32();
+ if (result == NO_ERROR) {
graphicBuffer = new GraphicBuffer();
reply.read(*graphicBuffer);
// reply.readStrongBinder();
// here we don't even have to read the BufferReference from
// the parcel, it'll die with the parcel.
}
+ *error = result;
return graphicBuffer;
}
};
@@ -91,8 +92,10 @@ status_t BnGraphicBufferAlloc::onTransact(
uint32_t h = data.readInt32();
PixelFormat format = data.readInt32();
uint32_t usage = data.readInt32();
- sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
- reply->writeInt32(result != 0);
+ status_t error;
+ sp<GraphicBuffer> result =
+ createGraphicBuffer(w, h, format, usage, &error);
+ reply->writeInt32(error);
if (result != 0) {
reply->write(*result);
// We add a BufferReference to this parcel to make sure the
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 40450a3..c1156d5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,8 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <private/surfaceflinger/LayerState.h>
+
#include <surfaceflinger/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
@@ -74,18 +76,17 @@ public:
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
}
- virtual void openGlobalTransaction()
+ virtual void setTransactionState(const Vector<ComposerState>& state)
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply);
- }
-
- virtual void closeGlobalTransaction()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply);
+ Vector<ComposerState>::const_iterator b(state.begin());
+ Vector<ComposerState>::const_iterator e(state.end());
+ data.writeInt32(state.size());
+ for ( ; b != e ; ++b ) {
+ b->write(data);
+ }
+ remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
@@ -218,13 +219,17 @@ status_t BnSurfaceComposer::onTransact(
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
reply->writeStrongBinder(b);
} break;
- case OPEN_GLOBAL_TRANSACTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- openGlobalTransaction();
- } break;
- case CLOSE_GLOBAL_TRANSACTION: {
+ case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- closeGlobalTransaction();
+ size_t count = data.readInt32();
+ ComposerState s;
+ Vector<ComposerState> state;
+ state.setCapacity(count);
+ for (size_t i=0 ; i<count ; i++) {
+ s.read(data);
+ state.add(s);
+ }
+ setTransactionState(state);
} break;
case SET_ORIENTATION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 8d83392..bc97cac 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -51,8 +51,7 @@ namespace android {
enum {
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
- DESTROY_SURFACE,
- SET_STATE
+ DESTROY_SURFACE
};
class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@@ -92,17 +91,6 @@ public:
remote()->transact(DESTROY_SURFACE, data, &reply);
return reply.readInt32();
}
-
- virtual status_t setState(int32_t count, const layer_state_t* states)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- data.writeInt32(count);
- for (int i=0 ; i<count ; i++)
- states[i].write(data);
- remote()->transact(SET_STATE, data, &reply);
- return reply.readInt32();
- }
};
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
@@ -133,17 +121,6 @@ status_t BnSurfaceComposerClient::onTransact(
reply->writeInt32( destroySurface( data.readInt32() ) );
return NO_ERROR;
} break;
- case SET_STATE: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- int32_t count = data.readInt32();
- layer_state_t* states = new layer_state_t[count];
- for (int i=0 ; i<count ; i++)
- states[i].read(data);
- status_t err = setState(count, states);
- delete [] states;
- reply->writeInt32(err);
- return NO_ERROR;
- } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 01c4c7e..87901e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -17,6 +17,7 @@
#include <utils/Errors.h>
#include <binder/Parcel.h>
#include <private/surfaceflinger/LayerState.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
namespace android {
@@ -58,4 +59,14 @@ status_t layer_state_t::read(const Parcel& input)
return NO_ERROR;
}
+status_t ComposerState::write(Parcel& output) const {
+ output.writeStrongBinder(client->asBinder());
+ return state.write(output);
+}
+
+status_t ComposerState::read(const Parcel& input) {
+ client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder());
+ return state.read(input);
+}
+
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4d1d923..9185e1e 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/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1678711..8cead80 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -74,75 +74,52 @@ static inline surface_flinger_cblk_t const volatile * get_cblk() {
// ---------------------------------------------------------------------------
+// NOTE: this is NOT a member function (it's a friend defined with its
+// declaration).
+static inline
+int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
+ if (lhs.client < rhs.client) return -1;
+ if (lhs.client > rhs.client) return 1;
+ if (lhs.state.surface < rhs.state.surface) return -1;
+ if (lhs.state.surface > rhs.state.surface) return 1;
+ return 0;
+}
+
class Composer : public Singleton<Composer>
{
- Mutex mLock;
- SortedVector< wp<SurfaceComposerClient> > mActiveConnections;
- SortedVector<sp<SurfaceComposerClient> > mOpenTransactions;
+ friend class Singleton<Composer>;
- Composer() : Singleton<Composer>() {
- }
+ mutable Mutex mLock;
+ SortedVector<ComposerState> mStates;
- void addClientImpl(const sp<SurfaceComposerClient>& client) {
- Mutex::Autolock _l(mLock);
- mActiveConnections.add(client);
- }
+ Composer() : Singleton<Composer>() { }
- void removeClientImpl(const sp<SurfaceComposerClient>& client) {
- Mutex::Autolock _l(mLock);
- mActiveConnections.remove(client);
- }
+ void closeGlobalTransactionImpl();
- void openGlobalTransactionImpl()
- {
- Mutex::Autolock _l(mLock);
- if (mOpenTransactions.size()) {
- LOGE("openGlobalTransaction() called more than once. skipping.");
- return;
- }
- const size_t N = mActiveConnections.size();
- for (size_t i=0; i<N; i++) {
- sp<SurfaceComposerClient> client(mActiveConnections[i].promote());
- if (client != 0 && mOpenTransactions.indexOf(client) < 0) {
- if (client->openTransaction() == NO_ERROR) {
- mOpenTransactions.add(client);
- } else {
- LOGE("openTransaction on client %p failed", client.get());
- // let it go, it'll fail later when the user
- // tries to do something with the transaction
- }
- }
- }
- }
+ layer_state_t* getLayerStateLocked(
+ const sp<SurfaceComposerClient>& client, SurfaceID id);
- void closeGlobalTransactionImpl()
- {
- mLock.lock();
- SortedVector< sp<SurfaceComposerClient> > clients(mOpenTransactions);
- mOpenTransactions.clear();
- mLock.unlock();
-
- sp<ISurfaceComposer> sm(getComposerService());
- sm->openGlobalTransaction();
- const size_t N = clients.size();
- for (size_t i=0; i<N; i++) {
- clients[i]->closeTransaction();
- }
- sm->closeGlobalTransaction();
- }
+public:
- friend class Singleton<Composer>;
+ status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ int32_t x, int32_t y);
+ status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t w, uint32_t h);
+ status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ int32_t z);
+ status_t setFlags(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t flags, uint32_t mask);
+ status_t setTransparentRegionHint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ const Region& transparentRegion);
+ status_t setAlpha(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ float alpha);
+ status_t setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ float dsdx, float dtdx, float dsdy, float dtdy);
+ status_t setFreezeTint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t tint);
-public:
- static void addClient(const sp<SurfaceComposerClient>& client) {
- Composer::getInstance().addClientImpl(client);
- }
- static void removeClient(const sp<SurfaceComposerClient>& client) {
- Composer::getInstance().removeClientImpl(client);
- }
- static void openGlobalTransaction() {
- Composer::getInstance().openGlobalTransactionImpl();
- }
static void closeGlobalTransaction() {
Composer::getInstance().closeGlobalTransactionImpl();
}
@@ -152,127 +129,185 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer);
// ---------------------------------------------------------------------------
-static inline int compare_type( const layer_state_t& lhs,
- const layer_state_t& rhs) {
- if (lhs.surface < rhs.surface) return -1;
- if (lhs.surface > rhs.surface) return 1;
- return 0;
+void Composer::closeGlobalTransactionImpl() {
+ sp<ISurfaceComposer> sm(getComposerService());
+
+ Vector<ComposerState> transaction;
+
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ transaction = mStates;
+ mStates.clear();
+ }
+
+ sm->setTransactionState(transaction);
+}
+
+layer_state_t* Composer::getLayerStateLocked(
+ const sp<SurfaceComposerClient>& client, SurfaceID id) {
+
+ ComposerState s;
+ s.client = client->mClient;
+ s.state.surface = id;
+
+ ssize_t index = mStates.indexOf(s);
+ if (index < 0) {
+ // we don't have it, add an initialized layer_state to our list
+ index = mStates.add(s);
+ }
+
+ ComposerState* const out = mStates.editArray();
+ return &(out[index].state);
+}
+
+status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, int32_t x, int32_t y) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::ePositionChanged;
+ s->x = x;
+ s->y = y;
+ return NO_ERROR;
+}
+
+status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t w, uint32_t h) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eSizeChanged;
+ s->w = w;
+ s->h = h;
+ return NO_ERROR;
+}
+
+status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, int32_t z) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eLayerChanged;
+ s->z = z;
+ return NO_ERROR;
+}
+
+status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t flags,
+ uint32_t mask) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eVisibilityChanged;
+ s->flags &= ~mask;
+ s->flags |= (flags & mask);
+ s->mask |= mask;
+ return NO_ERROR;
+}
+
+status_t Composer::setTransparentRegionHint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ const Region& transparentRegion) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eTransparentRegionChanged;
+ s->transparentRegion = transparentRegion;
+ return NO_ERROR;
+}
+
+status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, float alpha) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eAlphaChanged;
+ s->alpha = alpha;
+ return NO_ERROR;
+}
+
+status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, float dsdx, float dtdx,
+ float dsdy, float dtdy) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eMatrixChanged;
+ layer_state_t::matrix22_t matrix;
+ matrix.dsdx = dsdx;
+ matrix.dtdx = dtdx;
+ matrix.dsdy = dsdy;
+ matrix.dtdy = dtdy;
+ s->matrix = matrix;
+ return NO_ERROR;
}
+status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t tint) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eFreezeTintChanged;
+ s->tint = tint;
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
SurfaceComposerClient::SurfaceComposerClient()
- : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT)
+ : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
-void SurfaceComposerClient::onFirstRef()
-{
+void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sm(getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
- Composer::addClient(this);
- mPrebuiltLayerState = new layer_state_t;
mStatus = NO_ERROR;
}
}
}
-SurfaceComposerClient::~SurfaceComposerClient()
-{
- delete mPrebuiltLayerState;
+SurfaceComposerClient::~SurfaceComposerClient() {
dispose();
}
-status_t SurfaceComposerClient::initCheck() const
-{
+status_t SurfaceComposerClient::initCheck() const {
return mStatus;
}
-sp<IBinder> SurfaceComposerClient::connection() const
-{
+sp<IBinder> SurfaceComposerClient::connection() const {
return (mClient != 0) ? mClient->asBinder() : 0;
}
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
- void* cookie, uint32_t flags)
-{
+ void* cookie, uint32_t flags) {
sp<ISurfaceComposer> sm(getComposerService());
return sm->asBinder()->linkToDeath(recipient, cookie, flags);
}
-void SurfaceComposerClient::dispose()
-{
+void SurfaceComposerClient::dispose() {
// this can be called more than once.
sp<ISurfaceComposerClient> client;
Mutex::Autolock _lm(mLock);
if (mClient != 0) {
- Composer::removeClient(this);
client = mClient; // hold ref while lock is held
mClient.clear();
}
mStatus = NO_INIT;
}
-status_t SurfaceComposerClient::getDisplayInfo(
- DisplayID dpy, DisplayInfo* info)
-{
- if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
- return BAD_VALUE;
-
- volatile surface_flinger_cblk_t const * cblk = get_cblk();
- volatile display_cblk_t const * dcblk = cblk->displays + dpy;
-
- info->w = dcblk->w;
- info->h = dcblk->h;
- info->orientation = dcblk->orientation;
- info->xdpi = dcblk->xdpi;
- info->ydpi = dcblk->ydpi;
- info->fps = dcblk->fps;
- info->density = dcblk->density;
- return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));
-}
-
-ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
-{
- if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
- return BAD_VALUE;
- volatile surface_flinger_cblk_t const * cblk = get_cblk();
- volatile display_cblk_t const * dcblk = cblk->displays + dpy;
- return dcblk->w;
-}
-
-ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
-{
- if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
- return BAD_VALUE;
- volatile surface_flinger_cblk_t const * cblk = get_cblk();
- volatile display_cblk_t const * dcblk = cblk->displays + dpy;
- return dcblk->h;
-}
-
-ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
-{
- if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
- return BAD_VALUE;
- volatile surface_flinger_cblk_t const * cblk = get_cblk();
- volatile display_cblk_t const * dcblk = cblk->displays + dpy;
- return dcblk->orientation;
-}
-
-ssize_t SurfaceComposerClient::getNumberOfDisplays()
-{
- volatile surface_flinger_cblk_t const * cblk = get_cblk();
- uint32_t connected = cblk->connected;
- int n = 0;
- while (connected) {
- if (connected&1) n++;
- connected >>= 1;
- }
- return n;
-}
-
sp<SurfaceControl> SurfaceComposerClient::createSurface(
DisplayID display,
uint32_t w,
@@ -310,237 +345,167 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
return result;
}
-status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
-{
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
if (mStatus != NO_ERROR)
return mStatus;
-
- // it's okay to destroy a surface while a transaction is open,
- // (transactions really are a client-side concept)
- // however, this indicates probably a misuse of the API or a bug
- // in the client code.
- LOGW_IF(mTransactionOpen,
- "Destroying surface while a transaction is open. "
- "Client %p: destroying surface %d, mTransactionOpen=%d",
- this, sid, mTransactionOpen);
-
status_t err = mClient->destroySurface(sid);
return err;
}
-void SurfaceComposerClient::openGlobalTransaction()
-{
- Composer::openGlobalTransaction();
+inline Composer& SurfaceComposerClient::getComposer() {
+ return mComposer;
}
-void SurfaceComposerClient::closeGlobalTransaction()
-{
- Composer::closeGlobalTransaction();
-}
+// ----------------------------------------------------------------------------
-status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
-{
- sp<ISurfaceComposer> sm(getComposerService());
- return sm->freezeDisplay(dpy, flags);
+void SurfaceComposerClient::openGlobalTransaction() {
+ // Currently a no-op
}
-status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
-{
- sp<ISurfaceComposer> sm(getComposerService());
- return sm->unfreezeDisplay(dpy, flags);
+void SurfaceComposerClient::closeGlobalTransaction() {
+ Composer::closeGlobalTransaction();
}
-int SurfaceComposerClient::setOrientation(DisplayID dpy,
- int orientation, uint32_t flags)
-{
- sp<ISurfaceComposer> sm(getComposerService());
- return sm->setOrientation(dpy, orientation, flags);
-}
+// ----------------------------------------------------------------------------
-status_t SurfaceComposerClient::openTransaction()
-{
- if (mStatus != NO_ERROR)
- return mStatus;
- Mutex::Autolock _l(mLock);
- mTransactionOpen++;
- return NO_ERROR;
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
+ return getComposer().setFreezeTint(this, id, tint);
}
-status_t SurfaceComposerClient::closeTransaction()
-{
- if (mStatus != NO_ERROR)
- return mStatus;
-
- Mutex::Autolock _l(mLock);
- if (mTransactionOpen <= 0) {
- LOGE( "closeTransaction (client %p, mTransactionOpen=%d) "
- "called more times than openTransaction()",
- this, mTransactionOpen);
- return INVALID_OPERATION;
- }
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+ return getComposer().setPosition(this, id, x, y);
+}
- if (mTransactionOpen >= 2) {
- mTransactionOpen--;
- return NO_ERROR;
- }
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
+ return getComposer().setSize(this, id, w, h);
+}
- mTransactionOpen = 0;
- const ssize_t count = mStates.size();
- if (count) {
- mClient->setState(count, mStates.array());
- mStates.clear();
- }
- return NO_ERROR;
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) {
+ return getComposer().setLayer(this, id, z);
}
-layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index)
-{
- // API usage error, do nothing.
- if (mTransactionOpen<=0) {
- LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
- this, int(index), mTransactionOpen);
- return 0;
- }
+status_t SurfaceComposerClient::hide(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ ISurfaceComposer::eLayerHidden,
+ ISurfaceComposer::eLayerHidden);
+}
- // use mPrebuiltLayerState just to find out if we already have it
- layer_state_t& dummy(*mPrebuiltLayerState);
- dummy.surface = index;
- ssize_t i = mStates.indexOf(dummy);
- if (i < 0) {
- // we don't have it, add an initialized layer_state to our list
- i = mStates.add(dummy);
- }
- return mStates.editArray() + i;
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t) {
+ return getComposer().setFlags(this, id,
+ 0,
+ ISurfaceComposer::eLayerHidden);
}
-layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
-{
- layer_state_t* s;
- mLock.lock();
- s = get_state_l(id);
- if (!s) mLock.unlock();
- return s;
+status_t SurfaceComposerClient::freeze(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ ISurfaceComposer::eLayerFrozen,
+ ISurfaceComposer::eLayerFrozen);
}
-void SurfaceComposerClient::unlockLayerState()
-{
- mLock.unlock();
+status_t SurfaceComposerClient::unfreeze(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ 0,
+ ISurfaceComposer::eLayerFrozen);
}
-status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::ePositionChanged;
- s->x = x;
- s->y = y;
- unlockLayerState();
- return NO_ERROR;
+status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags,
+ uint32_t mask) {
+ return getComposer().setFlags(this, id, flags, mask);
}
-status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eSizeChanged;
- s->w = w;
- s->h = h;
- unlockLayerState();
- return NO_ERROR;
+status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id,
+ const Region& transparentRegion) {
+ return getComposer().setTransparentRegionHint(this, id, transparentRegion);
}
-status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eLayerChanged;
- s->z = z;
- unlockLayerState();
- return NO_ERROR;
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) {
+ return getComposer().setAlpha(this, id, alpha);
}
-status_t SurfaceComposerClient::hide(SurfaceID id)
-{
- return setFlags(id, ISurfaceComposer::eLayerHidden,
- ISurfaceComposer::eLayerHidden);
+status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx,
+ float dsdy, float dtdy) {
+ return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
}
-status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::getDisplayInfo(
+ DisplayID dpy, DisplayInfo* info)
{
- return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+ return BAD_VALUE;
+
+ volatile surface_flinger_cblk_t const * cblk = get_cblk();
+ volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+
+ info->w = dcblk->w;
+ info->h = dcblk->h;
+ info->orientation = dcblk->orientation;
+ info->xdpi = dcblk->xdpi;
+ info->ydpi = dcblk->ydpi;
+ info->fps = dcblk->fps;
+ info->density = dcblk->density;
+ return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));
}
-status_t SurfaceComposerClient::freeze(SurfaceID id)
+ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
{
- return setFlags(id, ISurfaceComposer::eLayerFrozen,
- ISurfaceComposer::eLayerFrozen);
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+ return BAD_VALUE;
+ volatile surface_flinger_cblk_t const * cblk = get_cblk();
+ volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+ return dcblk->w;
}
-status_t SurfaceComposerClient::unfreeze(SurfaceID id)
+ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
{
- return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+ return BAD_VALUE;
+ volatile surface_flinger_cblk_t const * cblk = get_cblk();
+ volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+ return dcblk->h;
}
-status_t SurfaceComposerClient::setFlags(SurfaceID id,
- uint32_t flags, uint32_t mask)
+ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eVisibilityChanged;
- s->flags &= ~mask;
- s->flags |= (flags & mask);
- s->mask |= mask;
- unlockLayerState();
- return NO_ERROR;
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+ return BAD_VALUE;
+ volatile surface_flinger_cblk_t const * cblk = get_cblk();
+ volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+ return dcblk->orientation;
}
-status_t SurfaceComposerClient::setTransparentRegionHint(
- SurfaceID id, const Region& transparentRegion)
+ssize_t SurfaceComposerClient::getNumberOfDisplays()
{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eTransparentRegionChanged;
- s->transparentRegion = transparentRegion;
- unlockLayerState();
- return NO_ERROR;
+ volatile surface_flinger_cblk_t const * cblk = get_cblk();
+ uint32_t connected = cblk->connected;
+ int n = 0;
+ while (connected) {
+ if (connected&1) n++;
+ connected >>= 1;
+ }
+ return n;
}
-status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eAlphaChanged;
- s->alpha = alpha;
- unlockLayerState();
- return NO_ERROR;
+ sp<ISurfaceComposer> sm(getComposerService());
+ return sm->freezeDisplay(dpy, flags);
}
-status_t SurfaceComposerClient::setMatrix(
- SurfaceID id,
- float dsdx, float dtdx,
- float dsdy, float dtdy )
+status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eMatrixChanged;
- layer_state_t::matrix22_t matrix;
- matrix.dsdx = dsdx;
- matrix.dtdx = dtdx;
- matrix.dsdy = dsdy;
- matrix.dtdy = dtdy;
- s->matrix = matrix;
- unlockLayerState();
- return NO_ERROR;
+ sp<ISurfaceComposer> sm(getComposerService());
+ return sm->unfreezeDisplay(dpy, flags);
}
-status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
+int SurfaceComposerClient::setOrientation(DisplayID dpy,
+ int orientation, uint32_t flags)
{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eFreezeTintChanged;
- s->tint = tint;
- unlockLayerState();
- return NO_ERROR;
+ sp<ISurfaceComposer> sm(getComposerService());
+ return sm->setOrientation(dpy, orientation, flags);
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 3cecdb4..886a3fb 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();
@@ -147,6 +148,11 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
LOGV("SurfaceTexture::setBufferCount");
Mutex::Autolock lock(mMutex);
+ if (bufferCount > NUM_BUFFER_SLOTS) {
+ LOGE("setBufferCount: bufferCount larger than slots available");
+ return BAD_VALUE;
+ }
+
// Error out if the user has dequeued buffers
for (int i=0 ; i<mBufferCount ; i++) {
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
@@ -207,7 +213,7 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
uint32_t format, uint32_t usage) {
LOGV("SurfaceTexture::dequeueBuffer");
- if ((w && !h) || (!w & h)) {
+ if ((w && !h) || (!w && h)) {
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
return BAD_VALUE;
}
@@ -346,11 +352,13 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
((uint32_t(buffer->usage) & usage) != usage))
{
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ status_t error;
sp<GraphicBuffer> graphicBuffer(
- mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+ mGraphicBufferAlloc->createGraphicBuffer(
+ w, h, format, usage, &error));
if (graphicBuffer == 0) {
LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
- return NO_MEMORY;
+ return error;
}
if (updateFormat) {
mPixelFormat = format;
@@ -371,6 +379,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 +424,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 +495,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 +540,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 +555,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)
@@ -700,10 +706,10 @@ nsecs_t SurfaceTexture::getTimestamp() {
}
void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& l) {
+ const sp<FrameAvailableListener>& listener) {
LOGV("SurfaceTexture::setFrameAvailableListener");
Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = l;
+ mFrameAvailableListener = listener;
}
sp<IBinder> SurfaceTexture::getAllocator() {
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index f219639..c06400e 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -84,10 +84,10 @@ protected:
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+ SurfaceComposerClient::openGlobalTransaction();
ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+ SurfaceComposerClient::closeGlobalTransaction();
sp<ANativeWindow> window = mSurfaceControl->getSurface();
mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
@@ -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/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 35c8640..ce587b3 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -31,15 +31,15 @@ protected:
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
mSurfaceControl = mComposerClient->createSurface(
- String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0);
+ String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff));
ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+ SurfaceComposerClient::closeGlobalTransaction();
mSurface = mSurfaceControl->getSurface();
ASSERT_TRUE(mSurface != NULL);
@@ -84,7 +84,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
PixelFormat fmt=0;
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0,
- 40000));
+ 0x7fffffff));
ASSERT_TRUE(heap != NULL);
// Set the PROTECTED usage bit and verify that the screenshot fails. Note
@@ -94,6 +94,18 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
GRALLOC_USAGE_PROTECTED));
ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
ANativeWindowBuffer* buf = 0;
+
+ status_t err = anw->dequeueBuffer(anw.get(), &buf);
+ if (err) {
+ // we could fail if GRALLOC_USAGE_PROTECTED is not supported.
+ // that's okay as long as this is the reason for the failure.
+ // try again without the GRALLOC_USAGE_PROTECTED bit.
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0));
+ ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
+ return;
+ }
+ ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf));
+
for (int i = 0; i < 4; i++) {
// Loop to make sure SurfaceFlinger has retired a protected buffer.
ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
@@ -103,7 +115,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
heap = 0;
w = h = fmt = 0;
ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt,
- 64, 64, 0, 40000));
+ 64, 64, 0, 0x7fffffff));
ASSERT_TRUE(heap == NULL);
// XXX: This should not be needed, but it seems that the new buffers don't
@@ -126,7 +138,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) {
heap = 0;
w = h = fmt = 0;
ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0,
- 40000));
+ 0x7fffffff));
ASSERT_TRUE(heap != NULL);
}
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 @@ 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 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/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index ffdfe66..c46d6f4 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -443,7 +443,8 @@ status_t InputPublisher::appendMotionSample(
if (! mPinned || ! mMotionEventSampleDataTail) {
LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
- "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+ "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
+ mChannel->getName().string());
return INVALID_OPERATION;
}
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 093189c..774e8c9 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -27,6 +27,7 @@ commonSources:= \
Debug.cpp \
FileMap.cpp \
Flattenable.cpp \
+ LinearTransform.cpp \
ObbFile.cpp \
Pool.cpp \
PropertyMap.cpp \
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index f963058..8791263 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/libs/utils/LinearTransform.cpp b/libs/utils/LinearTransform.cpp
new file mode 100644
index 0000000..d752415
--- /dev/null
+++ b/libs/utils/LinearTransform.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2011 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 __STDC_LIMIT_MACROS
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+static bool scale_u64_to_u64(
+ uint64_t val,
+ uint32_t N,
+ uint32_t D,
+ uint64_t* res,
+ bool round_up_not_down) {
+ uint64_t tmp1, tmp2;
+ uint32_t r;
+
+ assert(res);
+ assert(D);
+
+ // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+ // integer X.
+ // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+ // integer X.
+ // Let X[A, B] with A <= B denote bits A through B of the integer X.
+ // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+ // IOW X = (A | B) => U32(X) == A && L32(X) == B
+ //
+ // compute M = val * N (a 96 bit int)
+ // ---------------------------------
+ // tmp2 = U32(val) * N (a 64 bit int)
+ // tmp1 = L32(val) * N (a 64 bit int)
+ // which means
+ // M = val * N = (tmp2 << 32) + tmp1
+ tmp2 = (val >> 32) * N;
+ tmp1 = (val & UINT32_MAX) * N;
+
+ // compute M[32, 95]
+ // tmp2 = tmp2 + U32(tmp1)
+ // = (U32(val) * N) + U32(L32(val) * N)
+ // = M[32, 95]
+ tmp2 += tmp1 >> 32;
+
+ // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+ // an overflow.
+ if ((tmp2 >> 32) >= D) {
+ *res = UINT64_MAX;
+ return false;
+ }
+
+ // Divide. Going in we know
+ // tmp2 = M[32, 95]
+ // U32(tmp2) < D
+ r = tmp2 % D;
+ tmp2 /= D;
+
+ // At this point
+ // tmp1 = L32(val) * N
+ // tmp2 = M[32, 95] / D
+ // = (M / D)[32, 95]
+ // r = M[32, 95] % D
+ // U32(tmp2) = 0
+ //
+ // compute tmp1 = (r | M[0, 31])
+ tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+ // Divide again. Keep the remainder around in order to round properly.
+ r = tmp1 % D;
+ tmp1 /= D;
+
+ // At this point
+ // tmp2 = (M / D)[32, 95]
+ // tmp1 = (M / D)[ 0, 31]
+ // r = M % D
+ // U32(tmp1) = 0
+ // U32(tmp2) = 0
+
+ // Pack the result and deal with the round-up case (As well as the
+ // remote possiblility over overflow in such a case).
+ *res = (tmp2 << 32) | tmp1;
+ if (r && round_up_not_down) {
+ ++(*res);
+ if (!(*res)) {
+ *res = UINT64_MAX;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool linear_transform_s64_to_s64(
+ int64_t val,
+ int64_t basis1,
+ int32_t N,
+ uint32_t D,
+ int64_t basis2,
+ int64_t* out) {
+ uint64_t scaled, res;
+ uint64_t abs_val;
+ bool is_neg;
+
+ if (!out)
+ return false;
+
+ // Compute abs(val - basis_64). Keep track of whether or not this delta
+ // will be negative after the scale opertaion.
+ if (val < basis1) {
+ is_neg = true;
+ abs_val = basis1 - val;
+ } else {
+ is_neg = false;
+ abs_val = val - basis1;
+ }
+
+ if (N < 0)
+ is_neg = !is_neg;
+
+ if (!scale_u64_to_u64(abs_val,
+ ABS(N),
+ D,
+ &scaled,
+ is_neg))
+ return false; // overflow/undeflow
+
+ // if scaled is >= 0x8000<etc>, then we are going to overflow or
+ // underflow unless ABS(basis2) is large enough to pull us back into the
+ // non-overflow/underflow region.
+ if (scaled & INT64_MIN) {
+ if (is_neg && (basis2 < 0))
+ return false; // certain underflow
+
+ if (!is_neg && (basis2 >= 0))
+ return false; // certain overflow
+
+ if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+ return false; // not enough
+
+ // Looks like we are OK
+ *out = (is_neg ? (-scaled) : scaled) + basis2;
+ } else {
+ // Scaled fits within signed bounds, so we just need to check for
+ // over/underflow for two signed integers. Basically, if both scaled
+ // and basis2 have the same sign bit, and the result has a different
+ // sign bit, then we have under/overflow. An easy way to compute this
+ // is
+ // (scaled_signbit XNOR basis_signbit) &&
+ // (scaled_signbit XOR res_signbit)
+ // ==
+ // (scaled_signbit XOR basis_signbit XOR 1) &&
+ // (scaled_signbit XOR res_signbit)
+
+ if (is_neg)
+ scaled = -scaled;
+ res = scaled + basis2;
+
+ if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+ return false;
+
+ *out = res;
+ }
+
+ return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+ if (0 == a_to_b_denom)
+ return false;
+
+ return linear_transform_s64_to_s64(a_in,
+ a_zero,
+ a_to_b_numer,
+ a_to_b_denom,
+ b_zero,
+ b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+ if (0 == a_to_b_numer)
+ return false;
+
+ return linear_transform_s64_to_s64(b_in,
+ b_zero,
+ a_to_b_denom,
+ a_to_b_numer,
+ a_zero,
+ a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+ T a, b;
+ if (!N || !D || !(*D)) {
+ assert(false);
+ return;
+ }
+
+ a = *N;
+ b = *D;
+
+ if (a == 0) {
+ *D = 1;
+ return;
+ }
+
+ // This implements Euclid's method to find GCD.
+ if (a < b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ while (1) {
+ // a is now the greater of the two.
+ const T remainder = a % b;
+ if (remainder == 0) {
+ *N /= b;
+ *D /= b;
+ return;
+ }
+ // by swapping remainder and b, we are guaranteeing that a is
+ // still the greater of the two upon entrance to the loop.
+ a = b;
+ b = remainder;
+ }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+ if (N && D && *D) {
+ if (*N < 0) {
+ *N = -(*N);
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ *N = -(*N);
+ } else {
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ }
+ }
+}
+
+} // namespace android
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 48ce5d1..50312e7 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -316,6 +316,10 @@ int androidSetThreadSchedulingGroup(pid_t tid, int grp)
#if defined(HAVE_PTHREADS)
pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
if (gDoSchedulingGroup) {
+ // set_sched_policy does not support tid == 0
+ if (tid == 0) {
+ tid = androidGetTid();
+ }
if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
SP_BACKGROUND : SP_FOREGROUND)) {
return PERMISSION_DENIED;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index a774841..33125c4 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -103,6 +103,11 @@ void DisplayHardware::init(uint32_t dpy)
{
mNativeWindow = new FramebufferNativeWindow();
framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+ if (!fbDev) {
+ LOGE("Display subsystem failed to initialize. check logs. exiting...");
+ exit(0);
+ }
+
mDpiX = mNativeWindow->xdpi;
mDpiY = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
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 @@ 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 97edfee..cccab4a 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,17 +68,19 @@
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),
- mTransactionCount(0),
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),
@@ -160,9 +163,34 @@ void SurfaceFlinger::bootFinished()
const nsecs_t duration = now - mBootTime;
LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mBootFinished = true;
+
+ // wait patiently for the window manager death
+ const String16 name("window");
+ sp<IBinder> window(defaultServiceManager()->getService(name));
+ if (window != 0) {
+ window->linkToDeath(this);
+ }
+
+ // stop boot animation
property_set("ctl.stop", "bootanim");
}
+void SurfaceFlinger::binderDied(const wp<IBinder>& who)
+{
+ // the window manager died on us. prepare its eulogy.
+
+ // unfreeze the screen in case it was... frozen
+ mFreezeDisplayTime = 0;
+ mFreezeCount = 0;
+ mFreezeDisplay = false;
+
+ // reset screen orientation
+ setOrientation(0, eOrientationDefault, 0);
+
+ // restart the boot-animation
+ property_set("ctl.start", "bootanim");
+}
+
void SurfaceFlinger::onFirstRef()
{
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
@@ -381,13 +409,11 @@ bool SurfaceFlinger::threadLoop()
handleConsoleEvents();
}
- if (LIKELY(mTransactionCount == 0)) {
- // if we're in a global transaction, don't do anything.
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
- if (LIKELY(transactionFlags)) {
- handleTransaction(transactionFlags);
- }
+ // if we're in a global transaction, don't do anything.
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ uint32_t transactionFlags = peekTransactionFlags(mask);
+ if (UNLIKELY(transactionFlags)) {
+ handleTransaction(transactionFlags);
}
// post surfaces (if needed)
@@ -1172,28 +1198,33 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
return old;
}
-void SurfaceFlinger::openGlobalTransaction()
-{
- android_atomic_inc(&mTransactionCount);
-}
-void SurfaceFlinger::closeGlobalTransaction()
-{
- if (android_atomic_dec(&mTransactionCount) == 1) {
- signalEvent();
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
+ Mutex::Autolock _l(mStateLock);
- // if there is a transaction with a resize, wait for it to
- // take effect before returning.
- Mutex::Autolock _l(mStateLock);
- while (mResizeTransationPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
- mResizeTransationPending = false;
- break;
- }
+ uint32_t flags = 0;
+ const size_t count = state.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const ComposerState& s(state[i]);
+ sp<Client> client( static_cast<Client *>(s.client.get()) );
+ flags |= setClientStateLocked(client, s.state);
+ }
+ if (flags) {
+ setTransactionFlags(flags);
+ }
+
+ signalEvent();
+
+ // if there is a transaction with a resize, wait for it to
+ // take effect before returning.
+ while (mResizeTransationPending) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+ mResizeTransationPending = false;
+ break;
}
}
}
@@ -1389,60 +1420,52 @@ status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
return err;
}
-status_t SurfaceFlinger::setClientState(
+uint32_t SurfaceFlinger::setClientStateLocked(
const sp<Client>& client,
- int32_t count,
- const layer_state_t* states)
+ const layer_state_t& s)
{
- Mutex::Autolock _l(mStateLock);
uint32_t flags = 0;
- for (int i=0 ; i<count ; i++) {
- const layer_state_t& s(states[i]);
- sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- if (what & ePositionChanged) {
- if (layer->setPosition(s.x, s.y))
- flags |= eTraversalNeeded;
- }
- if (what & eLayerChanged) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- if (what & eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- mResizeTransationPending = true;
- }
- }
- if (what & eAlphaChanged) {
- if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
- flags |= eTraversalNeeded;
- }
- if (what & eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
- flags |= eTraversalNeeded;
- }
- if (what & eTransparentRegionChanged) {
- if (layer->setTransparentRegionHint(s.transparentRegion))
- flags |= eTraversalNeeded;
+ sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+ if (layer != 0) {
+ const uint32_t what = s.what;
+ if (what & ePositionChanged) {
+ if (layer->setPosition(s.x, s.y))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eLayerChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setLayer(s.z)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
}
- if (what & eVisibilityChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
+ }
+ if (what & eSizeChanged) {
+ if (layer->setSize(s.w, s.h)) {
+ flags |= eTraversalNeeded;
+ mResizeTransationPending = true;
}
}
+ if (what & eAlphaChanged) {
+ if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eMatrixChanged) {
+ if (layer->setMatrix(s.matrix))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eTransparentRegionChanged) {
+ if (layer->setTransparentRegionHint(s.transparentRegion))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eVisibilityChanged) {
+ if (layer->setFlags(s.flags, s.mask))
+ flags |= eTraversalNeeded;
+ }
}
- if (flags) {
- setTransactionFlags(flags);
- }
- return NO_ERROR;
+ return flags;
}
void SurfaceFlinger::screenReleased(int dpy)
@@ -1464,7 +1487,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(),
@@ -1583,8 +1607,7 @@ status_t SurfaceFlinger::onTransact(
{
switch (code) {
case CREATE_CONNECTION:
- case OPEN_GLOBAL_TRANSACTION:
- case CLOSE_GLOBAL_TRANSACTION:
+ case SET_TRANSACTION_STATE:
case SET_ORIENTATION:
case FREEZE_DISPLAY:
case UNFREEZE_DISPLAY:
@@ -1596,7 +1619,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 +1633,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 +1646,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();
@@ -1799,10 +1824,10 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
const GLfloat h = hw_h - (hw_h * v);
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y;
- vtx[2] = x; vtx[3] = y + h;
- vtx[4] = x + w; vtx[5] = y + h;
- vtx[6] = x + w; vtx[7] = y;
+ vtx[0] = x; vtx[1] = y + h;
+ vtx[2] = x; vtx[3] = y;
+ vtx[4] = x + w; vtx[5] = y;
+ vtx[6] = x + w; vtx[7] = y + h;
}
};
@@ -1817,10 +1842,10 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
const GLfloat h = 1.0f;
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y;
- vtx[2] = x; vtx[3] = y + h;
- vtx[4] = x + w; vtx[5] = y + h;
- vtx[6] = x + w; vtx[7] = y;
+ vtx[0] = x; vtx[1] = y + h;
+ vtx[2] = x; vtx[3] = y;
+ vtx[4] = x + w; vtx[5] = y;
+ vtx[6] = x + w; vtx[7] = y + h;
}
};
@@ -2404,8 +2429,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);
@@ -2463,9 +2487,6 @@ sp<ISurface> Client::createSurface(
status_t Client::destroySurface(SurfaceID sid) {
return mFlinger->removeSurface(this, sid);
}
-status_t Client::setState(int32_t count, const layer_state_t* states) {
- return mFlinger->setClientState(this, count, states);
-}
// ---------------------------------------------------------------------------
@@ -2474,11 +2495,14 @@ GraphicBufferAlloc::GraphicBufferAlloc() {}
GraphicBufferAlloc::~GraphicBufferAlloc() {}
sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint32_t usage, status_t* error) {
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
status_t err = graphicBuffer->initCheck();
+ *error = err;
if (err != 0 || graphicBuffer->handle == 0) {
- GraphicBuffer::dumpAllocationsToSystemLog();
+ if (err == NO_MEMORY) {
+ GraphicBuffer::dumpAllocationsToSystemLog();
+ }
LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
"failed (%s), handle=%p",
w, h, strerror(-err), graphicBuffer->handle);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index af1ef04..15661f0 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"
@@ -71,14 +70,12 @@ public:
sp<LayerBaseClient> getLayerUser(int32_t i) const;
private:
-
// ISurfaceComposerClient interface
virtual sp<ISurface> createSurface(
surface_data_t* params, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
- virtual status_t setState(int32_t count, const layer_state_t* states);
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
@@ -99,7 +96,7 @@ public:
GraphicBufferAlloc();
virtual ~GraphicBufferAlloc();
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage);
+ PixelFormat format, uint32_t usage, status_t* error);
};
// ---------------------------------------------------------------------------
@@ -150,6 +147,7 @@ enum {
class SurfaceFlinger :
public BinderService<SurfaceFlinger>,
public BnSurfaceComposer,
+ public IBinder::DeathRecipient,
protected Thread
{
public:
@@ -169,8 +167,7 @@ public:
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
- virtual void openGlobalTransaction();
- virtual void closeGlobalTransaction();
+ virtual void setTransactionState(const Vector<ComposerState>& state);
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
@@ -197,6 +194,10 @@ public:
sp<Layer> getLayer(const sp<ISurface>& sur) const;
private:
+ // DeathRecipient interface
+ virtual void binderDied(const wp<IBinder>& who);
+
+private:
friend class Client;
friend class LayerBase;
friend class LayerBaseClient;
@@ -221,8 +222,7 @@ private:
status_t removeSurface(const sp<Client>& client, SurfaceID sid);
status_t destroySurface(const wp<LayerBaseClient>& layer);
- status_t setClientState(const sp<Client>& client,
- int32_t count, const layer_state_t* states);
+ uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
class LayerVector : public SortedVector< sp<LayerBase> > {
public:
@@ -338,7 +338,6 @@ private:
mutable Mutex mStateLock;
State mCurrentState;
volatile int32_t mTransactionFlags;
- volatile int32_t mTransactionCount;
Condition mTransactionCV;
SortedVector< sp<LayerBase> > mLayerPurgatory;
bool mResizeTransationPending;
@@ -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;
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 18c54b3..56b2a8f 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -43,9 +43,9 @@ int main(int argc, char** argv)
PIXEL_FORMAT_RGB_565);
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surface->setLayer(100000);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
Surface::SurfaceInfo info;
surface->lock(&info);
@@ -57,9 +57,9 @@ int main(int argc, char** argv)
android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
surface->unlockAndPost();
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surface->setSize(320, 240);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
IPCThreadState::self()->joinThreadPool();
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 5265f91..8e1c3fe 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -39,9 +39,9 @@ int main(int argc, char** argv)
sp<SurfaceControl> surfaceControl = client->createSurface(
getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565);
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setLayer(100000);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
// pretend it went cross-process
Parcel parcel;
diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl
deleted file mode 100644
index 6bf3edd..0000000
--- a/vpn/java/android/net/vpn/IVpnService.aidl
+++ /dev/null
@@ -1,50 +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.
- */
-
-package android.net.vpn;
-
-import android.net.vpn.VpnProfile;
-
-/**
- * Interface to access a VPN service.
- * {@hide}
- */
-interface IVpnService {
- /**
- * Sets up a VPN connection.
- * @param profile the profile object
- * @param username the username for authentication
- * @param password the corresponding password for authentication
- * @return true if VPN is successfully connected
- */
- boolean connect(in VpnProfile profile, String username, String password);
-
- /**
- * Tears down the VPN connection.
- */
- void disconnect();
-
- /**
- * Gets the the current connection state.
- */
- String getState(in VpnProfile profile);
-
- /**
- * Returns the idle state.
- * @return true if the system is not connecting/connected to a VPN
- */
- boolean isIdle();
-}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecProfile.java b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
deleted file mode 100644
index 4ae2dec..0000000
--- a/vpn/java/android/net/vpn/L2tpIpsecProfile.java
+++ /dev/null
@@ -1,65 +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.
- */
-
-package android.net.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for certificate-based L2TP-over-IPSec type of VPN.
- * {@hide}
- */
-public class L2tpIpsecProfile extends L2tpProfile {
- private static final long serialVersionUID = 1L;
-
- private String mUserCertificate;
- private String mCaCertificate;
-
- @Override
- public VpnType getType() {
- return VpnType.L2TP_IPSEC;
- }
-
- public void setCaCertificate(String name) {
- mCaCertificate = name;
- }
-
- public String getCaCertificate() {
- return mCaCertificate;
- }
-
- public void setUserCertificate(String name) {
- mUserCertificate = name;
- }
-
- public String getUserCertificate() {
- return mUserCertificate;
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- super.readFromParcel(in);
- mCaCertificate = in.readString();
- mUserCertificate = in.readString();
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeString(mCaCertificate);
- parcel.writeString(mUserCertificate);
- }
-}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java b/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
deleted file mode 100644
index 7a03018..0000000
--- a/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
+++ /dev/null
@@ -1,54 +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.
- */
-
-package android.net.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for pre-shared-key-based L2TP-over-IPSec type of VPN.
- * {@hide}
- */
-public class L2tpIpsecPskProfile extends L2tpProfile {
- private static final long serialVersionUID = 1L;
-
- private String mPresharedKey;
-
- @Override
- public VpnType getType() {
- return VpnType.L2TP_IPSEC_PSK;
- }
-
- public void setPresharedKey(String key) {
- mPresharedKey = key;
- }
-
- public String getPresharedKey() {
- return mPresharedKey;
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- super.readFromParcel(in);
- mPresharedKey = in.readString();
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeString(mPresharedKey);
- }
-}
diff --git a/vpn/java/android/net/vpn/L2tpProfile.java b/vpn/java/android/net/vpn/L2tpProfile.java
deleted file mode 100644
index dbba0c5..0000000
--- a/vpn/java/android/net/vpn/L2tpProfile.java
+++ /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.
- */
-
-package android.net.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for L2TP type of VPN.
- * {@hide}
- */
-public class L2tpProfile extends VpnProfile {
- private static final long serialVersionUID = 1L;
-
- private boolean mSecret;
- private String mSecretString;
-
- @Override
- public VpnType getType() {
- return VpnType.L2TP;
- }
-
- /**
- * Enables/disables the secret for authenticating tunnel connection.
- */
- public void setSecretEnabled(boolean enabled) {
- mSecret = enabled;
- }
-
- public boolean isSecretEnabled() {
- return mSecret;
- }
-
- public void setSecretString(String secret) {
- mSecretString = secret;
- }
-
- public String getSecretString() {
- return mSecretString;
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- super.readFromParcel(in);
- mSecret = in.readInt() > 0;
- mSecretString = in.readString();
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeInt(mSecret ? 1 : 0);
- parcel.writeString(mSecretString);
- }
-}
diff --git a/vpn/java/android/net/vpn/PptpProfile.java b/vpn/java/android/net/vpn/PptpProfile.java
deleted file mode 100644
index b4b7be5..0000000
--- a/vpn/java/android/net/vpn/PptpProfile.java
+++ /dev/null
@@ -1,56 +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.
- */
-
-package android.net.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for PPTP type of VPN.
- * {@hide}
- */
-public class PptpProfile extends VpnProfile {
- private static final long serialVersionUID = 1L;
- private boolean mEncryption = true;
-
- @Override
- public VpnType getType() {
- return VpnType.PPTP;
- }
-
- /**
- * Enables/disables the encryption for PPTP tunnel.
- */
- public void setEncryptionEnabled(boolean enabled) {
- mEncryption = enabled;
- }
-
- public boolean isEncryptionEnabled() {
- return mEncryption;
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- super.readFromParcel(in);
- mEncryption = in.readInt() > 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeInt(mEncryption ? 1 : 0);
- }
-}
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
deleted file mode 100644
index 02486bb..0000000
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ /dev/null
@@ -1,242 +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.
- */
-
-package android.net.vpn;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Environment;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import com.android.server.vpn.VpnServiceBinder;
-
-/**
- * The class provides interface to manage all VPN-related tasks, including:
- * <ul>
- * <li>The list of supported VPN types.
- * <li>API's to start/stop the service of a particular type.
- * <li>API's to start the settings activity.
- * <li>API's to create a profile.
- * <li>API's to register/unregister a connectivity receiver and the keys to
- * access the fields in a connectivity broadcast event.
- * </ul>
- * {@hide}
- */
-public class VpnManager {
- /** Key to the profile name of a connectivity broadcast event. */
- public static final String BROADCAST_PROFILE_NAME = "profile_name";
- /** Key to the connectivity state of a connectivity broadcast event. */
- public static final String BROADCAST_CONNECTION_STATE = "connection_state";
- /** Key to the error code of a connectivity broadcast event. */
- public static final String BROADCAST_ERROR_CODE = "err";
- /** Error code to indicate an error from authentication. */
- public static final int VPN_ERROR_AUTH = 51;
- /** Error code to indicate the connection attempt failed. */
- public static final int VPN_ERROR_CONNECTION_FAILED = 101;
- /** Error code to indicate the server is not known. */
- public static final int VPN_ERROR_UNKNOWN_SERVER = 102;
- /** Error code to indicate an error from challenge response. */
- public static final int VPN_ERROR_CHALLENGE = 5;
- /** Error code to indicate an error of remote server hanging up. */
- public static final int VPN_ERROR_REMOTE_HUNG_UP = 7;
- /** Error code to indicate an error of remote PPP server hanging up. */
- public static final int VPN_ERROR_REMOTE_PPP_HUNG_UP = 48;
- /** Error code to indicate a PPP negotiation error. */
- public static final int VPN_ERROR_PPP_NEGOTIATION_FAILED = 42;
- /** Error code to indicate an error of losing connectivity. */
- public static final int VPN_ERROR_CONNECTION_LOST = 103;
- /** Largest error code used by VPN. */
- public static final int VPN_ERROR_LARGEST = 200;
- /** Error code to indicate a successful connection. */
- public static final int VPN_ERROR_NO_ERROR = 0;
-
- public static final String PROFILES_PATH = "/misc/vpn/profiles";
-
- private static final String PACKAGE_PREFIX =
- VpnManager.class.getPackage().getName() + ".";
-
- // Action for broadcasting a connectivity state.
- private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
-
- private static final String VPN_SERVICE_NAME = "vpn";
-
- // Action to start VPN settings
- private static final String ACTION_VPN_SETTINGS =
- PACKAGE_PREFIX + "SETTINGS";
-
- public static final String TAG = VpnManager.class.getSimpleName();
-
- // TODO(oam): Test VPN when EFS is enabled (will do later)...
- public static String getProfilePath() {
- // This call will return the correct path if Encrypted FS is enabled or not.
- return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH;
- }
-
- /**
- * Returns all supported VPN types.
- */
- public static VpnType[] getSupportedVpnTypes() {
- return VpnType.values();
- }
-
- public static void startVpnService(Context c) {
- ServiceManager.addService(VPN_SERVICE_NAME, new VpnServiceBinder(c));
- }
-
- private Context mContext;
- private IVpnService mVpnService;
-
- /**
- * Creates a manager object with the specified context.
- */
- public VpnManager(Context c) {
- mContext = c;
- createVpnServiceClient();
- }
-
- private void createVpnServiceClient() {
- IBinder b = ServiceManager.getService(VPN_SERVICE_NAME);
- mVpnService = IVpnService.Stub.asInterface(b);
- }
-
- /**
- * Sets up a VPN connection.
- * @param profile the profile object
- * @param username the username for authentication
- * @param password the corresponding password for authentication
- * @return true if VPN is successfully connected
- */
- public boolean connect(VpnProfile p, String username, String password) {
- try {
- return mVpnService.connect(p, username, password);
- } catch (RemoteException e) {
- Log.e(TAG, "connect()", e);
- return false;
- }
- }
-
- /**
- * Tears down the VPN connection.
- */
- public void disconnect() {
- try {
- mVpnService.disconnect();
- } catch (RemoteException e) {
- Log.e(TAG, "disconnect()", e);
- }
- }
-
- /**
- * Gets the the current connection state.
- */
- public VpnState getState(VpnProfile p) {
- try {
- return Enum.valueOf(VpnState.class, mVpnService.getState(p));
- } catch (RemoteException e) {
- Log.e(TAG, "getState()", e);
- return VpnState.IDLE;
- }
- }
-
- /**
- * Returns the idle state.
- * @return true if the system is not connecting/connected to a VPN
- */
- public boolean isIdle() {
- try {
- return mVpnService.isIdle();
- } catch (RemoteException e) {
- Log.e(TAG, "isIdle()", e);
- return true;
- }
- }
-
- /**
- * Creates a VPN profile of the specified type.
- *
- * @param type the VPN type
- * @return the profile object
- */
- public VpnProfile createVpnProfile(VpnType type) {
- return createVpnProfile(type, false);
- }
-
- /**
- * Creates a VPN profile of the specified type.
- *
- * @param type the VPN type
- * @param customized true if the profile is custom made
- * @return the profile object
- */
- public VpnProfile createVpnProfile(VpnType type, boolean customized) {
- try {
- VpnProfile p = (VpnProfile) type.getProfileClass().newInstance();
- p.setCustomized(customized);
- return p;
- } catch (InstantiationException e) {
- return null;
- } catch (IllegalAccessException e) {
- return null;
- }
- }
-
- /** Broadcasts the connectivity state of the specified profile. */
- public void broadcastConnectivity(String profileName, VpnState s) {
- broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR);
- }
-
- /** Broadcasts the connectivity state with an error code. */
- public void broadcastConnectivity(String profileName, VpnState s,
- int error) {
- Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
- intent.putExtra(BROADCAST_PROFILE_NAME, profileName);
- intent.putExtra(BROADCAST_CONNECTION_STATE, s);
- if (error != VPN_ERROR_NO_ERROR) {
- intent.putExtra(BROADCAST_ERROR_CODE, error);
- }
- mContext.sendBroadcast(intent);
- }
-
- public void registerConnectivityReceiver(BroadcastReceiver r) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY);
- mContext.registerReceiver(r, filter);
- }
-
- public void unregisterConnectivityReceiver(BroadcastReceiver r) {
- mContext.unregisterReceiver(r);
- }
-
- /** Starts the VPN settings activity. */
- public void startSettingsActivity() {
- Intent intent = new Intent(ACTION_VPN_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- }
-
- /** Creates an intent to start the VPN settings activity. */
- public Intent createSettingsActivityIntent() {
- Intent intent = new Intent(ACTION_VPN_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return intent;
- }
-}
diff --git a/vpn/java/android/net/vpn/VpnProfile.aidl b/vpn/java/android/net/vpn/VpnProfile.aidl
deleted file mode 100644
index edeaef0..0000000
--- a/vpn/java/android/net/vpn/VpnProfile.aidl
+++ /dev/null
@@ -1,19 +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.
- */
-
-package android.net.vpn;
-
-parcelable VpnProfile;
diff --git a/vpn/java/android/net/vpn/VpnProfile.java b/vpn/java/android/net/vpn/VpnProfile.java
deleted file mode 100644
index bd6c809..0000000
--- a/vpn/java/android/net/vpn/VpnProfile.java
+++ /dev/null
@@ -1,177 +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.
- */
-
-package android.net.vpn;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-/**
- * A VPN profile.
- * {@hide}
- */
-public abstract class VpnProfile implements Parcelable, Serializable {
- private static final long serialVersionUID = 1L;
- private String mName; // unique display name
- private String mId; // unique identifier
- private String mServerName; // VPN server name
- private String mDomainSuffices; // space separated list
- private String mRouteList; // space separated list
- private String mSavedUsername;
- private boolean mIsCustomized;
- private transient VpnState mState = VpnState.IDLE;
-
- /** Sets a user-friendly name for this profile. */
- public void setName(String name) {
- mName = name;
- }
-
- public String getName() {
- return mName;
- }
-
- /**
- * Sets an ID for this profile. The caller should make sure the
- * uniqueness of the ID.
- */
- public void setId(String id) {
- mId = id;
- }
-
- public String getId() {
- return mId;
- }
-
- /**
- * Sets the name of the VPN server. Used for DNS lookup.
- */
- public void setServerName(String name) {
- mServerName = name;
- }
-
- public String getServerName() {
- return mServerName;
- }
-
- /**
- * Sets the domain suffices for DNS resolution.
- *
- * @param entries a comma-separated list of domain suffices
- */
- public void setDomainSuffices(String entries) {
- mDomainSuffices = entries;
- }
-
- public String getDomainSuffices() {
- return mDomainSuffices;
- }
-
- /**
- * Sets the routing info for this VPN connection.
- *
- * @param entries a comma-separated list of routes; each entry is in the
- * format of "(network address)/(network mask)"
- */
- public void setRouteList(String entries) {
- mRouteList = entries;
- }
-
- public String getRouteList() {
- return mRouteList;
- }
-
- public void setSavedUsername(String name) {
- mSavedUsername = name;
- }
-
- public String getSavedUsername() {
- return mSavedUsername;
- }
-
- public void setState(VpnState state) {
- mState = state;
- }
-
- public VpnState getState() {
- return ((mState == null) ? VpnState.IDLE : mState);
- }
-
- public boolean isIdle() {
- return (mState == VpnState.IDLE);
- }
-
- /**
- * Returns whether this profile is custom made (as opposed to being
- * created by provided user interface).
- */
- public boolean isCustomized() {
- return mIsCustomized;
- }
-
- /**
- * Returns the VPN type of the profile.
- */
- public abstract VpnType getType();
-
- void setCustomized(boolean customized) {
- mIsCustomized = customized;
- }
-
- protected void readFromParcel(Parcel in) {
- mName = in.readString();
- mId = in.readString();
- mServerName = in.readString();
- mDomainSuffices = in.readString();
- mRouteList = in.readString();
- mSavedUsername = in.readString();
- }
-
- public static final Parcelable.Creator<VpnProfile> CREATOR =
- new Parcelable.Creator<VpnProfile>() {
- public VpnProfile createFromParcel(Parcel in) {
- VpnType type = Enum.valueOf(VpnType.class, in.readString());
- boolean customized = in.readInt() > 0;
- VpnProfile p = new VpnManager(null).createVpnProfile(type,
- customized);
- if (p == null) return null;
- p.readFromParcel(in);
- return p;
- }
-
- public VpnProfile[] newArray(int size) {
- return new VpnProfile[size];
- }
- };
-
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeString(getType().toString());
- parcel.writeInt(mIsCustomized ? 1 : 0);
- parcel.writeString(mName);
- parcel.writeString(mId);
- parcel.writeString(mServerName);
- parcel.writeString(mDomainSuffices);
- parcel.writeString(mRouteList);
- parcel.writeString(mSavedUsername);
- }
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java
deleted file mode 100644
index 6e61f9c..0000000
--- a/vpn/java/android/net/vpn/VpnState.java
+++ /dev/null
@@ -1,38 +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.
- */
-
-package android.net.vpn;
-
-/**
- * Enumeration of all VPN states.
- *
- * A normal VPN connection lifetime starts in {@link IDLE}. When a new
- * connection is about to be set up, it goes to {@link CONNECTING} and then
- * {@link CONNECTED} if successful; back to {@link IDLE} if failed.
- * When the connection is about to be torn down, it goes to
- * {@link DISCONNECTING} and then {@link IDLE}.
- * {@link CANCELLED} is a state when a VPN connection attempt is aborted, and
- * is in transition to {@link IDLE}.
- * The {@link UNUSABLE} state indicates that the profile is not in a state for
- * connecting due to possibly the integrity of the fields or another profile is
- * connecting etc.
- * The {@link UNKNOWN} state indicates that the profile state is to be
- * determined.
- * {@hide}
- */
-public enum VpnState {
- CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE, UNUSABLE, UNKNOWN
-}
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
deleted file mode 100644
index 356f8b1..0000000
--- a/vpn/java/android/net/vpn/VpnType.java
+++ /dev/null
@@ -1,55 +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.
- */
-
-package android.net.vpn;
-
-import com.android.internal.R;
-
-/**
- * Enumeration of all supported VPN types.
- * {@hide}
- */
-public enum VpnType {
- PPTP("PPTP", R.string.pptp_vpn_description, PptpProfile.class),
- L2TP("L2TP", R.string.l2tp_vpn_description, L2tpProfile.class),
- L2TP_IPSEC_PSK("L2TP/IPSec PSK", R.string.l2tp_ipsec_psk_vpn_description,
- L2tpIpsecPskProfile.class),
- L2TP_IPSEC("L2TP/IPSec CRT", R.string.l2tp_ipsec_crt_vpn_description,
- L2tpIpsecProfile.class);
-
- private String mDisplayName;
- private int mDescriptionId;
- private Class<? extends VpnProfile> mClass;
-
- VpnType(String displayName, int descriptionId,
- Class<? extends VpnProfile> klass) {
- mDisplayName = displayName;
- mDescriptionId = descriptionId;
- mClass = klass;
- }
-
- public String getDisplayName() {
- return mDisplayName;
- }
-
- public int getDescriptionId() {
- return mDescriptionId;
- }
-
- public Class<? extends VpnProfile> getProfileClass() {
- return mClass;
- }
-}
diff --git a/vpn/java/com/android/server/vpn/DaemonProxy.java b/vpn/java/com/android/server/vpn/DaemonProxy.java
deleted file mode 100644
index 289ee45..0000000
--- a/vpn/java/com/android/server/vpn/DaemonProxy.java
+++ /dev/null
@@ -1,199 +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.
- */
-
-package com.android.server.vpn;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.net.vpn.VpnManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-
-/**
- * Proxy to start, stop and interact with a VPN daemon.
- * The daemon is expected to accept connection through Unix domain socket.
- * When the proxy successfully starts the daemon, it will establish a socket
- * connection with the daemon, to both send commands to the daemon and receive
- * response and connecting error code from the daemon.
- */
-class DaemonProxy implements Serializable {
- private static final long serialVersionUID = 1L;
- private static final boolean DBG = true;
-
- private static final int WAITING_TIME = 15; // sec
-
- private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
- private static final String SVC_START_CMD = "ctl.start";
- private static final String SVC_STOP_CMD = "ctl.stop";
- private static final String SVC_STATE_RUNNING = "running";
- private static final String SVC_STATE_STOPPED = "stopped";
-
- private static final int END_OF_ARGUMENTS = 255;
-
- private String mName;
- private String mTag;
- private transient LocalSocket mControlSocket;
-
- /**
- * Creates a proxy of the specified daemon.
- * @param daemonName name of the daemon
- */
- DaemonProxy(String daemonName) {
- mName = daemonName;
- mTag = "SProxy_" + daemonName;
- }
-
- String getName() {
- return mName;
- }
-
- void start() throws IOException {
- String svc = mName;
-
- Log.i(mTag, "Start VPN daemon: " + svc);
- SystemProperties.set(SVC_START_CMD, svc);
-
- if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
- throw new IOException("cannot start service: " + svc);
- } else {
- mControlSocket = createServiceSocket();
- }
- }
-
- void sendCommand(String ...args) throws IOException {
- OutputStream out = getControlSocketOutput();
- for (String arg : args) outputString(out, arg);
- out.write(END_OF_ARGUMENTS);
- out.flush();
-
- int result = getResultFromSocket(true);
- if (result != args.length) {
- throw new IOException("socket error, result from service: "
- + result);
- }
- }
-
- // returns 0 if nothing is in the receive buffer
- int getResultFromSocket() throws IOException {
- return getResultFromSocket(false);
- }
-
- void closeControlSocket() {
- if (mControlSocket == null) return;
- try {
- mControlSocket.close();
- } catch (IOException e) {
- Log.w(mTag, "close control socket", e);
- } finally {
- mControlSocket = null;
- }
- }
-
- void stop() {
- String svc = mName;
- Log.i(mTag, "Stop VPN daemon: " + svc);
- SystemProperties.set(SVC_STOP_CMD, svc);
- boolean success = blockUntil(SVC_STATE_STOPPED, 5);
- if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success);
- }
-
- boolean isStopped() {
- String cmd = SVC_STATE_CMD_PREFIX + mName;
- return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd));
- }
-
- private int getResultFromSocket(boolean blocking) throws IOException {
- LocalSocket s = mControlSocket;
- if (s == null) return 0;
- InputStream in = s.getInputStream();
- if (!blocking && in.available() == 0) return 0;
-
- int data = in.read();
- Log.i(mTag, "got data from control socket: " + data);
-
- return data;
- }
-
- private LocalSocket createServiceSocket() throws IOException {
- LocalSocket s = new LocalSocket();
- LocalSocketAddress a = new LocalSocketAddress(mName,
- LocalSocketAddress.Namespace.RESERVED);
-
- // try a few times in case the service has not listen()ed
- IOException excp = null;
- for (int i = 0; i < 10; i++) {
- try {
- s.connect(a);
- return s;
- } catch (IOException e) {
- if (DBG) Log.d(mTag, "service not yet listen()ing; try again");
- excp = e;
- sleep(500);
- }
- }
- throw excp;
- }
-
- private OutputStream getControlSocketOutput() throws IOException {
- if (mControlSocket != null) {
- return mControlSocket.getOutputStream();
- } else {
- throw new IOException("no control socket available");
- }
- }
-
- /**
- * Waits for the process to be in the expected state. The method returns
- * false if after the specified duration (in seconds), the process is still
- * not in the expected state.
- */
- private boolean blockUntil(String expectedState, int waitTime) {
- String cmd = SVC_STATE_CMD_PREFIX + mName;
- int sleepTime = 200; // ms
- int n = waitTime * 1000 / sleepTime;
- for (int i = 0; i < n; i++) {
- if (expectedState.equals(SystemProperties.get(cmd))) {
- if (DBG) {
- Log.d(mTag, mName + " is " + expectedState + " after "
- + (i * sleepTime) + " msec");
- }
- break;
- }
- sleep(sleepTime);
- }
- return expectedState.equals(SystemProperties.get(cmd));
- }
-
- private void outputString(OutputStream out, String s) throws IOException {
- byte[] bytes = s.getBytes();
- out.write(bytes.length);
- out.write(bytes);
- out.flush();
- }
-
- private void sleep(int msec) {
- try {
- Thread.currentThread().sleep(msec);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java b/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
deleted file mode 100644
index 50e0de1..0000000
--- a/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
+++ /dev/null
@@ -1,47 +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.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpIpsecPskProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the preshared key based L2TP-over-IPSec VPN
- * connection.
- */
-class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> {
- private static final String IPSEC = "racoon";
-
- @Override
- protected void connect(String serverIp, String username, String password)
- throws IOException {
- L2tpIpsecPskProfile p = getProfile();
- VpnDaemons daemons = getDaemons();
-
- // IPSEC
- daemons.startIpsecForL2tp(serverIp, p.getPresharedKey())
- .closeControlSocket();
-
- sleep(2000); // 2 seconds
-
- // L2TP
- daemons.startL2tp(serverIp,
- (p.isSecretEnabled() ? p.getSecretString() : null),
- username, password);
- }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpIpsecService.java b/vpn/java/com/android/server/vpn/L2tpIpsecService.java
deleted file mode 100644
index 663b0e8..0000000
--- a/vpn/java/com/android/server/vpn/L2tpIpsecService.java
+++ /dev/null
@@ -1,50 +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.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpIpsecProfile;
-import android.security.Credentials;
-
-import java.io.IOException;
-
-/**
- * The service that manages the certificate based L2TP-over-IPSec VPN connection.
- */
-class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
- private static final String IPSEC = "racoon";
-
- @Override
- protected void connect(String serverIp, String username, String password)
- throws IOException {
- L2tpIpsecProfile p = getProfile();
- VpnDaemons daemons = getDaemons();
-
- // IPSEC
- DaemonProxy ipsec = daemons.startIpsecForL2tp(serverIp,
- Credentials.USER_PRIVATE_KEY + p.getUserCertificate(),
- Credentials.USER_CERTIFICATE + p.getUserCertificate(),
- Credentials.CA_CERTIFICATE + p.getCaCertificate());
- ipsec.closeControlSocket();
-
- sleep(2000); // 2 seconds
-
- // L2TP
- daemons.startL2tp(serverIp,
- (p.isSecretEnabled() ? p.getSecretString() : null),
- username, password);
- }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpService.java b/vpn/java/com/android/server/vpn/L2tpService.java
deleted file mode 100644
index 784a366..0000000
--- a/vpn/java/com/android/server/vpn/L2tpService.java
+++ /dev/null
@@ -1,35 +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.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the L2TP VPN connection.
- */
-class L2tpService extends VpnService<L2tpProfile> {
- @Override
- protected void connect(String serverIp, String username, String password)
- throws IOException {
- L2tpProfile p = getProfile();
- getDaemons().startL2tp(serverIp,
- (p.isSecretEnabled() ? p.getSecretString() : null),
- username, password);
- }
-}
diff --git a/vpn/java/com/android/server/vpn/PptpService.java b/vpn/java/com/android/server/vpn/PptpService.java
deleted file mode 100644
index de12710..0000000
--- a/vpn/java/com/android/server/vpn/PptpService.java
+++ /dev/null
@@ -1,34 +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.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.PptpProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the PPTP VPN connection.
- */
-class PptpService extends VpnService<PptpProfile> {
- @Override
- protected void connect(String serverIp, String username, String password)
- throws IOException {
- PptpProfile p = getProfile();
- getDaemons().startPptp(serverIp, username, password,
- p.isEncryptionEnabled());
- }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnConnectingError.java b/vpn/java/com/android/server/vpn/VpnConnectingError.java
deleted file mode 100644
index 3c4ec7d..0000000
--- a/vpn/java/com/android/server/vpn/VpnConnectingError.java
+++ /dev/null
@@ -1,35 +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.
- */
-
-package com.android.server.vpn;
-
-import java.io.IOException;
-
-/**
- * Exception thrown when a connecting attempt fails.
- */
-class VpnConnectingError extends IOException {
- private int mErrorCode;
-
- VpnConnectingError(int errorCode) {
- super("Connecting error: " + errorCode);
- mErrorCode = errorCode;
- }
-
- int getErrorCode() {
- return mErrorCode;
- }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnDaemons.java b/vpn/java/com/android/server/vpn/VpnDaemons.java
deleted file mode 100644
index 499195f..0000000
--- a/vpn/java/com/android/server/vpn/VpnDaemons.java
+++ /dev/null
@@ -1,147 +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.
- */
-
-package com.android.server.vpn;
-
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A helper class for managing native VPN daemons.
- */
-class VpnDaemons implements Serializable {
- static final long serialVersionUID = 1L;
- private final String TAG = VpnDaemons.class.getSimpleName();
-
- private static final String MTPD = "mtpd";
- private static final String IPSEC = "racoon";
-
- private static final String L2TP = "l2tp";
- private static final String L2TP_PORT = "1701";
-
- private static final String PPTP = "pptp";
- private static final String PPTP_PORT = "1723";
-
- private static final String VPN_LINKNAME = "vpn";
- private static final String PPP_ARGS_SEPARATOR = "";
-
- private List<DaemonProxy> mDaemonList = new ArrayList<DaemonProxy>();
-
- public DaemonProxy startL2tp(String serverIp, String secret,
- String username, String password) throws IOException {
- return startMtpd(L2TP, serverIp, L2TP_PORT, secret, username, password,
- false);
- }
-
- public DaemonProxy startPptp(String serverIp, String username,
- String password, boolean encryption) throws IOException {
- return startMtpd(PPTP, serverIp, PPTP_PORT, null, username, password,
- encryption);
- }
-
- public DaemonProxy startIpsecForL2tp(String serverIp, String pskKey)
- throws IOException {
- DaemonProxy ipsec = startDaemon(IPSEC);
- ipsec.sendCommand(serverIp, L2TP_PORT, pskKey);
- return ipsec;
- }
-
- public DaemonProxy startIpsecForL2tp(String serverIp, String userKeyKey,
- String userCertKey, String caCertKey) throws IOException {
- DaemonProxy ipsec = startDaemon(IPSEC);
- ipsec.sendCommand(serverIp, L2TP_PORT, userKeyKey, userCertKey,
- caCertKey);
- return ipsec;
- }
-
- public synchronized void stopAll() {
- new DaemonProxy(MTPD).stop();
- new DaemonProxy(IPSEC).stop();
- }
-
- public synchronized void closeSockets() {
- for (DaemonProxy s : mDaemonList) s.closeControlSocket();
- }
-
- public synchronized boolean anyDaemonStopped() {
- for (DaemonProxy s : mDaemonList) {
- if (s.isStopped()) {
- Log.w(TAG, " VPN daemon gone: " + s.getName());
- return true;
- }
- }
- return false;
- }
-
- public synchronized int getSocketError() {
- for (DaemonProxy s : mDaemonList) {
- int errCode = getResultFromSocket(s);
- if (errCode != 0) return errCode;
- }
- return 0;
- }
-
- private synchronized DaemonProxy startDaemon(String daemonName)
- throws IOException {
- DaemonProxy daemon = new DaemonProxy(daemonName);
- mDaemonList.add(daemon);
- daemon.start();
- return daemon;
- }
-
- private int getResultFromSocket(DaemonProxy s) {
- try {
- return s.getResultFromSocket();
- } catch (IOException e) {
- return -1;
- }
- }
-
- private DaemonProxy startMtpd(String protocol,
- String serverIp, String port, String secret, String username,
- String password, boolean encryption) throws IOException {
- ArrayList<String> args = new ArrayList<String>();
- args.addAll(Arrays.asList(protocol, serverIp, port));
- if (secret != null) args.add(secret);
- args.add(PPP_ARGS_SEPARATOR);
- addPppArguments(args, serverIp, username, password, encryption);
-
- DaemonProxy mtpd = startDaemon(MTPD);
- mtpd.sendCommand(args.toArray(new String[args.size()]));
- return mtpd;
- }
-
- private static void addPppArguments(ArrayList<String> args, String serverIp,
- String username, String password, boolean encryption)
- throws IOException {
- args.addAll(Arrays.asList(
- "linkname", VPN_LINKNAME,
- "name", username,
- "password", password,
- "refuse-eap", "nodefaultroute", "usepeerdns",
- "idle", "1800",
- "mtu", "1400",
- "mru", "1400"));
- if (encryption) {
- args.add("+mppe");
- }
- }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnService.java b/vpn/java/com/android/server/vpn/VpnService.java
deleted file mode 100644
index 4966c06..0000000
--- a/vpn/java/com/android/server/vpn/VpnService.java
+++ /dev/null
@@ -1,477 +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.
- */
-
-package com.android.server.vpn;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.R;
-
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.UnknownHostException;
-
-/**
- * The service base class for managing a type of VPN connection.
- */
-abstract class VpnService<E extends VpnProfile> {
- private static final boolean DBG = true;
- private static final int NOTIFICATION_ID = 1;
-
- private static final String DNS1 = "net.dns1";
- private static final String DNS2 = "net.dns2";
- private static final String VPN_DNS1 = "vpn.dns1";
- private static final String VPN_DNS2 = "vpn.dns2";
- private static final String VPN_STATUS = "vpn.status";
- private static final String VPN_IS_UP = "ok";
- private static final String VPN_IS_DOWN = "down";
-
- private static final String REMOTE_IP = "net.ipremote";
- private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
-
- private final String TAG = VpnService.class.getSimpleName();
-
- E mProfile;
- transient Context mContext;
-
- private VpnState mState = VpnState.IDLE;
- private Throwable mError;
-
- // connection settings
- private String mOriginalDns1;
- private String mOriginalDns2;
- private String mOriginalDomainSuffices;
- private String mLocalIp;
- private String mLocalIf;
-
- private long mStartTime; // VPN connection start time
-
- // for helping managing daemons
- private VpnDaemons mDaemons = new VpnDaemons();
-
- // for helping showing, updating notification
- private transient NotificationHelper mNotification;
-
- /**
- * Establishes a VPN connection with the specified username and password.
- */
- protected abstract void connect(String serverIp, String username,
- String password) throws IOException;
-
- /**
- * Returns the daemons management class for this service object.
- */
- protected VpnDaemons getDaemons() {
- return mDaemons;
- }
-
- /**
- * Returns the VPN profile associated with the connection.
- */
- protected E getProfile() {
- return mProfile;
- }
-
- /**
- * Returns the IP address of the specified host name.
- */
- protected String getIp(String hostName) throws IOException {
- return InetAddress.getByName(hostName).getHostAddress();
- }
-
- void setContext(Context context, E profile) {
- mProfile = profile;
- mContext = context;
- mNotification = new NotificationHelper();
-
- if (VpnState.CONNECTED.equals(mState)) {
- Log.i("VpnService", " recovered: " + mProfile.getName());
- startConnectivityMonitor();
- }
- }
-
- VpnState getState() {
- return mState;
- }
-
- boolean isIdle() {
- return (mState == VpnState.IDLE);
- }
-
- synchronized boolean onConnect(String username, String password) {
- try {
- setState(VpnState.CONNECTING);
-
- mDaemons.stopAll();
- String serverIp = getIp(getProfile().getServerName());
- saveLocalIpAndInterface(serverIp);
- onBeforeConnect();
- connect(serverIp, username, password);
- waitUntilConnectedOrTimedout();
- return true;
- } catch (Throwable e) {
- onError(e);
- return false;
- }
- }
-
- synchronized void onDisconnect() {
- try {
- Log.i(TAG, "disconnecting VPN...");
- setState(VpnState.DISCONNECTING);
- mNotification.showDisconnect();
-
- mDaemons.stopAll();
- } catch (Throwable e) {
- Log.e(TAG, "onDisconnect()", e);
- } finally {
- onFinalCleanUp();
- }
- }
-
- private void onError(Throwable error) {
- // error may occur during or after connection setup
- // and it may be due to one or all services gone
- if (mError != null) {
- Log.w(TAG, " multiple errors occur, record the last one: "
- + error);
- }
- Log.e(TAG, "onError()", error);
- mError = error;
- onDisconnect();
- }
-
- private void onError(int errorCode) {
- onError(new VpnConnectingError(errorCode));
- }
-
-
- private void onBeforeConnect() throws IOException {
- mNotification.disableNotification();
-
- SystemProperties.set(VPN_DNS1, "");
- SystemProperties.set(VPN_DNS2, "");
- SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
- if (DBG) {
- Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_STATUS));
- }
- }
-
- private void waitUntilConnectedOrTimedout() throws IOException {
- sleep(2000); // 2 seconds
- for (int i = 0; i < 80; i++) {
- if (mState != VpnState.CONNECTING) {
- break;
- } else if (VPN_IS_UP.equals(
- SystemProperties.get(VPN_STATUS))) {
- onConnected();
- return;
- } else {
- int err = mDaemons.getSocketError();
- if (err != 0) {
- onError(err);
- return;
- }
- }
- sleep(500); // 0.5 second
- }
-
- if (mState == VpnState.CONNECTING) {
- onError(new IOException("Connecting timed out"));
- }
- }
-
- private synchronized void onConnected() throws IOException {
- if (DBG) Log.d(TAG, "onConnected()");
-
- mDaemons.closeSockets();
- saveOriginalDns();
- saveAndSetDomainSuffices();
-
- mStartTime = System.currentTimeMillis();
-
- setState(VpnState.CONNECTED);
- setVpnDns();
-
- startConnectivityMonitor();
- }
-
- private synchronized void onFinalCleanUp() {
- if (DBG) Log.d(TAG, "onFinalCleanUp()");
-
- if (mState == VpnState.IDLE) return;
-
- // keep the notification when error occurs
- if (!anyError()) mNotification.disableNotification();
-
- restoreOriginalDns();
- restoreOriginalDomainSuffices();
- setState(VpnState.IDLE);
-
- SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
- }
-
- private boolean anyError() {
- return (mError != null);
- }
-
- private void restoreOriginalDns() {
- // restore only if they are not overridden
- String vpnDns1 = SystemProperties.get(VPN_DNS1);
- if (vpnDns1.equals(SystemProperties.get(DNS1))) {
- Log.i(TAG, String.format("restore original dns prop: %s --> %s",
- SystemProperties.get(DNS1), mOriginalDns1));
- Log.i(TAG, String.format("restore original dns prop: %s --> %s",
- SystemProperties.get(DNS2), mOriginalDns2));
- SystemProperties.set(DNS1, mOriginalDns1);
- SystemProperties.set(DNS2, mOriginalDns2);
- }
- }
-
- private void saveOriginalDns() {
- mOriginalDns1 = SystemProperties.get(DNS1);
- mOriginalDns2 = SystemProperties.get(DNS2);
- Log.i(TAG, String.format("save original dns prop: %s, %s",
- mOriginalDns1, mOriginalDns2));
- }
-
- private void setVpnDns() {
- String vpnDns1 = SystemProperties.get(VPN_DNS1);
- String vpnDns2 = SystemProperties.get(VPN_DNS2);
- SystemProperties.set(DNS1, vpnDns1);
- SystemProperties.set(DNS2, vpnDns2);
- Log.i(TAG, String.format("set vpn dns prop: %s, %s",
- vpnDns1, vpnDns2));
- }
-
- private void saveAndSetDomainSuffices() {
- mOriginalDomainSuffices = SystemProperties.get(DNS_DOMAIN_SUFFICES);
- Log.i(TAG, "save original suffices: " + mOriginalDomainSuffices);
- String list = mProfile.getDomainSuffices();
- if (!TextUtils.isEmpty(list)) {
- SystemProperties.set(DNS_DOMAIN_SUFFICES, list);
- }
- }
-
- private void restoreOriginalDomainSuffices() {
- Log.i(TAG, "restore original suffices --> " + mOriginalDomainSuffices);
- SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
- }
-
- private void setState(VpnState newState) {
- mState = newState;
- broadcastConnectivity(newState);
- }
-
- private void broadcastConnectivity(VpnState s) {
- VpnManager m = new VpnManager(mContext);
- Throwable err = mError;
- if ((s == VpnState.IDLE) && (err != null)) {
- if (err instanceof UnknownHostException) {
- m.broadcastConnectivity(mProfile.getName(), s,
- VpnManager.VPN_ERROR_UNKNOWN_SERVER);
- } else if (err instanceof VpnConnectingError) {
- m.broadcastConnectivity(mProfile.getName(), s,
- ((VpnConnectingError) err).getErrorCode());
- } else if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
- m.broadcastConnectivity(mProfile.getName(), s,
- VpnManager.VPN_ERROR_CONNECTION_LOST);
- } else {
- m.broadcastConnectivity(mProfile.getName(), s,
- VpnManager.VPN_ERROR_CONNECTION_FAILED);
- }
- } else {
- m.broadcastConnectivity(mProfile.getName(), s);
- }
- }
-
- private void startConnectivityMonitor() {
- new Thread(new Runnable() {
- public void run() {
- Log.i(TAG, "VPN connectivity monitor running");
- try {
- mNotification.update(mStartTime); // to pop up notification
- for (int i = 10; ; i--) {
- long now = System.currentTimeMillis();
-
- boolean heavyCheck = i == 0;
- synchronized (VpnService.this) {
- if (mState != VpnState.CONNECTED) break;
- mNotification.update(now);
-
- if (heavyCheck) {
- i = 10;
- if (checkConnectivity()) checkDns();
- }
- long t = 1000L - System.currentTimeMillis() + now;
- if (t > 100L) VpnService.this.wait(t);
- }
- }
- } catch (InterruptedException e) {
- onError(e);
- }
- Log.i(TAG, "VPN connectivity monitor stopped");
- }
- }).start();
- }
-
- private void saveLocalIpAndInterface(String serverIp) throws IOException {
- DatagramSocket s = new DatagramSocket();
- int port = 80; // arbitrary
- s.connect(InetAddress.getByName(serverIp), port);
- InetAddress localIp = s.getLocalAddress();
- mLocalIp = localIp.getHostAddress();
- NetworkInterface localIf = NetworkInterface.getByInetAddress(localIp);
- mLocalIf = (localIf == null) ? null : localIf.getName();
- if (TextUtils.isEmpty(mLocalIf)) {
- throw new IOException("Local interface is empty!");
- }
- if (DBG) {
- Log.d(TAG, " Local IP: " + mLocalIp + ", if: " + mLocalIf);
- }
- }
-
- // returns false if vpn connectivity is broken
- private boolean checkConnectivity() {
- if (mDaemons.anyDaemonStopped() || isLocalIpChanged()) {
- onError(new IOException("Connectivity lost"));
- return false;
- } else {
- return true;
- }
- }
-
- private void checkDns() {
- String dns1 = SystemProperties.get(DNS1);
- String vpnDns1 = SystemProperties.get(VPN_DNS1);
- if (!dns1.equals(vpnDns1) && dns1.equals(mOriginalDns1)) {
- // dhcp expires?
- setVpnDns();
- }
- }
-
- private boolean isLocalIpChanged() {
- try {
- InetAddress localIp = InetAddress.getByName(mLocalIp);
- NetworkInterface localIf =
- NetworkInterface.getByInetAddress(localIp);
- if (localIf == null || !mLocalIf.equals(localIf.getName())) {
- Log.w(TAG, " local If changed from " + mLocalIf
- + " to " + localIf);
- return true;
- } else {
- return false;
- }
- } catch (IOException e) {
- Log.w(TAG, "isLocalIpChanged()", e);
- return true;
- }
- }
-
- protected void sleep(int ms) {
- try {
- Thread.currentThread().sleep(ms);
- } catch (InterruptedException e) {
- }
- }
-
- // Helper class for showing, updating notification.
- private class NotificationHelper {
- private NotificationManager mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- private Notification mNotification =
- new Notification(R.drawable.vpn_connected, null, 0L);
- private PendingIntent mPendingIntent = PendingIntent.getActivity(
- mContext, 0,
- new VpnManager(mContext).createSettingsActivityIntent(), 0);
- private String mConnectedTitle;
-
- void update(long now) {
- Notification n = mNotification;
- if (now == mStartTime) {
- // to pop up the notification for the first time
- n.when = mStartTime;
- n.tickerText = mConnectedTitle = getNotificationTitle(true);
- } else {
- n.tickerText = null;
- }
- n.setLatestEventInfo(mContext, mConnectedTitle,
- getConnectedNotificationMessage(now),
- mPendingIntent);
- n.flags |= Notification.FLAG_NO_CLEAR;
- n.flags |= Notification.FLAG_ONGOING_EVENT;
- enableNotification(n);
- }
-
- void showDisconnect() {
- String title = getNotificationTitle(false);
- Notification n = new Notification(R.drawable.vpn_disconnected,
- title, System.currentTimeMillis());
- n.setLatestEventInfo(mContext, title,
- getDisconnectedNotificationMessage(),
- mPendingIntent);
- n.flags |= Notification.FLAG_AUTO_CANCEL;
- disableNotification();
- enableNotification(n);
- }
-
- void disableNotification() {
- mNotificationManager.cancel(NOTIFICATION_ID);
- }
-
- private void enableNotification(Notification n) {
- mNotificationManager.notify(NOTIFICATION_ID, n);
- }
-
- private String getNotificationTitle(boolean connected) {
- String formatString = connected
- ? mContext.getString(
- R.string.vpn_notification_title_connected)
- : mContext.getString(
- R.string.vpn_notification_title_disconnected);
- return String.format(formatString, mProfile.getName());
- }
-
- private String getFormattedTime(int duration) {
- int hours = duration / 3600;
- StringBuilder sb = new StringBuilder();
- if (hours > 0) sb.append(hours).append(':');
- sb.append(String.format("%02d:%02d", (duration % 3600 / 60),
- (duration % 60)));
- return sb.toString();
- }
-
- private String getConnectedNotificationMessage(long now) {
- return getFormattedTime((int) (now - mStartTime) / 1000);
- }
-
- private String getDisconnectedNotificationMessage() {
- return mContext.getString(
- R.string.vpn_notification_hint_disconnected);
- }
- }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnServiceBinder.java b/vpn/java/com/android/server/vpn/VpnServiceBinder.java
deleted file mode 100644
index c474ff9..0000000
--- a/vpn/java/com/android/server/vpn/VpnServiceBinder.java
+++ /dev/null
@@ -1,117 +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.
- */
-
-package com.android.server.vpn;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.net.vpn.IVpnService;
-import android.net.vpn.L2tpIpsecProfile;
-import android.net.vpn.L2tpIpsecPskProfile;
-import android.net.vpn.L2tpProfile;
-import android.net.vpn.PptpProfile;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.util.Log;
-
-/**
- * The service class for managing a VPN connection. It implements the
- * {@link IVpnService} binder interface.
- */
-public class VpnServiceBinder extends IVpnService.Stub {
- private static final String TAG = VpnServiceBinder.class.getSimpleName();
- private static final boolean DBG = true;
-
- // The actual implementation is delegated to the VpnService class.
- private VpnService<? extends VpnProfile> mService;
-
- private Context mContext;
-
- public VpnServiceBinder(Context context) {
- mContext = context;
- }
-
- @Override
- public synchronized boolean connect(VpnProfile p, final String username,
- final String password) {
- if ((mService != null) && !mService.isIdle()) return false;
- final VpnService s = mService = createService(p);
-
- new Thread(new Runnable() {
- public void run() {
- s.onConnect(username, password);
- }
- }).start();
- return true;
- }
-
- @Override
- public synchronized void disconnect() {
- if (mService == null) return;
- final VpnService s = mService;
- mService = null;
-
- new Thread(new Runnable() {
- public void run() {
- s.onDisconnect();
- }
- }).start();
- }
-
- @Override
- public synchronized String getState(VpnProfile p) {
- if ((mService == null)
- || (!p.getName().equals(mService.mProfile.getName()))) {
- return VpnState.IDLE.toString();
- } else {
- return mService.getState().toString();
- }
- }
-
- @Override
- public synchronized boolean isIdle() {
- return (mService == null || mService.isIdle());
- }
-
- private VpnService<? extends VpnProfile> createService(VpnProfile p) {
- switch (p.getType()) {
- case L2TP:
- L2tpService l2tp = new L2tpService();
- l2tp.setContext(mContext, (L2tpProfile) p);
- return l2tp;
-
- case PPTP:
- PptpService pptp = new PptpService();
- pptp.setContext(mContext, (PptpProfile) p);
- return pptp;
-
- case L2TP_IPSEC_PSK:
- L2tpIpsecPskService psk = new L2tpIpsecPskService();
- psk.setContext(mContext, (L2tpIpsecPskProfile) p);
- return psk;
-
- case L2TP_IPSEC:
- L2tpIpsecService l2tpIpsec = new L2tpIpsecService();
- l2tpIpsec.setContext(mContext, (L2tpIpsecProfile) p);
- return l2tpIpsec;
-
- default:
- return null;
- }
- }
-}
diff --git a/vpn/tests/vpntests/Android.mk b/vpn/tests/vpntests/Android.mk
deleted file mode 100644
index a19fb56..0000000
--- a/vpn/tests/vpntests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := FrameworksVpnTests
-
-include $(BUILD_PACKAGE)
-
diff --git a/vpn/tests/vpntests/AndroidManifest.xml b/vpn/tests/vpntests/AndroidManifest.xml
deleted file mode 100644
index d8405f6..0000000
--- a/vpn/tests/vpntests/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.vpntests">
- <uses-permission android:name="android.permission.RECEIVE_SMS"/>
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
- <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
- <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation
- android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.frameworks.vpntests"
- android:label="Frameworks VPN Tests" />
-</manifest>
diff --git a/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java b/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
deleted file mode 100755
index 46a57d3..0000000
--- a/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
+++ /dev/null
@@ -1,157 +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.
- */
-
-package android.net.vpn;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.vpn.L2tpProfile;
-import android.net.vpn.L2tpIpsecProfile;
-import android.net.vpn.L2tpIpsecPskProfile;
-import android.net.vpn.PptpProfile;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.net.vpn.VpnType;
-import android.os.ConditionVariable;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.TextUtils;
-
-/**
- * Unit test class to test VPN api
- * Use the below command to run the vpn unit test only
- * runtest vpntest or
- * adb shell am instrument -e class 'com.android.unit_tests.VpnTest'
- * -w com.android.unit_tests/android.test.InstrumentationTestRunner
- */
-public class VpnTest extends AndroidTestCase {
- private static final String NAME = "a name";
- private static final String SERVER_NAME = "a server name";
- private static final String ID = "some id";
- private static final String SUFFICES = "some suffices";
- private static final String ROUTES = "some routes";
- private static final String SAVED_NAME = "some name";
-
- @Override
- public void setUp() {
- }
-
- @Override
- public void tearDown() {
- }
-
- @SmallTest
- public void testVpnType() {
- testVpnType(VpnType.L2TP);
- testVpnType(VpnType.L2TP_IPSEC);
- testVpnType(VpnType.L2TP_IPSEC_PSK);
- testVpnType(VpnType.PPTP);
- }
-
- @SmallTest
- public void testVpnProfile() {
- VpnState state = VpnState.CONNECTING;
- testVpnProfile(createTestProfile(state), state);
- }
-
- @SmallTest
- public void testGetType() {
- assertEquals(VpnType.L2TP, new L2tpProfile().getType());
- assertEquals(VpnType.L2TP_IPSEC, new L2tpIpsecProfile().getType());
- assertEquals(VpnType.L2TP_IPSEC_PSK,
- new L2tpIpsecPskProfile().getType());
- assertEquals(VpnType.PPTP, new PptpProfile().getType());
- }
-
- @SmallTest
- public void testVpnTypes() {
- assertTrue(VpnManager.getSupportedVpnTypes().length > 0);
- }
-
- @SmallTest
- public void testGetTypeFromManager() {
- VpnManager m = new VpnManager(getContext());
- VpnType[] types = VpnManager.getSupportedVpnTypes();
- for (VpnType t : types) {
- assertEquals(t, m.createVpnProfile(t).getType());
- }
- }
-
- @SmallTest
- public void testParcelable() {
- VpnProfile p = createTestProfile(VpnState.CONNECTED);
- Parcel parcel = Parcel.obtain();
- p.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
-
- // VpnState is transient and not saved in the parcel
- testVpnProfile(VpnProfile.CREATOR.createFromParcel(parcel), null);
- }
-
- @SmallTest
- public void testReceiver() {
- final String profileName = "whatever";
- final VpnState state = VpnState.DISCONNECTING;
- final ConditionVariable cv = new ConditionVariable();
- cv.close();
- BroadcastReceiver r = new BroadcastReceiver() {
- public void onReceive(Context c, Intent i) {
- assertEquals(profileName,
- i.getStringExtra(VpnManager.BROADCAST_PROFILE_NAME));
- assertEquals(state, i.getSerializableExtra(
- VpnManager.BROADCAST_CONNECTION_STATE));
- cv.open();
- }
- };
-
- VpnManager m = new VpnManager(getContext());
- m.registerConnectivityReceiver(r);
- m.broadcastConnectivity(profileName, state);
-
- // fail it if onReceive() doesn't get executed in 5 sec
- assertTrue(cv.block(5000));
- }
-
- private void testVpnType(VpnType type) {
- assertFalse(TextUtils.isEmpty(type.getDisplayName()));
- assertNotNull(type.getProfileClass());
- }
-
- private VpnProfile createTestProfile(VpnState state) {
- VpnProfile p = new L2tpProfile();
- p.setName(NAME);
- p.setServerName(SERVER_NAME);
- p.setId(ID);
- p.setDomainSuffices(SUFFICES);
- p.setRouteList(ROUTES);
- p.setSavedUsername(SAVED_NAME);
- p.setState(state);
- return p;
- }
-
- private void testVpnProfile(VpnProfile p, VpnState state) {
- assertEquals(NAME, p.getName());
- assertEquals(SERVER_NAME, p.getServerName());
- assertEquals(ID, p.getId());
- assertEquals(SUFFICES, p.getDomainSuffices());
- assertEquals(ROUTES, p.getRouteList());
- assertEquals(SAVED_NAME, p.getSavedUsername());
- if (state != null) assertEquals(state, p.getState());
- }
-}