Merge commit 'goog/master' into merge_master
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 453dc29..81639ad 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -215,7 +215,7 @@
 {
     Mutex::Autolock _l(mLock);
     // allow anyone to use camera
-    LOGV("unlock (%p)", getCameraClient()->asBinder().get());
+    LOGD("unlock (%p)", getCameraClient()->asBinder().get());
     status_t result = checkPid();
     if (result == NO_ERROR) {
         mClientPid = 0;
@@ -230,7 +230,7 @@
 status_t CameraService::Client::connect(const sp<ICameraClient>& client)
 {
     // connect a new process to the camera
-    LOGV("connect (%p)", client->asBinder().get());
+    LOGD("connect (%p)", client->asBinder().get());
 
     // I hate this hack, but things get really ugly when the media recorder
     // service is handing back the camera to the app. The ICameraClient
@@ -245,7 +245,7 @@
         sp<ICameraClient> oldClient;
         {
             Mutex::Autolock _l(mLock);
-            if (mClientPid != 0) {
+            if (mClientPid != 0 && checkPid() != NO_ERROR) {
                 LOGW("Tried to connect to locked camera");
                 return -EBUSY;
             }
@@ -257,7 +257,7 @@
             mCameraClient = client;
             mClientPid = -1;
             mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
-            LOGV("connect new process (%d) to existing camera client", mClientPid);
+            LOGD("connect new process (%d) to existing camera client", mClientPid);
         }
 
     }
@@ -319,17 +319,17 @@
             IPCThreadState::self()->getCallingPid());
     Mutex::Autolock lock(mLock);
     if (mClientPid <= 0) {
-        LOGV("camera is unlocked, don't tear down hardware");
+        LOGD("camera is unlocked, don't tear down hardware");
         return;
     }
     if (checkPid() != NO_ERROR) {
-        LOGV("Different client - don't disconnect");
+        LOGD("Different client - don't disconnect");
         return;
     }
 
     mCameraService->removeClient(mCameraClient);
     if (mHardware != 0) {
-        LOGV("hardware teardown");
+        LOGD("hardware teardown");
         // Before destroying mHardware, we must make sure it's in the
         // idle state.
         mHardware->stopPreview();
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
new file mode 100644
index 0000000..20f4adf
--- /dev/null
+++ b/cmds/keystore/Android.mk
@@ -0,0 +1,21 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    keystore.c commands.c
+
+LOCAL_C_INCLUDES := \
+    $(call include-path-for, system-core)/cutils
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_MODULE:= keystore
+
+include $(BUILD_EXECUTABLE)
+
+endif # !simulator))
diff --git a/cmds/keystore/commands.c b/cmds/keystore/commands.c
new file mode 100644
index 0000000..e53cece
--- /dev/null
+++ b/cmds/keystore/commands.c
@@ -0,0 +1,141 @@
+/*
+** Copyright 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.
+*/
+
+#include "keystore.h"
+
+static DIR *open_keystore(const char *dir)
+{
+    DIR *d;
+    if ((d = opendir(dir)) == NULL) {
+        if (mkdir(dir, 0770) < 0) {
+            LOGE("cannot create dir '%s': %s\n", dir, strerror(errno));
+            unlink(dir);
+            return NULL;
+        }
+        d = open_keystore(dir);
+    }
+    return d;
+}
+
+static int list_files(const char *dir, char reply[REPLY_MAX]) {
+    struct dirent *de;
+    DIR *d;
+
+    if ((d = open_keystore(dir)) == NULL) {
+        return -1;
+    }
+    reply[0]=0;
+    while ((de = readdir(d))) {
+        if (de->d_type != DT_REG) continue;
+        if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX);
+        if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) {
+            LOGE("reply is too long(too many files under '%s'\n", dir);
+            return -1;
+        }
+    }
+    closedir(d);
+    return 0;
+}
+
+static int copy_keyfile(const char *keystore, const char *srcfile) {
+    int srcfd, dstfd;
+    int length;
+    char buf[2048];
+    char dstfile[KEYNAME_LENGTH];
+    const char *filename = strrchr(srcfile, '/');
+
+    strlcpy(dstfile, keystore, KEYNAME_LENGTH);
+    strlcat(dstfile, "/", KEYNAME_LENGTH);
+    if (strlcat(dstfile, filename ? filename + 1 : srcfile,
+                KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
+        LOGE("keyname is too long '%s'\n", srcfile);
+        return -1;
+    }
+
+    if ((srcfd = open(srcfile, O_RDONLY)) == -1) {
+        LOGE("Cannot open the original file '%s'\n", srcfile);
+        return -1;
+    }
+    if ((dstfd = open(dstfile, O_CREAT|O_RDWR)) == -1) {
+        LOGE("Cannot open the destination file '%s'\n", dstfile);
+        return -1;
+    }
+    while((length = read(srcfd, buf, 2048)) > 0) {
+        write(dstfd, buf, length);
+    }
+    close(srcfd);
+    close(dstfd);
+    chmod(dstfile, 0440);
+    return 0;
+}
+
+static int install_key(const char *dir, const char *keyfile)
+{
+    struct dirent *de;
+    DIR *d;
+
+    if ((d = open_keystore(dir)) == NULL) {
+        return -1;
+    }
+    return copy_keyfile(dir, keyfile);
+}
+
+static int remove_key(const char *dir, const char *keyfile)
+{
+    char dstfile[KEYNAME_LENGTH];
+
+    strlcpy(dstfile, dir, KEYNAME_LENGTH);
+    strlcat(dstfile, "/", KEYNAME_LENGTH);
+    if (strlcat(dstfile, keyfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
+        LOGE("keyname is too long '%s'\n", keyfile);
+        return -1;
+    }
+    if (unlink(dstfile)) {
+        LOGE("cannot delete '%s': %s\n", dstfile, strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+int list_certs(char reply[REPLY_MAX])
+{
+    return list_files(CERTS_DIR, reply);
+}
+
+int list_userkeys(char reply[REPLY_MAX])
+{
+    return list_files(USERKEYS_DIR, reply);
+}
+
+int install_cert(const char *certfile)
+{
+    return install_key(CERTS_DIR, certfile);
+}
+
+int install_userkey(const char *keyfile)
+{
+    return install_key(USERKEYS_DIR, keyfile);
+}
+
+int remove_cert(const char *certfile)
+{
+    return remove_key(CERTS_DIR, certfile);
+}
+
+int remove_userkey(const char *keyfile)
+{
+    return remove_key(USERKEYS_DIR, keyfile);
+}
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
new file mode 100644
index 0000000..5193b3d
--- /dev/null
+++ b/cmds/keystore/keystore.c
@@ -0,0 +1,255 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "keystore.h"
+
+
+static int do_list_certs(char **arg, char reply[REPLY_MAX])
+{
+    return list_certs(reply);
+}
+
+static int do_list_userkeys(char **arg, char reply[REPLY_MAX])
+{
+    return list_userkeys(reply);
+}
+
+static int do_install_cert(char **arg, char reply[REPLY_MAX])
+{
+    return install_cert(arg[0]); /* move the certificate to keystore */
+}
+
+static int do_remove_cert(char **arg, char reply[REPLY_MAX])
+{
+    return remove_cert(arg[0]); /* certificate */
+}
+
+static int do_install_userkey(char **arg, char reply[REPLY_MAX])
+{
+    return install_userkey(arg[0]); /* move the certificate to keystore */
+}
+
+static int do_remove_userkey(char **arg, char reply[REPLY_MAX])
+{
+    return remove_userkey(arg[0]); /* userkey */
+}
+
+struct cmdinfo {
+    const char *name;
+    unsigned numargs;
+    int (*func)(char **arg, char reply[REPLY_MAX]);
+};
+
+
+struct cmdinfo cmds[] = {
+    { "listcerts",            0, do_list_certs },
+    { "listuserkeys",         0, do_list_userkeys },
+    { "installcert",          1, do_install_cert },
+    { "removecert",           1, do_remove_cert },
+    { "installuserkey",       1, do_install_userkey },
+    { "removeuserkey",        1, do_remove_userkey },
+};
+
+static int readx(int s, void *_buf, int count)
+{
+    char *buf = _buf;
+    int n = 0, r;
+    if (count < 0) return -1;
+    while (n < count) {
+        r = read(s, buf + n, count - n);
+        if (r < 0) {
+            if (errno == EINTR) continue;
+            LOGE("read error: %s\n", strerror(errno));
+            return -1;
+        }
+        if (r == 0) {
+            LOGE("eof\n");
+            return -1; /* EOF */
+        }
+        n += r;
+    }
+    return 0;
+}
+
+static int writex(int s, const void *_buf, int count)
+{
+    const char *buf = _buf;
+    int n = 0, r;
+    if (count < 0) return -1;
+    while (n < count) {
+        r = write(s, buf + n, count - n);
+        if (r < 0) {
+            if (errno == EINTR) continue;
+            LOGE("write error: %s\n", strerror(errno));
+            return -1;
+        }
+        n += r;
+    }
+    return 0;
+}
+
+
+/* Tokenize the command buffer, locate a matching command,
+ * ensure that the required number of arguments are provided,
+ * call the function(), return the result.
+ */
+static int execute(int s, char cmd[BUFFER_MAX])
+{
+    char reply[REPLY_MAX];
+    char *arg[TOKEN_MAX+1];
+    unsigned i;
+    unsigned n = 0;
+    unsigned short count;
+    short ret = -1;
+
+    /* default reply is "" */
+    reply[0] = 0;
+
+    /* n is number of args (not counting arg[0]) */
+    arg[0] = cmd;
+    while (*cmd) {
+        if (isspace(*cmd)) {
+            *cmd++ = 0;
+            n++;
+            arg[n] = cmd;
+            if (n == TOKEN_MAX) {
+                LOGE("too many arguments\n");
+                goto done;
+            }
+        }
+        cmd++;
+    }
+
+    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
+        if (!strcmp(cmds[i].name,arg[0])) {
+            if (n != cmds[i].numargs) {
+                LOGE("%s requires %d arguments (%d given)\n",
+                     cmds[i].name, cmds[i].numargs, n);
+            } else {
+                ret = (short) cmds[i].func(arg + 1, reply);
+            }
+            goto done;
+        }
+    }
+    LOGE("unsupported command '%s'\n", arg[0]);
+
+done:
+    if (reply[0]) {
+        strlcpy(cmd, reply, BUFFER_MAX);
+        count = strlen(cmd);
+    } else {
+        count = 0;
+    }
+    if (writex(s, &ret, sizeof(ret))) return -1;
+    if (ret == 0) {
+        if (writex(s, &count, sizeof(count))) return -1;
+        if (writex(s, cmd, count)) return -1;
+    }
+
+    return 0;
+}
+
+int shell_command(const int argc, const char **argv)
+{
+    int fd, i;
+    short ret;
+    unsigned short count;
+    char buf[BUFFER_MAX]="";
+
+    fd = socket_local_client(SOCKET_PATH,
+                             ANDROID_SOCKET_NAMESPACE_RESERVED,
+                             SOCK_STREAM);
+    if (fd == -1) {
+        fprintf(stderr, "Keystore service is not up and running\n");
+        exit(1);
+    }
+    for(i = 0; i < argc; i++) {
+        if (i > 0) strlcat(buf, " ", BUFFER_MAX);
+        if(strlcat(buf, argv[i], BUFFER_MAX) >= BUFFER_MAX) {
+            fprintf(stderr, "Arguments are too long\n");
+            exit(1);
+        }
+    }
+    count = strlen(buf);
+    if (writex(fd, &count, sizeof(count))) return -1;
+    if (writex(fd, buf, strlen(buf))) return -1;
+    if (readx(fd, &ret, sizeof(ret))) return -1;
+    if (ret == 0) {
+        if (readx(fd, &count, sizeof(count))) return -1;
+        if (readx(fd, buf, count)) return -1;
+        buf[count]=0;
+        fprintf(stdout, "%s\n", buf);
+    } else {
+        fprintf(stderr, "Failed, please check log!\n");
+    }
+    return 0;
+}
+
+int main(const int argc, const char *argv[])
+{
+    char buf[BUFFER_MAX];
+    struct sockaddr addr;
+    socklen_t alen;
+    int lsocket, s, count;
+
+    if (argc > 1) {
+        return shell_command(argc - 1, argv + 1);
+    }
+
+    lsocket = android_get_control_socket(SOCKET_PATH);
+    if (lsocket < 0) {
+        LOGE("Failed to get socket from environment: %s\n", strerror(errno));
+        exit(1);
+    }
+    if (listen(lsocket, 5)) {
+        LOGE("Listen on socket failed: %s\n", strerror(errno));
+        exit(1);
+    }
+    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
+
+    for (;;) {
+        alen = sizeof(addr);
+        s = accept(lsocket, &addr, &alen);
+        if (s < 0) {
+            LOGE("Accept failed: %s\n", strerror(errno));
+            continue;
+        }
+        fcntl(s, F_SETFD, FD_CLOEXEC);
+
+        LOGI("new connection\n");
+        for (;;) {
+            unsigned short count;
+            if (readx(s, &count, sizeof(count))) {
+                LOGE("failed to read size\n");
+                break;
+            }
+            if ((count < 1) || (count >= BUFFER_MAX)) {
+                LOGE("invalid size %d\n", count);
+                break;
+            }
+            if (readx(s, buf, count)) {
+                LOGE("failed to read command\n");
+                break;
+            }
+            buf[count] = 0;
+            if (execute(s, buf)) break;
+        }
+        LOGI("closing connection\n");
+        close(s);
+    }
+
+    return 0;
+}
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
new file mode 100644
index 0000000..35acf0b
--- /dev/null
+++ b/cmds/keystore/keystore.h
@@ -0,0 +1,57 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "keystore"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <utime.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <cutils/sockets.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#define SOCKET_PATH "keystore"
+
+
+/* path of the keystore */
+
+#define KEYSTORE_DIR_PREFIX "/data/misc/keystore"
+#define CERTS_DIR           KEYSTORE_DIR_PREFIX "/certs"
+#define USERKEYS_DIR         KEYSTORE_DIR_PREFIX "/userkeys"
+
+#define BUFFER_MAX      1024  /* input buffer for commands */
+#define TOKEN_MAX       8     /* max number of arguments in buffer */
+#define REPLY_MAX       1024  /* largest reply allowed */
+#define KEYNAME_LENGTH  128
+
+/* commands.c */
+int list_certs(char reply[REPLY_MAX]);
+int list_userkeys(char reply[REPLY_MAX]);
+int install_cert(const char *certfile);
+int install_userkey(const char *keyfile);
+int remove_cert(const char *certfile);
+int remove_userkey(const char *keyfile);
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index bf62995..d2aa30e 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -16,33 +16,45 @@
 #include <media/AudioSystem.h>
 
 // This header defines the interface used by the Android platform
-// to access Text-To-Speech functionality in shared libraries that implement speech
-// synthesis and the management of resources associated with the synthesis.
-// An example of the implementation of this interface can be found in 
+// to access Text-To-Speech functionality in shared libraries that implement
+// speech synthesis and the management of resources associated with the
+// synthesis.
+// An example of the implementation of this interface can be found in
 // FIXME: add path+name to implementation of default TTS engine
 // Libraries implementing this interface are used in:
 //  frameworks/base/tts/jni/android_tts_SpeechSynthesis.cpp
 
 namespace android {
 
+enum tts_synth_status {
+    TTS_SYNTH_DONE              = 0,
+    TTS_SYNTH_PENDING           = 1
+};
+
+enum tts_callback_status {
+    TTS_CALLBACK_HALT           = 0,
+    TTS_CALLBACK_CONTINUE       = 1
+};
+
 // The callback is used by the implementation of this interface to notify its
 // client, the Android TTS service, that the last requested synthesis has been
-// completed.
+// completed. // TODO reword
 // The callback for synthesis completed takes:
-//    void *       - The userdata pointer set in the original synth call
-//    uint32_t     - Track sampling rate in Hz
-//    audio_format - The AudioSystem::audio_format enum
-//    int          - The number of channels
-//    int8_t *     - A buffer of audio data only valid during the execution of the callback
-//    size_t       - The size of the buffer
-// Note about memory management:
-//    The implementation of TtsEngine is responsible for the management of the memory
-//    it allocates to store the synthesized speech. After the execution of the callback
-//    to hand the synthesized data to the client of TtsEngine, the TTS engine is
-//    free to reuse or free the previously allocated memory.
-//    This implies that the implementation of the "synthDoneCB" callback cannot use
-//    the pointer to the buffer of audio samples outside of the callback itself.
-typedef void (synthDoneCB_t)(void *, uint32_t, AudioSystem::audio_format, int, int8_t *, size_t);
+// @param [inout] void *&       - The userdata pointer set in the original
+//                                 synth call
+// @param [in]    uint32_t      - Track sampling rate in Hz
+// @param [in]    audio_format  - The AudioSystem::audio_format enum
+// @param [in]    int           - The number of channels
+// @param [inout] int8_t *&     - A buffer of audio data only valid during the
+//                                execution of the callback
+// @param [inout] size_t  &     - The size of the buffer
+// @param [in] tts_synth_status - indicate whether the synthesis is done, or
+//                                 if more data is to be synthesized.
+// @return TTS_CALLBACK_HALT to indicate the synthesis must stop,
+//         TTS_CALLBACK_CONTINUE to indicate the synthesis must continue if
+//            there is more data to produce.
+typedef tts_callback_status (synthDoneCB_t)(void *&, uint32_t,
+        AudioSystem::audio_format, int, int8_t *&, size_t&, tts_synth_status);
 
 class TtsEngine;
 extern "C" TtsEngine* getTtsEngine();
@@ -69,38 +81,41 @@
     // @return TTS_SUCCESS, or TTS_FAILURE
     virtual tts_result shutdown();
 
-    // Interrupt synthesis and flushes any synthesized data that hasn't been output yet.
-    // This will block until callbacks underway are completed.
+    // Interrupt synthesis and flushes any synthesized data that hasn't been
+    // output yet. This will block until callbacks underway are completed.
     // @return TTS_SUCCESS, or TTS_FAILURE
     virtual tts_result stop();
 
-    // Load the resources associated with the specified language. The loaded language will
-    // only be used once a call to setLanguage() with the same language value is issued.
-    // Language values are based on the Android conventions for localization as described in
-    // the Android platform documentation on internationalization. This implies that language
-    // data is specified in the format xx-rYY, where xx is a two letter ISO 639-1 language code
-    // in lowercase and rYY is a two letter ISO 3166-1-alpha-2 language code in uppercase
-    // preceded by a lowercase "r".
+    // Load the resources associated with the specified language. The loaded
+    // language will only be used once a call to setLanguage() with the same
+    // language value is issued. Language values are based on the Android
+    // conventions for localization as described in the Android platform
+    // documentation on internationalization. This implies that language
+    // data is specified in the format xx-rYY, where xx is a two letter
+    // ISO 639-1 language code in lowercase and rYY is a two letter
+    // ISO 3166-1-alpha-2 language code in uppercase preceded by a
+    // lowercase "r".
     // @param value pointer to the language value
     // @param size  length of the language value
     // @return TTS_SUCCESS, or TTS_FAILURE
     virtual tts_result loadLanguage(const char *value, const size_t size);
 
-    // Signal the engine to use the specified language. This will force the language to be
-    // loaded if it wasn't loaded previously with loadLanguage().
+    // Signal the engine to use the specified language. This will force the
+    // language to be loaded if it wasn't loaded previously with loadLanguage().
     // See loadLanguage for the specification of the language.
     // @param value pointer to the language value
     // @param size  length of the language value
     // @return TTS_SUCCESS, or TTS_FAILURE
     virtual tts_result setLanguage(const char *value, const size_t size);
 
-    // Retrieve the currently set language, or an empty "value" if no language has
-    // been set.
+    // Retrieve the currently set language, or an empty "value" if no language
+    // has been set.
     // @param[out]   value pointer to the retrieved language value
-    // @param[inout] iosize  in: stores the size available to store the language value in *value
-    //                       out: stores the size required to hold the language value if
-    //                         getLanguage() returned  TTS_PROPERTY_SIZE_TOO_SMALL,
-    //                         unchanged otherwise.
+    // @param[inout] iosize in: stores the size available to store the language
+    //                         value in *value
+    //                      out: stores the size required to hold the language
+    //                         value if  getLanguage() returned
+    //                         TTS_PROPERTY_SIZE_TOO_SMALL, unchanged otherwise.
     // @return TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL, or TTS_FAILURE
     virtual tts_result getLanguage(char *value, size_t *iosize);
 
@@ -109,23 +124,31 @@
     // @param property pointer to the property name
     // @param value    pointer to the property value
     // @param size     maximum size required to store this type of property
-    // @return         TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE, 
+    // @return         TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE,
     //                  or TTS_VALUE_INVALID
-    virtual tts_result setProperty(const char *property, const char *value, const size_t size);
+    virtual tts_result setProperty(const char *property, const char *value,
+            const size_t size);
 
     // Retrieve a property from the TTS engine
     // @param        property pointer to the property name
     // @param[out]   value    pointer to the retrieved language value
-    // @param[inout] iosize   in: stores the size available to store the property value
-    //                        out: stores the size required to hold the language value if
-    //                         getLanguage() returned  TTS_PROPERTY_SIZE_TOO_SMALL,
-    //                         unchanged otherwise.
-    // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL
-    virtual tts_result getProperty(const char *property, char *value, size_t *iosize);
+    // @param[inout] iosize   in: stores the size available to store the
+    //                          property value.
+    //                        out: stores the size required to hold the language
+    //                          value if getLanguage() returned
+    //                          TTS_PROPERTY_SIZE_TOO_SMALL, unchanged otherwise
+    // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS,
+    //         or TTS_PROPERTY_SIZE_TOO_SMALL
+    virtual tts_result getProperty(const char *property, char *value,
+            size_t *iosize);
 
     // Synthesize the text.
-    // When synthesis completes, the engine invokes the callback to notify the TTS framework.
-    // Note about the format of the input: the text parameter may use the following elements
+    // As the synthesis is performed, the engine invokes the callback to notify
+    // the TTS framework that it has filled the given buffer, and indicates how
+    // many bytes it wrote. The callback is called repeatedly until the engine
+    // has generated all the audio data corresponding to the text.
+    // Note about the format of the input: the text parameter may use the
+    // following elements
     // and their respective attributes as defined in the SSML 1.0 specification:
     //    * lang
     //    * say-as:
@@ -154,14 +177,25 @@
     // Text is coded in UTF-8.
     // @param text      the UTF-8 text to synthesize
     // @param userdata  pointer to be returned when the call is invoked
+    // @param buffer    the location where the synthesized data must be written
+    // @param bufferSize the number of bytes that can be written in buffer
     // @return          TTS_SUCCESS or TTS_FAILURE
-    virtual tts_result synthesizeText(const char *text, void *userdata);
+    virtual tts_result synthesizeText(const char *text, int8_t *buffer,
+            size_t bufferSize, void *userdata);
 
-    // Synthesize IPA text. When synthesis completes, the engine must call the given callback to notify the TTS API.
+    // Synthesize IPA text.
+    // As the synthesis is performed, the engine invokes the callback to notify
+    // the TTS framework that it has filled the given buffer, and indicates how
+    // many bytes it wrote. The callback is called repeatedly until the engine
+    // has generated all the audio data corresponding to the IPA data.
     // @param ipa      the IPA data to synthesize
     // @param userdata  pointer to be returned when the call is invoked
-    // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported, otherwise TTS_SUCCESS or TTS_FAILURE
-    virtual tts_result synthesizeIpa(const char *ipa, void *userdata);
+    // @param buffer    the location where the synthesized data must be written
+    // @param bufferSize the number of bytes that can be written in buffer
+    // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported,
+    //         otherwise TTS_SUCCESS or TTS_FAILURE
+    virtual tts_result synthesizeIpa(const char *ipa, int8_t *buffer,
+            size_t bufferSize, void *userdata);
 };
 
 } // namespace android
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
index 24b6c9e..f60f4ea 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -118,7 +118,7 @@
 };
 
 int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
-        char const* fileBase, char const* const* files, int fileCount);
+        char const* const* files, char const* const *keys, int fileCount);
 
 
 #define TEST_BACKUP_HELPERS 1
@@ -127,6 +127,8 @@
 int backup_helper_test_empty();
 int backup_helper_test_four();
 int backup_helper_test_files();
+int backup_helper_test_null_base();
+int backup_helper_test_missing_file();
 int backup_helper_test_data_writer();
 int backup_helper_test_data_reader();
 #endif
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index 874f2c4..ea7d6c2 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -51,8 +51,7 @@
   LOCAL_SRC_FILES += A2dpAudioInterface.cpp
   LOCAL_SHARED_LIBRARIES += liba2dp
   LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
-  LOCAL_C_INCLUDES += $(call include-path-for, bluez-libs)
-  LOCAL_C_INCLUDES += $(call include-path-for, bluez-utils)
+  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
 endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index 120f23d..8c9f875 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -327,7 +327,7 @@
     }
     size_t size = m_header.app.packageLen;
     char* buf = packageName->lockBuffer(size);
