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());
+ }
+}