Merge "NativeDaemonConnector: Cleanup socket code and use a proper exception Signed-off-by: San Mehat <san@google.com>"
diff --git a/common/java/com/android/common/speech/LoggingEvents.java b/common/java/com/android/common/speech/LoggingEvents.java
new file mode 100644
index 0000000..3b3ecb8
--- /dev/null
+++ b/common/java/com/android/common/speech/LoggingEvents.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010 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.common.speech;
+
+/**
+ * Logging event constants used for Voice Search and VoiceIME. These are the
+ * keys and values of extras to be specified in logging broadcast intents.
+ * This class is used by clients of the android.speech APIs to log how the
+ * user interacts with the IME settings and speech recognition result.
+ */
+public class LoggingEvents {
+    // The name of the broadcast intent for logging.
+    public static final String ACTION_LOG_EVENT = "com.android.common.speech.LOG_EVENT";
+
+    // The extra key used for the name of the app being logged.
+    public static final String EXTRA_APP_NAME = "app_name";
+
+    // The extra key used for the name of the app issuing the VoiceSearch
+    // or VoiceIME request
+    public static final String EXTRA_CALLING_APP_NAME = "";
+
+    // The extra key used for the event value. The possible event values depend
+    // on the app being logged for, and are defined in the subclasses below.
+    public static final String EXTRA_EVENT = "extra_event";
+
+    // The extra key used to log the time in milliseconds at which the EXTRA_EVENT
+    // occurred in the client.
+    public static final String EXTRA_TIMESTAMP = "timestamp";
+
+    // The extra key used (with a boolean value of 'true') as a way to trigger a
+    // flush of the log events to the server.
+    public static final String EXTRA_FLUSH = "flush";
+
+    /**
+     * Logging event constants for voice search. Below are the extra values for
+     * {@link LoggingEvents#EXTRA_EVENT}, clustered with keys to additional
+     * extras for some events that need to be included as additional fields in
+     * the event. Note that this is not representative of *all* voice search
+     * events - only the ones that need to be reported from outside the voice
+     * search app, such as from Browser.
+     */
+    public class VoiceSearch {
+        // The app name to be used for logging VoiceSearch events.
+        public static final String APP_NAME = "googlemobile";
+
+        public static final int RETRY = 0;
+
+        public static final int N_BEST_REVEAL = 1;
+
+        public static final int N_BEST_CHOOSE = 2;
+        public static final String EXTRA_N_BEST_CHOOSE_INDEX = "index";  // value should be int
+
+        public static final int QUERY_UPDATED = 3;
+        public static final String EXTRA_QUERY_UPDATED_VALUE = "value";  // value should be String
+    }
+
+    /**
+     * Logging event constants for VoiceIME. Below are the extra values for
+     * {@link LoggingEvents#EXTRA_EVENT}, clustered with keys to additional
+     * extras for some events that need to be included as additional fields in
+     * the event.
+     */
+    public class VoiceIme {
+        // The app name to be used for logging VoiceIME events.
+        public static final String APP_NAME = "voiceime";
+
+        public static final int KEYBOARD_WARNING_DIALOG_SHOWN = 0;
+
+        public static final int KEYBOARD_WARNING_DIALOG_DISMISSED = 1;
+
+        public static final int KEYBOARD_WARNING_DIALOG_OK = 2;
+
+        public static final int KEYBOARD_WARNING_DIALOG_CANCEL = 3;
+
+        public static final int SETTINGS_WARNING_DIALOG_SHOWN = 4;
+
+        public static final int SETTINGS_WARNING_DIALOG_DISMISSED = 5;
+
+        public static final int SETTINGS_WARNING_DIALOG_OK = 6;
+
+        public static final int SETTINGS_WARNING_DIALOG_CANCEL = 7;
+
+        public static final int SWIPE_HINT_DISPLAYED = 8;
+
+        public static final int PUNCTUATION_HINT_DISPLAYED = 9;
+
+        public static final int CANCEL_DURING_LISTENING = 10;
+
+        public static final int CANCEL_DURING_WORKING = 11;
+
+        public static final int CANCEL_DURING_ERROR = 12;
+
+        public static final int ERROR = 13;
+        public static final String EXTRA_ERROR_CODE = "code";  // value should be int
+
+        public static final int START = 14;
+        public static final String EXTRA_START_LOCALE = "locale";  // value should be String
+        public static final String EXTRA_START_SWIPE = "swipe";  // value should be boolean
+
+        public static final int VOICE_INPUT_DELIVERED = 15;
+
+        public static final int N_BEST_CHOOSE = 16;
+        public static final String EXTRA_N_BEST_CHOOSE_INDEX = "index";  // value should be int
+
+        public static final int TEXT_MODIFIED = 17;
+
+        public static final int INPUT_ENDED = 18;
+
+        public static final int VOICE_INPUT_SETTING_ENABLED = 19;
+
+        public static final int VOICE_INPUT_SETTING_DISABLED = 20;
+
+        public static final int IME_TEXT_ACCEPTED = 21;
+    }
+
+}
diff --git a/common/java/com/android/common/userhappiness/UserHappinessSignals.java b/common/java/com/android/common/userhappiness/UserHappinessSignals.java
new file mode 100644
index 0000000..347bdaa
--- /dev/null
+++ b/common/java/com/android/common/userhappiness/UserHappinessSignals.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 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.common.userhappiness;
+
+import android.content.Intent;
+import android.content.Context;
+import com.android.common.speech.LoggingEvents;
+
+/**
+ * Metrics for User Happiness are recorded here. Each app can define when to
+ * call these User Happiness metrics.
+ */
+public class UserHappinessSignals {
+
+    /**
+     *  Log when a user "accepted" IME text. Each application can define what
+     *  it means to "accept" text. In the case of Gmail, pressing the "Send"
+     *  button indicates text acceptance. We broadcast this information to
+     *  VoiceSearch LoggingEvents and use it to aggregate VoiceIME Happiness Metrics
+     */
+    public static void userAcceptedImeText(Context context) {
+        // Create a Voice IME Logging intent.
+        Intent i = new Intent(LoggingEvents.ACTION_LOG_EVENT);
+        i.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
+        i.putExtra(LoggingEvents.EXTRA_EVENT, LoggingEvents.VoiceIme.IME_TEXT_ACCEPTED);
+        i.putExtra(LoggingEvents.EXTRA_CALLING_APP_NAME, context.getPackageName());
+        i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis());
+        context.sendBroadcast(i);
+    }
+
+}
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 03ac70a..170f20d 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -22,232 +22,35 @@
 #include <sys/types.h>
 
 #include <binder/IMemory.h>