-    if (packageName == NULL) {
+    if (buf == NULL) {
         packageName->unlockBuffer();
         m_status = ENOMEM;
         return m_status;
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 7f423a8..4c3e37d 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -41,8 +41,8 @@
 #define MAGIC0 0x70616e53 // Snap
 #define MAGIC1 0x656c6946 // File
 
-#if 0 // TEST_BACKUP_HELPERS
-#define LOGP(x...) printf(x)
+#if 1 // TEST_BACKUP_HELPERS
+#define LOGP(f, x...) printf(f "\n", x)
 #else
 #define LOGP(x...) LOGD(x)
 #endif
@@ -62,6 +62,12 @@
     int nameLen;
 };
 
+struct FileRec {
+    char const* file; // this object does not own this string
+    bool deleted;
+    FileState s;
+};
+
 const static int ROUND_UP[4] = { 0, 3, 2, 1 };
 
 static inline int
@@ -92,8 +98,8 @@
         FileState file;
         char filenameBuf[128];
 
-        amt = read(fd, &file, sizeof(file));
-        if (amt != sizeof(file)) {
+        amt = read(fd, &file, sizeof(FileState));
+        if (amt != sizeof(FileState)) {
             LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
             return 1;
         }
@@ -128,20 +134,25 @@
 }
 
 static int
-write_snapshot_file(int fd, const KeyedVector<String8,FileState>& snapshot)
+write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
 {
+    int fileCount = 0;
     int bytesWritten = sizeof(SnapshotHeader);
     // preflight size
     const int N = snapshot.size();
     for (int i=0; i<N; i++) {
-        const String8& name = snapshot.keyAt(i);
-        bytesWritten += sizeof(FileState) + round_up(name.length());
+        const FileRec& g = snapshot.valueAt(i);
+        if (!g.deleted) {
+            const String8& name = snapshot.keyAt(i);
+            bytesWritten += sizeof(FileState) + round_up(name.length());
+            fileCount++;
+        }
     }
 
     LOGP("write_snapshot_file fd=%d\n", fd);
 
     int amt;
-    SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
+    SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
 
     amt = write(fd, &header, sizeof(header));
     if (amt != sizeof(header)) {
@@ -149,32 +160,34 @@
         return errno;
     }
 
-    for (int i=0; i<header.fileCount; i++) {
-        const String8& name = snapshot.keyAt(i);
-        FileState file = snapshot.valueAt(i);
-        int nameLen = file.nameLen = name.length();
+    for (int i=0; i<N; i++) {
+        FileRec r = snapshot.valueAt(i);
+        if (!r.deleted) {
+            const String8& name = snapshot.keyAt(i);
+            int nameLen = r.s.nameLen = name.length();
 
-        amt = write(fd, &file, sizeof(file));
-        if (amt != sizeof(file)) {
-            LOGW("write_snapshot_file error writing header %s", strerror(errno));
-            return 1;
-        }
-
-        // filename is not NULL terminated, but it is padded
-        amt = write(fd, name.string(), nameLen);
-        if (amt != nameLen) {
-            LOGW("write_snapshot_file error writing filename %s", strerror(errno));
-            return 1;
-        }
-        int paddingLen = ROUND_UP[nameLen % 4];
-        if (paddingLen != 0) {
-            int padding = 0xabababab;
-            amt = write(fd, &padding, paddingLen);
-            if (amt != paddingLen) {
-                LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
-                        paddingLen, strerror(errno));
+            amt = write(fd, &r.s, sizeof(FileState));
+            if (amt != sizeof(FileState)) {
+                LOGW("write_snapshot_file error writing header %s", strerror(errno));
                 return 1;
             }
+
+            // filename is not NULL terminated, but it is padded
+            amt = write(fd, name.string(), nameLen);
+            if (amt != nameLen) {
+                LOGW("write_snapshot_file error writing filename %s", strerror(errno));
+                return 1;
+            }
+            int paddingLen = ROUND_UP[nameLen % 4];
+            if (paddingLen != 0) {
+                int padding = 0xabababab;
+                amt = write(fd, &padding, paddingLen);
+                if (amt != paddingLen) {
+                    LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
+                            paddingLen, strerror(errno));
+                    return 1;
+                }
+            }
         }
     }
 
@@ -190,9 +203,9 @@
 
 static int
 write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
-        const String8& realFilename)
+        char const* realFilename)
 {
-    LOGP("write_update_file %s (%s)\n", realFilename.string(), key.string());
+    LOGP("write_update_file %s (%s)\n", realFilename, key.string());
 
     const int bufsize = 4*1024;
     int err;
@@ -237,8 +250,7 @@
             }
         }
         LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
