Merge change 25628 into eclair
* changes:
Inefficient but correct fix for 2122381: call finishBackup after every performBackup
diff --git a/Android.mk b/Android.mk
index 4e7b14e..90f2acb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -341,6 +341,7 @@
-since ./frameworks/base/api/2.xml 2 \
-since ./frameworks/base/api/3.xml 3 \
-since ./frameworks/base/api/4.xml 4 \
+ -since ./frameworks/base/api/current.xml Eclair \
-error 1 -error 2 -warning 3 -error 4 -error 6 -error 8 \
-overview $(LOCAL_PATH)/core/java/overview.html
diff --git a/api/current.xml b/api/current.xml
index b348555..b38176d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -17165,27 +17165,6 @@
<parameter name="id" type="int">
</parameter>
</method>
-<method name="startActivity"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.app.PendingIntent">
-</parameter>
-<parameter name="fillInIntent" type="android.content.Intent">
-</parameter>
-<parameter name="flagsMask" type="int">
-</parameter>
-<parameter name="flagsValues" type="int">
-</parameter>
-<exception name="PendingIntent.CanceledException" type="android.app.PendingIntent.CanceledException">
-</exception>
-</method>
<method name="startActivityForResult"
return="void"
abstract="false"
@@ -17201,29 +17180,6 @@
<parameter name="requestCode" type="int">
</parameter>
</method>
-<method name="startActivityForResult"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.app.PendingIntent">
-</parameter>
-<parameter name="requestCode" type="int">
-</parameter>
-<parameter name="fillInIntent" type="android.content.Intent">
-</parameter>
-<parameter name="flagsMask" type="int">
-</parameter>
-<parameter name="flagsValues" type="int">
-</parameter>
-<exception name="PendingIntent.CanceledException" type="android.app.PendingIntent.CanceledException">
-</exception>
-</method>
<method name="startActivityFromChild"
return="void"
abstract="false"
@@ -17241,31 +17197,6 @@
<parameter name="requestCode" type="int">
</parameter>
</method>
-<method name="startActivityFromChild"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="child" type="android.app.Activity">
-</parameter>
-<parameter name="intent" type="android.app.PendingIntent">
-</parameter>
-<parameter name="requestCode" type="int">
-</parameter>
-<parameter name="fillInIntent" type="android.content.Intent">
-</parameter>
-<parameter name="flagsMask" type="int">
-</parameter>
-<parameter name="flagsValues" type="int">
-</parameter>
-<exception name="PendingIntent.CanceledException" type="android.app.PendingIntent.CanceledException">
-</exception>
-</method>
<method name="startActivityIfNeeded"
return="boolean"
abstract="false"
@@ -17281,6 +17212,58 @@
<parameter name="requestCode" type="int">
</parameter>
</method>
+<method name="startIntentSenderForResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.IntentSender">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+<parameter name="flagsMask" type="int">
+</parameter>
+<parameter name="flagsValues" type="int">
+</parameter>
+<parameter name="extraFlags" type="int">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
+<method name="startIntentSenderFromChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="child" type="android.app.Activity">
+</parameter>
+<parameter name="intent" type="android.content.IntentSender">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+<parameter name="flagsMask" type="int">
+</parameter>
+<parameter name="flagsValues" type="int">
+</parameter>
+<parameter name="extraFlags" type="int">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
<method name="startManagingCursor"
return="void"
abstract="false"
@@ -31782,6 +31765,29 @@
<parameter name="arguments" type="android.os.Bundle">
</parameter>
</method>
+<method name="startIntentSender"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.IntentSender">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+<parameter name="flagsMask" type="int">
+</parameter>
+<parameter name="flagsValues" type="int">
+</parameter>
+<parameter name="extraFlags" type="int">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
<method name="startService"
return="android.content.ComponentName"
abstract="true"
@@ -33095,6 +33101,29 @@
<parameter name="arguments" type="android.os.Bundle">
</parameter>
</method>
+<method name="startIntentSender"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.IntentSender">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+<parameter name="flagsMask" type="int">
+</parameter>
+<parameter name="flagsValues" type="int">
+</parameter>
+<parameter name="extraFlags" type="int">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
<method name="startService"
return="android.content.ComponentName"
abstract="false"
@@ -77611,8 +77640,8 @@
<parameter name="tag" type="java.lang.String">
</parameter>
</method>
-<method name="getDateTime"
- return="long"
+<method name="getAttributeInt"
+ return="int"
abstract="false"
native="false"
synchronized="false"
@@ -77621,9 +77650,13 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+<parameter name="defaultValue" type="int">
+</parameter>
</method>
<method name="getLatLong"
- return="float[]"
+ return="boolean"
abstract="false"
native="false"
synchronized="false"
@@ -77632,17 +77665,8 @@
deprecated="not deprecated"
visibility="public"
>
-</method>
-<method name="getOrientationString"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
+<parameter name="output" type="float[]">
+</parameter>
</method>
<method name="getThumbnail"
return="byte[]"
@@ -77655,17 +77679,6 @@
visibility="public"
>
</method>
-<method name="getWhiteBalanceString"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="hasThumbnail"
return="boolean"
abstract="false"
@@ -121613,6 +121626,153 @@
</field>
</class>
</package>
+<package name="android.telephony.cdma"
+>
+<class name="CdmaCellLocation"
+ extends="android.telephony.CellLocation"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CdmaCellLocation"
+ type="android.telephony.cdma.CdmaCellLocation"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="CdmaCellLocation"
+ type="android.telephony.cdma.CdmaCellLocation"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bundleWithValues" type="android.os.Bundle">
+</parameter>
+</constructor>
+<method name="fillInNotifierBundle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bundleToFill" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="getBaseStationId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBaseStationLatitude"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBaseStationLongitude"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNetworkId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSystemId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCellLocationData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="baseStationId" type="int">
+</parameter>
+<parameter name="baseStationLatitude" type="int">
+</parameter>
+<parameter name="baseStationLongitude" type="int">
+</parameter>
+</method>
+<method name="setCellLocationData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="baseStationId" type="int">
+</parameter>
+<parameter name="baseStationLatitude" type="int">
+</parameter>
+<parameter name="baseStationLongitude" type="int">
+</parameter>
+<parameter name="systemId" type="int">
+</parameter>
+<parameter name="networkId" type="int">
+</parameter>
+</method>
+<method name="setStateInvalid"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
<package name="android.telephony.gsm"
>
<class name="GsmCellLocation"
@@ -126597,6 +126757,29 @@
<parameter name="arguments" type="android.os.Bundle">
</parameter>
</method>
+<method name="startIntentSender"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.IntentSender">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+<parameter name="flagsMask" type="int">
+</parameter>
+<parameter name="flagsValues" type="int">
+</parameter>
+<parameter name="extraFlags" type="int">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
<method name="startService"
return="android.content.ComponentName"
abstract="false"
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
new file mode 100644
index 0000000..2bcba97
--- /dev/null
+++ b/cmds/keystore/keystore.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+#define LOG_TAG "keystore"
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include "keystore.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+#define KEY_SIZE 120
+#define VALUE_SIZE 32768
+#define PASSWORD_SIZE VALUE_SIZE
+
+/* Here is the encoding of keys. This is necessary in order to allow arbitrary
+ * characters in keys. Characters in [0-~] are not encoded. Others are encoded
+ * into two bytes. The first byte is one of [+-.] which represents the first
+ * two bits of the character. The second byte encodes the rest of the bits into
+ * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
+ * that Base64 cannot be used here due to the need of prefix match on keys. */
+
+static int encode_key(char *out, uint8_t *in, int length)
+{
+ int i;
+ for (i = length; i > 0; --i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = '+' + (*in >> 6);
+ *++out = '0' + (*in & 0x3F);
+ ++length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+static int decode_key(uint8_t *out, char *in, int length)
+{
+ int i;
+ for (i = 0; i < length; ++i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = (*in - '+') << 6;
+ *out |= (*++in - '0') & 0x3F;
+ --length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+/* Here is the protocol used in both requests and responses:
+ * code [length_1 message_1 ... length_n message_n] end-of-file
+ * where code is one byte long and lengths are unsigned 16-bit integers in
+ * network order. Thus the maximum length of a message is 65535 bytes. */
+
+static int the_socket = -1;
+
+static int recv_code(int8_t *code)
+{
+ return recv(the_socket, code, 1, 0) == 1;
+}
+
+static int recv_message(uint8_t *message, int length)
+{
+ uint8_t bytes[2];
+ if (recv(the_socket, &bytes[0], 1, 0) != 1 ||
+ recv(the_socket, &bytes[1], 1, 0) != 1) {
+ return -1;
+ } else {
+ int offset = bytes[0] << 8 | bytes[1];
+ if (length < offset) {
+ return -1;
+ }
+ length = offset;
+ offset = 0;
+ while (offset < length) {
+ int n = recv(the_socket, &message[offset], length - offset, 0);
+ if (n <= 0) {
+ return -1;
+ }
+ offset += n;
+ }
+ }
+ return length;
+}
+
+static void send_code(int8_t code)
+{
+ send(the_socket, &code, 1, 0);
+}
+
+static void send_message(uint8_t *message, int length)
+{
+ uint16_t bytes = htons(length);
+ send(the_socket, &bytes, 2, 0);
+ send(the_socket, message, length, 0);
+}
+
+/* Here is the file format. Values are encrypted by AES CBC, and MD5 is used to
+ * compute their checksums. To make the files portable, the length is stored in
+ * network order. Note that the first four bytes are reserved for future use and
+ * are always set to zero in this implementation. */
+
+static int the_entropy = -1;
+
+static struct __attribute__((packed)) {
+ uint32_t reserved;
+ uint8_t vector[AES_BLOCK_SIZE];
+ uint8_t encrypted[0];
+ uint8_t digest[MD5_DIGEST_LENGTH];
+ uint8_t digested[0];
+ int32_t length;
+ uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+} blob;
+
+static int8_t encrypt_blob(char *name, AES_KEY *aes_key)
+{
+ uint8_t vector[AES_BLOCK_SIZE];
+ int length = blob.length;
+ int fd;
+
+ if (read(the_entropy, vector, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) {
+ return SYSTEM_ERROR;
+ }
+
+ length += blob.value - blob.digested;
+ blob.length = htonl(blob.length);
+ MD5(blob.digested, length, blob.digest);
+
+ length += blob.digested - blob.encrypted;
+ length = (length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
+ memcpy(vector, blob.vector, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, vector,
+ AES_ENCRYPT);
+
+ blob.reserved = 0;
+ length += blob.encrypted - (uint8_t *)&blob;
+
+ fd = open(".tmp", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1 || write(fd, &blob, length) != length) {
+ return SYSTEM_ERROR;
+ }
+ close(fd);
+ return rename(".tmp", name) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t decrypt_blob(char *name, AES_KEY *aes_key)
+{
+ int fd = open(name, O_RDONLY);
+ int length;
+
+ if (fd == -1) {
+ return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+ }
+ length = read(fd, &blob, sizeof(blob));
+ close(fd);
+
+ length -= blob.encrypted - (uint8_t *)&blob;
+ if (length < blob.value - blob.encrypted || length % AES_BLOCK_SIZE != 0) {
+ return VALUE_CORRUPTED;
+ }
+
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key,
+ blob.vector, AES_DECRYPT);
+ length -= blob.digested - blob.encrypted;
+ if (!memcmp(blob.digest, MD5(blob.digested, length, NULL),
+ MD5_DIGEST_LENGTH)) {
+ return VALUE_CORRUPTED;
+ }
+
+ length -= blob.value - blob.digested;
+ blob.length = ntohl(blob.length);
+ return (length < blob.length) ? VALUE_CORRUPTED : NO_ERROR;
+}
+
+/* Here are the actions. Each of them is a function without arguments. All
+ * information is defined in global variables, which are set properly before
+ * performing an action. The number of parameters required by each action is
+ * fixed and defined in a table. Note that the lengths of parameters are checked
+ * when they are received, so boundary checks on parameters are omitted. */
+
+#define MAX_PARAM 2
+#define MAX_RETRY 4
+
+static uid_t uid = -1;
+static int8_t state = UNINITIALIZED;
+static int8_t retry = MAX_RETRY;
+
+static struct {
+ int length;
+ uint8_t value[VALUE_SIZE];
+} params[MAX_PARAM];
+
+static AES_KEY encryption_key;
+static AES_KEY decryption_key;
+
+static int8_t test()
+{
+ return state;
+}
+
+static int8_t get()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ n = decrypt_blob(name, &decryption_key);
+ if (n != NO_ERROR) {
+ return n;
+ }
+ send_code(NO_ERROR);
+ send_message(blob.value, blob.length);
+ return -NO_ERROR;
+}
+
+static int8_t insert()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ blob.length = params[1].length;
+ memcpy(blob.value, params[1].value, params[1].length);
+ return encrypt_blob(name, &encryption_key);
+}
+
+static int8_t delete()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ return (unlink(name) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t exist()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ if (access(name, R_OK) == -1) {
+ return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
+ }
+ return NO_ERROR;
+}
+
+static int8_t scan()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+ char name[NAME_MAX];
+ int n;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ n = sprintf(name, "%u_", uid);
+ n += encode_key(&name[n], params[0].value, params[0].length);
+ send_code(NO_ERROR);
+ while ((file = readdir(dir)) != NULL) {
+ if (!strncmp(name, file->d_name, n)) {
+ char *p = &file->d_name[n];
+ params[0].length = decode_key(params[0].value, p, strlen(p));
+ send_message(params[0].value, params[0].length);
+ }
+ }
+ closedir(dir);
+ return -NO_ERROR;
+}
+
+static int8_t reset()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = UNINITIALIZED;
+ retry = MAX_RETRY;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ while ((file = readdir(dir)) != NULL) {
+ if (strcmp(".", file->d_name) || strcmp("..", file->d_name)) {
+ unlink(file->d_name);
+ }
+ }
+ closedir(dir);
+ return UNINITIALIZED;
+}
+
+#define MASTER_KEY_FILE ".masterkey"
+#define MASTER_KEY_SIZE 16
+
+static void generate_key(uint8_t *key, uint8_t *password, int length)
+{
+ PKCS5_PBKDF2_HMAC_SHA1((char *)password, length, (uint8_t *)"keystore",
+ sizeof("keystore"), 1024, MASTER_KEY_SIZE, key);
+}
+
+static int8_t password()
+{
+ uint8_t key[MASTER_KEY_SIZE];
+ AES_KEY aes_key;
+ int n;
+
+ if (state == UNINITIALIZED) {
+ blob.length = MASTER_KEY_SIZE;
+ if (read(the_entropy, blob.value, MASTER_KEY_SIZE) != MASTER_KEY_SIZE) {
+ return SYSTEM_ERROR;
+ }
+ } else {
+ generate_key(key, params[0].value, params[0].length);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ n = decrypt_blob(MASTER_KEY_FILE, &aes_key);
+ if (n == SYSTEM_ERROR) {
+ return SYSTEM_ERROR;
+ }
+ if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
+ if (retry <= 0) {
+ return reset();
+ }
+ return WRONG_PASSWORD + --retry;
+ }
+ }
+
+ if (params[1].length == -1) {
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ } else {
+ generate_key(key, params[1].value, params[1].length);
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ n = encrypt_blob(MASTER_KEY_FILE, &aes_key);
+ }
+
+ if (n == NO_ERROR) {
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &encryption_key);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &decryption_key);
+ state = NO_ERROR;
+ retry = MAX_RETRY;
+ }
+ return n;
+}
+
+static int8_t lock()
+{
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = LOCKED;
+ return LOCKED;
+}
+
+static int8_t unlock()
+{
+ params[1].length = -1;
+ return password();
+}
+
+/* Here are the permissions, actions, users, and the main function. */
+
+enum perm {
+ TEST = 1,
+ GET = 2,
+ INSERT = 4,
+ DELETE = 8,
+ EXIST = 16,
+ SCAN = 32,
+ RESET = 64,
+ PASSWORD = 128,
+ LOCK = 256,
+ UNLOCK = 512,
+};
+
+static struct action {
+ int8_t (*run)();
+ int8_t code;
+ int8_t state;
+ uint32_t perm;
+ int lengths[MAX_PARAM];
+} actions[] = {
+ {test, 't', 0, TEST, {0}},
+ {get, 'g', NO_ERROR, GET, {KEY_SIZE}},
+ {insert, 'i', NO_ERROR, INSERT, {KEY_SIZE, VALUE_SIZE}},
+ {delete, 'd', NO_ERROR, DELETE, {KEY_SIZE}},
+ {exist, 'e', NO_ERROR, EXIST, {KEY_SIZE}},
+ {scan, 's', NO_ERROR, SCAN, {KEY_SIZE}},
+ {reset, 'r', 0, RESET, {0}},
+ {password, 'p', 0, PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
+ {lock, 'l', NO_ERROR, LOCK, {0}},
+ {unlock, 'u', LOCKED, UNLOCK, {PASSWORD_SIZE}},
+ {NULL, 0 , 0, 0, {0}},
+};
+
+static struct user {
+ uid_t uid;
+ uid_t euid;
+ uint32_t perms;
+} users[] = {
+ {AID_SYSTEM, 0, ~GET},
+ {AID_VPN, AID_SYSTEM, GET},
+ {AID_WIFI, AID_SYSTEM, GET},
+ {0, 0, TEST | GET | INSERT | DELETE | EXIST | SCAN},
+};
+
+static int8_t process(int8_t code) {
+ struct user *user = users;
+ struct action *action = actions;
+ int i;
+
+ while (user->uid && user->uid != uid) {
+ ++user;
+ }
+ while (action->code && action->code != code) {
+ ++action;
+ }
+ if (!action->code) {
+ return UNDEFINED_ACTION;
+ }
+ if (!(action->perm & user->perms)) {
+ return PERMISSION_DENIED;
+ }
+ if (action->state && action->state != state) {
+ return state;
+ }
+ if (user->euid) {
+ uid = user->euid;
+ }
+ for (i = 0; i < MAX_PARAM && action->lengths[i]; ++i) {
+ params[i].length = recv_message(params[i].value, action->lengths[i]);
+ if (params[i].length == -1) {
+ return PROTOCOL_ERROR;
+ }
+ }
+ return action->run();
+}
+
+#define RANDOM_DEVICE "/dev/urandom"
+
+int main(int argc, char **argv)
+{
+ int control_socket = android_get_control_socket("keystore");
+ if (argc < 2) {
+ LOGE("A directory must be specified!");
+ return 1;
+ }
+ if (chdir(argv[1]) == -1) {
+ LOGE("chdir: %s: %s", argv[1], strerror(errno));
+ return 1;
+ }
+ if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) {
+ LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno));
+ return 1;
+ }
+ if (listen(control_socket, 3) == -1) {
+ LOGE("listen: %s", strerror(errno));
+ return 1;
+ }
+
+ signal(SIGPIPE, SIG_IGN);
+ if (access(MASTER_KEY_FILE, R_OK) == 0) {
+ state = LOCKED;
+ }
+
+ while ((the_socket = accept(control_socket, NULL, 0)) != -1) {
+ struct timeval tv = {.tv_sec = 3};
+ struct ucred cred;
+ socklen_t size = sizeof(cred);
+ int8_t request;
+
+ setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+ if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
+ LOGW("getsockopt: %s", strerror(errno));
+ } else if (recv_code(&request)) {
+ int8_t old_state = state;
+ int8_t response;
+ uid = cred.uid;
+
+ if ((response = process(request)) > 0) {
+ send_code(response);
+ response = -response;
+ }
+
+ LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
+ cred.uid, request, -response, old_state, state, retry);
+ }
+ close(the_socket);
+ }
+ LOGE("accept: %s", strerror(errno));
+ return 1;
+}
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
new file mode 100644
index 0000000..5ef51e9
--- /dev/null
+++ b/cmds/keystore/keystore.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KEYSTORE_H__
+#define __KEYSTORE_H__
+
+enum response_code {
+ NO_ERROR = 1,
+ LOCKED = 2,
+ UNINITIALIZED = 3,
+ SYSTEM_ERROR = 4,
+ PROTOCOL_ERROR = 5,
+ PERMISSION_DENIED = 6,
+ KEY_NOT_FOUND = 7,
+ VALUE_CORRUPTED = 8,
+ UNDEFINED_ACTION = 9,
+ WRONG_PASSWORD = 10,
+};
+
+#endif
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
new file mode 100644
index 0000000..b0b76ff
--- /dev/null
+++ b/cmds/keystore/keystore_cli.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <cutils/sockets.h>
+
+#include "keystore.h"
+
+char *responses[256] = {
+ [NO_ERROR] = "No error",
+ [LOCKED] = "Locked",
+ [UNINITIALIZED] = "Uninitialized",
+ [SYSTEM_ERROR] = "System error",
+ [PROTOCOL_ERROR] = "Protocol error",
+ [PERMISSION_DENIED] = "Permission denied",
+ [KEY_NOT_FOUND] = "Key not found",
+ [VALUE_CORRUPTED] = "Value corrupted",
+ [UNDEFINED_ACTION] = "Undefined action",
+ [WRONG_PASSWORD] = "Wrong password (last chance)",
+ [WRONG_PASSWORD + 1] = "Wrong password (2 tries left)",
+ [WRONG_PASSWORD + 2] = "Wrong password (3 tries left)",
+ [WRONG_PASSWORD + 3] = "Wrong password (4 tries left)",
+};
+
+#define MAX_RESPONSE (WRONG_PASSWORD + 3)
+
+int main(int argc, char **argv)
+{
+ uint8_t bytes[65536];
+ uint8_t code;
+ int sock, i;
+
+ if (argc < 2) {
+ printf("Usage: %s action [parameter ...]\n", argv[0]);
+ return 0;
+ }
+
+ sock = socket_local_client("keystore",
+ ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (sock == -1) {
+ puts("Failed to connect");
+ return 1;
+ }
+
+ send(sock, argv[1], 1, 0);
+ for (i = 2; i < argc; ++i) {
+ uint16_t length = strlen(argv[i]);
+ bytes[0] = length >> 8;
+ bytes[1] = length;
+ send(sock, &bytes, 2, 0);
+ send(sock, argv[i], length, 0);
+ }
+ shutdown(sock, SHUT_WR);
+
+ if (recv(sock, &code, 1, 0) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ printf("%d %s\n", code , responses[code] ? responses[code] : "Unknown");
+ while ((i = recv(sock, &bytes[0], 1, 0)) == 1) {
+ int length;
+ int offset;
+ if ((i = recv(sock, &bytes[1], 1, 0)) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ length = bytes[0] << 8 | bytes[1];
+ for (offset = 0; offset < length; offset += i) {
+ i = recv(sock, &bytes[offset], length - offset, 0);
+ if (i <= 0) {
+ puts("Failed to receive");
+ return 1;
+ }
+ }
+ fwrite(bytes, 1, length, stdout);
+ puts("");
+ }
+ return 0;
+}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 9c8006e..32a2997 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -287,25 +287,18 @@
private String readUserDataFromDatabase(Account account, String key) {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- db.beginTransaction();
+ Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE},
+ EXTRAS_ACCOUNTS_ID
+ + "=(select _id FROM accounts WHERE name=? AND type=?) AND "
+ + EXTRAS_KEY + "=?",
+ new String[]{account.name, account.type, key}, null, null, null);
try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
- return null;
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
}
- Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE},
- EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
- new String[]{key}, null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- }
- return null;
- } finally {
- cursor.close();
- }
+ return null;
} finally {
- db.endTransaction();
+ cursor.close();
}
}
@@ -530,15 +523,18 @@
public String readAuthTokenFromDatabase(Account account, String authTokenType) {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- db.beginTransaction();
+ Cursor cursor = db.query(TABLE_AUTHTOKENS, new String[]{AUTHTOKENS_AUTHTOKEN},
+ AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?) AND "
+ + AUTHTOKENS_TYPE + "=?",
+ new String[]{account.name, account.type, authTokenType},
+ null, null, null);
try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
- return null;
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
}
- return getAuthToken(db, accountId, authTokenType);
+ return null;
} finally {
- db.endTransaction();
+ cursor.close();
}
}
@@ -1069,21 +1065,6 @@
}
}
- private String getAuthToken(SQLiteDatabase db, long accountId, String authTokenType) {
- Cursor cursor = db.query(TABLE_AUTHTOKENS, new String[]{AUTHTOKENS_AUTHTOKEN},
- AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
- new String[]{authTokenType},
- null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- }
- return null;
- } finally {
- cursor.close();
- }
- }
-
private abstract class Session extends IAccountAuthenticatorResponse.Stub
implements AuthenticatorBindHelper.Callback, IBinder.DeathRecipient {
IAccountManagerResponse mResponse;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 545db17..a86fe90 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IIntentSender;
+import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -2774,48 +2775,50 @@
/**
* Like {@link #startActivityForResult(Intent, int)}, but allowing you
- * to use a PendingIntent to describe the activity to be started. Note
- * that the given PendingIntent <em>must</em> have been created with
- * {@link PendingIntent#getActivity PendingIntent.getActivity}; all other
- * types will result in an IllegalArgumentException being thrown.
+ * to use a IntentSender to describe the activity to be started. If
+ * the IntentSender is for an activity, that activity will be started
+ * as if you had called the regular {@link #startActivityForResult(Intent, int)}
+ * here; otherwise, its associated action will be executed (such as
+ * sending a broadcast) as if you had called
+ * {@link IntentSender#sendIntent IntentSender.sendIntent} on it.
*
- * @param intent The PendingIntent to launch.
+ * @param intent The IntentSender to launch.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
* @param fillInIntent If non-null, this will be provided as the
- * intent parameter to {@link PendingIntent#send(Context, int, Intent)
- * PendingIntent.send(Context, int, Intent)}.
- * @param flagsMask Intent flags in the original PendingIntent that you
+ * intent parameter to {@link IntentSender#sendIntent}.
+ * @param flagsMask Intent flags in the original IntentSender that you
* would like to change.
* @param flagsValues Desired values for any bits set in
* <var>flagsMask</var>
+ * @param extraFlags Always set to 0.
*/
- public void startActivityForResult(PendingIntent intent, int requestCode,
- Intent fillInIntent, int flagsMask, int flagsValues)
- throws PendingIntent.CanceledException {
+ public void startIntentSenderForResult(IntentSender intent, int requestCode,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
if (mParent == null) {
- startActivityForResultInner(intent, requestCode, fillInIntent,
+ startIntentSenderForResultInner(intent, requestCode, fillInIntent,
flagsMask, flagsValues, this);
} else {
- mParent.startActivityFromChild(this, intent, requestCode,
- fillInIntent, flagsMask, flagsValues);
+ mParent.startIntentSenderFromChild(this, intent, requestCode,
+ fillInIntent, flagsMask, flagsValues, extraFlags);
}
}
- private void startActivityForResultInner(PendingIntent intent, int requestCode,
+ private void startIntentSenderForResultInner(IntentSender intent, int requestCode,
Intent fillInIntent, int flagsMask, int flagsValues, Activity activity)
- throws PendingIntent.CanceledException {
+ throws IntentSender.SendIntentException {
try {
String resolvedType = null;
if (fillInIntent != null) {
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
- .startActivityPendingIntent(mMainThread.getApplicationThread(), intent,
+ .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
fillInIntent, resolvedType, mToken, activity.mEmbeddedID,
requestCode, flagsMask, flagsValues);
if (result == IActivityManager.START_CANCELED) {
- throw new PendingIntent.CanceledException();
+ throw new IntentSender.SendIntentException();
}
Instrumentation.checkStartActivityResult(result, null);
} catch (RemoteException e) {
@@ -2856,24 +2859,25 @@
}
/**
- * Like {@link #startActivity(Intent)}, but taking a PendingIntent
+ * Like {@link #startActivity(Intent)}, but taking a IntentSender
* to start; see
- * {@link #startActivityForResult(PendingIntent, int, Intent, int, int)}
+ * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
* for more information.
*
- * @param intent The PendingIntent to launch.
+ * @param intent The IntentSender to launch.
* @param fillInIntent If non-null, this will be provided as the
- * intent parameter to {@link PendingIntent#send(Context, int, Intent)
- * PendingIntent.send(Context, int, Intent)}.
- * @param flagsMask Intent flags in the original PendingIntent that you
+ * intent parameter to {@link IntentSender#sendIntent}.
+ * @param flagsMask Intent flags in the original IntentSender that you
* would like to change.
* @param flagsValues Desired values for any bits set in
* <var>flagsMask</var>
+ * @param extraFlags Always set to 0.
*/
- public void startActivity(PendingIntent intent,
- Intent fillInIntent, int flagsMask, int flagsValues)
- throws PendingIntent.CanceledException {
- startActivityForResult(intent, -1, fillInIntent, flagsMask, flagsValues);
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ startIntentSenderForResult(intent, -1, fillInIntent, flagsMask,
+ flagsValues, extraFlags);
}
/**
@@ -2998,14 +3002,15 @@
/**
* Like {@link #startActivityFromChild(Activity, Intent, int)}, but
- * taking a PendingIntent; see
- * {@link #startActivityForResult(PendingIntent, int, Intent, int, int)}
+ * taking a IntentSender; see
+ * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
* for more information.
*/
- public void startActivityFromChild(Activity child, PendingIntent intent,
- int requestCode, Intent fillInIntent, int flagsMask, int flagsValues)
- throws PendingIntent.CanceledException {
- startActivityForResultInner(intent, requestCode, fillInIntent,
+ public void startIntentSenderFromChild(Activity child, IntentSender intent,
+ int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
+ int extraFlags)
+ throws IntentSender.SendIntentException {
+ startIntentSenderForResultInner(intent, requestCode, fillInIntent,
flagsMask, flagsValues, child);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 722c75c..82d49e3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -21,6 +21,7 @@
import android.content.IntentFilter;
import android.content.IIntentSender;
import android.content.IIntentReceiver;
+import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
@@ -145,12 +146,12 @@
return true;
}
- case START_ACTIVITY_PENDING_INTENT_TRANSACTION:
+ case START_ACTIVITY_INTENT_SENDER_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
- PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data);
+ IntentSender intent = IntentSender.CREATOR.createFromParcel(data);
Intent fillInIntent = null;
if (data.readInt() != 0) {
fillInIntent = Intent.CREATOR.createFromParcel(data);
@@ -161,7 +162,7 @@
int requestCode = data.readInt();
int flagsMask = data.readInt();
int flagsValues = data.readInt();
- int result = startActivityPendingIntent(app, intent,
+ int result = startActivityIntentSender(app, intent,
fillInIntent, resolvedType, resultTo, resultWho,
requestCode, flagsMask, flagsValues);
reply.writeNoException();
@@ -1202,8 +1203,8 @@
data.recycle();
return result;
}
- public int startActivityPendingIntent(IApplicationThread caller,
- PendingIntent intent, Intent fillInIntent, String resolvedType,
+ public int startActivityIntentSender(IApplicationThread caller,
+ IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -1223,7 +1224,7 @@
data.writeInt(requestCode);
data.writeInt(flagsMask);
data.writeInt(flagsValues);
- mRemote.transact(START_ACTIVITY_PENDING_INTENT_TRANSACTION, data, reply, 0);
+ mRemote.transact(START_ACTIVITY_INTENT_SENDER_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 487cfda..dc8d873 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -561,6 +561,27 @@
}
@Override
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ try {
+ String resolvedType = null;
+ if (fillInIntent != null) {
+ resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
+ }
+ int result = ActivityManagerNative.getDefault()
+ .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
+ fillInIntent, resolvedType, null, null,
+ 0, flagsMask, flagsValues);
+ if (result == IActivityManager.START_CANCELED) {
+ throw new IntentSender.SendIntentException();
+ }
+ Instrumentation.checkStartActivityResult(result, null);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 7d9dd3a..110b72d 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -23,6 +23,7 @@
import android.content.IntentFilter;
import android.content.IIntentSender;
import android.content.IIntentReceiver;
+import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
@@ -83,8 +84,8 @@
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo, String resultWho, int requestCode,
boolean onlyIfNeeded, boolean debug) throws RemoteException;
- public int startActivityPendingIntent(IApplicationThread caller,
- PendingIntent intent, Intent fillInIntent, String resolvedType,
+ public int startActivityIntentSender(IApplicationThread caller,
+ IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues) throws RemoteException;
public boolean startNextMatchingActivity(IBinder callingActivity,
@@ -442,5 +443,5 @@
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
- int START_ACTIVITY_PENDING_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
+ int START_ACTIVITY_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 1209d0f..d05c9ab 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -191,7 +191,10 @@
mSearchPlate = findViewById(com.android.internal.R.id.search_plate);
mWorkingSpinner = getContext().getResources().
getDrawable(com.android.internal.R.drawable.search_spinner);
-
+ mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, mWorkingSpinner, null);
+ setWorking(false);
+
// attach listeners
mSearchAutoComplete.addTextChangedListener(mTextWatcher);
mSearchAutoComplete.setOnKeyListener(mTextKeyListener);
@@ -407,15 +410,9 @@
* @param working true to show spinner, false to hide spinner
*/
public void setWorking(boolean working) {
- if (working) {
- mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
- null, null, mWorkingSpinner, null);
- ((Animatable) mWorkingSpinner).start();
- } else {
- mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
- null, null, null, null);
- ((Animatable) mWorkingSpinner).stop();
- }
+ mWorkingSpinner.setAlpha(working ? 255 : 0);
+ mWorkingSpinner.setVisible(working, false);
+ mWorkingSpinner.invalidateSelf();
}
/**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 96a927b..1fc22fe 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -573,6 +573,7 @@
/**
* Validate a Bluetooth address, such as "00:43:A8:23:10:F0"
+ * <p>Alphabetic characters must be uppercase to be valid.
*
* @param address Bluetooth address as string
* @return true if the address is valid, false otherwise
@@ -586,8 +587,9 @@
switch (i % 3) {
case 0:
case 1:
- if (Character.digit(c, 16) != -1) {
- break; // hex character, OK
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
+ // hex character, OK
+ break;
}
return false;
case 2:
diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java
index 1bf786f..116310a 100644
--- a/core/java/android/bluetooth/ScoSocket.java
+++ b/core/java/android/bluetooth/ScoSocket.java
@@ -87,7 +87,7 @@
* Does not block.
*/
public synchronized boolean connect(String address) {
- if (VDBG) log("connect() " + this);
+ if (DBG) log("connect() " + this);
if (mState != STATE_READY) {
if (DBG) log("connect(): Bad state");
return false;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 60551b8..a3c4f9a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -559,6 +559,27 @@
public abstract void startActivity(Intent intent);
/**
+ * Like {@link #startActivity(Intent)}, but taking a IntentSender
+ * to start. If the IntentSender is for an activity, that activity will be started
+ * as if you had called the regular {@link #startActivity(Intent)}
+ * here; otherwise, its associated action will be executed (such as
+ * sending a broadcast) as if you had called
+ * {@link IntentSender#sendIntent IntentSender.sendIntent} on it.
+ *
+ * @param intent The IntentSender to launch.
+ * @param fillInIntent If non-null, this will be provided as the
+ * intent parameter to {@link IntentSender#sendIntent}.
+ * @param flagsMask Intent flags in the original IntentSender that you
+ * would like to change.
+ * @param flagsValues Desired values for any bits set in
+ * <var>flagsMask</var>
+ * @param extraFlags Always set to 0.
+ */
+ public abstract void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException;
+
+ /**
* Broadcast the given intent to all interested BroadcastReceivers. This
* call is asynchronous; it returns immediately, and you will continue
* executing while the receivers are run. No results are propagated from
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 15612ce..d580c47 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -249,6 +249,14 @@
}
@Override
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ mBase.startIntentSender(intent, fillInIntent, flagsMask,
+ flagsValues, extraFlags);
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index fc977c8..1359761 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2334,6 +2334,13 @@
*/
public static final int FLAG_RECEIVER_BOOT_UPGRADE = 0x10000000;
+ /**
+ * @hide Flags that can't be changed with PendingIntent.
+ */
+ public static final int IMMUTABLE_FLAGS =
+ FLAG_GRANT_READ_URI_PERMISSION
+ | FLAG_GRANT_WRITE_URI_PERMISSION;
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// toUri() and parseUri() options.
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 0e4d984..c8f7aa9 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -249,6 +249,11 @@
}
/** @hide */
+ public IIntentSender getTarget() {
+ return mTarget;
+ }
+
+ /** @hide */
public IntentSender(IIntentSender target) {
mTarget = target;
}
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index 06b0636..b212f5a 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -20,11 +20,14 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.OperationApplicationException;
+import android.database.Cursor;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Miscellaneous;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
@@ -1023,14 +1026,37 @@
}
}
+ // From HardCodedSources.java in Contacts app.
+ // TODO: fix this.
+ private static final String ACCOUNT_TYPE_GOOGLE = "com.google.GAIA";
+ private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
+
public void pushIntoContentResolver(ContentResolver resolver) {
ArrayList<ContentProviderOperation> operationList =
new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder =
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
+ String myGroupsId = null;
if (mAccount != null) {
builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
+
+ // TODO: temporal fix for "My Groups" issue. Need to be refactored.
+ if (ACCOUNT_TYPE_GOOGLE.equals(mAccount.type)) {
+ final Cursor cursor = resolver.query(Groups.CONTENT_URI, new String[] {
+ Groups.SOURCE_ID },
+ Groups.TITLE + "=?", new String[] {
+ GOOGLE_MY_CONTACTS_GROUP }, null);
+ try {
+ if (cursor != null && cursor.moveToFirst()) {
+ myGroupsId = cursor.getString(0);
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
} else {
builder.withValues(new ContentValues());
}
@@ -1196,6 +1222,14 @@
operationList.add(builder.build());
}
+ if (myGroupsId != null) {
+ builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0);
+ builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
+ builder.withValue(GroupMembership.GROUP_SOURCE_ID, myGroupsId);
+ operationList.add(builder.build());
+ }
+
try {
resolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (RemoteException e) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 17c2207..93ee3ba 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1794,7 +1794,7 @@
* @hide
*/
public static final String ACTION_FAST_TRACK =
- "com.android.contacts.ACTION_FAST_TRACK";
+ "com.android.contacts.action.FAST_TRACK";
/**
* Extra used to specify pivot dialog location in screen coordinates.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 920bcc7..1d41df2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3599,6 +3599,14 @@
"search_per_source_concurrent_query_limit";
/**
+ * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
+ * on application crashes and ANRs. If this is disabled, the crash/ANR dialog
+ * will never display the "Report" button.
+ * Type: int ( 0 = disallow, 1 = allow )
+ */
+ public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
+
+ /**
* @deprecated
* @hide
*/
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bd38b2d..45ff27e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -436,6 +436,12 @@
public int subWindowTypeToLayerLw(int type);
/**
+ * Get the highest layer (actually one more than) that the wallpaper is
+ * allowed to be in.
+ */
+ public int getMaxWallpaperLayer();
+
+ /**
* Called when the system would like to show a UI to indicate that an
* application is starting. You can use this to add a
* APPLICATION_STARTING_TYPE window with the given appToken to the window
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 465eef8..dbddb2e 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -103,7 +103,7 @@
// Create a global JWebCoreJavaBridge to handle timers and
// cookies in the WebCore thread.
if (sJavaBridge == null) {
- sJavaBridge = new JWebCoreJavaBridge();
+ sJavaBridge = new JWebCoreJavaBridge(context);
// set WebCore native cache size
sJavaBridge.setCacheSize(4 * 1024 * 1024);
// initialize CacheManager
diff --git a/core/java/android/webkit/CertTool.java b/core/java/android/webkit/CertTool.java
new file mode 100644
index 0000000..99757d2
--- /dev/null
+++ b/core/java/android/webkit/CertTool.java
@@ -0,0 +1,70 @@
+/*
+ * 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.webkit;
+
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.jce.netscape.NetscapeCertRequest;
+import org.bouncycastle.util.encoders.Base64;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.security.Credentials;
+import android.util.Log;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+class CertTool {
+ private static final String LOGTAG = "CertTool";
+
+ private static final AlgorithmIdentifier MD5_WITH_RSA =
+ new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
+
+ static final String CERT = Credentials.CERTIFICATE;
+ static final String PKCS12 = Credentials.PKCS12;
+
+ static String[] getKeyStrengthList() {
+ return new String[] {"High Grade", "Medium Grade"};
+ }
+
+ static String getSignedPublicKey(Context context, int index, String challenge) {
+ try {
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+ generator.initialize((index == 0) ? 2048 : 1024);
+ KeyPair pair = generator.genKeyPair();
+
+ NetscapeCertRequest request = new NetscapeCertRequest(challenge,
+ MD5_WITH_RSA, pair.getPublic());
+ request.sign(pair.getPrivate());
+ byte[] signed = request.toASN1Object().getDEREncoded();
+
+ Credentials.getInstance().install(context, pair);
+ return new String(Base64.encode(signed));
+ } catch (Exception e) {
+ Log.w(LOGTAG, e);
+ }
+ return null;
+ }
+
+ static void addCertificate(Context context, String type, byte[] value) {
+ Credentials.getInstance().install(context, type, value);
+ }
+
+ private CertTool() {}
+}
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index c10355c..8b783e8 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -36,10 +36,12 @@
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ViewManager.ChildView;
import android.widget.AbsoluteLayout;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.VideoView;
@@ -90,6 +92,10 @@
// The VideoView instance. This is a singleton for now, at least until
// http://b/issue?id=1973663 is fixed.
private static VideoView mVideoView;
+ // The progress view.
+ private static View mProgressView;
+ // The container for the progress view and video view
+ private static FrameLayout mLayout;
private static final WebChromeClient.CustomViewCallback mCallback =
new WebChromeClient.CustomViewCallback() {
@@ -101,7 +107,13 @@
// is invoked.
mCurrentProxy.playbackEnded();
mCurrentProxy = null;
+ mLayout.removeView(mVideoView);
mVideoView = null;
+ if (mProgressView != null) {
+ mLayout.removeView(mProgressView);
+ mProgressView = null;
+ }
+ mLayout = null;
}
};
@@ -113,6 +125,13 @@
return;
}
mCurrentProxy = proxy;
+ // Create a FrameLayout that will contain the VideoView and the
+ // progress view (if any).
+ mLayout = new FrameLayout(proxy.getContext());
+ FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER);
mVideoView = new VideoView(proxy.getContext());
mVideoView.setWillNotDraw(false);
mVideoView.setMediaController(new MediaController(proxy.getContext()));
@@ -120,8 +139,15 @@
mVideoView.setOnCompletionListener(proxy);
mVideoView.setOnPreparedListener(proxy);
mVideoView.seekTo(time);
+ mLayout.addView(mVideoView, layoutParams);
+ mProgressView = client.getVideoLoadingProgressView();
+ if (mProgressView != null) {
+ mLayout.addView(mProgressView, layoutParams);
+ mProgressView.setVisibility(View.VISIBLE);
+ }
+ mLayout.setVisibility(View.VISIBLE);
mVideoView.start();
- client.onShowCustomView(mVideoView, mCallback);
+ client.onShowCustomView(mLayout, mCallback);
}
public static void seek(int time, HTML5VideoViewProxy proxy) {
@@ -135,11 +161,20 @@
mVideoView.pause();
}
}
+
+ public static void onPrepared() {
+ if (mProgressView != null) {
+ mProgressView.setVisibility(View.GONE);
+ mLayout.removeView(mProgressView);
+ mProgressView = null;
+ }
+ }
}
// A bunch event listeners for our VideoView
// MediaPlayer.OnPreparedListener
public void onPrepared(MediaPlayer mp) {
+ VideoPlayer.onPrepared();
Message msg = Message.obtain(mWebCoreHandler, PREPARED);
Map<String, Object> map = new HashMap<String, Object>();
map.put("dur", new Integer(mp.getDuration()));
@@ -166,6 +201,13 @@
switch (msg.what) {
case INIT: {
mPosterView = new ImageView(mWebView.getContext());
+ WebChromeClient client = mWebView.getWebChromeClient();
+ if (client != null) {
+ Bitmap poster = client.getDefaultVideoPoster();
+ if (poster != null) {
+ mPosterView.setImageBitmap(poster);
+ }
+ }
mChildView.mView = mPosterView;
break;
}
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index ddc2da1..f350d13 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -16,9 +16,9 @@
package android.webkit;
+import android.content.Context;
import android.os.Handler;
import android.os.Message;
-import android.security.CertTool;
import android.util.Log;
final class JWebCoreJavaBridge extends Handler {
@@ -41,6 +41,8 @@
private boolean mTimerPaused;
private boolean mHasDeferredTimers;
+ private Context mContext;
+
/* package */
static final int REFRESH_PLUGINS = 100;
@@ -48,7 +50,8 @@
* Construct a new JWebCoreJavaBridge to interface with
* WebCore timers and cookies.
*/
- public JWebCoreJavaBridge() {
+ public JWebCoreJavaBridge(Context context) {
+ mContext = context;
nativeConstructor();
}
@@ -230,12 +233,12 @@
}
private String[] getKeyStrengthList() {
- return CertTool.getInstance().getSupportedKeyStrenghs();
+ return CertTool.getKeyStrengthList();
}
private String getSignedPublicKey(int index, String challenge, String url) {
// generateKeyPair expects organizations which we don't have. Ignore url.
- return CertTool.getInstance().generateKeyPair(index, challenge, null);
+ return CertTool.getSignedPublicKey(mContext, index, challenge);
}
private native void nativeConstructor();
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index aee8a6d..5995121 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -28,7 +28,6 @@
import android.os.Handler;
import android.os.Message;
-import android.security.CertTool;
import android.util.Log;
import android.webkit.CacheManager.CacheResult;
@@ -37,7 +36,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
@@ -70,12 +68,12 @@
private static final int HTTP_NOT_FOUND = 404;
private static final int HTTP_PROXY_AUTH = 407;
- private static HashSet<String> sCertificateMimeTypeMap;
+ private static HashMap<String, String> sCertificateTypeMap;
static {
- sCertificateMimeTypeMap = new HashSet<String>();
- sCertificateMimeTypeMap.add("application/x-x509-ca-cert");
- sCertificateMimeTypeMap.add("application/x-x509-user-cert");
- sCertificateMimeTypeMap.add("application/x-pkcs12");
+ sCertificateTypeMap = new HashMap<String, String>();
+ sCertificateTypeMap.put("application/x-x509-ca-cert", CertTool.CERT);
+ sCertificateTypeMap.put("application/x-x509-user-cert", CertTool.CERT);
+ sCertificateTypeMap.put("application/x-pkcs12", CertTool.PKCS12);
}
private static int sNativeLoaderCount;
@@ -964,9 +962,9 @@
// This commits the headers without checking the response status code.
private void commitHeaders() {
- if (mIsMainPageLoader && sCertificateMimeTypeMap.contains(mMimeType)) {
+ if (mIsMainPageLoader && sCertificateTypeMap.containsKey(mMimeType)) {
// In the case of downloading certificate, we will save it to the
- // Keystore in commitLoad. Do not call webcore.
+ // KeyStore in commitLoad. Do not call webcore.
return;
}
@@ -1009,26 +1007,28 @@
private void commitLoad() {
if (mCancelled) return;
- if (mIsMainPageLoader && sCertificateMimeTypeMap.contains(mMimeType)) {
- // In the case of downloading certificate, we will save it to the
- // Keystore and stop the current loading so that it will not
- // generate a new history page
- byte[] cert = new byte[mDataBuilder.getByteSize()];
- int position = 0;
- ByteArrayBuilder.Chunk c;
- while (true) {
- c = mDataBuilder.getFirstChunk();
- if (c == null) break;
+ if (mIsMainPageLoader) {
+ String type = sCertificateTypeMap.get(mMimeType);
+ if (type != null) {
+ // In the case of downloading certificate, we will save it to
+ // the KeyStore and stop the current loading so that it will not
+ // generate a new history page
+ byte[] cert = new byte[mDataBuilder.getByteSize()];
+ int offset = 0;
+ while (true) {
+ ByteArrayBuilder.Chunk c = mDataBuilder.getFirstChunk();
+ if (c == null) break;
- if (c.mLength != 0) {
- System.arraycopy(c.mArray, 0, cert, position, c.mLength);
- position += c.mLength;
+ if (c.mLength != 0) {
+ System.arraycopy(c.mArray, 0, cert, offset, c.mLength);
+ offset += c.mLength;
+ }
+ mDataBuilder.releaseChunk(c);
}
- mDataBuilder.releaseChunk(c);
+ CertTool.addCertificate(mContext, type, cert);
+ mBrowserFrame.stopLoading();
+ return;
}
- CertTool.getInstance().addCertificate(cert, mContext);
- mBrowserFrame.stopLoading();
- return;
}
// Give the data to WebKit now
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 6421fe7..0e08514 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -273,4 +273,26 @@
* @hide pending API council.
*/
public void addMessageToConsole(String message, int lineNumber, String sourceID) {}
+
+ /**
+ * Ask the host application for an icon to represent a <video> element.
+ * This icon will be used if the Web page did not specify a poster attribute.
+ *
+ * @return Bitmap The icon or null if no such icon is available.
+ * @hide pending API Council approval
+ */
+ public Bitmap getDefaultVideoPoster() {
+ return null;
+ }
+
+ /**
+ * Ask the host application for a custom progress view to show while
+ * a <video> is loading.
+ *
+ * @return View The progress view.
+ * @hide pending API Council approval
+ */
+ public View getVideoLoadingProgressView() {
+ return null;
+ }
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 12eb934..7e8ba8f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -905,8 +905,9 @@
/*
* Return the width of the view where the content of WebView should render
* to.
+ * Note: this can be called from WebCoreThread.
*/
- private int getViewWidth() {
+ /* package */ int getViewWidth() {
if (!isVerticalScrollBarEnabled() || mOverlayVerticalScrollbar) {
return getWidth();
} else {
@@ -932,8 +933,9 @@
/*
* Return the height of the view where the content of WebView should render
* to. Note that this excludes mTitleBar, if there is one.
+ * Note: this can be called from WebCoreThread.
*/
- private int getViewHeight() {
+ /* package */ int getViewHeight() {
int height = getHeight();
if (isHorizontalScrollBarEnabled() && !mOverlayHorizontalScrollbar) {
height -= getHorizontalScrollbarHeight();
@@ -1747,6 +1749,14 @@
private View mTitleBar;
/**
+ * Since we draw the title bar ourselves, we removed the shadow from the
+ * browser's activity. We do want a shadow at the bottom of the title bar,
+ * or at the top of the screen if the title bar is not visible. This
+ * drawable serves that purpose.
+ */
+ private Drawable mTitleShadow;
+
+ /**
* Add or remove a title bar to be embedded into the WebView, and scroll
* along with it vertically, while remaining in view horizontally. Pass
* null to remove the title bar from the WebView, and return to drawing
@@ -1762,6 +1772,10 @@
addView(v, new AbsoluteLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0));
+ if (mTitleShadow == null) {
+ mTitleShadow = (Drawable) mContext.getResources().getDrawable(
+ com.android.internal.R.drawable.title_bar_shadow);
+ }
}
mTitleBar = v;
}
@@ -2470,8 +2484,11 @@
}
// scale from content to view coordinates, and pin
- // return true if pin caused the final x/y different than the request cx/cy;
- // return false if the view scroll to the exact position as it is requested.
+ // return true if pin caused the final x/y different than the request cx/cy,
+ // and a future scroll may reach the request cx/cy after our size has
+ // changed
+ // return false if the view scroll to the exact position as it is requested,
+ // where negative numbers are taken to mean 0
private boolean setContentScrollTo(int cx, int cy) {
if (mDrawHistory) {
// disallow WebView to change the scroll position as History Picture
@@ -2486,7 +2503,9 @@
// Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
// vx + " " + vy + "]");
pinScrollTo(vx, vy, false, 0);
- if (mScrollX != vx || mScrollY != vy) {
+ // If the request was to scroll to a negative coordinate, treat it as if
+ // it was a request to scroll to 0
+ if ((mScrollX != vx && cx >= 0) || (mScrollY != vy && cy >= 0)) {
return true;
} else {
return false;
@@ -2676,16 +2695,14 @@
@Override
protected void onDraw(Canvas canvas) {
- int saveCount = canvas.getSaveCount();
- if (mTitleBar != null) {
- canvas.save();
- canvas.translate(0, (int) mTitleBar.getHeight());
- }
// if mNativeClass is 0, the WebView has been destroyed. Do nothing.
if (mNativeClass == 0) {
return;
}
- canvas.save();
+ int saveCount = canvas.save();
+ if (mTitleBar != null) {
+ canvas.translate(0, (int) mTitleBar.getHeight());
+ }
// Update the buttons in the picture, so when we draw the picture
// to the screen, they are in the correct state.
// Tell the native side if user is a) touching the screen,
@@ -2700,6 +2717,15 @@
drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
canvas.restoreToCount(saveCount);
+ // Now draw the shadow.
+ if (mTitleBar != null) {
+ int y = mScrollY + getVisibleTitleHeight();
+ int height = (int) (5f * getContext().getResources()
+ .getDisplayMetrics().density);
+ mTitleShadow.setBounds(mScrollX, y, mScrollX + getWidth(),
+ y + height);
+ mTitleShadow.draw(canvas);
+ }
if (AUTO_REDRAW_HACK && mAutoRedraw) {
invalidate();
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index ac3334c..d4142bb 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1890,7 +1890,22 @@
if (mViewportWidth != 0 && !updateRestoreState) return;
// now notify webview
- int webViewWidth = Math.round(mCurrentViewWidth * mCurrentViewScale);
+ // webViewWidth refers to the width in the view system
+ int webViewWidth;
+ // viewportWidth refers to the width in the document system
+ int viewportWidth = mCurrentViewWidth;
+ if (viewportWidth == 0) {
+ // this may happen when WebView just starts. This is not perfect as
+ // we call WebView method from WebCore thread. But not perfect
+ // reference is better than no reference.
+ webViewWidth = mWebView.getViewWidth();
+ viewportWidth = webViewWidth * 100 / WebView.DEFAULT_SCALE_PERCENT;
+ if (viewportWidth == 0) {
+ Log.w(LOGTAG, "Can't get the viewWidth after the first layout");
+ }
+ } else {
+ webViewWidth = Math.round(viewportWidth * mCurrentViewScale);
+ }
mRestoreState = new RestoreState();
mRestoreState.mMinScale = mViewportMinimumScale / 100.0f;
mRestoreState.mMaxScale = mViewportMaximumScale / 100.0f;
@@ -1942,7 +1957,7 @@
mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
EventHub.VIEW_SIZE_CHANGED, data));
} else if (mSettings.getUseWideViewPort()) {
- if (mCurrentViewWidth == 0) {
+ if (viewportWidth == 0) {
// Trick to ensure VIEW_SIZE_CHANGED will be sent from WebView
// to WebViewCore
mWebView.mLastWidthSent = 0;
@@ -1956,8 +1971,7 @@
: mRestoreState.mTextWrapScale)
: mRestoreState.mViewScale;
data.mWidth = Math.round(webViewWidth / data.mScale);
- data.mHeight = mCurrentViewHeight * data.mWidth
- / mCurrentViewWidth;
+ data.mHeight = mCurrentViewHeight * data.mWidth / viewportWidth;
data.mTextWrapWidth = Math.round(webViewWidth
/ mRestoreState.mTextWrapScale);
data.mIgnoreHeight = false;
diff --git a/core/java/android/widget/FasttrackBadgeWidget.java b/core/java/android/widget/FasttrackBadgeWidget.java
index 22ca5fd..9d2307f 100644
--- a/core/java/android/widget/FasttrackBadgeWidget.java
+++ b/core/java/android/widget/FasttrackBadgeWidget.java
@@ -22,9 +22,9 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.database.Cursor;
-import android.graphics.Rect;
import android.net.Uri;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.FastTrack;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
@@ -32,7 +32,6 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.ImageView;
/**
* Widget used to show an image with the standard fasttrack badge
@@ -87,7 +86,7 @@
com.android.internal.R.styleable.FasttrackBadgeWidget, defStyle, 0);
mMode = a.getInt(com.android.internal.R.styleable.FasttrackBadgeWidget_fasttrackWindowSize,
- Intents.MODE_MEDIUM);
+ FastTrack.MODE_MEDIUM);
a.recycle();
@@ -100,12 +99,12 @@
}
/**
- * Assign the contact uri that this fasttrack badge should be associated with.
- * Note that this is only used for displaying the fasttrack window and won't
- * bind the contact's photo for you.
+ * Assign the contact uri that this fasttrack badge should be associated
+ * with. Note that this is only used for displaying the fasttrack window and
+ * won't bind the contact's photo for you.
*
- * @param conatctUri Either a {Contacts.CONTENT_URI} or {Contacts.CONTENT_LOOKUP_URI}
- * style URI.
+ * @param contactUri Either a {@link Contacts#CONTENT_URI} or
+ * {@link Contacts#CONTENT_LOOKUP_URI} style URI.
*/
public void assignContactUri(Uri contactUri) {
mContactUri = contactUri;
@@ -126,6 +125,8 @@
mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
EMAIL_LOOKUP_PROJECTION, null, null, null);
+ } else {
+ mContactUri = null;
}
}
@@ -144,12 +145,14 @@
mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
PHONE_LOOKUP_PROJECTION, null, null, null);
+ } else {
+ mContactUri = null;
}
}
/**
- * Set the fasttrack window mode. Options are {@link Intents.MODE_SMALL},
- * {@link Intents.MODE_MEDIUM}, {@link Intents.MODE_LARGE}.
+ * Set the fasttrack window mode. Options are {@link FastTrack#MODE_SMALL},
+ * {@link FastTrack#MODE_MEDIUM}, {@link FastTrack#MODE_LARGE}.
* @param size
*/
public void setMode(int size) {
@@ -157,16 +160,16 @@
}
public void onClick(View v) {
- final Rect target = getTargetRect(v);
-
if (mContactUri != null) {
- trigger(mContactUri, target);
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri lookupUri = Contacts.getLookupUri(resolver, mContactUri);
+ trigger(lookupUri);
} else if (mContactEmail != null) {
- mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, target,
+ mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, mContactEmail,
Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
EMAIL_LOOKUP_PROJECTION, null, null, null);
} else if (mContactPhone != null) {
- mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, target,
+ mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, mContactPhone,
Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
PHONE_LOOKUP_PROJECTION, null, null, null);
} else {
@@ -184,23 +187,8 @@
mExcludeMimes = excludeMimes;
}
- private void trigger(Uri contactUri, Rect target) {
- Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, contactUri);
- intent.putExtra(Intents.EXTRA_TARGET_RECT, target);
- intent.putExtra(Intents.EXTRA_MODE, mMode);
- mContext.startActivity(intent);
- }
-
- private Rect getTargetRect(View anchor) {
- final int[] location = new int[2];
- anchor.getLocationOnScreen(location);
-
- final Rect rect = new Rect();
- rect.left = location[0];
- rect.top = location[1];
- rect.right = rect.left + anchor.getWidth();
- rect.bottom = rect.top + anchor.getHeight();
- return rect;
+ private void trigger(Uri lookupUri) {
+ FastTrack.showFastTrack(getContext(), this, lookupUri, mMode, mExcludeMimes);
}
private class QueryHandler extends AsyncQueryHandler {
@@ -211,28 +199,34 @@
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- Uri contactUri = null;
+ Uri lookupUri = null;
+ Uri createUri = null;
boolean trigger = false;
- try{
+ try {
switch(token) {
case TOKEN_PHONE_LOOKUP_AND_TRIGGER:
trigger = true;
+ createUri = Uri.fromParts("tel", (String)cookie, null);
+
case TOKEN_PHONE_LOOKUP: {
if (cursor != null && cursor.moveToFirst()) {
long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
String lookupKey = cursor.getString(PHONE_LOOKUP_STRING_COLUMN_INDEX);
- contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ lookupUri = Contacts.getLookupUri(contactId, lookupKey);
}
+
break;
}
case TOKEN_EMAIL_LOOKUP_AND_TRIGGER:
trigger = true;
+ createUri = Uri.fromParts("mailto", (String)cookie, null);
+
case TOKEN_EMAIL_LOOKUP: {
if (cursor != null && cursor.moveToFirst()) {
long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
- contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ lookupUri = Contacts.getLookupUri(contactId, lookupKey);
}
}
}
@@ -242,11 +236,15 @@
}
}
- if (contactUri != null) {
- mContactUri = contactUri;
- if (trigger && cookie != null) {
- trigger(contactUri, (Rect) cookie);
- }
+ mContactUri = lookupUri;
+
+ if (trigger && lookupUri != null) {
+ // Found contact, so trigger track
+ trigger(lookupUri);
+ } else if (createUri != null) {
+ // Prompt user to add this person to contacts
+ final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, createUri);
+ getContext().startActivity(intent);
}
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2dac652..8ef65db 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -17,8 +17,9 @@
package android.widget;
import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
@@ -137,8 +138,11 @@
public void onClick(View v) {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
- pendingIntent.send();
- } catch (CanceledException e) {
+ v.getContext().startIntentSender(
+ pendingIntent.getIntentSender(), null,
+ Intent.FLAG_ACTIVITY_NEW_TASK,
+ Intent.FLAG_ACTIVITY_NEW_TASK, 0);
+ } catch (IntentSender.SendIntentException e) {
throw new ActionException(e.toString());
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e98fd13..2e3364b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3408,7 +3408,8 @@
if (mPopup != null) {
TextView tv = (TextView) mPopup.getContentView();
chooseSize(mPopup, mError, tv);
- mPopup.update(this, getErrorX(), getErrorY(), -1, -1);
+ mPopup.update(this, getErrorX(), getErrorY(),
+ mPopup.getWidth(), mPopup.getHeight());
}
restartMarqueeIfNeeded();
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
index aff92b8..712f1bf 100644
--- a/core/java/com/android/internal/widget/RotarySelector.java
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -106,6 +106,11 @@
private static final int EDGE_PADDING_DIP = 9;
/**
+ * How far from the edge of the screen the user must drag to trigger the event.
+ */
+ private static final int EDGE_TRIGGER_DIP = 65;
+
+ /**
* Dimensions of arc in background drawable.
*/
static final int OUTER_ROTARY_RADIUS_DIP = 390;
@@ -113,12 +118,12 @@
private static final int ANIMATION_DURATION_MILLIS = 300;
private static final boolean DRAW_CENTER_DIMPLE = false;
+ private int mEdgeTriggerThresh;
public RotarySelector(Context context) {
this(context, null);
}
-
/**
* Constructor used when this widget is created from a layout file.
*/
@@ -148,6 +153,8 @@
mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
mInterpolator = new AccelerateInterpolator();
+
+ mEdgeTriggerThresh = (int) (mDensity * EDGE_TRIGGER_DIP);
}
/**
@@ -252,7 +259,6 @@
}
}
-
// Background:
final int backgroundW = mBackground.getIntrinsicWidth();
final int backgroundH = mBackground.getIntrinsicHeight();
@@ -268,7 +274,7 @@
Drawable currentArrow;
switch (mGrabbedState) {
case NOTHING_GRABBED:
- currentArrow = mArrowShortLeftAndRight;
+ currentArrow = null; //mArrowShortLeftAndRight;
break;
case LEFT_HANDLE_GRABBED:
currentArrow = mArrowLongLeft;
@@ -279,7 +285,7 @@
default:
throw new IllegalStateException("invalid mGrabbedState: " + mGrabbedState);
}
- currentArrow.draw(canvas);
+ if (currentArrow != null) currentArrow.draw(canvas);
// debug: draw circle that should match the outer arc (good sanity check)
// mPaint.setColor(Color.RED);
@@ -300,7 +306,9 @@
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
- drawCentered(mLeftHandleIcon, canvas, xOffset, drawableY + bgTop);
+ if (mGrabbedState != RIGHT_HANDLE_GRABBED) {
+ drawCentered(mLeftHandleIcon, canvas, xOffset, drawableY + bgTop);
+ }
}
if (DRAW_CENTER_DIMPLE) {
@@ -323,7 +331,9 @@
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
- drawCentered(mRightHandleIcon, canvas, xOffset, drawableY + bgTop);
+ if (mGrabbedState != LEFT_HANDLE_GRABBED) {
+ drawCentered(mRightHandleIcon, canvas, xOffset, drawableY + bgTop);
+ }
}
if (mAnimating) invalidate();
@@ -407,14 +417,14 @@
if (mGrabbedState == LEFT_HANDLE_GRABBED) {
mTouchDragOffset = eventX - mLeftHandleX;
invalidate();
- if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) {
+ if (eventX >= getRight() - mEdgeTriggerThresh && !mTriggered) {
mTriggered = true;
mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
}
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
mTouchDragOffset = eventX - mRightHandleX;
invalidate();
- if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
+ if (eventX <= mEdgeTriggerThresh && !mTriggered) {
mTriggered = true;
mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
}
diff --git a/core/java/com/google/android/gdata/client/AndroidGDataClient.java b/core/java/com/google/android/gdata/client/AndroidGDataClient.java
index 998f940..9a2a51d 100644
--- a/core/java/com/google/android/gdata/client/AndroidGDataClient.java
+++ b/core/java/com/google/android/gdata/client/AndroidGDataClient.java
@@ -19,6 +19,7 @@
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,6 +27,7 @@
import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
+import android.os.SystemProperties;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -55,6 +57,10 @@
private static final int MAX_REDIRECTS = 10;
+ // boolean system property that can be used to control whether or not
+ // requests/responses are gzip'd.
+ private static final String NO_GZIP_SYSTEM_PROPERTY = "sync.nogzip";
+
private final GoogleHttpClient mHttpClient;
private ContentResolver mResolver;
@@ -212,7 +218,10 @@
HttpUriRequest request = creator.createRequest(uri);
- AndroidHttpClient.modifyRequestToAcceptGzipResponse(request);
+ if (!SystemProperties.getBoolean(NO_GZIP_SYSTEM_PROPERTY, false)) {
+ AndroidHttpClient.modifyRequestToAcceptGzipResponse(request);
+ }
+
// only add the auth token if not null (to allow for GData feeds that do not require
// authentication.)
if (!TextUtils.isEmpty(authToken)) {
@@ -487,7 +496,12 @@
}
}
- AbstractHttpEntity entity = AndroidHttpClient.getCompressedEntity(entryBytes, mResolver);
+ AbstractHttpEntity entity;
+ if (SystemProperties.getBoolean(NO_GZIP_SYSTEM_PROPERTY, false)) {
+ entity = new ByteArrayEntity(entryBytes);
+ } else {
+ entity = AndroidHttpClient.getCompressedEntity(entryBytes, mResolver);
+ }
entity.setContentType(entry.getContentType());
return entity;
}
diff --git a/core/java/com/google/android/gdata2/client/AndroidGDataClient.java b/core/java/com/google/android/gdata2/client/AndroidGDataClient.java
index 6ba791d..3721fa4 100644
--- a/core/java/com/google/android/gdata2/client/AndroidGDataClient.java
+++ b/core/java/com/google/android/gdata2/client/AndroidGDataClient.java
@@ -22,6 +22,7 @@
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
import android.content.ContentResolver;
import android.content.Context;
@@ -29,6 +30,7 @@
import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
+import android.os.SystemProperties;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -59,6 +61,9 @@
private static final int MAX_REDIRECTS = 10;
private static String DEFAULT_GDATA_VERSION = "2.0";
+ // boolean system property that can be used to control whether or not
+ // requests/responses are gzip'd.
+ private static final String NO_GZIP_SYSTEM_PROPERTY = "sync.nogzip";
private String mGDataVersion;
private final GoogleHttpClient mHttpClient;
@@ -213,7 +218,7 @@
HttpResponse response = null;
int status = 500;
int redirectsLeft = MAX_REDIRECTS;
-
+
URI uri;
try {
uri = new URI(uriString);
@@ -230,7 +235,10 @@
HttpUriRequest request = creator.createRequest(uri);
- AndroidHttpClient.modifyRequestToAcceptGzipResponse(request);
+ if (!SystemProperties.getBoolean(NO_GZIP_SYSTEM_PROPERTY, false)) {
+ AndroidHttpClient.modifyRequestToAcceptGzipResponse(request);
+ }
+
// only add the auth token if not null (to allow for GData feeds that do not require
// authentication.)
if (!TextUtils.isEmpty(authToken)) {
@@ -547,7 +555,13 @@
}
}
- AbstractHttpEntity entity = AndroidHttpClient.getCompressedEntity(entryBytes, mResolver);
+ AbstractHttpEntity entity;
+ if (SystemProperties.getBoolean(NO_GZIP_SYSTEM_PROPERTY, false)) {
+ entity = new ByteArrayEntity(entryBytes);
+ } else {
+ entity = AndroidHttpClient.getCompressedEntity(entryBytes, mResolver);
+ }
+
entity.setContentType(entry.getContentType());
return entity;
}
@@ -587,4 +601,3 @@
throw new IOException("Unable to process batch request.");
}
}
-
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
index df91ea6..568aeb7 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/core/java/com/google/android/mms/pdu/PduPersister.java
@@ -810,7 +810,7 @@
public void updateHeaders(Uri uri, SendReq sendReq) {
PDU_CACHE_INSTANCE.purge(uri);
- ContentValues values = new ContentValues(9);
+ ContentValues values = new ContentValues(10);
byte[] contentType = sendReq.getContentType();
if (contentType != null) {
values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
@@ -856,6 +856,11 @@
values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
}
+
+ long messageSize = sendReq.getMessageSize();
+ if (messageSize > 0) {
+ values.put(Mms.MESSAGE_SIZE, messageSize);
+ }
PduHeaders headers = sendReq.getPduHeaders();
HashSet<String> recipients = new HashSet<String>();
diff --git a/core/java/com/google/android/mms/pdu/SendReq.java b/core/java/com/google/android/mms/pdu/SendReq.java
index 9081b0c..9ea6e47 100644
--- a/core/java/com/google/android/mms/pdu/SendReq.java
+++ b/core/java/com/google/android/mms/pdu/SendReq.java
@@ -206,6 +206,26 @@
}
/**
+ * Get X-Mms-MessageSize value.
+ *
+ * Expiry-value = size of message
+ *
+ * @return the value
+ */
+ public long getMessageSize() {
+ return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
+ }
+
+ /**
+ * Set X-Mms-MessageSize value.
+ *
+ * @param value the value
+ */
+ public void setMessageSize(long value) {
+ mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
+ }
+
+ /**
* Get From value.
* From-value = Value-length
* (Address-present-token Encoded-string-value | Insert-address-token)
diff --git a/core/res/res/anim/dialog_enter.xml b/core/res/res/anim/dialog_enter.xml
index cc409e8..167f4bc 100644
--- a/core/res/res/anim/dialog_enter.xml
+++ b/core/res/res/anim/dialog_enter.xml
@@ -22,7 +22,7 @@
android:interpolator="@anim/decelerate_interpolator">
<scale android:fromXScale="0.9" android:toXScale="1.0"
android:fromYScale="0.9" android:toYScale="1.0"
- android:pivotX="50%" android:pivotY="50%"
+ android:pivotX="50%p" android:pivotY="50%p"
android:duration="@android:integer/config_shortAnimTime" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_shortAnimTime" />
diff --git a/core/res/res/anim/dialog_exit.xml b/core/res/res/anim/dialog_exit.xml
index 8bf8082..d412cfb 100644
--- a/core/res/res/anim/dialog_exit.xml
+++ b/core/res/res/anim/dialog_exit.xml
@@ -21,7 +21,7 @@
android:interpolator="@anim/accelerate_interpolator">
<scale android:fromXScale="1.0" android:toXScale="0.9"
android:fromYScale="1.0" android:toYScale="0.9"
- android:pivotX="50%" android:pivotY="50%"
+ android:pivotX="50%p" android:pivotY="50%p"
android:duration="@android:integer/config_shortAnimTime" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_shortAnimTime"/>
diff --git a/core/res/res/anim/recent_enter.xml b/core/res/res/anim/recent_enter.xml
new file mode 100644
index 0000000..deeb96b
--- /dev/null
+++ b/core/res/res/anim/recent_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/decelerate_interpolator">
+ <scale android:fromXScale="2.0" android:toXScale="1.0"
+ android:fromYScale="2.0" android:toYScale="1.0"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/anim/recent_exit.xml b/core/res/res/anim/recent_exit.xml
new file mode 100644
index 0000000..fed7014
--- /dev/null
+++ b/core/res/res/anim/recent_exit.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/decelerate_interpolator"
+ android:zAdjustment="top">
+ <scale android:fromXScale="1.0" android:toXScale="2.0"
+ android:fromYScale="1.0" android:toYScale="2.0"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/drawable-hdpi/dark_header.9.png b/core/res/res/drawable-hdpi/dark_header.9.png
index a2fa569..3e63fa6 100644
--- a/core/res/res/drawable-hdpi/dark_header.9.png
+++ b/core/res/res/drawable-hdpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
index c7803a2..99a67b9 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
index d8d8aa9..cfe258b 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
index 63859f7..30a68d0 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
index ced2832..8f35315 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
index 1035656..99a67b9 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
similarity index 100%
rename from core/res/res/drawable/divider_vertical_bright_opaque.9.png
rename to core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
new file mode 100644
index 0000000..30a68d0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
similarity index 100%
rename from core/res/res/drawable/divider_vertical_dark_opaque.9.png
rename to core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/light_header.9.png b/core/res/res/drawable-hdpi/light_header.9.png
index 27db59d..6fc53ca 100644
--- a/core/res/res/drawable-hdpi/light_header.9.png
+++ b/core/res/res/drawable-hdpi/light_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dark_header.9.png b/core/res/res/drawable-mdpi/dark_header.9.png
index 7242b61..f4a14f1d 100644
--- a/core/res/res/drawable-mdpi/dark_header.9.png
+++ b/core/res/res/drawable-mdpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
similarity index 100%
copy from core/res/res/drawable/divider_vertical_bright_opaque.9.png
copy to core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable/divider_vertical_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
similarity index 100%
rename from core/res/res/drawable/divider_vertical_dark.9.png
rename to core/res/res/drawable-mdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
similarity index 100%
copy from core/res/res/drawable/divider_vertical_dark_opaque.9.png
copy to core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/layout/tab_indicator.xml b/core/res/res/layout/tab_indicator.xml
index e3ea555..71e4001 100644
--- a/core/res/res/layout/tab_indicator.xml
+++ b/core/res/res/layout/tab_indicator.xml
@@ -18,8 +18,8 @@
android:layout_width="0dip"
android:layout_height="64dip"
android:layout_weight="1"
- android:layout_marginLeft="-4px"
- android:layout_marginRight="-4px"
+ android:layout_marginLeft="-3dip"
+ android:layout_marginRight="-3dip"
android:orientation="vertical"
android:background="@android:drawable/tab_indicator">
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index c967c4c..2f09aca 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -19,7 +19,7 @@
-->
<resources>
<drawable name="screen_background_light">#ffffffff</drawable>
- <drawable name="screen_background_dark">#ff202020</drawable>
+ <drawable name="screen_background_dark">#ff1a1a1a</drawable>
<drawable name="status_bar_closed_default_background">#ff000000</drawable>
<drawable name="status_bar_opened_default_background">#ff000000</drawable>
<drawable name="search_bar_default_color">#ff000000</drawable>
@@ -36,7 +36,7 @@
<color name="white">#ffffffff</color>
<color name="black">#ff000000</color>
<color name="transparent">#00000000</color>
- <color name="background_dark">#ff202020</color>
+ <color name="background_dark">#ff1a1a1a</color>
<color name="bright_foreground_dark">#ffffffff</color>
<color name="bright_foreground_dark_disabled">#80ffffff</color>
<color name="bright_foreground_dark_inverse">#ff000000</color>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 69612e9..35db8ee 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -177,6 +177,13 @@
<item name="windowExitAnimation">@anim/wallpaper_exit</item>
</style>
+ <!-- A special animation we can use for recent applications,
+ for devices that can support it (do alpha transformations). -->
+ <style name="Animation.RecentApplications">
+ <item name="windowEnterAnimation">@anim/recent_enter</item>
+ <item name="windowExitAnimation">@anim/recent_exit</item>
+ </style>
+
<!-- Status Bar Styles -->
<style name="TextAppearance.StatusBarTitle">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 1aa48ee..04402fd 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -500,4 +500,10 @@
<item name="windowContentOverlay">@null</item>
<item name="textAppearance">@style/TextAppearance.Theme.Dialog.AppError</item>
</style>
+
+ <!-- Special theme for the recent apps dialog, to allow customization
+ with overlays. -->
+ <style name="Theme.Dialog.RecentApplications">
+ </style>
+
</resources>
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index eae6f24..c7b5448 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -255,28 +255,24 @@
static void * SF_SaveInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
{
- LOGE("Save Int");
_env->SetIntField(_obj, _field, ((int32_t *)buffer)[0]);
return ((uint8_t *)buffer) + 4;
}
static void * SF_SaveShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
{
- LOGE("Save Short");
_env->SetShortField(_obj, _field, ((int16_t *)buffer)[0]);
return ((uint8_t *)buffer) + 2;
}
static void * SF_SaveByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
{
- LOGE("Save Byte");
_env->SetByteField(_obj, _field, ((int8_t *)buffer)[0]);
return ((uint8_t *)buffer) + 1;
}
static void * SF_SaveFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
{
- LOGE("Save Float");
_env->SetFloatField(_obj, _field, ((float *)buffer)[0]);
return ((uint8_t *)buffer) + 4;
}
@@ -601,11 +597,8 @@
void * buf = bufAlloc;
rsAllocationRead(con, (RsAllocation)alloc, bufAlloc);
- LOGE("size %i, ", tc->size);
-
for (int ct=0; ct < tc->fieldCount; ct++) {
const TypeFieldCache *tfc = &tc->fields[ct];
- LOGE("ct=%i, buf=%p", ct, buf);
buf = tfc->readPtr(_env, _o, tfc->field, buf);
}
free(bufAlloc);
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index 68144b5..8ea3ab9 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -54,6 +54,7 @@
bool isUpdateOnDemand() const { return mUpdateOnDemand; }
status_t setUpdateRectangle(const Rect& updateRect);
+ status_t compositionComplete();
private:
friend class LightRefBase<FramebufferNativeWindow>;
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
new file mode 100644
index 0000000..28c2992
--- /dev/null
+++ b/keystore/java/android/security/Credentials.java
@@ -0,0 +1,98 @@
+/*
+ * 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.security;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import java.security.KeyPair;
+
+/**
+ * {@hide}
+ */
+public class Credentials {
+ private static final String LOGTAG = "Credentials";
+ private static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
+ private static final String INSTALL_ACTION = "android.credentials.INSTALL";
+ private static Credentials singleton;
+
+ /** Key prefix for CA certificates. */
+ public static final String CA_CERTIFICATE = "CACERT_";
+
+ /** Key prefix for user certificates. */
+ public static final String USER_CERTIFICATE = "USRCERT_";
+
+ /** Key prefix for user private keys. */
+ public static final String USER_PRIVATE_KEY = "USRPKEY_";
+
+ /** Key prefix for VPN. */
+ public static final String VPN = "VPN_";
+
+ /** Key prefix for WIFI. */
+ public static final String WIFI = "WIFI_";
+
+ /** Data type for public keys. */
+ public static final String PUBLIC_KEY = "KEY";
+
+ /** Data type for private keys. */
+ public static final String PRIVATE_KEY = "PKEY";
+
+ /** Data type for certificates. */
+ public static final String CERTIFICATE = "CERT";
+
+ /** Data type for PKCS12. */
+ public static final String PKCS12 = "PKCS12";
+
+ public static Credentials getInstance() {
+ if (singleton == null) {
+ singleton = new Credentials();
+ }
+ return singleton;
+ }
+
+ public void unlock(Context context) {
+ try {
+ Intent intent = new Intent(UNLOCK_ACTION);
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, e.toString());
+ }
+ }
+
+ public void install(Context context, KeyPair pair) {
+ try {
+ Intent intent = new Intent(INSTALL_ACTION);
+ intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
+ intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, e.toString());
+ }
+ }
+
+ public void install(Context context, String type, byte[] value) {
+ try {
+ Intent intent = new Intent(INSTALL_ACTION);
+ intent.putExtra(type, value);
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, e.toString());
+ }
+ }
+}
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index add358b..e534447 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -307,6 +307,9 @@
if (lStatus == NO_ERROR) {
trackHandle = new TrackHandle(track);
} else {
+ // remove local strong reference to Client before deleting the Track so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
track.clear();
}
@@ -707,10 +710,10 @@
}
}
-void AudioFlinger::removeClient(pid_t pid)
+// removeClient_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::removeClient_l(pid_t pid)
{
- LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
- Mutex::Autolock _l(mLock);
+ LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
mClients.removeItem(pid);
}
@@ -2078,7 +2081,10 @@
}
}
mCblkMemory.clear(); // and free the shared memory
- mClient.clear();
+ if (mClient != NULL) {
+ Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ mClient.clear();
+ }
}
void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2712,9 +2718,10 @@
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
}
+// Client destructor must be called with AudioFlinger::mLock held
AudioFlinger::Client::~Client()
{
- mAudioFlinger->removeClient(mPid);
+ mAudioFlinger->removeClient_l(mPid);
}
const sp<MemoryDealer>& AudioFlinger::Client::heap() const
@@ -2820,6 +2827,9 @@
format, channelCount, frameCount, flags);
}
if (recordTrack->getCblk() == NULL) {
+ // remove local strong reference to Client before deleting the RecordTrack so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
recordTrack.clear();
lStatus = NO_MEMORY;
goto Exit;
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 7a6641f..3699019 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -189,6 +189,8 @@
virtual ~Client();
const sp<MemoryDealer>& heap() const;
pid_t pid() const { return mPid; }
+ sp<AudioFlinger> audioFlinger() { return mAudioFlinger; }
+
private:
Client(const Client&);
Client& operator = (const Client&);
@@ -641,7 +643,7 @@
friend class PlaybackThread::Track;
- void removeClient(pid_t pid);
+ void removeClient_l(pid_t pid);
// record thread
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index d10076b..6dc3e8b 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -321,6 +321,16 @@
return v * v;
}
+static float SC_fracf(float v)
+{
+ return v - floorf(v);
+}
+
+static float SC_roundf(float v)
+{
+ return floorf(v + 0.4999999999);
+}
+
static float SC_distf2(float x1, float y1, float x2, float y2)
{
float x = x2 - x1;
@@ -1014,8 +1024,12 @@
"float", "(float, float)" },
{ "floorf", (void *)&floorf,
"float", "(float)" },
+ { "fracf", (void *)&SC_fracf,
+ "float", "(float)" },
{ "ceilf", (void *)&ceilf,
"float", "(float)" },
+ { "roundf", (void *)&SC_roundf,
+ "float", "(float)" },
{ "expf", (void *)&expf,
"float", "(float)" },
{ "logf", (void *)&logf,
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index cc913cb..7bdf885 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -297,9 +297,9 @@
return mPageFlipCount;
}
-/*
- * "Flip" the front and back buffers.
- */
+status_t DisplayHardware::compositionComplete() const {
+ return mNativeWindow->compositionComplete();
+}
void DisplayHardware::flip(const Region& dirty) const
{
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 8972d51..b7f1cdb 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -80,6 +80,8 @@
EGLDisplay getEGLDisplay() const { return mDisplay; }
overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
+ status_t compositionComplete() const;
+
Rect bounds() const {
return Rect(mWidth, mHeight);
}
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 7387c85..8dfc2cf 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -176,7 +176,7 @@
// this failed, for instance, because we don't support
// NPOT.
// FIXME: do something!
- LOGD("layer=%p, glEGLImageTargetTexture2DOES(%d) "
+ LOGD("layer=%p, glEGLImageTargetTexture2DOES(%p) "
"failed err=0x%04x",
this, mTextures[index].image, error);
mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
@@ -256,11 +256,17 @@
w = mWidth;
h = mHeight;
buffer = mBuffers[index];
+
+ // destroy() could have been called before we get here, we log it
+ // because it's uncommon, and the code below should handle it
+ LOGW_IF(buffer==0,
+ "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
+ index, w, h);
+
mBuffers[index].clear();
}
-
- if (buffer->getStrongCount() == 1) {
+ if (buffer!=0 && buffer->getStrongCount() == 1) {
err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
} else {
// here we have to reallocate a new buffer because we could have a
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 31b5128c..e87b563 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -495,6 +495,9 @@
// repaint the framebuffer (if needed)
handleRepaint();
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+
// release the clients before we flip ('cause flip might block)
unlockClients();
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 90b5163..fc2e2f6 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -158,6 +158,14 @@
return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
}
+status_t FramebufferNativeWindow::compositionComplete()
+{
+ if (fbDev->compositionComplete) {
+ return fbDev->compositionComplete(fbDev);
+ }
+ return INVALID_OPERATION;
+}
+
int FramebufferNativeWindow::setSwapInterval(
android_native_window_t* window, int interval)
{
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 73b6483..29409ab 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -63,12 +63,12 @@
private String mFilename;
private HashMap<String, String> mAttributes;
- private boolean mHasThumbnail = false;
+ private boolean mHasThumbnail;
// Because the underlying implementation (jhead) uses static variables,
// there can only be one user at a time for the native functions (and
// they cannot keep state in the native code across function calls). We
- // use sLock the serialize the accesses.
+ // use sLock to serialize the accesses.
private static Object sLock = new Object();
/**
@@ -81,7 +81,7 @@
/**
* Returns the value of the specified tag or {@code null} if there
- * is no such tag in the file.
+ * is no such tag in the JPEG file.
*
* @param tag the name of the tag.
*/
@@ -90,6 +90,24 @@
}
/**
+ * Returns the integer value of the specified tag. If there is no such tag
+ * in the JPEG file or the value cannot be parsed as integer, return
+ * @{code defaultValue}.
+ *
+ * @param tag the name of the tag.
+ * @param defaultValue the value to return if the tag is not available.
+ */
+ public int getAttributeInt(String tag, int defaultValue) {
+ String value = mAttributes.get(tag);
+ if (value == null) return defaultValue;
+ try {
+ return Integer.valueOf(value);
+ } catch (NumberFormatException ex) {
+ return defaultValue;
+ }
+ }
+
+ /**
* Set the value of the specified tag.
*
* @param tag the name of the tag.
@@ -109,7 +127,7 @@
* This function also initialize mHasThumbnail to indicate whether the
* file has a thumbnail inside.
*/
- private void loadAttributes() {
+ private void loadAttributes() throws IOException {
// format of string passed from native C code:
// "attrCnt attr1=valueLen value1attr2=value2Len value2..."
// example:
@@ -153,9 +171,9 @@
/**
* Save the tag data into the JPEG file. This is expensive because it involves
* copying all the JPG data from one file to another and deleting the old file
- * and renaming the other. It's best to use {@link #setAttribute(String,String)} to set all
- * attributes to write and make a single call rather than multiple calls for
- * each attribute.
+ * and renaming the other. It's best to use {@link #setAttribute(String,String)}
+ * to set all attributes to write and make a single call rather than multiple
+ * calls for each attribute.
*/
public void saveAttributes() throws IOException {
// format of string passed to native C code:
@@ -195,6 +213,8 @@
/**
* Returns the thumbnail inside the JPEG file, or {@code null} if there is no thumbnail.
+ * The returned data is in JPEG format and can be decoded using
+ * {@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)}
*/
public byte[] getThumbnail() {
synchronized (sLock) {
@@ -203,98 +223,23 @@
}
/**
- * Returns a human-readable string describing the white balance value. Returns empty
- * string if there is no white balance value or it is not recognized.
+ * Stores the latitude and longitude value in a float array. The first element is
+ * the latitude, and the second element is the longitude. Returns false if the
+ * Exif tags are not available.
*/
- public String getWhiteBalanceString() {
- String value = getAttribute(TAG_WHITE_BALANCE);
- if (value == null) return "";
-
- int whitebalance;
- try {
- whitebalance = Integer.parseInt(value);
- } catch (NumberFormatException ex) {
- return "";
- }
-
- switch (whitebalance) {
- case WHITEBALANCE_AUTO:
- return "Auto";
- case WHITEBALANCE_MANUAL:
- return "Manual";
- default:
- return "";
- }
- }
-
- /**
- * Returns a human-readable string describing the orientation value. Returns empty
- * string if there is no orientation value or it it not recognized.
- */
- public String getOrientationString() {
- // TODO: this function needs to be localized.
- String value = getAttribute(TAG_ORIENTATION);
- if (value == null) return "";
-
- int orientation;
- try {
- orientation = Integer.parseInt(value);
- } catch (NumberFormatException ex) {
- return "";
- }
-
- String orientationString;
- switch (orientation) {
- case ORIENTATION_NORMAL:
- orientationString = "Normal";
- break;
- case ORIENTATION_FLIP_HORIZONTAL:
- orientationString = "Flipped horizontal";
- break;
- case ORIENTATION_ROTATE_180:
- orientationString = "Rotated 180 degrees";
- break;
- case ORIENTATION_FLIP_VERTICAL:
- orientationString = "Upside down mirror";
- break;
- case ORIENTATION_TRANSPOSE:
- orientationString = "Transposed";
- break;
- case ORIENTATION_ROTATE_90:
- orientationString = "Rotated 90 degrees";
- break;
- case ORIENTATION_TRANSVERSE:
- orientationString = "Transversed";
- break;
- case ORIENTATION_ROTATE_270:
- orientationString = "Rotated 270 degrees";
- break;
- default:
- orientationString = "Undefined";
- break;
- }
- return orientationString;
- }
-
- /**
- * Returns the latitude and longitude value in a float array. The first element is
- * the latitude, and the second element is the longitude.
- */
- public float[] getLatLong() {
+ public boolean getLatLong(float output[]) {
String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
- float[] latlng = null;
- if (latValue != null && latRef != null
- && lngValue != null && lngRef != null) {
- latlng = new float[2];
- latlng[0] = convertRationalLatLonToFloat(latValue, latRef);
- latlng[1] = convertRationalLatLonToFloat(lngValue, lngRef);
+ if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
+ output[0] = convertRationalLatLonToFloat(latValue, latRef);
+ output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
+ return true;
+ } else {
+ return false;
}
-
- return latlng;
}
private static SimpleDateFormat sFormatter =
@@ -303,6 +248,7 @@
/**
* Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
* Returns -1 if the date time information if not available.
+ * @hide
*/
public long getDateTime() {
String dateTimeString = mAttributes.get(TAG_DATETIME);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index d9127e7..37a3bd5 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -726,8 +726,8 @@
// exif is null
}
if (exif != null) {
- float[] latlng = exif.getLatLong();
- if (latlng != null) {
+ float[] latlng = new float[2];
+ if (exif.getLatLong(latlng)) {
values.put(Images.Media.LATITUDE, latlng[0]);
values.put(Images.Media.LONGITUDE, latlng[1]);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index ef211b3..9b7ff6c 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -490,17 +490,17 @@
//Streaming test files
public static final String STREAM_H264_480_360_1411k =
- "http://sridharg.googlejunta.com/yslau/stress_media/h264_regular.mp4";
+ "http://75.17.48.204:10088/yslau/stress_media/h264_regular.mp4";
public static final String STREAM_WMV =
- "http://sridharg.googlejunta.com/yslau/stress_media/bugs.wmv";
+ "http://75.17.48.204:10088/yslau/stress_media/bugs.wmv";
public static final String STREAM_H263_176x144_325k =
- "http://sridharg.googlejunta.com/yslau/stress_media/h263_regular.3gp";
+ "http://75.17.48.204:10088/yslau/stress_media/h263_regular.3gp";
public static final String STREAM_H264_352x288_1536k =
- "http://sridharg.googlejunta.com/yslau/stress_media/h264_highBitRate.mp4";
+ "http://75.17.48.204:10088/yslau/stress_media/h264_highBitRate.mp4";
public static final String STREAM_MP3=
- "http://sridharg.googlejunta.com/yslau/stress_media/mp3_regular.mp3";
+ "http://75.17.48.204:10088/yslau/stress_media/mp3_regular.mp3";
public static final String STREAM_MPEG4_QVGA_128k =
- "http://sridharg.googlejunta.com/yslau/stress_media/mpeg4_qvga_24fps.3gp";
+ "http://75.17.48.204:10088/yslau/stress_media/mpeg4_qvga_24fps.3gp";
public static final int STREAM_H264_480_360_1411k_DURATION = 46000;
public static final int VIDEO_H263_AAC_DURATION = 501000;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index 39846c6..4a4ad6f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -214,8 +214,10 @@
Log.v(TAG, "before getduration");
mOutputDuration = mediaPlayer.getDuration();
Log.v(TAG, "get video dimension");
- mOutputVideoHeight = CodecTest.videoHeight(outputFilePath);
- mOutputVideoWidth = CodecTest.videoWidth(outputFilePath);
+ mOutputVideoHeight = mediaPlayer.getVideoHeight();
+ mOutputVideoWidth = mediaPlayer.getVideoWidth();
+ //mOutputVideoHeight = CodecTest.videoHeight(outputFilePath);
+ //mOutputVideoWidth = CodecTest.videoWidth(outputFilePath);
mediaPlayer.release();
} catch (Exception e) {
Log.v(TAG, e.toString());
@@ -321,10 +323,10 @@
recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263,
MediaRecorder.OutputFormat.THREE_GPP,
MediaNames.RECORDED_PORTRAIT_H263, true);
- videoRecordedResult =
- validateVideo(MediaNames.RECORDED_PORTRAIT_H263, 352, 288);
mCamera.lock();
mCamera.release();
+ videoRecordedResult =
+ validateVideo(MediaNames.RECORDED_PORTRAIT_H263, 352, 288);
} catch (Exception e) {
Log.v(TAG, e.toString());
}
@@ -453,4 +455,3 @@
}
}
}
-
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 408a4d2..63845e9 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -809,6 +809,8 @@
intent.putExtra(ConnectivityManager.
EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
+ true);
newNet.reconnect();
}
} else {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 45e0ceb..323a11f 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -6376,7 +6376,10 @@
if (mBackupSettingsFilename.exists()) {
mBackupSettingsFilename.delete();
}
- mSettingsFilename.renameTo(mBackupSettingsFilename);
+ if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
+ Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
+ return;
+ }
}
mPastSignatures.clear();
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index d53f002..0cd5949 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1384,12 +1384,18 @@
(mLowerWallpaperTarget == null && foundW.mAppToken != null)
? foundW.mAppToken.animLayerAdjustment : 0;
+ final int maxLayer = mPolicy.getMaxWallpaperLayer()
+ * TYPE_LAYER_MULTIPLIER
+ + TYPE_LAYER_OFFSET;
+
// Now w is the window we are supposed to be behind... but we
// need to be sure to also be behind any of its attached windows,
- // AND any starting window associated with it.
+ // AND any starting window associated with it, AND below the
+ // maximum layer the policy allows for wallpapers.
while (foundI > 0) {
WindowState wb = (WindowState)localmWindows.get(foundI-1);
- if (wb.mAttachedWindow != foundW &&
+ if (wb.mBaseLayer < maxLayer &&
+ wb.mAttachedWindow != foundW &&
(wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
wb.mToken != foundW.mToken)) {
// This window is not related to the previous one in any
@@ -2266,6 +2272,12 @@
// Currently in a hide animation... turn this into
// an exit.
win.mExiting = true;
+ } else if (win == mWallpaperTarget) {
+ // If the wallpaper is currently behind this
+ // window, we need to change both of them inside
+ // of a transaction to avoid artifacts.
+ win.mExiting = true;
+ win.mAnimating = true;
} else {
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
@@ -3158,6 +3170,10 @@
return;
}
if (ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsFloating, false)) {
+ return;
+ }
+ if (ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
return;
}
@@ -7087,8 +7103,8 @@
mAppToken.firstWindowDrawn = true;
if (mAppToken.startingData != null) {
- if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
- + mToken
+ if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Log.v(TAG,
+ "Finish starting " + mToken
+ ": first real window is shown, no animation");
// If this initial window is animating, stop it -- we
// will do an animation to reveal it from behind the
@@ -7305,13 +7321,13 @@
// Compute the desired transformation.
tmpMatrix.setTranslate(frame.left, frame.top);
if (selfTransformation) {
- tmpMatrix.preConcat(mTransformation.getMatrix());
+ tmpMatrix.postConcat(mTransformation.getMatrix());
}
if (attachedTransformation != null) {
- tmpMatrix.preConcat(attachedTransformation.getMatrix());
+ tmpMatrix.postConcat(attachedTransformation.getMatrix());
}
if (appTransformation != null) {
- tmpMatrix.preConcat(appTransformation.getMatrix());
+ tmpMatrix.postConcat(appTransformation.getMatrix());
}
// "convert" it into SurfaceFlinger's format
@@ -8928,11 +8944,14 @@
wallpaperMayChange = true;
}
}
+ boolean wasAnimating = w.mAnimating;
if (w.stepAnimationLocked(currentTime, dw, dh)) {
animating = true;
//w.dump(" ");
}
-
+ if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
+ wallpaperMayChange = true;
+ }
mPolicy.animatingWindowLw(w, attrs);
}
@@ -9269,6 +9288,7 @@
boolean covered = false;
boolean syswin = false;
boolean backgroundFillerShown = false;
+ boolean forceHiding = false;
final int N = mWindows.size();
@@ -9401,7 +9421,10 @@
}
}
- if (w.mAttachedHidden) {
+ if ((forceHiding
+ && attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
+ && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER)
+ || w.mAttachedHidden) {
if (!w.mLastHidden) {
//dump();
w.mLastHidden = true;
@@ -9515,6 +9538,9 @@
}
if (displayed) {
+ if (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
+ forceHiding = true;
+ }
if (!covered) {
if (attrs.width == LayoutParams.FILL_PARENT
&& attrs.height == LayoutParams.FILL_PARENT) {
@@ -9597,7 +9623,7 @@
}
backgroundFillerShown = true;
mBackgroundFillerShown = true;
- } else if (canBeSeen && !obscured &&
+ } else if (canBeSeen && !obscured && !forceHiding &&
(attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
if (localLOGV) Log.v(TAG, "Win " + w
+ ": blurring=" + blurring
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1597270..4db5239 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -33,7 +33,6 @@
import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IActivityController;
-import android.app.IActivityManager;
import android.app.IActivityWatcher;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
@@ -53,6 +52,7 @@
import android.content.IntentFilter;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
+import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
@@ -3613,8 +3613,8 @@
}
}
- public int startActivityPendingIntent(IApplicationThread caller,
- PendingIntent intent, Intent fillInIntent, String resolvedType,
+ public int startActivityIntentSender(IApplicationThread caller,
+ IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues) {
// Refuse possible leaked file descriptors
@@ -3628,8 +3628,15 @@
}
PendingIntentRecord pir = (PendingIntentRecord)sender;
- if (pir.key.type != IActivityManager.INTENT_SENDER_ACTIVITY) {
- return START_NOT_ACTIVITY;
+
+ synchronized (this) {
+ // If this is coming from the currently resumed activity, it is
+ // effectively saying that app switches are allowed at this point.
+ if (mResumedActivity != null
+ && mResumedActivity.info.applicationInfo.uid ==
+ Binder.getCallingUid()) {
+ mAppSwitchesAllowedTime = 0;
+ }
}
return pir.sendInner(0, fillInIntent, resolvedType,
@@ -8424,6 +8431,13 @@
}
private ComponentName getErrorReportReceiver(ProcessRecord app) {
+ // check if error reporting is enabled in Gservices
+ int enabled = Settings.Gservices.getInt(mContext.getContentResolver(),
+ Settings.Gservices.SEND_ACTION_APP_ERROR, 0);
+ if (enabled == 0) {
+ return null;
+ }
+
IPackageManager pm = ActivityThread.getPackageManager();
try {
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index d994362..a753d05 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -198,6 +198,7 @@
} else {
resolvedType = key.requestResolvedType;
}
+ flagsMask &= ~Intent.IMMUTABLE_FLAGS;
flagsValues &= flagsMask;
finalIntent.setFlags((finalIntent.getFlags()&~flagsMask) | flagsValues);
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index b8778f8..676fba7 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -20,8 +20,7 @@
import android.telephony.CellLocation;
/**
- * Represents the cell location on a GSM phone.
- * @hide
+ * Represents the cell location on a CDMA phone.
*/
public class CdmaCellLocation extends CellLocation {
private int mBaseStationId = -1;
@@ -31,7 +30,8 @@
private int mNetworkId = -1;
/**
- * Empty constructor. Initializes the LAC and CID to -1.
+ * Empty constructor.
+ * Initializes the BID, SID, NID and base station latitude and longitude to -1.
*/
public CdmaCellLocation() {
this.mBaseStationId = -1;
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 8d2785a..5581a24 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -127,7 +127,7 @@
/** Retry configuration for secondary networks: 4 tries in 20 sec */
protected static final String SECONDARY_DATA_RETRY_CONFIG =
- "max_retries=3; 5000, 5000, 5000";
+ "max_retries=3, 5000, 5000, 5000";
/** Slow poll when attempting connection recovery. */
protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 0c94e6a..2f4d238 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -492,6 +492,8 @@
newParent = parentFromDCState(dc.state);
+ if (Phone.DEBUG_PHONE) log("parent= " +parent +", newParent= " + newParent);
+
if (!equalsHandlesNulls(address, dc.number)) {
if (Phone.DEBUG_PHONE) log("update: phone # changed!");
address = dc.number;
@@ -509,7 +511,7 @@
cnapName = dc.name;
}
- log("--dssds----"+cnapName);
+ if (Phone.DEBUG_PHONE) log("--dssds----"+cnapName);
cnapNamePresentation = dc.namePresentation;
numberPresentation = dc.numberPresentation;
@@ -529,9 +531,7 @@
/** Some state-transition events */
if (Phone.DEBUG_PHONE) log(
- "update: parent=" + parent +
- ", hasNewParent=" + (newParent != parent) +
- ", wasConnectingInOrOut=" + wasConnectingInOrOut +
+ "Update, wasConnectingInOrOut=" + wasConnectingInOrOut +
", wasHolding=" + wasHolding +
", isConnectingInOrOut=" + isConnectingInOrOut() +
", changed=" + changed);
@@ -860,10 +860,13 @@
// Append the PW char
ret = (isPause(c)) ? PhoneNumberUtils.PAUSE : PhoneNumberUtils.WAIT;
- // if there is a PAUSE in at the beginning of PW character sequences, and this
- // PW character sequences has more than 2 PAUSE and WAIT Characters,skip PAUSE,
- // append WAIT.
- if (isPause(c) && (nextNonPwCharIndex > (currPwIndex + 2))) {
+ // If the nextNonPwCharIndex is greater than currPwIndex + 1,
+ // it means the PW sequence contains not only P characters.
+ // Since for the sequence that only contains P character,
+ // the P character is handled one by one, the nextNonPwCharIndex
+ // equals to currPwIndex + 1.
+ // In this case, skip P, append W.
+ if (nextNonPwCharIndex > (currPwIndex + 1)) {
ret = PhoneNumberUtils.WAIT;
}
return ret;
@@ -882,6 +885,11 @@
* and if there is any WAIT in PAUSE/WAIT sequence, treat them like WAIT.
*/
public static String formatDialString(String phoneNumber) {
+ /**
+ * TODO(cleanup): This function should move to PhoneNumberUtils, and
+ * tests should be added.
+ */
+
if (phoneNumber == null) {
return null;
}
@@ -901,9 +909,9 @@
char pC = findPOrWCharToAppend(phoneNumber, currIndex, nextIndex);
ret.append(pC);
// If PW char sequence has more than 2 PW characters,
- // skip to the last character since the sequence already be
+ // skip to the last PW character since the sequence already be
// converted to WAIT character
- if (nextIndex > (currIndex + 2)) {
+ if (nextIndex > (currIndex + 1)) {
currIndex = nextIndex - 1;
}
} else if (nextIndex == length) {
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index 9fb1e61..5368526 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
+import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
@@ -228,6 +229,13 @@
}
@Override
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
throw new UnsupportedOperationException();
}
diff --git a/tests/AndroidTests/Android.mk b/tests/AndroidTests/Android.mk
index f5e49d7..ced796a 100644
--- a/tests/AndroidTests/Android.mk
+++ b/tests/AndroidTests/Android.mk
@@ -8,7 +8,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client
# Resource unit tests use a private locale
-LOCAL_AAPT_FLAGS = -c xx_YY -c cs
+LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c 160dpi -c 32dpi -c 240dpi
LOCAL_SRC_FILES := \
$(call all-subdir-java-files) \
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index f48c8db..4e7e925 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
@@ -1124,6 +1125,13 @@
}
@Override
+ public void startIntentSender(IntentSender intent,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
+ throws IntentSender.SendIntentException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public boolean startInstrumentation(ComponentName arg0, String arg1,
Bundle arg2) {
// TODO Auto-generated method stub