-#include <utils/threads.h>
 #include <binder/MemoryHeapBase.h>
 
 namespace android {
 // ----------------------------------------------------------------------------
-class String8;
 
-/*
- * interface for implementing a "heap". A heap basically provides
- * the IMemoryHeap interface for cross-process sharing and the
- * ability to map/unmap pages within the heap.
- */
-class HeapInterface : public virtual BnMemoryHeap
-{
-public:
-    // all values must be page-aligned
-    virtual sp<IMemory> mapMemory(size_t offset, size_t size) = 0;
-
-    HeapInterface();
-protected:
-    virtual ~HeapInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * interface for implementing an allocator. An allocator provides
- * methods for allocating and freeing memory blocks and dumping
- * its state.
- */
-class AllocatorInterface : public RefBase
-{
-public:
-    enum {
-        PAGE_ALIGNED = 0x00000001
-    };
-
-    virtual size_t      allocate(size_t size, uint32_t flags = 0) = 0;
-    virtual status_t    deallocate(size_t offset) = 0;
-    virtual size_t      size() const = 0;
-    virtual void        dump(const char* what, uint32_t flags = 0) const = 0;
-    virtual void        dump(String8& res,
-            const char* what, uint32_t flags = 0) const = 0;
-
-    AllocatorInterface();
-protected:
-    virtual ~AllocatorInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * concrete implementation of HeapInterface on top of mmap() 
- */
-class SharedHeap : public HeapInterface, public MemoryHeapBase
-{
-public:
-                        SharedHeap();
-                        SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL);
-    virtual             ~SharedHeap();
-    virtual sp<IMemory> mapMemory(size_t offset, size_t size);
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * A simple templatized doubly linked-list implementation
- */
-
-template <typename NODE>
-class LinkedList
-{
-    NODE*  mFirst;
-    NODE*  mLast;
-
-public:
-                LinkedList() : mFirst(0), mLast(0) { }
-    bool        isEmpty() const { return mFirst == 0; }
-    NODE const* head() const { return mFirst; }
-    NODE*       head() { return mFirst; }
-    NODE const* tail() const { return mLast; }
-    NODE*       tail() { return mLast; }
-
-    void insertAfter(NODE* node, NODE* newNode) {
-        newNode->prev = node;
-        newNode->next = node->next;
-        if (node->next == 0) mLast = newNode;
-        else                 node->next->prev = newNode;
-        node->next = newNode;
-    }
-
-    void insertBefore(NODE* node, NODE* newNode) {
-         newNode->prev = node->prev;
-         newNode->next = node;
-         if (node->prev == 0)   mFirst = newNode;
-         else                   node->prev->next = newNode;
-         node->prev = newNode;
-    }
-
-    void insertHead(NODE* newNode) {
-        if (mFirst == 0) {
-            mFirst = mLast = newNode;
-            newNode->prev = newNode->next = 0;
-        } else {
-            newNode->prev = 0;
-            newNode->next = mFirst;
-            mFirst->prev = newNode;
-            mFirst = newNode;
-        }
-    }
-    
-    void insertTail(NODE* newNode) {
-        if (mLast == 0) {
-            insertHead(newNode);
-        } else {
-            newNode->prev = mLast;
-            newNode->next = 0;
-            mLast->next = newNode;
-            mLast = newNode;
-        }
-    }
-
-    NODE* remove(NODE* node) {
-        if (node->prev == 0)    mFirst = node->next;
-        else                    node->prev->next = node->next;
-        if (node->next == 0)    mLast = node->prev;
-        else                    node->next->prev = node->prev;
-        return node;
-    }
-};
-
-
-/*
- * concrete implementation of AllocatorInterface using a simple
- * best-fit allocation scheme
- */
-class SimpleBestFitAllocator : public AllocatorInterface
-{
-public:
-
-                        SimpleBestFitAllocator(size_t size);
-    virtual             ~SimpleBestFitAllocator();
-
-    virtual size_t      allocate(size_t size, uint32_t flags = 0);
-    virtual status_t    deallocate(size_t offset);
-    virtual size_t      size() const;
-    virtual void        dump(const char* what, uint32_t flags = 0) const;
-    virtual void        dump(String8& res,
-            const char* what, uint32_t flags = 0) const;
-
-private:
-
-    struct chunk_t {
-        chunk_t(size_t start, size_t size) 
-            : start(start), size(size), free(1), prev(0), next(0) {
-        }
-        size_t              start;
-        size_t              size : 28;
-        int                 free : 4;
-        mutable chunk_t*    prev;
-        mutable chunk_t*    next;
-    };
-
-    ssize_t  alloc(size_t size, uint32_t flags);
-    chunk_t* dealloc(size_t start);
-    void     dump_l(const char* what, uint32_t flags = 0) const;
-    void     dump_l(String8& res, const char* what, uint32_t flags = 0) const;
-
-    static const int    kMemoryAlign;
-    mutable Mutex       mLock;
-    LinkedList<chunk_t> mList;
-    size_t              mHeapSize;
-};
+class SimpleBestFitAllocator;
 
 // ----------------------------------------------------------------------------
 
 class MemoryDealer : public RefBase
 {
 public:
+    MemoryDealer(size_t size, const char* name = 0);
 
-    enum {
-        READ_ONLY = MemoryHeapBase::READ_ONLY,
-        PAGE_ALIGNED = AllocatorInterface::PAGE_ALIGNED
-    };
-
-    // creates a memory dealer with the SharedHeap and SimpleBestFitAllocator
-    MemoryDealer(size_t size, uint32_t flags = 0, const char* name = 0);
-
-    // provide a custom heap but use the SimpleBestFitAllocator
-    MemoryDealer(const sp<HeapInterface>& heap);
-
-    // provide both custom heap and allocotar
-    MemoryDealer(
-            const sp<HeapInterface>& heap,
-            const sp<AllocatorInterface>& allocator);
-
-    virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
+    virtual sp<IMemory> allocate(size_t size);
     virtual void        deallocate(size_t offset);
-    virtual void        dump(const char* what, uint32_t flags = 0) const;
-
+    virtual void        dump(const char* what) const;
 
     sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
-    sp<AllocatorInterface> getAllocator() const { return allocator(); }
 
 protected:
     virtual ~MemoryDealer();
 
-private:    
-    const sp<HeapInterface>&        heap() const;
-    const sp<AllocatorInterface>&   allocator() const;
+private:
+    const sp<IMemoryHeap>&      heap() const;
+    SimpleBestFitAllocator*     allocator() const;
 
-    class Allocation : public BnMemory {
-    public:
-        Allocation(const sp<MemoryDealer>& dealer,
-                ssize_t offset, size_t size, const sp<IMemory>& memory);
-        virtual ~Allocation();
-        virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
-    private:
-        sp<MemoryDealer>        mDealer;
-        ssize_t                 mOffset;
-        size_t                  mSize;
-        sp<IMemory>             mMemory;
-    };
-
-    sp<HeapInterface>           mHeap;
-    sp<AllocatorInterface>      mAllocator;
+    sp<IMemoryHeap>             mHeap;
+    SimpleBestFitAllocator*     mAllocator;
 };
 
 
diff --git a/include/binder/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
index dbf26ff..aac164f 100644
--- a/include/binder/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -20,10 +20,10 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include <binder/MemoryDealer.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/IMemory.h>
 #include <utils/SortedVector.h>
+#include <utils/threads.h>
 
 namespace android {
 
@@ -31,7 +31,7 @@
 
 // ---------------------------------------------------------------------------
 
-class MemoryHeapPmem : public HeapInterface, public MemoryHeapBase
+class MemoryHeapPmem : public MemoryHeapBase
 {
 public:
     class MemoryPmem : public BnMemory {
diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h
index cae0676..2c29bfb 100644
--- a/include/ui/CameraParameters.h
+++ b/include/ui/CameraParameters.h
@@ -34,8 +34,10 @@
 
     void set(const char *key, const char *value);
     void set(const char *key, int value);
+    void setFloat(const char *key, float value);
     const char *get(const char *key) const;
     int getInt(const char *key) const;
+    float getFloat(const char *key) const;
 
     /* preview-size=176x144 */
     void setPreviewSize(int width, int height);
@@ -176,6 +178,16 @@
     // Supported focus modes.
     // Example value: "auto,macro,fixed". Read only.
     static const char KEY_SUPPORTED_FOCUS_MODES[];
+    // Focal length in millimeter.
+    // Example value: "4.31". Read only.
+    static const char KEY_FOCAL_LENGTH[];
+    // Horizontal angle of view in degrees.
+    // Example value: "54.8". Read only.
+    static const char KEY_HORIZONTAL_VIEW_ANGLE[];
+    // Vertical angle of view in degrees.
+    // Example value: "42.5". Read only.
+    static const char KEY_VERTICAL_VIEW_ANGLE[];
+
 
         // Values for white balance settings.
     static const char WHITE_BALANCE_AUTO[];
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index cad420a..9d52882 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2929,7 +2929,7 @@
 AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
     :   RefBase(),
         mAudioFlinger(audioFlinger),
-        mMemoryDealer(new MemoryDealer(1024*1024)),
+        mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
         mPid(pid)
 {
     // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index d5ffe7f..18669f7 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -17,12 +17,13 @@
 #define LOG_TAG "MemoryDealer"
 
 #include <binder/MemoryDealer.h>
+#include <binder/IPCThreadState.h>
+#include <binder/MemoryBase.h>
 
 #include <utils/Log.h>
-#include <binder/IPCThreadState.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
-#include <binder/MemoryBase.h>
+#include <utils/threads.h>
 
 #include <stdint.h>
 #include <stdio.h>
@@ -40,90 +41,203 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-HeapInterface::HeapInterface() { }
-HeapInterface::~HeapInterface() { }
+/*
+ * A simple templatized doubly linked-list implementation
+ */
 
-// ----------------------------------------------------------------------------
+template <typename NODE>
+class LinkedList
+{
+    NODE*  mFirst;
+    NODE*  mLast;
 
-AllocatorInterface::AllocatorInterface() { }
-AllocatorInterface::~AllocatorInterface() { }
-
-// ----------------------------------------------------------------------------
-
-class SimpleMemory : public MemoryBase {
 public:
-    SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
-    virtual ~SimpleMemory();
+                LinkedList() : mFirst(0), mLast(0) { }
+    bool        isEmpty() const { return mFirst == 0; }
+    NODE const* head() const { return mFirst; }
+    NODE*       head() { return mFirst; }
+    NODE const* tail() const { return mLast; }
+    NODE*       tail() { return mLast; }
+
+    void insertAfter(NODE* node, NODE* newNode) {
+        newNode->prev = node;
+        newNode->next = node->next;
+        if (node->next == 0) mLast = newNode;
+        else                 node->next->prev = newNode;
+        node->next = newNode;
+    }
+
+    void insertBefore(NODE* node, NODE* newNode) {
+         newNode->prev = node->prev;
+         newNode->next = node;
+         if (node->prev == 0)   mFirst = newNode;
+         else                   node->prev->next = newNode;
+         node->prev = newNode;
+    }
+
+    void insertHead(NODE* newNode) {
+        if (mFirst == 0) {
+            mFirst = mLast = newNode;
+            newNode->prev = newNode->next = 0;
+        } else {
+            newNode->prev = 0;
+            newNode->next = mFirst;
+            mFirst->prev = newNode;
+            mFirst = newNode;
+        }
+    }
+
+    void insertTail(NODE* newNode) {
+        if (mLast == 0) {
+            insertHead(newNode);
+        } else {
+            newNode->prev = mLast;
+            newNode->next = 0;
+            mLast->next = newNode;
+            mLast = newNode;
+        }
+    }
+
+    NODE* remove(NODE* node) {
+        if (node->prev == 0)    mFirst = node->next;
+        else                    node->prev->next = node->next;
+        if (node->next == 0)    mLast = node->prev;
+        else                    node->next->prev = node->prev;
+        return node;
+    }
 };
 
+// ----------------------------------------------------------------------------
+
+class Allocation : public MemoryBase {
+public:
+    Allocation(const sp<MemoryDealer>& dealer,
+            const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
+    virtual ~Allocation();
+private:
+    sp<MemoryDealer> mDealer;
+};
 
 // ----------------------------------------------------------------------------
 
-MemoryDealer::Allocation::Allocation(
-        const sp<MemoryDealer>& dealer, ssize_t offset, size_t size,
-        const sp<IMemory>& memory)
-    : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) 
+class SimpleBestFitAllocator
 {
+    enum {
+        PAGE_ALIGNED = 0x00000001
+    };
+public:
+    SimpleBestFitAllocator(size_t size);
+    ~SimpleBestFitAllocator();
+
+    size_t      allocate(size_t size, uint32_t flags = 0);
+    status_t    deallocate(size_t offset);
+    size_t      size() const;
+    void        dump(const char* what) const;
+    void        dump(String8& res, const char* what) const;
+
+private:
+
+    struct chunk_t {
+        chunk_t(size_t start, size_t size)
+        : start(start), size(size), free(1), prev(0), next(0) {
+        }
+        size_t              start;
+        size_t              size : 28;
+        int                 free : 4;
+        mutable chunk_t*    prev;
+        mutable chunk_t*    next;
+    };
+
+    ssize_t  alloc(size_t size, uint32_t flags);
+    chunk_t* dealloc(size_t start);
+    void     dump_l(const char* what) const;
+    void     dump_l(String8& res, const char* what) const;
+
+    static const int    kMemoryAlign;
+    mutable Mutex       mLock;
+    LinkedList<chunk_t> mList;
+    size_t              mHeapSize;
+};
+
+// ----------------------------------------------------------------------------
+
+Allocation::Allocation(
+        const sp<MemoryDealer>& dealer,
+        const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
+    : MemoryBase(heap, offset, size), mDealer(dealer)
+{
+#ifndef NDEBUG
+    void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
+    memset(start_ptr, 0xda, size);
+#endif
 }
 
-MemoryDealer::Allocation::~Allocation()
+Allocation::~Allocation()
 {
-    if (mSize) {
+    size_t freedOffset = getOffset();
+    size_t freedSize   = getSize();
+    if (freedSize) {
         /* NOTE: it's VERY important to not free allocations of size 0 because
          * they're special as they don't have any record in the allocator
          * and could alias some real allocation (their offset is zero). */
-        mDealer->deallocate(mOffset);
-    }
-}
+        mDealer->deallocate(freedOffset);
 
-sp<IMemoryHeap> MemoryDealer::Allocation::getMemory(
-    ssize_t* offset, size_t* size) const
-{
-    return mMemory->getMemory(offset, size);
+        // keep the size to unmap in excess
+        size_t pagesize = getpagesize();
+        size_t start = freedOffset;
+        size_t end = start + freedSize;
+        start &= ~(pagesize-1);
+        end = (end + pagesize-1) & ~(pagesize-1);
+
+        // give back to the kernel the pages we don't need
+        size_t free_start = freedOffset;
+        size_t free_end = free_start + freedSize;
+        if (start < free_start)
+            start = free_start;
+        if (end > free_end)
+            end = free_end;
+        start = (start + pagesize-1) & ~(pagesize-1);
+        end &= ~(pagesize-1);
+
+        if (start < end) {
+            void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
+            size_t size = end-start;
+
+#ifndef NDEBUG
+            memset(start_ptr, 0xdf, size);
+#endif
+
+            // MADV_REMOVE is not defined on Dapper based Goobuntu
+#ifdef MADV_REMOVE
+            if (size) {
+                int err = madvise(start_ptr, size, MADV_REMOVE);
+                LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
+                        start_ptr, size, err<0 ? strerror(errno) : "Ok");
+            }
+#endif
+        }
+    }
 }
 
 // ----------------------------------------------------------------------------
 
-MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name)
-    : mHeap(new SharedHeap(size, flags, name)),
+MemoryDealer::MemoryDealer(size_t size, const char* name)
+    : mHeap(new MemoryHeapBase(size, 0, name)),
     mAllocator(new SimpleBestFitAllocator(size))
 {    
 }
 
-MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap)
-    : mHeap(heap),
-    mAllocator(new SimpleBestFitAllocator(heap->virtualSize()))
-{
-}
-
-MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap,
-        const sp<AllocatorInterface>& allocator)
-    : mHeap(heap), mAllocator(allocator)
-{
-}
-
 MemoryDealer::~MemoryDealer()
 {
+    delete mAllocator;
 }
 
-sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags)
+sp<IMemory> MemoryDealer::allocate(size_t size)
 {
     sp<IMemory> memory;
-    const ssize_t offset = allocator()->allocate(size, flags);
+    const ssize_t offset = allocator()->allocate(size);
     if (offset >= 0) {
-        sp<IMemory> new_memory = heap()->mapMemory(offset, size);
-        if (new_memory != 0) {
-            memory = new Allocation(this, offset, size, new_memory);
-        } else {
-            LOGE("couldn't map [%8lx, %u]", offset, size);
-            if (size) {
-                /* NOTE: it's VERY important to not free allocations of size 0
-                 * because they're special as they don't have any record in the 
-                 * allocator and could alias some real allocation 
-                 * (their offset is zero). */
-                allocator()->deallocate(offset);
-            }
-        }        
+        memory = new Allocation(this, heap(), offset, size);
     }
     return memory;
 }
@@ -133,16 +247,16 @@
     allocator()->deallocate(offset);
 }
 
-void MemoryDealer::dump(const char* what, uint32_t flags) const
+void MemoryDealer::dump(const char* what) const
 {
-    allocator()->dump(what, flags);
+    allocator()->dump(what);
 }
 
-const sp<HeapInterface>& MemoryDealer::heap() const {
+const sp<IMemoryHeap>& MemoryDealer::heap() const {
     return mHeap;
 }
 
-const sp<AllocatorInterface>& MemoryDealer::allocator() const {
+SimpleBestFitAllocator* MemoryDealer::allocator() const {
     return mAllocator;
 }
 
@@ -287,28 +401,28 @@
     return 0;
 }
 
-void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump(const char* what) const
 {
     Mutex::Autolock _l(mLock);
-    dump_l(what, flags);
+    dump_l(what);
 }
 
-void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump_l(const char* what) const
 {
     String8 result;
-    dump_l(result, what, flags);
+    dump_l(result, what);
     LOGD("%s", result.string());
 }
 
 void SimpleBestFitAllocator::dump(String8& result,
-        const char* what, uint32_t flags) const
+        const char* what) const
 {
     Mutex::Autolock _l(mLock);
-    dump_l(result, what, flags);
+    dump_l(result, what);
 }
 
 void SimpleBestFitAllocator::dump_l(String8& result,
-        const char* what, uint32_t flags) const
+        const char* what) const
 {
     size_t size = 0;
     int32_t i = 0;
@@ -341,81 +455,10 @@
         i++;
         cur = cur->next;
     }
-    snprintf(buffer, SIZE, "  size allocated: %u (%u KB)\n", int(size), int(size/1024));
+    snprintf(buffer, SIZE,
+            "  size allocated: %u (%u KB)\n", int(size), int(size/1024));
     result.append(buffer);
 }
-        
-// ----------------------------------------------------------------------------
 
-SharedHeap::SharedHeap() 
-    : HeapInterface(), MemoryHeapBase() 
-{ 
-}
-
-SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name)
-    : MemoryHeapBase(size, flags, name)
-{
-}
-
-SharedHeap::~SharedHeap()
-{
-}
-
-sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size)
-{
-    return new SimpleMemory(this, offset, size);
-}
- 
-
-SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap,
-        ssize_t offset, size_t size)
-    : MemoryBase(heap, offset, size)
-{
-#ifndef NDEBUG
-    void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
-    memset(start_ptr, 0xda, size);
-#endif
-}
-
-SimpleMemory::~SimpleMemory()
-{
-    size_t freedOffset = getOffset();
-    size_t freedSize   = getSize();
-
-    // keep the size to unmap in excess
-    size_t pagesize = getpagesize();
-    size_t start = freedOffset;
-    size_t end = start + freedSize;
-    start &= ~(pagesize-1);
-    end = (end + pagesize-1) & ~(pagesize-1);
-
-    // give back to the kernel the pages we don't need
-    size_t free_start = freedOffset;
-    size_t free_end = free_start + freedSize;
-    if (start < free_start)
-        start = free_start;
-    if (end > free_end)
-        end = free_end;
-    start = (start + pagesize-1) & ~(pagesize-1);
-    end &= ~(pagesize-1);    
-
-    if (start < end) {
-        void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
-        size_t size = end-start;
-
-#ifndef NDEBUG
-        memset(start_ptr, 0xdf, size);
-#endif
-
-        // MADV_REMOVE is not defined on Dapper based Goobuntu 
-#ifdef MADV_REMOVE 
-        if (size) {
-            int err = madvise(start_ptr, size, MADV_REMOVE);
-            LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
-                    start_ptr, size, err<0 ? strerror(errno) : "Ok");
-        }
-#endif
-    }
-}
 
 }; // namespace android
diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
index c660947..16e92f9 100644
--- a/libs/binder/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -127,7 +127,7 @@
 
 MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
         uint32_t flags)
-    : HeapInterface(), MemoryHeapBase()
+    : MemoryHeapBase()
 {
     char const * const device = pmemHeap->getDevice();
 #if HAVE_ANDROID_OS
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
index a94f6b9..c4958a0 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/ui/CameraParameters.cpp
@@ -56,6 +56,9 @@
 const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
 const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
 const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
+const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
+const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
 
 // Values for white balance settings.
 const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
@@ -206,6 +209,13 @@
     set(key, str);
 }
 
+void CameraParameters::setFloat(const char *key, float value)
+{
+    char str[16];  // 14 should be enough. We overestimate to be safe.
+    snprintf(str, sizeof(str), "%g", value);
+    set(key, str);
+}
+
 const char *CameraParameters::get(const char *key) const
 {
     String8 v = mMap.valueFor(String8(key));
@@ -222,6 +232,13 @@
     return strtol(v, 0, 0);
 }
 
+float CameraParameters::getFloat(const char *key) const
+{
+    const char *v = get(key);
+    if (v == 0) return -1;
+    return strtof(v, 0);
+}
+
 static int parse_size(const char *str, int &width, int &height)
 {
     // Find the width.
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 2875c13..fae89b9 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -1389,9 +1389,20 @@
     // (x,y) is the lower-left corner of colorBuffer
     y = cbSurface.height - (y + height);
 
+    /* The GLES spec says:
+     * If any of the pixels within the specified rectangle are outside
+     * the framebuffer associated with the current rendering context,
+     * then the values obtained for those pixels are undefined.
+     */
+    if (x+width > GLint(cbSurface.width))
+        width = cbSurface.width - x;
+
+    if (y+height > GLint(cbSurface.height))
+        height = cbSurface.height - y;
+
     int err = copyPixels(c,
             txSurface, 0, 0,
-            cbSurface, x, y, cbSurface.width, cbSurface.height);
+            cbSurface, x, y, width, height);
     if (err) {
         ogles_error(c, err);
     }