-                " You aren't doing proper locking!",
-                realFilename.string(), fileSize, fileSize-bytesLeft);
+                " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
     }
 
     free(buf);
@@ -247,10 +259,10 @@
 }
 
 static int
-write_update_file(BackupDataWriter* dataStream, const String8& key, const String8& realFilename)
+write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
 {
     int err;
-    int fd = open(realFilename.string(), O_RDONLY);
+    int fd = open(realFilename, O_RDONLY);
     if (fd == -1) {
         return errno;
     }
@@ -281,12 +293,11 @@
 
 int
 back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
-        char const* fileBase, char const* const* files, int fileCount)
+        char const* const* files, char const* const* keys, int fileCount)
 {
     int err;
-    const String8 base(fileBase);
     KeyedVector<String8,FileState> oldSnapshot;
-    KeyedVector<String8,FileState> newSnapshot;
+    KeyedVector<String8,FileRec> newSnapshot;
 
     if (oldSnapshotFD != -1) {
         err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
@@ -297,26 +308,29 @@
     }
 
     for (int i=0; i<fileCount; i++) {
-        String8 name(files[i]);
-        FileState s;
+        String8 key(keys[i]);
+        FileRec r;
+        char const* file = r.file = files[i];
         struct stat st;
-        String8 realFilename(base);
-        realFilename.appendPath(name);
 
-        err = stat(realFilename.string(), &st);
+        err = stat(file, &st);
         if (err != 0) {
-            LOGW("Error stating file %s", realFilename.string());
-            continue;
+            LOGW("Error stating file %s", file);
+            r.deleted = true;
+        } else {
+            r.deleted = false;
+            r.s.modTime_sec = st.st_mtime;
+            r.s.modTime_nsec = 0; // workaround sim breakage
+            //r.s.modTime_nsec = st.st_mtime_nsec;
+            r.s.size = st.st_size;
+            // we compute the crc32 later down below, when we already have the file open.
+
+            if (newSnapshot.indexOfKey(key) >= 0) {
+                LOGP("back_up_files key already in use '%s'", key.string());
+                return -1;
+            }
         }
-
-        s.modTime_sec = st.st_mtime;
-        s.modTime_nsec = 0; // workaround sim breakage
-        //s.modTime_nsec = st.st_mtime_nsec;
-        s.size = st.st_size;
-
-        // we compute the crc32 later down below, when we already have the file open.
-
-        newSnapshot.add(name, s);
+        newSnapshot.add(key, r);
     }
 
     int n = 0;
@@ -326,46 +340,42 @@
     while (n<N && m<fileCount) {
         const String8& p = oldSnapshot.keyAt(n);
         const String8& q = newSnapshot.keyAt(m);
+        FileRec& g = newSnapshot.editValueAt(m);
         int cmp = p.compare(q);
-        if (cmp > 0) {
-            // file added
-            String8 realFilename(base);
-            realFilename.appendPath(q);
-            LOGP("file added: %s\n", realFilename.string());
-            write_update_file(dataStream, q, realFilename);
-            m++;
-        }
-        else if (cmp < 0) {
+        if (g.deleted || cmp < 0) {
             // file removed
-            LOGP("file removed: %s\n", p.string());
+            LOGP("file removed: %s", p.string());
+            g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
             dataStream->WriteEntityHeader(p, -1);
             n++;
         }
+        else if (cmp > 0) {
+            // file added
+            LOGP("file added: %s", g.file);
+            write_update_file(dataStream, q, g.file);
+            m++;
+        }
         else {
-
             // both files exist, check them
-            String8 realFilename(base);
-            realFilename.appendPath(q);
             const FileState& f = oldSnapshot.valueAt(n);
-            FileState& g = newSnapshot.editValueAt(m);
 
-            int fd = open(realFilename.string(), O_RDONLY);
+            int fd = open(g.file, O_RDONLY);
             if (fd < 0) {
                 // We can't open the file.  Don't report it as a delete either.  Let the
                 // server keep the old version.  Maybe they'll be able to deal with it
                 // on restore.
-                LOGP("Unable to open file %s - skipping", realFilename.string());
+                LOGP("Unable to open file %s - skipping", g.file);
             } else {
-                g.crc32 = compute_crc32(fd);
+                g.s.crc32 = compute_crc32(fd);
 
-                LOGP("%s\n", q.string());
-                LOGP("  new: modTime=%d,%d size=%-3d crc32=0x%08x\n",
+                LOGP("%s", q.string());
+                LOGP("  new: modTime=%d,%d size=%-3d crc32=0x%08x",
                         f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
-                LOGP("  old: modTime=%d,%d size=%-3d crc32=0x%08x\n",
-                        g.modTime_sec, g.modTime_nsec, g.size, g.crc32);
-                if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec
-                        || f.size != g.size || f.crc32 != g.crc32) {
-                    write_update_file(dataStream, fd, p, realFilename);
+                LOGP("  old: modTime=%d,%d size=%-3d crc32=0x%08x",
+                        g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
+                if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
+                        || f.size != g.s.size || f.crc32 != g.s.crc32) {
+                    write_update_file(dataStream, fd, p, g.file);
                 }
 
                 close(fd);
@@ -384,9 +394,8 @@
     // these were added
     while (m<fileCount) {
         const String8& q = newSnapshot.keyAt(m);
-        String8 realFilename(base);
-        realFilename.appendPath(q);
-        write_update_file(dataStream, q, realFilename);
+        FileRec& g = newSnapshot.editValueAt(m);
+        write_update_file(dataStream, q, g.file);
         m++;
     }
 
@@ -475,7 +484,7 @@
 {
     int err;
     int fd;
-    KeyedVector<String8,FileState> snapshot;
+    KeyedVector<String8,FileRec> snapshot;
     const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
 
     system("rm -r " SCRATCH_DIR);
@@ -534,7 +543,7 @@
 {
     int err;
     int fd;
-    KeyedVector<String8,FileState> snapshot;
+    KeyedVector<String8,FileRec> snapshot;
     const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
 
     system("rm -r " SCRATCH_DIR);
@@ -549,38 +558,45 @@
 
     String8 filenames[4];
     FileState states[4];
+    FileRec r;
+    r.deleted = false;
+    r.file = NULL;
 
     states[0].modTime_sec = 0xfedcba98;
     states[0].modTime_nsec = 0xdeadbeef;
     states[0].size = 0xababbcbc;
     states[0].crc32 = 0x12345678;
     states[0].nameLen = -12;
+    r.s = states[0];
     filenames[0] = String8("bytes_of_padding");
-    snapshot.add(filenames[0], states[0]);
+    snapshot.add(filenames[0], r);
 
     states[1].modTime_sec = 0x93400031;
     states[1].modTime_nsec = 0xdeadbeef;
     states[1].size = 0x88557766;
     states[1].crc32 = 0x22334422;
     states[1].nameLen = -1;
+    r.s = states[1];
     filenames[1] = String8("bytes_of_padding3");
-    snapshot.add(filenames[1], states[1]);
+    snapshot.add(filenames[1], r);
 
     states[2].modTime_sec = 0x33221144;
     states[2].modTime_nsec = 0xdeadbeef;
     states[2].size = 0x11223344;
     states[2].crc32 = 0x01122334;
     states[2].nameLen = 0;
+    r.s = states[2];
     filenames[2] = String8("bytes_of_padding_2");
-    snapshot.add(filenames[2], states[2]);
+    snapshot.add(filenames[2], r);
 
     states[3].modTime_sec = 0x33221144;
     states[3].modTime_nsec = 0xdeadbeef;
     states[3].size = 0x11223344;
     states[3].crc32 = 0x01122334;
     states[3].nameLen = 0;
+    r.s = states[3];
     filenames[3] = String8("bytes_of_padding__1");
-    snapshot.add(filenames[3], states[3]);
+    snapshot.add(filenames[3], r);
 
     err = write_snapshot_file(fd, snapshot);
 
@@ -982,6 +998,14 @@
     write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
 
     char const* files_before[] = {
+        SCRATCH_DIR "data/b",
+        SCRATCH_DIR "data/c",
+        SCRATCH_DIR "data/d",
+        SCRATCH_DIR "data/e",
+        SCRATCH_DIR "data/f"
+    };
+
+    char const* keys_before[] = {
         "data/b",
         "data/c",
         "data/d",
@@ -1004,7 +1028,7 @@
     {
         BackupDataWriter dataStream(dataStreamFD);
 
-        err = back_up_files(-1, &dataStream, newSnapshotFD, SCRATCH_DIR, files_before, 5);
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
         if (err != 0) {
             return err;
         }
@@ -1035,6 +1059,15 @@
     unlink(SCRATCH_DIR "data/f");
 
     char const* files_after[] = {
+        SCRATCH_DIR "data/a", // added
+        SCRATCH_DIR "data/b", // same
+        SCRATCH_DIR "data/c", // different mod time
+        SCRATCH_DIR "data/d", // different size (same mod time)
+        SCRATCH_DIR "data/e", // different contents (same mod time, same size)
+        SCRATCH_DIR "data/g"  // added
+    };
+
+    char const* keys_after[] = {
         "data/a", // added
         "data/b", // same
         "data/c", // different mod time
@@ -1064,8 +1097,7 @@
     {
         BackupDataWriter dataStream(dataStreamFD);
 
-        err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, SCRATCH_DIR,
-                files_after, 6);
+        err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
         if (err != 0) {
             return err;
         }
@@ -1078,6 +1110,109 @@
     return 0;
 }
 
+int
+backup_helper_test_null_base()
+{
+    int err;
+    int oldSnapshotFD;
+    int dataStreamFD;
+    int newSnapshotFD;
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
+
+    char const* files[] = {
+        SCRATCH_DIR "data/a",
+    };
+
+    char const* keys[] = {
+        "a",
+    };
+
+    dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
+        if (err != 0) {
+            return err;
+        }
+    }
+
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    return 0;
+}
+
+int
+backup_helper_test_missing_file()
+{
+    int err;
+    int oldSnapshotFD;
+    int dataStreamFD;
+    int newSnapshotFD;
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
+
+    char const* files[] = {
+        SCRATCH_DIR "data/a",
+        SCRATCH_DIR "data/b",
+        SCRATCH_DIR "data/c",
+    };
+
+    char const* keys[] = {
+        "a",
+        "b",
+        "c",
+    };
+
+    dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
+        if (err != 0) {
+            return err;
+        }
+    }
+
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    return 0;
+}
+
+
 #endif // TEST_BACKUP_HELPERS
 
 }
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 011a6ed..9bff0b2 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -4,14 +4,31 @@
 rm -rf out generated
 
 mkdir out
+
+# Create dummy Java files for Android APIs that are used by the code we generate.
+# This allows us to test the generated code without building the rest of Android.
+
 mkdir -p out/javax/microedition/khronos/opengles
 mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/app
 mkdir -p out/android/graphics
 mkdir -p out/android/opengl
+mkdir -p out/android/content
+mkdir -p out/android/content/pm
+mkdir -p out/android/os
+mkdir -p out/android/util
 
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
+echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
+# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
+echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
+echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};	}" > out/android/os/Build.java
+echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
+echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
+
 GLFILE=out/javax/microedition/khronos/opengles/GL.java
 cp stubs/jsr239/GLHeader.java-if $GLFILE
 
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 4896acb..4494643 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -44,9 +44,11 @@
 static jclass UOEClass;
 static jclass IAEClass;
 static jclass AIOOBEClass;
+static jclass G11ImplClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
+static jmethodID allowIndirectBuffersID;
 static jfieldID positionID;
 static jfieldID limitID;
 static jfieldID elementSizeShiftID;
@@ -62,13 +64,17 @@
     jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
     bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
 
+    jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
+    G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+
     getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
             "getBasePointer", "(Ljava/nio/Buffer;)J");
     getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
             "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
     getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
             "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
+    allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
+            "allowIndirectBuffers", "(Ljava/lang/String;)Z");
     positionID = _env->GetFieldID(bufferClass, "position", "I");
     limitID = _env->GetFieldID(bufferClass, "limit", "I");
     elementSizeShiftID =
@@ -118,6 +124,9 @@
     
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
+    if (*array == NULL) {
+        return (void*) NULL;
+    }
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
@@ -132,17 +141,43 @@
 					   commit ? 0 : JNI_ABORT);
 }
 
+extern "C" {
+extern char*  __progname;
+}
+
+static bool
+allowIndirectBuffers(JNIEnv *_env) {
+    static jint sIndirectBufferCompatability;
+    if (sIndirectBufferCompatability == 0) {
+        jobject appName = _env->NewStringUTF(::__progname);
+        sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
+    }
+    return sIndirectBufferCompatability == 2;
+}
+
 static void *
 getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
-    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+    if (!buffer) {
+        return NULL;
+    }
+    void* buf = _env->GetDirectBufferAddress(buffer);
     if (buf) {
         jint position = _env->GetIntField(buffer, positionID);
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
-        buf += position << elementSizeShift;
+        buf = ((char*) buf) + (position << elementSizeShift);
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        if (allowIndirectBuffers(_env)) {
+            jarray array = 0;
+            jint remaining;
+            buf = getPointer(_env, buffer, &array, &remaining);
+            if (array) {
+                releasePointer(_env, array, buf, 0);
+            }
+        } else {
+            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        }
     }
-    return (void*) buf;
+    return buf;
 }
 
 static int
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index db3a41c..fe60c5d 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -18,6 +18,12 @@
 
 package com.google.android.gles_jni;
 
+import android.app.ActivityThread;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Build;
+import android.util.Log;
+
 import java.nio.Buffer;
 import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.opengles.GL10Ext;
@@ -42,7 +48,28 @@
     public GLImpl() {
     }
 
-     public void glGetPointerv(int pname, java.nio.Buffer[] params) {
-         throw new UnsupportedOperationException("glGetPointerv");
-     }
+    public void glGetPointerv(int pname, java.nio.Buffer[] params) {
+        throw new UnsupportedOperationException("glGetPointerv");
+    }
+
+    private static boolean allowIndirectBuffers(String appName) {
+        boolean result = false;
+        int version = 0;
+        IPackageManager pm = ActivityThread.getPackageManager();
+        try {
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+            if (applicationInfo != null) {
+                version = applicationInfo.targetSdkVersion;
+            }
+        } catch (android.os.RemoteException e) {
+            // ignore
+        }
+        Log.e("OpenGLES", String.format(
+            "Application %s (SDK target %d) called a GL11 Pointer method with an indirect Buffer.",
+            appName, version));
+        if (version <= Build.VERSION_CODES.CUPCAKE) {
+            result = true;
+        }
+        return result;
+    }
 
diff --git a/tts/java/android/tts/ITts.aidl b/tts/java/android/tts/ITts.aidl
deleted file mode 100755
index 1fe4a6a..0000000
--- a/tts/java/android/tts/ITts.aidl
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.tts;
-
-import android.tts.ITtsCallback;
-
-import android.content.Intent;
-
-/**
- * AIDL for the TTS Service
- * ITts.java is autogenerated from this.
- *
- * {@hide}
- */
-interface ITts {
-    void setEngine(in String engineName, in String[] requestedLanguages, in int strictness);
-
-    void setEngineWithIntent(in Intent engineIntent);
-
-    void setSpeechRate(in int speechRate);
-
-    void speak(in String text, in int queueMode, in String[] params);
-
-    boolean isSpeaking();
-
-    void stop();
-
-    void addSpeech(in String text, in String packageName, in int resId);
-
-    void addSpeechFile(in String text, in String filename);
-
-    void setLanguage(in String language);
-
-    boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
-
-    void playEarcon(in String earcon, in int queueMode, in String[] params);
-
-    void addEarcon(in String earcon, in String packageName, in int resId);
-
-    void addEarconFile(in String earcon, in String filename);
-
-    void registerCallback(ITtsCallback cb);
-
-    void unregisterCallback(ITtsCallback cb);
-}
diff --git a/tts/java/android/tts/SynthProxy.java b/tts/java/android/tts/SynthProxy.java
deleted file mode 100755
index e065f40..0000000
--- a/tts/java/android/tts/SynthProxy.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc.
- *
- * 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.tts;
-
-import android.util.Log;
-import java.lang.ref.WeakReference;
-
-/**
- * @hide
- *
- * The SpeechSynthesis class provides a high-level api to create and play
- * synthesized speech. This class is used internally to talk to a native
- * TTS library that implements the interface defined in
- * frameworks/base/include/tts/TtsEngine.h
- *
- */
-@SuppressWarnings("unused")
-public class SynthProxy {
-
-    //
-    // External API
-    //
-
-    /**
-     * Constructor; pass the location of the native TTS .so to use.
-     */
-    public SynthProxy(String nativeSoLib) {
-        Log.e("TTS is loading", nativeSoLib);
-        native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
-    }
-
-    /**
-     * Stops and clears the AudioTrack.
-     */
-    public void stop() {
-        native_stop(mJniData);
-    }
-
-    /**
-     * Synthesize speech and speak it directly using AudioTrack.
-     */
-    public void speak(String text) {
-        native_speak(mJniData, text);
-    }
-
-    /**
-     * Synthesize speech to a file. The current implementation writes a valid
-     * WAV file to the given path, assuming it is writable. Something like
-     * "/sdcard/???.wav" is recommended.
-     */
-    public void synthesizeToFile(String text, String filename) {
-        native_synthesizeToFile(mJniData, text, filename);
-    }
-
-    // TODO add IPA methods
-
-    /**
-     * Sets the language
-     */
-    public void setLanguage(String language) {
-        native_setLanguage(mJniData, language);
-    }
-
-    /**
-     * Sets the speech rate
-     */
-    public final void setSpeechRate(int speechRate) {
-        native_setSpeechRate(mJniData, speechRate);
-    }
-
-
-    /**
-     * Plays the given audio buffer
-     */
-    public void playAudioBuffer(int bufferPointer, int bufferSize) {
-        native_playAudioBuffer(mJniData, bufferPointer, bufferSize);
-    }
-
-    /**
-     * Gets the currently set language
-     */
-    public String getLanguage() {
-        return native_getLanguage(mJniData);
-    }
-
-    /**
-     * Gets the currently set rate
-     */
-    public int getRate() {
-        return native_getRate(mJniData);
-    }
-
-    /**
-     * Shuts down the native synthesizer
-     */
-    public void shutdown()  {
-        native_shutdown(mJniData);
-    }
-
-    //
-    // Internal
-    //
-
-    protected void finalize() {
-        native_finalize(mJniData);
-        mJniData = 0;
-    }
-
-    static {
-        System.loadLibrary("ttssynthproxy");
-    }
-
-    private final static String TAG = "SynthProxy";
-
-    /**
-     * Accessed by native methods
-     */
-    private int mJniData = 0;
-
-    private native final void native_setup(Object weak_this,
-            String nativeSoLib);
-
-    private native final void native_finalize(int jniData);
-
-    private native final void native_stop(int jniData);
-
-    private native final void native_speak(int jniData, String text);
-
-    private native final void native_synthesizeToFile(int jniData, String text, String filename);
-
-    private native final void native_setLanguage(int jniData, String language);
-
-    private native final void native_setSpeechRate(int jniData, int speechRate);
-
-    // TODO add buffer format
-    private native final void native_playAudioBuffer(int jniData, int bufferPointer, int bufferSize);
-
-    private native final String native_getLanguage(int jniData);
-
-    private native final int native_getRate(int jniData);
-
-    private native final void native_shutdown(int jniData);
-
-
-    /**
-     * Callback from the C layer
-     */
-    @SuppressWarnings("unused")
-    private static void postNativeSpeechSynthesizedInJava(Object tts_ref,
-            int bufferPointer, int bufferSize) {
-
-        Log.i("TTS plugin debug", "bufferPointer: " + bufferPointer
-                + " bufferSize: " + bufferSize);
-
-        SynthProxy nativeTTS = (SynthProxy)((WeakReference)tts_ref).get();
-        // TODO notify TTS service of synthesis/playback completion,
-        //      method definition to be changed.
-    }
-}
diff --git a/tts/java/android/tts/Tts.java b/tts/java/android/tts/Tts.java
deleted file mode 100755
index 6c8b36d..0000000
--- a/tts/java/android/tts/Tts.java
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc.
- *
- * 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.tts;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * @hide
- *
- * Synthesizes speech from text. This abstracts away the complexities of using
- * the TTS service such as setting up the IBinder connection and handling
- * RemoteExceptions, etc.
- *
- * The TTS should always be safe the use; if the user does not have the
- * necessary TTS apk installed, the behavior is that all calls to the TTS act as
- * no-ops.
- *
- */
-//FIXME #TTS# review + complete javadoc
-public class Tts {
-
-
-    /**
-     * Called when the TTS has initialized
-     *
-     * The InitListener must implement the onInit function. onInit is passed the
-     * version number of the TTS library that the user has installed; since this
-     * is called when the TTS has started, it is a good time to make sure that
-     * the user's TTS library is up to date.
-     */
-    public interface OnInitListener {
-        public void onInit(int version);
-    }
-
-    /**
-     * Called when the TTS has finished speaking by itself (speaking
-     * finished without being canceled).
-     *
-     */
-    public interface OnSpeechCompletedListener {
-        public void onSpeechCompleted();
-    }
-
-    /**
-     * Connection needed for the TTS
-     */
-    private ServiceConnection serviceConnection;
-
-    private ITts itts = null;
-    private Context ctx = null;
-    private OnInitListener cb = null;
-    private int version = -1;
-    private boolean started = false;
-    private final Object startLock = new Object();
-    private boolean showInstaller = false;
-    private ITtsCallback ittscallback;
-    private OnSpeechCompletedListener speechCompletedCallback = null;
-
-
-    /**
-     * The constructor for the TTS.
-     *
-     * @param context
-     *            The context
-     * @param callback
-     *            The InitListener that should be called when the TTS has
-     *            initialized successfully.
-     * @param displayInstallMessage
-     *            Boolean indicating whether or not an installation prompt
-     *            should be displayed to users who do not have the TTS library.
-     *            If this is true, a generic alert asking the user to install
-     *            the TTS will be used. If you wish to specify the exact message
-     *            of that prompt, please use TTS(Context context, InitListener
-     *            callback, TTSVersionAlert alert) as the constructor instead.
-     */
-    public Tts(Context context, OnInitListener callback,
-                boolean displayInstallMessage) {
-        showInstaller = displayInstallMessage;
-        ctx = context;
-        cb = callback;
-        if (dataFilesCheck()) {
-            initTts();
-        }
-    }
-
-    /**
-     * The constructor for the TTS.
-     *
-     * @param context
-     *            The context
-     * @param callback
-     *            The InitListener that should be called when the TTS has
-     *            initialized successfully.
-     */
-    public Tts(Context context, OnInitListener callback) {
-        // FIXME #TTS# support TtsVersionAlert
-        //     showInstaller = true;
-        //     versionAlert = alert;
-        ctx = context;
-        cb = callback;
-        if (dataFilesCheck()) {
-            initTts();
-        }
-    }
-
-
-    public void setOnSpeechCompletedListener(
-            final OnSpeechCompletedListener listener) {
-        speechCompletedCallback = listener;
-    }
-
-
-    private boolean dataFilesCheck() {
-        // FIXME #TTS# config manager will be in settings
-        Log.i("TTS_FIXME", "FIXME in Tts: config manager will be in settings");
-        // FIXME #TTS# implement checking of the correct installation of
-        //             the data files.
-
-        return true;
-    }
-
-
-    private void initTts() {
-        started = false;
-
-        // Initialize the TTS, run the callback after the binding is successful
-        serviceConnection = new ServiceConnection() {
-            public void onServiceConnected(ComponentName name, IBinder service) {
-                synchronized(startLock) {
-                    itts = ITts.Stub.asInterface(service);
-                    try {
-                        ittscallback = new ITtsCallback.Stub() {
-                            //@Override
-                            public void markReached(String mark)
-                            throws RemoteException {
-                                if (speechCompletedCallback != null) {
-                                    speechCompletedCallback.onSpeechCompleted();
-                                }
-                            }
-                        };
-                        itts.registerCallback(ittscallback);
-
-                    } catch (RemoteException e) {
-                        initTts();
-                        return;
-                    }
-
-                    started = true;
-                    // The callback can become null if the Android OS decides to
-                    // restart the TTS process as well as whatever is using it.
-                    // In such cases, do nothing - the error handling from the
-                    // speaking calls will kick in and force a proper restart of
-                    // the TTS.
-                    if (cb != null) {
-                        cb.onInit(version);
-                    }
-                }
-            }
-
-            public void onServiceDisconnected(ComponentName name) {
-                synchronized(startLock) {
-                    itts = null;
-                    cb = null;
-                    started = false;
-                }
-            }
-        };
-
-        Intent intent = new Intent("android.intent.action.USE_TTS");
-        intent.addCategory("android.intent.category.TTS");
-        // Binding will fail only if the TTS doesn't exist;
-        // the TTSVersionAlert will give users a chance to install
-        // the needed TTS.
-        if (!ctx.bindService(intent, serviceConnection,
-                Context.BIND_AUTO_CREATE)) {
-            if (showInstaller) {
-                // FIXME #TTS# show version alert
-            }
-        }
-    }
-
-
-    /**
-     * Shuts down the TTS. It is good practice to call this in the onDestroy
-     * method of the Activity that is using the TTS so that the TTS is stopped
-     * cleanly.
-     */
-    public void shutdown() {
-        try {
-            ctx.unbindService(serviceConnection);
-        } catch (IllegalArgumentException e) {
-            // Do nothing and fail silently since an error here indicates that
-            // binding never succeeded in the first place.
-        }
-    }
-
-
-    /**
-     * Adds a mapping between a string of text and a sound resource in a
-     * package.
-     *
-     * @see #TTS.speak(String text, int queueMode, String[] params)
-     *
-     * @param text
-     *            Example: <b><code>"south_south_east"</code></b><br/>
-     *
-     * @param packagename
-     *            Pass the packagename of the application that contains the
-     *            resource. If the resource is in your own application (this is
-     *            the most common case), then put the packagename of your
-     *            application here.<br/>
-     *            Example: <b>"com.google.marvin.compass"</b><br/>
-     *            The packagename can be found in the AndroidManifest.xml of
-     *            your application.
-     *            <p>
-     *            <code>&lt;manifest xmlns:android=&quot;...&quot;
-     *      package=&quot;<b>com.google.marvin.compass</b>&quot;&gt;</code>
-     *            </p>
-     *
-     * @param resourceId
-     *            Example: <b><code>R.raw.south_south_east</code></b>
-     */
-    public void addSpeech(String text, String packagename, int resourceId) {
-        synchronized(startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.addSpeech(text, packagename, resourceId);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Adds a mapping between a string of text and a sound file. Using this, it
-     * is possible to add custom pronounciations for text.
-     *
-     * @param text
-     *            The string of text
-     * @param filename
-     *            The full path to the sound file (for example:
-     *            "/sdcard/mysounds/hello.wav")
-     */
-    public void addSpeech(String text, String filename) {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.addSpeechFile(text, filename);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Speaks the string using the specified queuing strategy and speech
-     * parameters. Note that the speech parameters are not universally supported
-     * by all engines and will be treated as a hint. The TTS library will try to
-     * fulfill these parameters as much as possible, but there is no guarantee
-     * that the voice used will have the properties specified.
-     *
-     * @param text
-     *            The string of text to be spoken.
-     * @param queueMode
-     *            The queuing strategy to use. Use 0 for no queuing, and 1 for
-     *            queuing.
-     * @param params
-     *            The array of speech parameters to be used. Currently, only
-     *            params[0] is defined - it is for setting the type of voice if
-     *            the engine allows it. Possible values are "VOICE_MALE",
-     *            "VOICE_FEMALE", and "VOICE_ROBOT". Note that right now only
-     *            the pre-recorded voice has this support - this setting has no
-     *            effect on eSpeak.
-     */
-    public void speak(String text, int queueMode, String[] params) {
-        synchronized (startLock) {
-            Log.i("TTS received: ", text);
-            if (!started) {
-                return;
-            }
-            try {
-                itts.speak(text, queueMode, params);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Plays the earcon using the specified queueing mode and parameters.
-     *
-     * @param earcon
-     *            The earcon that should be played
-     * @param queueMode
-     *            0 for no queue (interrupts all previous utterances), 1 for
-     *            queued
-     * @param params
-     *            An ArrayList of parameters.
-     */
-    public void playEarcon(String earcon, int queueMode, String[] params) {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.playEarcon(earcon, queueMode, params);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Returns whether or not the TTS is busy speaking.
-     *
-     * @return Whether or not the TTS is busy speaking.
-     */
-    public boolean isSpeaking() {
-        synchronized (startLock) {
-            if (!started) {
-                return false;
-            }
-            try {
-                return itts.isSpeaking();
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-            return false;
-        }
-    }
-
-
-    /**
-     * Stops speech from the TTS.
-     */
-    public void stop() {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.stop();
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Returns the version number of the TTS library that the user has
-     * installed.
-     *
-     * @return The version number of the TTS library that the user has
-     *         installed.
-     */
-    public int getVersion() {
-        return version;
-    }
-
-
-    /**
-     * Sets the TTS engine to be used.
-     *
-     * @param selectedEngine
-     *            The TTS engine that should be used.
-     */
-    public void setEngine(String engineName, String[] requestedLanguages, int strictness) {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.setEngine(engineName, requestedLanguages, strictness);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Sets the speech rate for the TTS engine.
-     *
-     * Note that the speech rate is not universally supported by all engines and
-     * will be treated as a hint. The TTS library will try to use the specified
-     * speech rate, but there is no guarantee.
-     *
-     * Currently, this will change the speech rate for the espeak engine, but it
-     * has no effect on any pre-recorded speech.
-     *
-     * @param speechRate
-     *            The speech rate for the TTS engine.
-     */
-    public void setSpeechRate(int speechRate) {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.setSpeechRate(speechRate);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Sets the language for the TTS engine.
-     *
-     * Note that the language is not universally supported by all engines and
-     * will be treated as a hint. The TTS library will try to use the specified
-     * language, but there is no guarantee.
-     *
-     * Currently, this will change the language for the espeak engine, but it
-     * has no effect on any pre-recorded speech.
-     *
-     * @param language
-     *            The language to be used. The languages are specified by their
-     *            IETF language tags as defined by BCP 47. This is the same
-     *            standard used for the lang attribute in HTML. See:
-     *            http://en.wikipedia.org/wiki/IETF_language_tag
-     */
-    public void setLanguage(String language) {
-        synchronized (startLock) {
-            if (!started) {
-                return;
-            }
-            try {
-                itts.setLanguage(language);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-        }
-    }
-
-
-    /**
-     * Speaks the given text using the specified queueing mode and parameters.
-     *
-     * @param text
-     *            The String of text that should be synthesized
-     * @param params
-     *            An ArrayList of parameters. The first element of this array
-     *            controls the type of voice to use.
-     * @param filename
-     *            The string that gives the full output filename; it should be
-     *            something like "/sdcard/myappsounds/mysound.wav".
-     * @return A boolean that indicates if the synthesis succeeded
-     */
-    public boolean synthesizeToFile(String text, String[] params,
-            String filename) {
-        synchronized (startLock) {
-            if (!started) {
-                return false;
-            }
-            try {
-                return itts.synthesizeToFile(text, params, filename);
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                started = false;
-                initTts();
-            }
-            return false;
-        }
-    }
-
-
-    /**
-     * Displays an alert that prompts users to install the TTS engine.
-     * This is useful if the application expects a newer version
-     * of the TTS than what the user has.
-     */
-    public void showVersionAlert() {
-        if (!started) {
-            return;
-        }
-        // FIXME #TTS# implement show version alert
-    }
-
-
-    /**
-     * Checks if the TTS service is installed or not
-     *
-     * @return A boolean that indicates whether the TTS service is installed
-     */
-    // TODO: TTS Service itself will always be installed. Factor this out
-    // (may need to add another method to see if there are any working
-    // TTS engines on the device).
-    public static boolean isInstalled(Context ctx) {
-        PackageManager pm = ctx.getPackageManager();
-        Intent intent = new Intent("android.intent.action.USE_TTS");
-        intent.addCategory("android.intent.category.TTS");
-        ResolveInfo info = pm.resolveService(intent, 0);
-        if (info == null) {
-            return false;
-        }
-        return true;
-    }
-
-}
diff --git a/tts/java/android/tts/TtsService.java b/tts/java/android/tts/TtsService.java
deleted file mode 100755
index d317181..0000000
--- a/tts/java/android/tts/TtsService.java
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc.
- *
- * 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.tts;
-
-import android.tts.ITts.Stub;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.net.Uri;
-import android.os.IBinder;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.preference.PreferenceManager;
-import android.util.Log;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * @hide Synthesizes speech from text. This is implemented as a service so that
- *       other applications can call the TTS without needing to bundle the TTS
- *       in the build.
- *
- */
-public class TtsService extends Service implements OnCompletionListener {
-
-    private static class SpeechItem {
-        public static final int SPEECH = 0;
-        public static final int EARCON = 1;
-        public static final int SILENCE = 2;
-        public String mText = null;
-        public ArrayList<String> mParams = null;
-        public int mType = SPEECH;
-        public long mDuration = 0;
-
-        public SpeechItem(String text, ArrayList<String> params, int itemType) {
-            mText = text;
-            mParams = params;
-            mType = itemType;
-        }
-
-        public SpeechItem(long silenceTime) {
-            mDuration = silenceTime;
-        }
-    }
-
-    /**
-     * Contains the information needed to access a sound resource; the name of
-     * the package that contains the resource and the resID of the resource
-     * within that package.
-     */
-    private static class SoundResource {
-        public String mSourcePackageName = null;
-        public int mResId = -1;
-        public String mFilename = null;
-
-        public SoundResource(String packageName, int id) {
-            mSourcePackageName = packageName;
-            mResId = id;
-            mFilename = null;
-        }
-
-        public SoundResource(String file) {
-            mSourcePackageName = null;
-            mResId = -1;
-            mFilename = file;
-        }
-    }
-
-    private static final String ACTION = "android.intent.action.USE_TTS";
-    private static final String CATEGORY = "android.intent.category.TTS";
-    private static final String PKGNAME = "android.tts";
-
-    final RemoteCallbackList<ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>();
-
-    private Boolean mIsSpeaking;
-    private ArrayList<SpeechItem> mSpeechQueue;
-    private HashMap<String, SoundResource> mEarcons;
-    private HashMap<String, SoundResource> mUtterances;
-    private MediaPlayer mPlayer;
-    private TtsService mSelf;
-
-    private SharedPreferences prefs;
-
-    private final ReentrantLock speechQueueLock = new ReentrantLock();
-    private final ReentrantLock synthesizerLock = new ReentrantLock();
-
-    // TODO support multiple SpeechSynthesis objects
-    private SynthProxy nativeSynth;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        Log.i("TTS", "TTS starting");
-
-
-        // TODO: Make this work when the settings are done in the main Settings
-        // app.
-        prefs = PreferenceManager.getDefaultSharedPreferences(this);
-
-        // TODO: This should be changed to work by requesting the path
-        // from the default engine.
-        nativeSynth = new SynthProxy(prefs.getString("engine_pref", ""));
-
-
-        mSelf = this;
-        mIsSpeaking = false;
-
-        mEarcons = new HashMap<String, SoundResource>();
-        mUtterances = new HashMap<String, SoundResource>();
-
-        mSpeechQueue = new ArrayList<SpeechItem>();
-        mPlayer = null;
-
-        setLanguage(prefs.getString("lang_pref", "en-rUS"));
-        setSpeechRate(Integer.parseInt(prefs.getString("rate_pref", "140")));
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        // Don't hog the media player
-        cleanUpPlayer();
-
-        nativeSynth.shutdown();
-
-        // Unregister all callbacks.
-        mCallbacks.kill();
-    }
-
-    private void setSpeechRate(int rate) {
-        if (prefs.getBoolean("override_pref", false)) {
-            // This is set to the default here so that the preview in the prefs
-            // activity will show the change without a restart, even if apps are
-            // not allowed to change the defaults.
-            rate = Integer.parseInt(prefs.getString("rate_pref", "140"));
-        }
-        nativeSynth.setSpeechRate(rate);
-    }
-
-    private void setLanguage(String lang) {
-        if (prefs.getBoolean("override_pref", false)) {
-            // This is set to the default here so that the preview in the prefs
-            // activity will show the change without a restart, even if apps are
-            // not
-            // allowed to change the defaults.
-            lang = prefs.getString("lang_pref", "en-rUS");
-        }
-        nativeSynth.setLanguage(lang);
-    }
-
-    private void setEngine(String engineName, String[] requestedLanguages,
-            int strictness) {
-        // TODO: Implement engine selection code here.
-        Intent engineIntent = new Intent(
-        "android.intent.action.START_TTS_ENGINE");
-        if (engineName != null) {
-            engineIntent.addCategory("android.intent.action.tts_engine."
-                    + engineName);
-        }
-        for (int i = 0; i < requestedLanguages.length; i++) {
-            engineIntent.addCategory("android.intent.action.tts_lang."
-                    + requestedLanguages[i]);
-        }
-        ResolveInfo[] enginesArray = new ResolveInfo[0];
-        PackageManager pm = getPackageManager();
-        enginesArray = pm.queryIntentActivities(engineIntent, 0).toArray(
-                enginesArray);
-    }
-
-    private void setEngine(Intent engineIntent) {
-        // TODO: Implement engine selection code here.
-    }
-
-    private int getEngineStatus() {
-        // TODO: Proposal - add a sanity check method that
-        // TTS engine plugins must implement.
-        return 0;
-    }
-
-    /**
-     * Adds a sound resource to the TTS.
-     *
-     * @param text
-     *            The text that should be associated with the sound resource
-     * @param packageName
-     *            The name of the package which has the sound resource
-     * @param resId
-     *            The resource ID of the sound within its package
-     */
-    private void addSpeech(String text, String packageName, int resId) {
-        mUtterances.put(text, new SoundResource(packageName, resId));
-    }
-
-    /**
-     * Adds a sound resource to the TTS.
-     *
-     * @param text
-     *            The text that should be associated with the sound resource
-     * @param filename
-     *            The filename of the sound resource. This must be a complete
-     *            path like: (/sdcard/mysounds/mysoundbite.mp3).
-     */
-    private void addSpeech(String text, String filename) {
-        mUtterances.put(text, new SoundResource(filename));
-    }
-
-    /**
-     * Adds a sound resource to the TTS as an earcon.
-     *
-     * @param earcon
-     *            The text that should be associated with the sound resource
-     * @param packageName
-     *            The name of the package which has the sound resource
-     * @param resId
-     *            The resource ID of the sound within its package
-     */
-    private void addEarcon(String earcon, String packageName, int resId) {
-        mEarcons.put(earcon, new SoundResource(packageName, resId));
-    }
-
-    /**
-     * Adds a sound resource to the TTS as an earcon.
-     *
-     * @param earcon
-     *            The text that should be associated with the sound resource
-     * @param filename
-     *            The filename of the sound resource. This must be a complete
-     *            path like: (/sdcard/mysounds/mysoundbite.mp3).
-     */
-    private void addEarcon(String earcon, String filename) {
-        mEarcons.put(earcon, new SoundResource(filename));
-    }
-
-    /**
-     * Speaks the given text using the specified queueing mode and parameters.
-     *
-     * @param text
-     *            The text that should be spoken
-     * @param queueMode
-     *            0 for no queue (interrupts all previous utterances), 1 for
-     *            queued
-     * @param params
-     *            An ArrayList of parameters. This is not implemented for all
-     *            engines.
-     */
-    private void speak(String text, int queueMode, ArrayList<String> params) {
-        if (queueMode == 0) {
-            stop();
-        }
-        mSpeechQueue.add(new SpeechItem(text, params, SpeechItem.SPEECH));
-        if (!mIsSpeaking) {
-            processSpeechQueue();
-        }
-    }
-
-    /**
-     * Plays the earcon using the specified queueing mode and parameters.
-     *
-     * @param earcon
-     *            The earcon that should be played
-     * @param queueMode
-     *            0 for no queue (interrupts all previous utterances), 1 for
-     *            queued
-     * @param params
-     *            An ArrayList of parameters. This is not implemented for all
-     *            engines.
-     */
-    private void playEarcon(String earcon, int queueMode,
-            ArrayList<String> params) {
-        if (queueMode == 0) {
-            stop();
-        }
-        mSpeechQueue.add(new SpeechItem(earcon, params, SpeechItem.EARCON));
-        if (!mIsSpeaking) {
-            processSpeechQueue();
-        }
-    }
-
-    /**
-     * Stops all speech output and removes any utterances still in the queue.
-     */
-    private void stop() {
-        Log.i("TTS", "Stopping");
-        mSpeechQueue.clear();
-
-        nativeSynth.stop();
-        mIsSpeaking = false;
-        if (mPlayer != null) {
-            try {
-                mPlayer.stop();
-            } catch (IllegalStateException e) {
-                // Do nothing, the player is already stopped.
-            }
-        }
-        Log.i("TTS", "Stopped");
-    }
-
-    public void onCompletion(MediaPlayer arg0) {
-        processSpeechQueue();
-    }
-
-    private void playSilence(long duration, int queueMode,
-            ArrayList<String> params) {
-        if (queueMode == 0) {
-            stop();
-        }
-        mSpeechQueue.add(new SpeechItem(duration));
-        if (!mIsSpeaking) {
-            processSpeechQueue();
-        }
-    }
-
-    private void silence(final long duration) {
-        class SilenceThread implements Runnable {
-            public void run() {
-                try {
-                    Thread.sleep(duration);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                } finally {
-                    processSpeechQueue();
-                }
-            }
-        }
-        Thread slnc = (new Thread(new SilenceThread()));
-        slnc.setPriority(Thread.MIN_PRIORITY);
-        slnc.start();
-    }
-
-    private void speakInternalOnly(final String text,
-            final ArrayList<String> params) {
-        class SynthThread implements Runnable {
-            public void run() {
-                boolean synthAvailable = false;
-                try {
-                    synthAvailable = synthesizerLock.tryLock();
-                    if (!synthAvailable) {
-                        Thread.sleep(100);
-                        Thread synth = (new Thread(new SynthThread()));
-                        synth.setPriority(Thread.MIN_PRIORITY);
-                        synth.start();
-                        return;
-                    }
-                    nativeSynth.speak(text);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                } finally {
-                    // This check is needed because finally will always run;
-                    // even if the
-                    // method returns somewhere in the try block.
-                    if (synthAvailable) {
-                        synthesizerLock.unlock();
-                    }
-                }
-            }
-        }
-        Thread synth = (new Thread(new SynthThread()));
-        synth.setPriority(Thread.MIN_PRIORITY);
-        synth.start();
-    }
-
-    private SoundResource getSoundResource(SpeechItem speechItem) {
-        SoundResource sr = null;
-        String text = speechItem.mText;
-        if (speechItem.mType == SpeechItem.SILENCE) {
-            // Do nothing if this is just silence
-        } else if (speechItem.mType == SpeechItem.EARCON) {
-            sr = mEarcons.get(text);
-        } else {
-            sr = mUtterances.get(text);
-        }
-        return sr;
-    }
-
-    private void dispatchSpeechCompletedCallbacks(String mark) {
-        Log.i("TTS callback", "dispatch started");
-        // Broadcast to all clients the new value.
-        final int N = mCallbacks.beginBroadcast();
-        for (int i = 0; i < N; i++) {
-            try {
-                mCallbacks.getBroadcastItem(i).markReached(mark);
-            } catch (RemoteException e) {
-                // The RemoteCallbackList will take care of removing
-                // the dead object for us.
-            }
-        }
-        mCallbacks.finishBroadcast();
-        Log.i("TTS callback", "dispatch completed to " + N);
-    }
-
-    private void processSpeechQueue() {
-        boolean speechQueueAvailable = false;
-        try {
-            speechQueueAvailable = speechQueueLock.tryLock();
-            if (!speechQueueAvailable) {
-                return;
-            }
-            if (mSpeechQueue.size() < 1) {
-                mIsSpeaking = false;
-                // Dispatch a completion here as this is the
-                // only place where speech completes normally.
-                // Nothing left to say in the queue is a special case
-                // that is always a "mark" - associated text is null.
-                dispatchSpeechCompletedCallbacks("");
-                return;
-            }
-
-            SpeechItem currentSpeechItem = mSpeechQueue.get(0);
-            mIsSpeaking = true;
-            SoundResource sr = getSoundResource(currentSpeechItem);
-            // Synth speech as needed - synthesizer should call
-            // processSpeechQueue to continue running the queue
-            Log.i("TTS processing: ", currentSpeechItem.mText);
-            if (sr == null) {
-                if (currentSpeechItem.mType == SpeechItem.SPEECH) {
-                    // TODO: Split text up into smaller chunks before accepting
-                    // them
-                    // for processing.
-                    speakInternalOnly(currentSpeechItem.mText,
-                            currentSpeechItem.mParams);
-                } else {
-                    // This is either silence or an earcon that was missing
-                    silence(currentSpeechItem.mDuration);
-                }
-            } else {
-                cleanUpPlayer();
-                if (sr.mSourcePackageName == PKGNAME) {
-                    // Utterance is part of the TTS library
-                    mPlayer = MediaPlayer.create(this, sr.mResId);
-                } else if (sr.mSourcePackageName != null) {
-                    // Utterance is part of the app calling the library
-                    Context ctx;
-                    try {
-                        ctx = this.createPackageContext(sr.mSourcePackageName,
-                                0);
-                    } catch (NameNotFoundException e) {
-                        e.printStackTrace();
-                        mSpeechQueue.remove(0); // Remove it from the queue and
-                        // move on
-                        mIsSpeaking = false;
-                        return;
-                    }
-                    mPlayer = MediaPlayer.create(ctx, sr.mResId);
-                } else {
-                    // Utterance is coming from a file
-                    mPlayer = MediaPlayer.create(this, Uri.parse(sr.mFilename));
-                }
-
-                // Check if Media Server is dead; if it is, clear the queue and
-                // give up for now - hopefully, it will recover itself.
-                if (mPlayer == null) {
-                    mSpeechQueue.clear();
-                    mIsSpeaking = false;
-                    return;
-                }
-                mPlayer.setOnCompletionListener(this);
-                try {
-                    mPlayer.start();
-                } catch (IllegalStateException e) {
-                    mSpeechQueue.clear();
-                    mIsSpeaking = false;
-                    cleanUpPlayer();
-                    return;
-                }
-            }
-            if (mSpeechQueue.size() > 0) {
-                mSpeechQueue.remove(0);
-            }
-        } finally {
-            // This check is needed because finally will always run; even if the
-            // method returns somewhere in the try block.
-            if (speechQueueAvailable) {
-                speechQueueLock.unlock();
-            }
-        }
-    }
-
-    private void cleanUpPlayer() {
-        if (mPlayer != null) {
-            mPlayer.release();
-            mPlayer = null;
-        }
-    }
-
-    /**
-     * Synthesizes the given text using the specified queuing mode and
-     * parameters.
-     *
-     * @param text
-     *            The String of text that should be synthesized
-     * @param params
-     *            An ArrayList of parameters. The first element of this array
-     *            controls the type of voice to use.
-     * @param filename
-     *            The string that gives the full output filename; it should be
-     *            something like "/sdcard/myappsounds/mysound.wav".
-     * @return A boolean that indicates if the synthesis succeeded
-     */
-    private boolean synthesizeToFile(String text, ArrayList<String> params,
-            String filename, boolean calledFromApi) {
-        // Only stop everything if this is a call made by an outside app trying
-        // to
-        // use the API. Do NOT stop if this is a call from within the service as
-        // clearing the speech queue here would be a mistake.
-        if (calledFromApi) {
-            stop();
-        }
-        Log.i("TTS", "Synthesizing to " + filename);
-        boolean synthAvailable = false;
-        try {
-            synthAvailable = synthesizerLock.tryLock();
-            if (!synthAvailable) {
-                return false;
-            }
-            // Don't allow a filename that is too long
-            // TODO use platform constant
-            if (filename.length() > 250) {
-                return false;
-            }
-            nativeSynth.synthesizeToFile(text, filename);
-        } finally {
-            // This check is needed because finally will always run; even if the
-            // method returns somewhere in the try block.
-            if (synthAvailable) {
-                synthesizerLock.unlock();
-            }
-        }
-        Log.i("TTS", "Completed synthesis for " + filename);
-        return true;
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        if (ACTION.equals(intent.getAction())) {
-            for (String category : intent.getCategories()) {
-                if (category.equals(CATEGORY)) {
-                    return mBinder;
-                }
-            }
-        }
-        return null;
-    }
-
-    private final ITts.Stub mBinder = new Stub() {
-
-        public void registerCallback(ITtsCallback cb) {
-            if (cb != null)
-                mCallbacks.register(cb);
-        }
-
-        public void unregisterCallback(ITtsCallback cb) {
-            if (cb != null)
-                mCallbacks.unregister(cb);
-        }
-
-        /**
-         * Gives a hint about the type of engine that is preferred.
-         *
-         * @param selectedEngine
-         *            The TTS engine that should be used
-         */
-        public void setEngine(String engineName, String[] supportedLanguages,
-                int strictness) {
-            mSelf.setEngine(engineName, supportedLanguages, strictness);
-        }
-
-        /**
-         * Specifies exactly what the engine has to support. Will always be
-         * considered "strict"; can be used for implementing
-         * optional/experimental features that are not supported by all engines.
-         *
-         * @param engineIntent
-         *            An intent that specifies exactly what the engine has to
-         *            support.
-         */
-        public void setEngineWithIntent(Intent engineIntent) {
-            mSelf.setEngine(engineIntent);
-        }
-
-        /**
-         * Speaks the given text using the specified queueing mode and
-         * parameters.
-         *
-         * @param text
-         *            The text that should be spoken
-         * @param queueMode
-         *            0 for no queue (interrupts all previous utterances), 1 for
-         *            queued
-         * @param params
-         *            An ArrayList of parameters. The first element of this
-         *            array controls the type of voice to use.
-         */
-        public void speak(String text, int queueMode, String[] params) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            mSelf.speak(text, queueMode, speakingParams);
-        }
-
-        /**
-         * Plays the earcon using the specified queueing mode and parameters.
-         *
-         * @param earcon
-         *            The earcon that should be played
-         * @param queueMode
-         *            0 for no queue (interrupts all previous utterances), 1 for
-         *            queued
-         * @param params
-         *            An ArrayList of parameters.
-         */
-        public void playEarcon(String earcon, int queueMode, String[] params) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            mSelf.playEarcon(earcon, queueMode, speakingParams);
-        }
-
-        /**
-         * Plays the silence using the specified queueing mode and parameters.
-         *
-         * @param duration
-         *            The duration of the silence that should be played
-         * @param queueMode
-         *            0 for no queue (interrupts all previous utterances), 1 for
-         *            queued
-         * @param params
-         *            An ArrayList of parameters.
-         */
-        public void playSilence(long duration, int queueMode, String[] params) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            mSelf.playSilence(duration, queueMode, speakingParams);
-        }
-
-
-        /**
-         * Stops all speech output and removes any utterances still in the
-         * queue.
-         */
-        public void stop() {
-            mSelf.stop();
-        }
-
-        /**
-         * Returns whether or not the TTS is speaking.
-         *
-         * @return Boolean to indicate whether or not the TTS is speaking
-         */
-        public boolean isSpeaking() {
-            return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1));
-        }
-
-        /**
-         * Adds a sound resource to the TTS.
-         *
-         * @param text
-         *            The text that should be associated with the sound resource
-         * @param packageName
-         *            The name of the package which has the sound resource
-         * @param resId
-         *            The resource ID of the sound within its package
-         */
-        public void addSpeech(String text, String packageName, int resId) {
-            mSelf.addSpeech(text, packageName, resId);
-        }
-
-        /**
-         * Adds a sound resource to the TTS.
-         *
-         * @param text
-         *            The text that should be associated with the sound resource
-         * @param filename
-         *            The filename of the sound resource. This must be a
-         *            complete path like: (/sdcard/mysounds/mysoundbite.mp3).
-         */
-        public void addSpeechFile(String text, String filename) {
-            mSelf.addSpeech(text, filename);
-        }
-
-        /**
-         * Adds a sound resource to the TTS as an earcon.
-         *
-         * @param earcon
-         *            The text that should be associated with the sound resource
-         * @param packageName
-         *            The name of the package which has the sound resource
-         * @param resId
-         *            The resource ID of the sound within its package
-         */
-        public void addEarcon(String earcon, String packageName, int resId) {
-            mSelf.addEarcon(earcon, packageName, resId);
-        }
-
-        /**
-         * Adds a sound resource to the TTS as an earcon.
-         *
-         * @param earcon
-         *            The text that should be associated with the sound resource
-         * @param filename
-         *            The filename of the sound resource. This must be a
-         *            complete path like: (/sdcard/mysounds/mysoundbite.mp3).
-         */
-        public void addEarconFile(String earcon, String filename) {
-            mSelf.addEarcon(earcon, filename);
-        }
-
-        /**
-         * Sets the speech rate for the TTS. Note that this will only have an
-         * effect on synthesized speech; it will not affect pre-recorded speech.
-         *
-         * @param speechRate
-         *            The speech rate that should be used
-         */
-        public void setSpeechRate(int speechRate) {
-            mSelf.setSpeechRate(speechRate);
-        }
-
-        // TODO: Fix comment about language
-        /**
-         * Sets the speech rate for the TTS. Note that this will only have an
-         * effect on synthesized speech; it will not affect pre-recorded speech.
-         *
-         * @param language
-         *            The language to be used. The languages are specified by
-         *            their IETF language tags as defined by BCP 47. This is the
-         *            same standard used for the lang attribute in HTML. See:
-         *            http://en.wikipedia.org/wiki/IETF_language_tag
-         */
-        public void setLanguage(String language) {
-            mSelf.setLanguage(language);
-        }
-
-        /**
-         * Speaks the given text using the specified queueing mode and
-         * parameters.
-         *
-         * @param text
-         *            The String of text that should be synthesized
-         * @param params
-         *            An ArrayList of parameters. The first element of this
-         *            array controls the type of voice to use.
-         * @param filename
-         *            The string that gives the full output filename; it should
-         *            be something like "/sdcard/myappsounds/mysound.wav".
-         * @return A boolean that indicates if the synthesis succeeded
-         */
-        public boolean synthesizeToFile(String text, String[] params,
-                String filename) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            return mSelf.synthesizeToFile(text, speakingParams, filename, true);
-        }
-    };
-
-}
diff --git a/tts/jni/Android.mk b/tts/jni/Android.mk
deleted file mode 100755
index 665d6d2..0000000
--- a/tts/jni/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	android_tts_SynthProxy.cpp
-
-LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE)
-
-LOCAL_SHARED_LIBRARIES := \
-	libandroid_runtime \
-	libnativehelper \
-	libmedia \
-	libutils \
-	libcutils
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-
-LOCAL_MODULE:= libttssynthproxy
-
-LOCAL_ARM_MODE := arm
-
-LOCAL_PRELINK_MODULE := false
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/tts/jni/android_tts_SynthProxy.cpp b/tts/jni/android_tts_SynthProxy.cpp
deleted file mode 100755
index d8f1bf3..0000000
--- a/tts/jni/android_tts_SynthProxy.cpp
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <stdio.h>
-#include <unistd.h>
-
-#define LOG_TAG "SynthProxy"
-
-#include <utils/Log.h>
-#include <nativehelper/jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <android_runtime/AndroidRuntime.h>
-#include <tts/TtsEngine.h>
-#include <media/AudioTrack.h>
-
-#include <dlfcn.h>
-
-#define DEFAULT_TTS_RATE        16000
-#define DEFAULT_TTS_FORMAT      AudioSystem::PCM_16_BIT
-#define DEFAULT_TTS_NB_CHANNELS 1
-
-#define USAGEMODE_PLAY_IMMEDIATELY 0
-#define USAGEMODE_WRITE_TO_FILE    1
-
-using namespace android;
-
-// ----------------------------------------------------------------------------
-struct fields_t {
-    jfieldID    synthProxyFieldJniData;
-    jclass      synthProxyClass;
-    jmethodID   synthProxyMethodPost;
-};
-
-struct afterSynthData_t {
-    jint jniStorage;
-    int  usageMode;
-    FILE* outputFile;
-};
-
-// ----------------------------------------------------------------------------
-static fields_t javaTTSFields;
-
-// ----------------------------------------------------------------------------
-class SynthProxyJniStorage {
-    public :
-        //jclass                    tts_class;
-        jobject                   tts_ref;
-        TtsEngine*                mNativeSynthInterface;
-        AudioTrack*               mAudioOut;
-        uint32_t                  mSampleRate;
-        AudioSystem::audio_format mAudFormat;
-        int                       mNbChannels;
-
-        SynthProxyJniStorage() {
-            //tts_class = NULL;
-            tts_ref = NULL;
-            mNativeSynthInterface = NULL;
-            mAudioOut = NULL;
-            mSampleRate = DEFAULT_TTS_RATE;
-            mAudFormat  = DEFAULT_TTS_FORMAT;
-            mNbChannels = DEFAULT_TTS_NB_CHANNELS;
-        }
-
-        ~SynthProxyJniStorage() {
-            killAudio();
-            if (mNativeSynthInterface) {
-                mNativeSynthInterface->shutdown();
-                mNativeSynthInterface = NULL;
-            }
-        }
-
-        void killAudio() {
-            if (mAudioOut) {
-                mAudioOut->stop();
-                delete mAudioOut;
-                mAudioOut = NULL;
-            }
-        }
-
-        void createAudioOut(uint32_t rate, AudioSystem::audio_format format,
-                int channel) {
-            mSampleRate = rate;
-            mAudFormat  = format;
-            mNbChannels = channel;
-
-            // TODO use the TTS stream type
-            int streamType = AudioSystem::MUSIC;
-
-            // retrieve system properties to ensure successful creation of the
-            // AudioTrack object for playback
-            int afSampleRate;
-            if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-                afSampleRate = 44100;
-            }
-            int afFrameCount;
-            if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-                afFrameCount = 2048;
-            }
-            uint32_t afLatency;
-            if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
-                afLatency = 500;
-            }
-            uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-            if (minBufCount < 2) minBufCount = 2;
-            int minFrameCount = (afFrameCount * rate * minBufCount)/afSampleRate;
-
-            mAudioOut = new AudioTrack(streamType, rate, format, channel,
-                    minFrameCount > 4096 ? minFrameCount : 4096,
-                    0, 0, 0, 0); // not using an AudioTrack callback
-
-            if (mAudioOut->initCheck() != NO_ERROR) {
-              LOGI("AudioTrack error");
-              delete mAudioOut;
-              mAudioOut = NULL;
-            } else {
-              LOGI("AudioTrack OK");
-              mAudioOut->start();
-              LOGI("AudioTrack started");
-            }
-        }
-};
-
-
-// ----------------------------------------------------------------------------
-void prepAudioTrack(SynthProxyJniStorage* pJniData,
-        uint32_t rate, AudioSystem::audio_format format, int channel)
-{
-    // Don't bother creating a new audiotrack object if the current
-    // object is already set.
-    if ( pJniData->mAudioOut &&
-         (rate == pJniData->mSampleRate) &&
-         (format == pJniData->mAudFormat) &&
-         (channel == pJniData->mNbChannels) ){
-        return;
-    }
-    if (pJniData->mAudioOut){
-        pJniData->killAudio();
-    }
-    pJniData->createAudioOut(rate, format, channel);
-}
-
-
-// ----------------------------------------------------------------------------
-/*
- * Callback from TTS engine.
- * Directly speaks using AudioTrack or write to file
- */
-static void ttsSynthDoneCB(void * userdata, uint32_t rate,
-                           AudioSystem::audio_format format, int channel,
-                           int8_t *wav, size_t bufferSize) {
-    LOGI("ttsSynthDoneCallback: %d bytes", bufferSize);
-
-    afterSynthData_t* pForAfter = (afterSynthData_t*)userdata;
-
-    if (pForAfter->usageMode == USAGEMODE_PLAY_IMMEDIATELY){
-        LOGI("Direct speech");
-
-        if (wav == NULL) {
-            LOGI("Null: speech has completed");
-        }
-
-        if (bufferSize > 0) {
-            SynthProxyJniStorage* pJniData =
-                    (SynthProxyJniStorage*)(pForAfter->jniStorage);
-            prepAudioTrack(pJniData, rate, format, channel);
-            if (pJniData->mAudioOut) {
-                pJniData->mAudioOut->write(wav, bufferSize);
-                LOGI("AudioTrack wrote: %d bytes", bufferSize);
-            } else {
-                LOGI("Can't play, null audiotrack");
-            }
-        }
-    } else  if (pForAfter->usageMode == USAGEMODE_WRITE_TO_FILE) {
-        LOGI("Save to file");
-        if (wav == NULL) {
-            LOGI("Null: speech has completed");
-        }
-        if (bufferSize > 0){
-            fwrite(wav, 1, bufferSize, pForAfter->outputFile);
-        }
-    }
-    // TODO update to call back into the SynthProxy class through the
-    //      javaTTSFields.synthProxyMethodPost methode to notify
-    //      playback has completed
-
-    delete pForAfter;
-    return;
-}
-
-
-// ----------------------------------------------------------------------------
-static void
-android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
-        jobject weak_this, jstring nativeSoLib)
-{
-    SynthProxyJniStorage* pJniStorage = new SynthProxyJniStorage();
-
-    prepAudioTrack(pJniStorage,
-            DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS);
-
-    const char *nativeSoLibNativeString =
-            env->GetStringUTFChars(nativeSoLib, 0);
-
-    void *engine_lib_handle = dlopen(nativeSoLibNativeString,
-            RTLD_NOW | RTLD_LOCAL);
-    if (engine_lib_handle==NULL) {
-       LOGI("engine_lib_handle==NULL");
-       // TODO report error so the TTS can't be used
-    } else {
-        TtsEngine *(*get_TtsEngine)() =
-            reinterpret_cast<TtsEngine* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
-        pJniStorage->mNativeSynthInterface = (*get_TtsEngine)();
-        if (pJniStorage->mNativeSynthInterface) {
-            pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
-        }
-    }
-
-    // we use a weak reference so the SynthProxy object can be garbage collected.
-    pJniStorage->tts_ref = env->NewGlobalRef(weak_this);
-
-    // save the JNI resources so we can use them (and free them) later
-    env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData,
-            (int)pJniStorage);
-
-    env->ReleaseStringUTFChars(nativeSoLib, nativeSoLibNativeString);
-}
-
-
-static void
-android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData) {
-        SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-        delete pSynthData;
-    }
-}
-
-
-static void
-android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
-        jstring language)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_setLanguage(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    const char *langNativeString = env->GetStringUTFChars(language, 0);
-    // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->setLanguage(langNativeString,
-                strlen(langNativeString));
-    }
-    env->ReleaseStringUTFChars(language, langNativeString);
-}
-
-
-static void
-android_tts_SynthProxy_setSpeechRate(JNIEnv *env, jobject thiz, jint jniData,
-        int speechRate)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_setSpeechRate(): invalid JNI data");
-        return;
-    }
-
-    int bufSize = 10;
-    char buffer [bufSize];
-    sprintf(buffer, "%d", speechRate);
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    LOGI("setting speech rate to %d", speechRate);
-    // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->setProperty("rate", buffer, bufSize);
-    }
-}
-
-
-// TODO: Refactor this to get rid of any assumptions about sample rate, etc.
-static void
-android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
-        jstring textJavaString, jstring filenameJavaString)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_synthesizeToFile(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-
-    const char *filenameNativeString =
-            env->GetStringUTFChars(filenameJavaString, 0);
-    const char *textNativeString = env->GetStringUTFChars(textJavaString, 0);
-
-    afterSynthData_t* pForAfter = new (afterSynthData_t);
-    pForAfter->jniStorage = jniData;
-    pForAfter->usageMode  = USAGEMODE_WRITE_TO_FILE;
-
-    pForAfter->outputFile = fopen(filenameNativeString, "wb");
-
-    // Write 44 blank bytes for WAV header, then come back and fill them in
-    // after we've written the audio data
-    char header[44];
-    fwrite(header, 1, 44, pForAfter->outputFile);
-
-    unsigned int unique_identifier;
-
-    // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->synthesizeText(textNativeString,
-                (void *)pForAfter);
-    }
-
-    long filelen = ftell(pForAfter->outputFile);
-
-    int samples = (((int)filelen) - 44) / 2;
-    header[0] = 'R';
-    header[1] = 'I';
-    header[2] = 'F';
-    header[3] = 'F';
-    ((uint32_t *)(&header[4]))[0] = filelen - 8;
-    header[8] = 'W';
-    header[9] = 'A';
-    header[10] = 'V';
-    header[11] = 'E';
-
-    header[12] = 'f';
-    header[13] = 'm';
-    header[14] = 't';
-    header[15] = ' ';
-
-    ((uint32_t *)(&header[16]))[0] = 16;  // size of fmt
-
-    ((unsigned short *)(&header[20]))[0] = 1;  // format
-    ((unsigned short *)(&header[22]))[0] = 1;  // channels
-    ((uint32_t *)(&header[24]))[0] = 22050;  // samplerate
-    ((uint32_t *)(&header[28]))[0] = 44100;  // byterate
-    ((unsigned short *)(&header[32]))[0] = 2;  // block align
-    ((unsigned short *)(&header[34]))[0] = 16;  // bits per sample
-
-    header[36] = 'd';
-    header[37] = 'a';
-    header[38] = 't';
-    header[39] = 'a';
-
-    ((uint32_t *)(&header[40]))[0] = samples * 2;  // size of data
-
-    // Skip back to the beginning and rewrite the header
-    fseek(pForAfter->outputFile, 0, SEEK_SET);
-    fwrite(header, 1, 44, pForAfter->outputFile);
-
-    fflush(pForAfter->outputFile);
-    fclose(pForAfter->outputFile);
-
-    env->ReleaseStringUTFChars(textJavaString, textNativeString);
-    env->ReleaseStringUTFChars(filenameJavaString, filenameNativeString);
-}
-
-
-static void
-android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData,
-        jstring textJavaString)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_speak(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-
-    if (pSynthData->mAudioOut) {
-        pSynthData->mAudioOut->stop();
-        pSynthData->mAudioOut->start();
-    }
-
-    afterSynthData_t* pForAfter = new (afterSynthData_t);
-    pForAfter->jniStorage = jniData;
-    pForAfter->usageMode  = USAGEMODE_PLAY_IMMEDIATELY;
-
-    if (pSynthData->mNativeSynthInterface) {
-        const char *textNativeString = env->GetStringUTFChars(textJavaString, 0);
-        pSynthData->mNativeSynthInterface->synthesizeText(textNativeString,
-                (void *)pForAfter);
-        env->ReleaseStringUTFChars(textJavaString, textNativeString);
-    }
-}
-
-
-static void
-android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_stop(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->stop();
-    }
-    if (pSynthData->mAudioOut) {
-        pSynthData->mAudioOut->stop();
-    }
-}
-
-
-static void
-android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_shutdown(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->shutdown();
-        pSynthData->mNativeSynthInterface = NULL;
-    }
-}
-
-
-// TODO add buffer format
-static void
-android_tts_SynthProxy_playAudioBuffer(JNIEnv *env, jobject thiz, jint jniData,
-        int bufferPointer, int bufferSize)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_playAudioBuffer(): invalid JNI data");
-        return;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    short* wav = (short*) bufferPointer;
-    pSynthData->mAudioOut->write(wav, bufferSize);
-    LOGI("AudioTrack wrote: %d bytes", bufferSize);
-}
-
-
-JNIEXPORT jstring JNICALL
-android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_getLanguage(): invalid JNI data");
-        return env->NewStringUTF("");
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    size_t bufSize = 100;
-    char buf[bufSize];
-    memset(buf, 0, bufSize);
-    // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->getLanguage(buf, &bufSize);
-    }
-    return env->NewStringUTF(buf);
-}
-
-JNIEXPORT int JNICALL
-android_tts_SynthProxy_getRate(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_getRate(): invalid JNI data");
-        return 0;
-    }
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    size_t bufSize = 100;
-
-    char buf[bufSize];
-    memset(buf, 0, bufSize);
-    // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->getProperty("rate", buf, &bufSize);
-    }
-    return atoi(buf);
-}
-
-// Dalvik VM type signatures
-static JNINativeMethod gMethods[] = {
-    {   "native_stop",
-        "(I)V",
-        (void*)android_tts_SynthProxy_stop
-    },
-    {   "native_speak",
-        "(ILjava/lang/String;)V",
-        (void*)android_tts_SynthProxy_speak
-    },
-    {   "native_synthesizeToFile",
-        "(ILjava/lang/String;Ljava/lang/String;)V",
-        (void*)android_tts_SynthProxy_synthesizeToFile
-    },
-    {   "native_setLanguage",
-        "(ILjava/lang/String;)V",
-        (void*)android_tts_SynthProxy_setLanguage
-    },
-    {   "native_setSpeechRate",
-        "(II)V",
-        (void*)android_tts_SynthProxy_setSpeechRate
-    },
-    {   "native_playAudioBuffer",
-        "(III)V",
-        (void*)android_tts_SynthProxy_playAudioBuffer
-    },
-    {   "native_getLanguage",
-        "(I)Ljava/lang/String;",
-        (void*)android_tts_SynthProxy_getLanguage
-    },
-    {   "native_getRate",
-        "(I)I",
-        (void*)android_tts_SynthProxy_getRate
-    },
-    {   "native_shutdown",
-        "(I)V",
-        (void*)android_tts_SynthProxy_shutdown
-    },
-    {   "native_setup",
-        "(Ljava/lang/Object;Ljava/lang/String;)V",
-        (void*)android_tts_SynthProxy_native_setup
-    },
-    {   "native_finalize",
-        "(I)V",
-        (void*)android_tts_SynthProxy_native_finalize
-    }
-};
-
-#define SP_JNIDATA_FIELD_NAME                "mJniData"
-#define SP_POSTSPEECHSYNTHESIZED_METHOD_NAME "postNativeSpeechSynthesizedInJava"
-
-// TODO: verify this is the correct path
-static const char* const kClassPathName = "android/tts/SynthProxy";
-
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
-    JNIEnv* env = NULL;
-    jint result = -1;
-    jclass clazz;
-
-    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        LOGE("ERROR: GetEnv failed\n");
-        goto bail;
-    }
-    assert(env != NULL);
-
-    clazz = env->FindClass(kClassPathName);
-    if (clazz == NULL) {
-        LOGE("Can't find %s", kClassPathName);
-        goto bail;
-    }
-
-    javaTTSFields.synthProxyClass = clazz;
-    javaTTSFields.synthProxyFieldJniData = NULL;
-    javaTTSFields.synthProxyMethodPost = NULL;
-
-    javaTTSFields.synthProxyFieldJniData = env->GetFieldID(clazz,
-            SP_JNIDATA_FIELD_NAME, "I");
-    if (javaTTSFields.synthProxyFieldJniData == NULL) {
-        LOGE("Can't find %s.%s field", kClassPathName, SP_JNIDATA_FIELD_NAME);
-        goto bail;
-    }
-
-    javaTTSFields.synthProxyMethodPost = env->GetStaticMethodID(clazz,
-            SP_POSTSPEECHSYNTHESIZED_METHOD_NAME, "(Ljava/lang/Object;II)V");
-    if (javaTTSFields.synthProxyMethodPost == NULL) {
-        LOGE("Can't find %s.%s method", kClassPathName, SP_POSTSPEECHSYNTHESIZED_METHOD_NAME);
-        goto bail;
-    }
-
-    if (jniRegisterNativeMethods(
-            env, kClassPathName, gMethods, NELEM(gMethods)) < 0)
-        goto bail;
-
-    /* success -- return valid version number */
-    result = JNI_VERSION_1_4;
-
- bail:
-    return result;
-}
diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl
new file mode 100644
index 0000000..0e658df
--- /dev/null
+++ b/vpn/java/android/net/vpn/IVpnService.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+import android.net.vpn.VpnProfile;
+
+/**
+ * Interface to access a VPN service.
+ * {@hide}
+ */
+interface IVpnService {
+    /**
+     * Sets up the VPN connection.
+     * @param profile the profile object
+     * @param username the username for authentication
+     * @param password the corresponding password for authentication
+     */
+    boolean connect(in VpnProfile profile, String username, String password);
+
+    /**
+     * Tears down the VPN connection.
+     */
+    void disconnect();
+
+    /**
+     * Makes the service broadcast the connectivity state.
+     */
+    void checkStatus(in VpnProfile profile);
+}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecProfile.java b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
new file mode 100644
index 0000000..181619d
--- /dev/null
+++ b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for L2TP-over-IPSec type of VPN.
+ * {@hide}
+ */
+public class L2tpIpsecProfile extends VpnProfile {
+    private static final long serialVersionUID = 1L;
+
+    private String mUserCertificate;
+    private String mCaCertificate;
+    private String mUserkey;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.L2TP_IPSEC;
+    }
+
+    public void setCaCertificate(String name) {
+        mCaCertificate = name;
+    }
+
+    public String getCaCertificate() {
+        return mCaCertificate;
+    }
+
+    public void setUserCertificate(String name) {
+        mUserCertificate = name;
+    }
+
+    public String getUserCertificate() {
+        return mUserCertificate;
+    }
+
+    public void setUserkey(String name) {
+        mUserkey = name;
+    }
+
+    public String getUserkey() {
+        return mUserkey;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mCaCertificate = in.readString();
+        mUserCertificate = in.readString();
+        mUserkey = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeString(mCaCertificate);
+        parcel.writeString(mUserCertificate);
+        parcel.writeString(mUserkey);
+    }
+}
diff --git a/tts/java/android/tts/ITtsCallback.aidl b/vpn/java/android/net/vpn/L2tpProfile.java
old mode 100755
new mode 100644
similarity index 60%
copy from tts/java/android/tts/ITtsCallback.aidl
copy to vpn/java/android/net/vpn/L2tpProfile.java
index 1314010..59d4981
--- a/tts/java/android/tts/ITtsCallback.aidl
+++ b/vpn/java/android/net/vpn/L2tpProfile.java
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2007, 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
+ *     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,
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 
-package android.tts;
+package android.net.vpn;
 
 /**
- * AIDL for the callback from the TTS Service
- * ITtsCallback.java is autogenerated from this.
- *
+ * The profile for L2TP type of VPN.
  * {@hide}
  */
