Merge "docs: Re-write of OpenGL Framework topic bug 4285030"
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index b48be6e..4b4b9b9 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -363,6 +363,7 @@
                 response = writeMasterKey(pw);
             }
             if (response == NO_ERROR) {
+                memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
                 setupMasterKeys();
             }
             return response;
@@ -707,11 +708,10 @@
     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
new file mode 100755
index 0000000..3be51b3
--- /dev/null
+++ b/cmds/keystore/test-keystore
@@ -0,0 +1,273 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+set -e
+
+prefix=$0
+log_file=$prefix.log
+baseline_file=$prefix.baseline
+
+function cleanup_output() {
+    rm -f $log_file
+    rm -f $baseline_file
+}
+
+function log() {
+    echo "$@"
+    append $log_file \# "$@"
+    append $baseline_file \# "$@"
+}
+
+function expect() {
+    append $baseline_file "$@"
+}
+
+function append() {
+    declare -r file=$1
+    shift
+    echo "$@" >> $file
+}
+
+function run() {
+    # strip out carriage returns from adb
+    # strip out date/time from ls -l
+    "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+}
+
+function keystore() {
+    declare -r user=$1
+    shift
+    run adb shell su $user keystore_cli "$@"
+}
+
+function list_keystore_directory() {
+    run adb shell ls -al /data/misc/keystore
+}
+
+function compare() {
+    log "comparing $baseline_file and $log_file"
+    diff $baseline_file $log_file || (log $tag FAILED && exit 1)
+}
+
+function test_basic() {
+
+    #
+    # reset
+    #
+    log "reset keystore as system user"
+    keystore system r
+    expect "1 No error"
+    list_keystore_directory
+
+    #
+    # basic tests as system/root
+    #
+    log "root does not have permission to run test"
+    keystore root t
+    expect "6 Permission denied"
+    
+    log "but system user does"
+    keystore system t
+    expect "3 Uninitialized"
+    list_keystore_directory
+
+    log "password is now bar"
+    keystore system p bar
+    expect "1 No error"
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    
+    log "no error implies initialized and unlocked"
+    keystore system t
+    expect "1 No error"
+    
+    log "saw with no argument"
+    keystore system s
+    expect "5 Protocol error"
+
+    log "saw nothing"
+    keystore system s ""
+    expect "1 No error"
+
+    log "add key baz"
+    keystore system i baz quux
+    expect "1 No error"
+
+    log "1000 is uid of system"
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "saw baz"
+    keystore system s ""
+    expect "1 No error"
+    expect "baz"
+
+    log "get baz"
+    keystore system g baz
+    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"
+
+    #
+    # app user tests
+    #
+
+    # app_0 has uid 10000, as seen below
+    log "other uses cannot see the system keys"
+    keystore app_0 g baz
+    expect "7 Key not found"
+    
+    log "app user cannot use reset, password, lock, unlock"
+    keystore app_0 r
+    expect "6 Permission denied"
+    keystore app_0 p
+    expect "6 Permission denied"
+    keystore app_0 l
+    expect "6 Permission denied"
+    keystore app_0 u
+    expect "6 Permission denied"
+
+    log "install app_0 key"
+    keystore app_0 i 0x deadbeef
+    expect 1 No error
+    list_keystore_directory
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 10000_0x"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "get with no argument"
+    keystore app_0 g
+    expect "5 Protocol error"
+    
+    keystore app_0 g 0x
+    expect "1 No error"
+    expect "deadbeef"
+    
+    keystore app_0 i fred barney
+    expect "1 No error"
+    
+    keystore app_0 s ""
+    expect "1 No error"
+    expect "0x"
+    expect "fred"
+
+    log "note that saw returns the suffix of prefix matches"
+    keystore app_0 s fr # fred
+    expect "1 No error"
+    expect "ed" # fred
+
+    #
+    # lock tests
+    #
+    log "lock the store as system"
+    keystore system l
+    expect "1 No error"
+    keystore system t
+    expect "2 Locked"
+    
+    log "saw works while locked"
+    keystore app_0 s ""
+    expect "1 No error"
+    expect "0x"
+    expect "fred"
+
+    log "...but cannot read keys..."
+    keystore app_0 g 0x
+    expect "2 Locked"
+    
+    log "...but they can be deleted."
+    keystore app_0 e 0x
+    expect "1 No error"
+    keystore app_0 d 0x
+    expect "1 No error"
+    keystore app_0 e 0x
+    expect "7 Key not found"
+
+    #
+    # password
+    #
+    log "wrong password"
+    keystore system u foo
+    expect "13 Wrong password (4 tries left)"
+    log "right password"
+    keystore system u bar
+    expect "1 No error"
+    
+    log "make the password foo"
+    keystore system p foo
+    expect "1 No error"
+    
+    #
+    # final reset
+    #
+    log "reset wipes everything for all users"
+    keystore system r
+    expect "1 No error"
+    list_keystore_directory
+    
+    keystore system t
+    expect "3 Uninitialized"
+
+}
+
+function test_4599735() {
+    # http://b/4599735
+    log "start regression test for b/4599735"
+    keystore system r
+    expect "1 No error"
+
+    keystore system p foo
+    expect "1 No error"
+
+    keystore system i baz quux
+    expect "1 No error"
+    
+    keystore root g baz
+    expect "1 No error"
+    expect "quux"
+
+    keystore system l
+    expect "1 No error"
+
+    keystore system p foo
+    expect "1 No error"
+
+    log "after unlock, regression led to result of '8 Value corrupted'"
+    keystore root g baz
+    expect "1 No error"
+    expect "quux"
+
+    keystore system r
+    expect "1 No error"
+    log "end regression test for b/4599735"
+}
+
+function main() {
+    cleanup_output
+    log $tag START
+    test_basic
+    test_4599735
+    compare
+    log $tag PASSED
+    cleanup_output
+}
+
+main
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 @@
     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 @@
 
 // ---------------------------------------------------------------------------
 
-class MemoryHeapBase : public virtual BnMemoryHeap 
+class MemoryHeapBase : public virtual BnMemoryHeap
 {
 public:
     enum {
@@ -38,12 +38,12 @@
         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 @@
     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 @@
             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 @@
     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 @@
     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 @@
     // 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 @@
 
     // 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 @@
     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 @@
     // 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 @@
             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 @@
     /* 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 @@
 // ----------------------------------------------------------------------------
 
 class IMemoryHeap;
+class ComposerState;
 
 class ISurfaceComposer : public IInterface
 {
@@ -105,8 +106,7 @@
     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 @@
         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 @@
 
 // ----------------------------------------------------------------------------
 
-class layer_state_t;
-
 class ISurfaceComposerClient : public IInterface
 {
 public:
@@ -69,11 +67,6 @@
      * 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 @@
 class GraphicBuffer;
 class GraphicBufferMapper;
 class IOMX;
+class ISurfaceTexture;
 class Rect;
 class Surface;
 class SurfaceComposerClient;
@@ -154,6 +155,7 @@
     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 @@
 // ---------------------------------------------------------------------------
 
 class DisplayInfo;
+class Composer;
 class IMemoryHeap;
 class ISurfaceComposer;
 class Region;
 class surface_flinger_cblk_t;
+struct layer_state_t;
 
 // ---------------------------------------------------------------------------
 
@@ -59,8 +61,11 @@
 
 // ---------------------------------------------------------------------------
 
+class Composer;
+
 class SurfaceComposerClient : public RefBase
 {
+    friend class Composer;
 public:    
                 SurfaceComposerClient();
     virtual     ~SurfaceComposerClient();
@@ -101,13 +106,7 @@
     // 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 @@
 
 private:
     virtual void onFirstRef();
-    inline layer_state_t*   get_state_l(SurfaceID id);
-    layer_state_t*          lockLayerState(SurfaceID id);
-    inline void             unlockLayerState();
+    Composer& getComposer();
 
-    mutable     Mutex                               mLock;
-                SortedVector<layer_state_t>         mStates;
-                int32_t                             mTransactionOpen;
-                layer_state_t*                      mPrebuiltLayerState;
-
-                // 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 @@
     // 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 @@
 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 @@
     
                             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 @@
 }
 
 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 @@
 
 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 0bd69cf..c8e9c04 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -133,13 +133,13 @@
 // 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
@@ -510,6 +510,10 @@
     // that case.
             status_t    requestExitAndWait();
 
+    // Wait until this object's thread exits. Returns immediately if not yet running.
+    // Do not call from this object's thread; will return WOULD_BLOCK in that case.
+            status_t    join();
+
 protected:
     // exitPending() returns true if requestExit() has been called.
             bool        exitPending() const;
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index f9d9f25..3a12e96 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,7 +27,7 @@
     MemoryHeapBase.cpp \
     MemoryHeapPmem.cpp \
     Parcel.cpp \
-    Permission.cpp \
+    PermissionCache.cpp \
     ProcessState.cpp \
     Static.cpp
 
diff --git a/libs/binder/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 @@
 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 @@
         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 @@
     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 @@
         return gHeapCache->get_heap(binder);
     }
     static inline void dump_heaps() {
-        gHeapCache->dump_heaps();       
+        gHeapCache->dump_heaps();
     }
 
     void assertMapped() const;
@@ -107,6 +108,7 @@
     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 @@
     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 @@
 BnMemory::BnMemory() {
 }
 
-BnMemory::~BnMemory() { 
+BnMemory::~BnMemory() {
 }
 
 status_t BnMemory::onTransact(
@@ -229,7 +231,7 @@
 
 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 @@
                 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 @@
             if (mHeapId == -1) {
                 mBase   = heap->mBase;
                 mSize   = heap->mSize;
+                mOffset = heap->mOffset;
                 android_atomic_write( dup( heap->mHeapId ), &mHeapId );
             }
         } else {
@@ -286,13 +289,14 @@
         // 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 @@
         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 @@
             } else {
                 mSize = size;
                 mFlags = flags;
+                mOffset = offset;
                 android_atomic_write(fd, &mHeapId);
             }
         }
@@ -343,14 +348,19 @@
     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 @@
             reply->writeFileDescriptor(getHeapID());
             reply->writeInt32(getSize());
             reply->writeInt32(getFlags());
+            reply->writeInt32(getOffset());
             return NO_ERROR;
         } break;
         default:
@@ -383,17 +394,17 @@
 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 @@
     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 @@
             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 @@
     return realHeap;
 }
 
-void HeapCache::dump_heaps() 
+void HeapCache::dump_heaps()
 {
     Mutex::Autolock _l(mHeapCacheLock);
     int c = mHeapCache.size();
@@ -459,7 +470,7 @@
         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 @@
 
 // ---------------------------------------------------------------------------
 
-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(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(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 @@
     }
     mFD = fd;
     mSize = size;
+    mOffset = offset;
     return NO_ERROR;
 }
 
@@ -183,5 +184,9 @@
     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 @@
     }
 
     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 @@
         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 @@
             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 @@
         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 @@
             sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
             reply->writeStrongBinder(b);
         } break;
-        case OPEN_GLOBAL_TRANSACTION: {
+        case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            openGlobalTransaction();
-        } break;
-        case CLOSE_GLOBAL_TRANSACTION: {
-            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 @@
 
 enum {
     CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
-    DESTROY_SURFACE,
-    SET_STATE
+    DESTROY_SURFACE
 };
 
 class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@@ -92,17 +91,6 @@
         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 @@
             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 @@
     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 @@
     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 @@
 
 // ---------------------------------------------------------------------------
 
+// 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;
-
-    Composer() : Singleton<Composer>() {
-    }
-
-    void addClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.add(client);
-    }
-
-    void removeClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.remove(client);
-    }
-
-    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
-                }
-            }
-        }
-    }
-
-    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();
-    }
-
     friend class Singleton<Composer>;
 
+    mutable Mutex               mLock;
+    SortedVector<ComposerState> mStates;
+
+    Composer() : Singleton<Composer>() { }
+
+    void closeGlobalTransactionImpl();
+
+    layer_state_t* getLayerStateLocked(
+            const sp<SurfaceComposerClient>& client, SurfaceID id);
+
 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();
-    }
+
+    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);
+
     static void closeGlobalTransaction() {
         Composer::getInstance().closeGlobalTransactionImpl();
     }
@@ -152,69 +129,306 @@
 
 // ---------------------------------------------------------------------------
 
-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;
 }
 
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    String8 name;
+    const size_t SIZE = 128;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "<pid_%d>", getpid());
+    name.append(buffer);
+
+    return SurfaceComposerClient::createSurface(name, display,
+            w, h, format, flags);
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        const String8& name,
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    sp<SurfaceControl> result;
+    if (mStatus == NO_ERROR) {
+        ISurfaceComposerClient::surface_data_t data;
+        sp<ISurface> surface = mClient->createSurface(&data, name,
+                display, w, h, format, flags);
+        if (surface != 0) {
+            result = new SurfaceControl(this, surface, data, w, h, format, flags);
+        }
+    }
+    return result;
+}
+
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
+    if (mStatus != NO_ERROR)
+        return mStatus;
+    status_t err = mClient->destroySurface(sid);
+    return err;
+}
+
+inline Composer& SurfaceComposerClient::getComposer() {
+    return mComposer;
+}
+
+// ----------------------------------------------------------------------------
+
+void SurfaceComposerClient::openGlobalTransaction() {
+    // Currently a no-op
+}
+
+void SurfaceComposerClient::closeGlobalTransaction() {
+    Composer::closeGlobalTransaction();
+}
+
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
+    return getComposer().setFreezeTint(this, id, tint);
+}
+
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+    return getComposer().setPosition(this, id, x, y);
+}
+
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
+    return getComposer().setSize(this, id, w, h);
+}
+
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) {
+    return getComposer().setLayer(this, id, z);
+}
+
+status_t SurfaceComposerClient::hide(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerHidden,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::freeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerFrozen,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::unfreeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags,
+        uint32_t mask) {
+    return getComposer().setFlags(this, id, flags, mask);
+}
+
+status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id,
+        const Region& transparentRegion) {
+    return getComposer().setTransparentRegionHint(this, id, transparentRegion);
+}
+
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) {
+    return getComposer().setAlpha(this, id, alpha);
+}
+
+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::getDisplayInfo(
         DisplayID dpy, DisplayInfo* info)
 {
@@ -273,70 +487,7 @@
     return n;
 }
 
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    String8 name;
-    const size_t SIZE = 128;
-    char buffer[SIZE];
-    snprintf(buffer, SIZE, "<pid_%d>", getpid());
-    name.append(buffer);
-
-    return SurfaceComposerClient::createSurface(name, display,
-            w, h, format, flags);
-}
-
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        const String8& name,
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    sp<SurfaceControl> result;
-    if (mStatus == NO_ERROR) {
-        ISurfaceComposerClient::surface_data_t data;
-        sp<ISurface> surface = mClient->createSurface(&data, name,
-                display, w, h, format, flags);
-        if (surface != 0) {
-            result = new SurfaceControl(this, surface, data, w, h, format, flags);
-        }
-    }
-    return result;
-}
-
-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();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction()
-{
-    Composer::closeGlobalTransaction();
-}
+// ----------------------------------------------------------------------------
 
 status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
 {
@@ -350,199 +501,13 @@
     return sm->unfreezeDisplay(dpy, flags);
 }
 
-int SurfaceComposerClient::setOrientation(DisplayID dpy, 
+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::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;
-    }
-
-    if (mTransactionOpen >= 2) {
-        mTransactionOpen--;
-        return NO_ERROR;
-    }
-
-    mTransactionOpen = 0;
-    const ssize_t count = mStates.size();
-    if (count) {
-        mClient->setState(count, mStates.array());
-        mStates.clear();
-    }
-    return NO_ERROR;
-}
-
-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;
-    }
-
-    // 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;
-}
-
-layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
-{
-    layer_state_t* s;
-    mLock.lock();
-    s = get_state_l(id);
-    if (!s) mLock.unlock();
-    return s;
-}
-
-void SurfaceComposerClient::unlockLayerState()
-{
-    mLock.unlock();
-}
-
-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::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::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::hide(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerHidden,
-            ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::freeze(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerFrozen,
-            ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::unfreeze(SurfaceID id)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::setFlags(SurfaceID id,
-        uint32_t flags, uint32_t mask)
-{
-    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;
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(
-        SurfaceID id, const Region& transparentRegion)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eTransparentRegionChanged;
-    s->transparentRegion = transparentRegion;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eAlphaChanged;
-    s->alpha = alpha;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setMatrix(
-        SurfaceID id,
-        float dsdx, float dtdx,
-        float dsdy, float dtdy )
-{
-    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;
-}
-
-status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eFreezeTintChanged;
-    s->tint = tint;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 ScreenshotClient::ScreenshotClient()
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 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 @@
     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 @@
     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 @@
         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 @@
         ((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 @@
     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 @@
             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::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 @@
         }
 
         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 @@
         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 @@
 }
 
 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 @@
             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 @@
         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 @@
     }
 }
 
+// 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 @@
         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 @@
     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 @@
             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 @@
     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 @@
     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 @@
 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 @@
 
     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 @@
 	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 @@
             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 15bb1d2..50312e7 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -316,6 +316,10 @@
 #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;
@@ -842,6 +846,25 @@
     return mStatus;
 }
 
+status_t Thread::join()
+{
+    Mutex::Autolock _l(mLock);
+    if (mThread == getThreadId()) {
+        LOGW(
+        "Thread (this=%p): don't call join() from this "
+        "Thread object's thread. It's a guaranteed deadlock!",
+        this);
+
+        return WOULD_BLOCK;
+    }
+
+    while (mRunning == true) {
+        mThreadExitedCondition.wait(mLock);
+    }
+
+    return mStatus;
+}
+
 bool Thread::exitPending() const
 {
     Mutex::Autolock _l(mLock);
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 @@
 {
     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 @@
 }
 
 void Layer::onFrameQueued() {
-    if (android_atomic_or(1, &mQueuedFrames) == 0) {
-        mFlinger->signalEvent();
-    }
+    android_atomic_inc(&mQueuedFrames);
+    mFlinger->signalEvent();
 }
 
 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -406,20 +405,18 @@
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
-    if (android_atomic_and(0, &mQueuedFrames)) {
+    if (mQueuedFrames > 0) {
+        // signal another event if we have more frames pending
+        if (android_atomic_dec(&mQueuedFrames) > 1) {
+            mFlinger->signalEvent();
+        }
+
         if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
             return;
         }
 
-        // signal another event if we have more frames waiting
-        if (mSurfaceTexture->getQueuedCount()) {
-            if (android_atomic_or(1, &mQueuedFrames) == 0) {
-                mFlinger->signalEvent();
-            }
-        }
-
         mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
         mSurfaceTexture->getTransformMatrix(mTextureMatrix);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 97edfee..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 @@
     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 @@
         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 @@
     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 @@
     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;
-            }
-            if (what & eVisibilityChanged) {
-                if (layer->setFlags(s.flags, s.mask))
-                    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 & 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 @@
     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 @@
 {
     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 @@
             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 @@
             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 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 @@
             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 @@
             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 @@
      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 @@
 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() {}
 
 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 @@
     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 @@
     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 @@
 class SurfaceFlinger :
         public BinderService<SurfaceFlinger>,
         public BnSurfaceComposer,
+        public IBinder::DeathRecipient,
         protected Thread
 {
 public:
@@ -169,8 +167,7 @@
     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 @@
     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 @@
 
     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 @@
     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 @@
                 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 @@
             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 @@
     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 @@
     
     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());
-    }
-}