@@ -1439,6 +1450,17 @@
     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
     y = cbSurface.height - (y + height);
 
+    /* The GLES spec says:
+     * If any of the pixels within the specified rectangle are outside
+     * the framebuffer associated with the current rendering context,
+     * then the values obtained for those pixels are undefined.
+     */
+    if (x+width > GLint(cbSurface.width))
+        width = cbSurface.width - x;
+
+    if (y+height > GLint(cbSurface.height))
+        height = cbSurface.height - y;
+
     int err = copyPixels(c,
             surface, xoffset, yoffset,
             cbSurface, x, y, width, height);
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
index ca9e6d2..d6012d9 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
+++ b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
@@ -7,14 +7,14 @@
 GLint glCheckFramebufferStatusOES ( GLint target )
 void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
 void glCopyTexImage2D ( GLint target, GLint level, GLint internalformat, GLint x, GLint y, GLint width, GLint height, GLint border )
-void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
-void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
 void glEnable ( GLint cap )
 void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer )
 void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level )
 void glGenerateMipmapOES ( GLint target )
-void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
-void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
 void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params )
 void glGetIntegerv ( GLint pname, GLint *params )
 void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params )
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index c28e403..9f8a793 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -29,28 +29,28 @@
 glDrawTexivOES check coords 5
 glDrawTexsvOES check coords 5
 glDrawTexxvOES check coords 5
