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><manifest xmlns:android="..."
- * package="<b>com.google.marvin.compass</b>"></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;
+ }
+}