-oneway interface ITtsCallback {
-    void markReached(String mark);
+public class L2tpProfile extends VpnProfile {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.L2TP;
+    }
 }
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
new file mode 100644
index 0000000..98795bd
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.util.Log;
+
+/**
+ * The class provides interface to manage all VPN-related tasks, including:
+ * <ul>
+ * <li>The list of supported VPN types.
+ * <li>API's to start/stop the service of a particular type.
+ * <li>API's to start the settings activity.
+ * <li>API's to create a profile.
+ * <li>API's to register/unregister a connectivity receiver and the keys to
+ *      access the fields in a connectivity broadcast event.
+ * </ul>
+ * {@hide}
+ */
+public class VpnManager {
+    // Action for broadcasting a connectivity state.
+    private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
+    /** Key to the profile name of a connectivity broadcast event. */
+    public static final String BROADCAST_PROFILE_NAME = "profile_name";
+    /** Key to the connectivity state of a connectivity broadcast event. */
+    public static final String BROADCAST_CONNECTION_STATE = "connection_state";
+
+    public static final String PROFILES_PATH = "/data/misc/vpn/profiles";
+
+    private static final String PACKAGE_PREFIX =
+            VpnManager.class.getPackage().getName() + ".";
+
+    // Action to start VPN service
+    private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE";
+
+    // Action to start VPN settings
+    private static final String ACTION_VPN_SETTINGS = PACKAGE_PREFIX + "SETTINGS";
+
+    private static final String TAG = VpnManager.class.getSimpleName();
+
+    /**
+     * Returns all supported VPN types.
+     */
+    public static VpnType[] getSupportedVpnTypes() {
+        return VpnType.values();
+    }
+
+    private Context mContext;
+
+    /**
+     * Creates a manager object with the specified context.
+     */
+    public VpnManager(Context c) {
+        mContext = c;
+    }
+
+    /**
+     * Creates a VPN profile of the specified type.
+     *
+     * @param type the VPN type
+     * @return the profile object
+     */
+    public VpnProfile createVpnProfile(VpnType type) {
+        return createVpnProfile(type, false);
+    }
+
+    /**
+     * Creates a VPN profile of the specified type.
+     *
+     * @param type the VPN type
+     * @param customized true if the profile is custom made
+     * @return the profile object
+     */
+    public VpnProfile createVpnProfile(VpnType type, boolean customized) {
+        try {
+            VpnProfile p = (VpnProfile) type.getProfileClass().newInstance();
+            p.setCustomized(customized);
+            return p;
+        } catch (InstantiationException e) {
+            return null;
+        } catch (IllegalAccessException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Starts the VPN service to establish VPN connection.
+     */
+    public void startVpnService() {
+        mContext.startService(new Intent(ACTION_VPN_SERVICE));
+    }
+
+    /**
+     * Stops the VPN service.
+     */
+    public void stopVpnService() {
+        mContext.stopService(new Intent(ACTION_VPN_SERVICE));
+    }
+
+    /**
+     * Binds the specified ServiceConnection with the VPN service.
+     */
+    public boolean bindVpnService(ServiceConnection c) {
+        if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) {
+            Log.w(TAG, "failed to connect to VPN service");
+            return false;
+        } else {
+            Log.d(TAG, "succeeded to connect to VPN service");
+            return true;
+        }
+    }
+
+    /** Broadcasts the connectivity state of the specified profile. */
+    public void broadcastConnectivity(String profileName, VpnState s) {
+        Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
+        intent.putExtra(BROADCAST_PROFILE_NAME, profileName);
+        intent.putExtra(BROADCAST_CONNECTION_STATE, s);
+        mContext.sendBroadcast(intent);
+    }
+
+    public void registerConnectivityReceiver(BroadcastReceiver r) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY);
+        mContext.registerReceiver(r, filter);
+    }
+
+    public void unregisterConnectivityReceiver(BroadcastReceiver r) {
+        mContext.unregisterReceiver(r);
+    }
+
+    /** Starts the VPN settings activity. */
+    public void startSettingsActivity() {
+        Intent intent = new Intent(ACTION_VPN_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    /** Creates an intent to start the VPN settings activity. */
+    public Intent createSettingsActivityIntent() {
+        Intent intent = new Intent(ACTION_VPN_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+}
diff --git a/tts/java/android/tts/ITtsCallback.aidl b/vpn/java/android/net/vpn/VpnProfile.aidl
old mode 100755
new mode 100644
similarity index 61%
rename from tts/java/android/tts/ITtsCallback.aidl
rename to vpn/java/android/net/vpn/VpnProfile.aidl
index 1314010..ad34bfc
--- a/tts/java/android/tts/ITtsCallback.aidl
+++ b/vpn/java/android/net/vpn/VpnProfile.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2007, 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
+ *     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,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.tts;
+package android.net.vpn;
 
-/**
- * AIDL for the callback from the TTS Service
- * ITtsCallback.java is autogenerated from this.
- *
- * {@hide}
- */
-oneway interface ITtsCallback {
-    void markReached(String mark);
-}
+parcelable VpnProfile;
diff --git a/vpn/java/android/net/vpn/VpnProfile.java b/vpn/java/android/net/vpn/VpnProfile.java
new file mode 100644
index 0000000..9e24da4
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnProfile.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * A VPN profile.
+ * {@hide}
+ */
+public abstract class VpnProfile implements Parcelable, Serializable {
+    private static final long serialVersionUID = 1L;
+    private String mName; // unique display name
+    private String mId; // unique identifier
+    private String mServerName; // VPN server name
+    private String mDomainSuffices; // space separated list
+    private String mRouteList; // space separated list
+    private String mSavedUsername;
+    private boolean mIsCustomized;
+    private transient VpnState mState = VpnState.IDLE;
+
+    /** Sets a user-friendly name for this profile. */
+    public void setName(String name) {
+        mName = name;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Sets an ID for this profile.  The caller should make sure the
+     * uniqueness of the ID.
+     */
+    public void setId(String id) {
+        mId = id;
+    }
+
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Sets the name of the VPN server. Used for DNS lookup.
+     */
+    public void setServerName(String name) {
+        mServerName = name;
+    }
+
+    public String getServerName() {
+        return mServerName;
+    }
+
+    /**
+     * Sets the domain suffices for DNS resolution.
+     *
+     * @param entries a comma-separated list of domain suffices
+     */
+    public void setDomainSuffices(String entries) {
+        mDomainSuffices = entries;
+    }
+
+    public String getDomainSuffices() {
+        return mDomainSuffices;
+    }
+
+    /**
+     * Sets the routing info for this VPN connection.
+     *
+     * @param entries a comma-separated list of routes; each entry is in the
+     *      format of "(network address)/(network mask)"
+     */
+    public void setRouteList(String entries) {
+        mRouteList = entries;
+    }
+
+    public String getRouteList() {
+        return mRouteList;
+    }
+
+    public void setSavedUsername(String name) {
+        mSavedUsername = name;
+    }
+
+    public String getSavedUsername() {
+        return mSavedUsername;
+    }
+
+    public void setState(VpnState state) {
+        mState = state;
+    }
+
+    public VpnState getState() {
+        return ((mState == null) ? VpnState.IDLE : mState);
+    }
+
+    public boolean isIdle() {
+        return (mState == VpnState.IDLE);
+    }
+
+    /**
+     * Returns whether this profile is custom made (as opposed to being
+     * created by provided user interface).
+     */
+    public boolean isCustomized() {
+        return mIsCustomized;
+    }
+
+    /**
+     * Returns the VPN type of the profile.
+     */
+    public abstract VpnType getType();
+
+    void setCustomized(boolean customized) {
+        mIsCustomized = customized;
+    }
+
+    protected void readFromParcel(Parcel in) {
+        mName = in.readString();
+        mId = in.readString();
+        mServerName = in.readString();
+        mDomainSuffices = in.readString();
+        mRouteList = in.readString();
+        mSavedUsername = in.readString();
+    }
+
+    public static final Parcelable.Creator<VpnProfile> CREATOR =
+            new Parcelable.Creator<VpnProfile>() {
+                public VpnProfile createFromParcel(Parcel in) {
+                    VpnType type = Enum.valueOf(VpnType.class, in.readString());
+                    boolean customized = in.readInt() > 0;
+                    VpnProfile p = new VpnManager(null).createVpnProfile(type,
+                            customized);
+                    if (p == null) return null;
+                    p.readFromParcel(in);
+                    return p;
+                }
+
+                public VpnProfile[] newArray(int size) {
+                    return new VpnProfile[size];
+                }
+            };
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(getType().toString());
+        parcel.writeInt(mIsCustomized ? 1 : 0);
+        parcel.writeString(mName);
+        parcel.writeString(mId);
+        parcel.writeString(mServerName);
+        parcel.writeString(mDomainSuffices);
+        parcel.writeString(mRouteList);
+        parcel.writeString(mSavedUsername);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java
new file mode 100644
index 0000000..977d938
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnState.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+/**
+ * Enumeration of all VPN states.
+ *
+ * A normal VPN connection lifetime starts in {@link IDLE}. When a new
+ * connection is about to be set up, it goes to {@link CONNECTING} and then
+ * {@link CONNECTED} if successful; back to {@link IDLE} if failed.
+ * When the connection is about to be torn down, it goes to
+ * {@link DISCONNECTING} and then {@link IDLE}.
+ * {@link CANCELLED} is a state when a VPN connection attempt is aborted, and
+ * is in transition to {@link IDLE}.
+ * {@hide}
+ */
+public enum VpnState {
+    CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE
+}
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
new file mode 100644
index 0000000..91b0ea2
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnType.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+/**
+ * Enumeration of all supported VPN types.
+ * {@hide}
+ */
+public enum VpnType {
+    L2TP_IPSEC("L2TP/IPSec", L2tpIpsecProfile.class),
+    L2TP("L2TP", L2tpProfile.class);
+
+    private String mDisplayName;
+    private Class<? extends VpnProfile> mClass;
+
+    VpnType(String displayName, Class<? extends VpnProfile> klass) {
+        mDisplayName = displayName;
+        mClass = klass;
+    }
+
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    public Class<? extends VpnProfile> getProfileClass() {
+        return mClass;
+    }
+}