-glBindFramebufferOES unsupported
-glBindRenderbufferOES unsupported
-glBlendEquation unsupported
-glBlendEquationSeparate unsupported
-glBlendFuncSeparate unsupported
-glCheckFramebufferStatusOES unsupported return 0
-glDeleteFramebuffersOES unsupported
-glDeleteRenderbuffersOES unsupported
-glFramebufferRenderbufferOES unsupported
-glFramebufferStorageOES unsupported
-glFramebufferTexture2DOES unsupported
-glGenFramebuffersOES unsupported
-glGenRenderbuffersOES unsupported
-glGenerateMipmapOES unsupported
+glBindFramebufferOES requires OES_framebuffer_object
+glBindRenderbufferOES requires OES_framebuffer_object
+glBlendEquation requires OES_blend_subtract
+glBlendEquationSeparate requires OES_blend_equation_separate
+glBlendFuncSeparate requires OES_blend_equation_separate
+glCheckFramebufferStatusOES requires OES_framebuffer_object return 0
+glDeleteFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glDeleteRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glFramebufferRenderbufferOES requires OES_framebuffer_object
+glFramebufferStorageOES requires OES_framebuffer_object
+glFramebufferTexture2DOES requires OES_framebuffer_object
+glGenFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glGenRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glGenerateMipmapOES requires OES_framebuffer_object
+glGetFramebufferAttachmentParameterivOES requires OES_framebuffer_object
+glGetRenderbufferParameterivOES requires OES_framebuffer_object
+glIsFramebufferOES requires OES_framebuffer_object return JNI_FALSE
+glIsRenderbufferOES requires OES_framebuffer_object return JNI_FALSE
+glRenderbufferStorageOES requires OES_framebuffer_object
+glGetTexGen requires OES_texture_cube_map
+glTexGen requires OES_texture_cube_map
+glTexGenf requires OES_texture_cube_map
+glTexGeni requires OES_texture_cube_map
+glTexGenx requires OES_texture_cube_map
 glGetBufferParameter unsupported
-glGetFramebufferAttachmentParameterivOES unsupported
-glGetRenderbufferParameterivOES unsupported
-glGetTexGen unsupported
-glIsFramebufferOES unsupported return JNI_FALSE
-glIsRenderbufferOES unsupported return JNI_FALSE
-glRenderbufferStorageOES unsupported return false
-glTexGen unsupported
-glTexGenf unsupported
-glTexGeni unsupported
-glTexGenx unsupported
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index e79170a..2db4e8d 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -211,6 +211,8 @@
                     index += 5;
                 } else if (checks[index].equals("unsupported")) {
                     index += 1;
+                } else if (checks[index].equals("requires")) {
+                    index += 2;
                 } else if (checks[index].equals("nullAllowed")) {
                     return true;
                 } else {
@@ -243,6 +245,8 @@
                     index += 5;
                 } else if (checks[index].equals("unsupported")) {
                     index += 1;
+                } else if (checks[index].equals("requires")) {
+                    index += 2;
                 } else if (checks[index].equals("nullAllowed")) {
                     index += 1;
                 } else {
@@ -263,6 +267,8 @@
             while (index < checks.length) {
                 if (checks[index].equals("unsupported")) {
                     return true;
+                } else if (checks[index].equals("requires")) {
+                    index += 2;
                 } else if (checks[index].equals("return")) {
                     index += 2;
                 } else if (checks[index].startsWith("check")) {
@@ -280,7 +286,34 @@
         }
         return false;
     }
-
+    
+    String isRequiresFunc(CFunc cfunc) {
+        String[] checks = mChecker.getChecks(cfunc.getName());
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].equals("unsupported")) {
+                    index += 1;
+                } else if (checks[index].equals("requires")) {
+                    return checks[index+1];
+                } else if (checks[index].equals("return")) {
+                    index += 2;
+                } else if (checks[index].startsWith("check")) {
+                    index += 3;
+                } else if (checks[index].equals("ifcheck")) {
+                    index += 5;
+                } else if (checks[index].equals("nullAllowed")) {
+                    index += 1;
+                } else {
+                    System.out.println("Error: unknown keyword \"" +
+                                       checks[index] + "\"");
+                    System.exit(0);
+                }
+            }
+        }
+        return null;
+    }
+    
     void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
             boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
 
@@ -365,6 +398,9 @@
                         } else if (checks[index].equals("unsupported")) {
                             // ignore
                             index += 1;
+                        } else if (checks[index].equals("requires")) {
+                            // ignore
+                            index += 2;
                         } else if (checks[index].equals("nullAllowed")) {
                             // ignore
                             index += 1;
@@ -776,7 +812,23 @@
             out.println();
             return;
         }
-
+        
+        String requiresExtension = isRequiresFunc(cfunc);
+        if (requiresExtension != null) {
+            out.println(indent +
+                        "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
+            out.println(indent + indent +
+                        "_env->ThrowNew(UOEClass,");
+            out.println(indent + indent +
+                        "    \"" + cfunc.getName() + "\");");
+            if (isVoid) {
+                out.println(indent + indent + "    return;");
+            } else {
+                String retval = getErrorReturnValue(cfunc);
+                out.println(indent + indent + "    return " + retval + ";");
+            }
+            out.println(indent + "}");
+        }
         if (mUseContextPointer) {
             out.println(indent +
                 "android::gl::ogles_context_t *ctx = getContext(_env, _this);");
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index b3d1c6c..c2464b0 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -23,6 +23,23 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+// Work around differences between the generated name and the actual name.
+
+#define glBlendEquation glBlendEquationOES
+#define glBlendEquationSeparate glBlendEquationSeparateOES
+#define glBlendFuncSeparate glBlendFuncSeparateOES
+#define glGetTexGenfv glGetTexGenfvOES
+#define glGetTexGeniv glGetTexGenivOES
+#define glGetTexGenxv glGetTexGenxvOES
+#define glTexGenf glTexGenfOES
+#define glTexGenfv glTexGenfvOES
+#define glTexGeni glTexGeniOES
+#define glTexGeniv glTexGenivOES
+#define glTexGenx glTexGenxOES
+#define glTexGenxv glTexGenxvOES
+
+
+
 /* special calls implemented in Android's GLES wrapper used to more
  * efficiently bound-check passed arrays */
 extern "C" {
@@ -58,6 +75,11 @@
 static jfieldID positionID;
 static jfieldID limitID;
 static jfieldID elementSizeShiftID;
+static jfieldID haveCheckedExtensionsID;
+static jfieldID have_OES_blend_equation_separateID;
+static jfieldID have_OES_blend_subtractID;
+static jfieldID have_OES_framebuffer_objectID;
+static jfieldID have_OES_texture_cube_mapID;
 
 /* Cache method IDs each time the class is loaded. */
 
@@ -72,6 +94,11 @@
 
     jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
     G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+    haveCheckedExtensionsID =  _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
+    have_OES_blend_equation_separateID =  _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
+    have_OES_blend_subtractID =  _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
+    have_OES_framebuffer_objectID =  _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
+    have_OES_texture_cube_mapID =  _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
 
     getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
             "getBasePointer", "(Ljava/nio/Buffer;)J");
@@ -193,5 +220,63 @@
     return numCompressedTextureFormats;
 }
 
+// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
+// terminated by either 0 or space, while pExtension is terminated by 0.
+
+static bool
+extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
+    while (true) {
+        char a = *pExtensions++;
+        char b = *pExtension++;
+        bool aEnd = a == '\0' || a == ' ';
+        bool bEnd = b == '\0';
+        if ( aEnd || bEnd) {
+            return aEnd == bEnd;
+        }
+        if ( a != b ) {
+            return false;
+        }
+    }
+}
+
+static const GLubyte*
+nextExtension(const GLubyte* pExtensions) {
+    while (true) {
+        char a = *pExtensions++;
+        if ( a == '\0') {
+            return pExtensions-1;
+        } else if ( a == ' ') {
+            return pExtensions;
+        }
+    }
+}
+    
+static bool
+checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
+    for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
+        if (extensionEqual(pExtensions, pExtension)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool
+supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
+    if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
+        _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
+        const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
+        _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
+            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
+        _env->SetBooleanField(impl, have_OES_blend_subtractID,
+            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
+        _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
+            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
+        _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
+            checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
+    }
+    return _env->GetBooleanField(impl, fieldId);
+}
+
 // --------------------------------------------------------------------------
 
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index 76fea3f..3727106 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -47,6 +47,12 @@
     Buffer _pointSizePointerOES = null;
     Buffer _matrixIndexPointerOES = null;
     Buffer _weightPointerOES = null;
+    
+    private boolean haveCheckedExtensions;
+    private boolean have_OES_blend_equation_separate;
+    private boolean have_OES_blend_subtract;
+    private boolean have_OES_framebuffer_object;
+    private boolean have_OES_texture_cube_map;
 
     public GLImpl() {
     }
diff --git a/vpn/tests/vpntests/Android.mk b/vpn/tests/vpntests/Android.mk
new file mode 100644
index 0000000..a19fb56
--- /dev/null
+++ b/vpn/tests/vpntests/Android.mk
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 0000000..d8405f6
--- /dev/null
+++ b/vpn/tests/vpntests/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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
new file mode 100755
index 0000000..46a57d3
--- /dev/null
+++ b/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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());
+    }
+}