Merge change 24814 into eclair
* changes:
Enable log message for tracking issue #2092299.
diff --git a/api/current.xml b/api/current.xml
index f2fb7c0..f8cf61f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6825,7 +6825,7 @@
value="16843221"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 3c2dc2b..f425f6b 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1101,8 +1101,7 @@
}
CameraParameters p(params);
- mHardware->setParameters(p);
- return NO_ERROR;
+ return mHardware->setParameters(p);
}
// get preview/capture parameters - key/value pairs
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e..8804636 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -4,7 +4,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- netkeystore.c keymgmt.c
+ netkeystore.c netkeystore_main.c keymgmt.c
LOCAL_C_INCLUDES := \
$(call include-path-for, system-core)/cutils \
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 69e0380..b5ace86 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -385,7 +385,10 @@
return -1;
}
while ((de = readdir(d))) {
- if (unlink(de->d_name) != 0) ret = -1;
+ char *dirname = de->d_name;
+ if (strcmp(".", dirname) == 0) continue;
+ if (strcmp("..", dirname) == 0) continue;
+ if (unlink(dirname) != 0) ret = -1;
}
closedir(d);
state = UNINITIALIZED;
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 82a92c3..83c7871 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -14,8 +14,6 @@
** limitations under the License.
*/
-#define LOG_TAG "keystore"
-
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -247,7 +245,7 @@
reply->retcode = reset_keystore();
}
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
{
uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
@@ -309,7 +307,7 @@
return 0;
}
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
{
uint32_t i, len = 0;
uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
@@ -335,30 +333,30 @@
}
}
-static int shell_command(const int argc, const char **argv)
+int shell_command(const int argc, const char **argv)
{
int fd, i;
LPC_MARSHAL cmd;
- if (parse_cmd(argc, argv , &cmd)) {
+ if (parse_cmd(argc, argv, &cmd)) {
fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
+ return -1;
}
fd = socket_local_client(SOCKET_PATH,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (fd == -1) {
fprintf(stderr, "Keystore service is not up and running.\n");
- exit(1);
+ return -1;
}
if (write_marshal(fd, &cmd)) {
fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
+ return -1;
}
if (read_marshal(fd, &cmd)) {
fprintf(stderr, "Failed to read the result.\n");
- exit(1);
+ return -1;
}
cmd.data[cmd.len] = 0;
fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
@@ -367,30 +365,26 @@
return 0;
}
-int main(const int argc, const char *argv[])
+int server_main(const int argc, const char *argv[])
{
struct sockaddr addr;
socklen_t alen;
int lsocket, s;
LPC_MARSHAL cmd, reply;
- if (argc > 1) {
- return shell_command(argc - 1, argv + 1);
- }
-
if (init_keystore(KEYSTORE_DIR)) {
LOGE("Can not initialize the keystore, the directory exist?\n");
- exit(1);
+ return -1;
}
lsocket = android_get_control_socket(SOCKET_PATH);
if (lsocket < 0) {
LOGE("Failed to get socket from environment: %s\n", strerror(errno));
- exit(1);
+ return -1;
}
if (listen(lsocket, 5)) {
LOGE("Listen on socket failed: %s\n", strerror(errno));
- exit(1);
+ return -1;
}
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
memset(&reply, 0, sizeof(LPC_MARSHAL));
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
index d80ddae..e2ffd8b 100644
--- a/cmds/keystore/netkeystore.h
+++ b/cmds/keystore/netkeystore.h
@@ -25,6 +25,10 @@
#include "common.h"
+// for testing
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd);
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
+
static inline int readx(int s, void *_buf, int count)
{
char *buf = _buf;
diff --git a/cmds/keystore/netkeystore_main.c b/cmds/keystore/netkeystore_main.c
new file mode 100644
index 0000000..606e67a
--- /dev/null
+++ b/cmds/keystore/netkeystore_main.c
@@ -0,0 +1,29 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "keystore"
+
+int shell_command(const int argc, const char **argv);
+int server_main(const int argc, const char *argv[]);
+
+int main(const int argc, const char *argv[])
+{
+ if (argc > 1) {
+ return shell_command(argc - 1, argv + 1);
+ } else {
+ return server_main(argc, argv);
+ }
+}
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
index 33541cc..e0a776a 100644
--- a/cmds/keystore/tests/Android.mk
+++ b/cmds/keystore/tests/Android.mk
@@ -16,7 +16,7 @@
ifdef KEYSTORE_TESTS
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
+LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c ../netkeystore.c
LOCAL_SHARED_LIBRARIES := libcutils libssl
LOCAL_MODULE:= netkeystore_test
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
index 00390e0..ce79503 100644
--- a/cmds/keystore/tests/netkeystore_test.c
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -29,9 +29,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <cutils/log.h>
#include "common.h"
#include "keymgmt.h"
+#include "netkeystore.h"
+
+#define LOG_TAG "keystore_test"
typedef int FUNC_PTR();
typedef struct {
@@ -61,7 +65,9 @@
void teardown()
{
- reset_keystore();
+ if (reset_keystore() != 0) {
+ fprintf(stderr, "Can not reset the test directory %s\n", TEST_DIR);
+ }
rmdir(TEST_DIR);
}
@@ -74,7 +80,7 @@
FUNC_BODY(reset_keystore)
{
- chdir("/procx");
+ int ret = chdir("/proc");
if (reset_keystore() == 0) return -1;
chdir(TEST_DIR);
return EXIT_SUCCESS;
@@ -87,7 +93,8 @@
if (get_state() != UNLOCKED) return -1;
lock();
if (get_state() != LOCKED) return -1;
- reset_keystore();
+
+ if (reset_keystore() != 0) return -1;
if (get_state() != UNINITIALIZED) return -1;
return EXIT_SUCCESS;
}
@@ -218,6 +225,37 @@
return EXIT_SUCCESS;
}
+static int execute_cmd(int argc, const char *argv[], LPC_MARSHAL *cmd,
+ LPC_MARSHAL *reply)
+{
+ memset(cmd, 0, sizeof(LPC_MARSHAL));
+ memset(reply, 0, sizeof(LPC_MARSHAL));
+ if (parse_cmd(argc, argv, cmd)) return -1;
+ execute(cmd, reply);
+ return (reply->retcode ? -1 : 0);
+}
+
+FUNC_BODY(client_passwd)
+{
+ LPC_MARSHAL cmd, reply;
+ const char *set_passwd_cmds[2] = {"passwd", TEST_PASSWD};
+ const char *change_passwd_cmds[3] = {"passwd", TEST_PASSWD, TEST_NPASSWD};
+
+ if (execute_cmd(2, set_passwd_cmds, &cmd, &reply)) return -1;
+
+ lock();
+ if (unlock("55555555") == 0) return -1;
+ if (unlock(TEST_PASSWD) != 0) return -1;
+
+ if (execute_cmd(3, change_passwd_cmds, &cmd, &reply)) return -1;
+
+ lock();
+ if (unlock(TEST_PASSWD) == 0) return -1;
+ if (unlock(TEST_NPASSWD) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
TESTFUNC all_tests[] = {
FUNC_NAME(init_keystore),
FUNC_NAME(reset_keystore),
@@ -229,11 +267,13 @@
FUNC_NAME(get_key),
FUNC_NAME(remove_key),
FUNC_NAME(list_keys),
+ FUNC_NAME(client_passwd),
};
int main(int argc, char **argv) {
int i, ret;
for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
+ LOGD("run %s...\n", all_tests[i].name);
setup();
if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2877aec..8142d1a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4246,12 +4246,9 @@
}
thread.detach();
- String name;
- if (thread.mInitialApplication != null) {
- name = thread.mInitialApplication.getPackageName();
- } else {
- name = "<unknown>";
- }
+ String name = (thread.mInitialApplication != null)
+ ? thread.mInitialApplication.getPackageName()
+ : "<unknown>";
Log.i(TAG, "Main thread of " + name + " is now exiting");
}
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 6d79aee..b8c3aa3 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -24,6 +24,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.os.PerformanceCollector;
import android.os.RemoteException;
import android.os.Debug;
import android.os.IBinder;
@@ -83,10 +84,8 @@
private List<ActivityWaiter> mWaitingActivities;
private List<ActivityMonitor> mActivityMonitors;
private IInstrumentationWatcher mWatcher;
- private long mPreCpuTime;
- private long mStart;
private boolean mAutomaticPerformanceSnapshots = false;
- private Bundle mPrePerfMetrics = new Bundle();
+ private PerformanceCollector mPerformanceCollector;
private Bundle mPerfMetrics = new Bundle();
public Instrumentation() {
@@ -191,96 +190,21 @@
public void setAutomaticPerformanceSnapshots() {
mAutomaticPerformanceSnapshots = true;
+ mPerformanceCollector = new PerformanceCollector();
}
public void startPerformanceSnapshot() {
- mStart = 0;
if (!isProfiling()) {
- // Add initial binder counts
- Bundle binderCounts = getBinderCounts();
- for (String key: binderCounts.keySet()) {
- addPerfMetricLong("pre_" + key, binderCounts.getLong(key));
- }
-
- // Force a GC and zero out the performance counters. Do this
- // before reading initial CPU/wall-clock times so we don't include
- // the cost of this setup in our final metrics.
- startAllocCounting();
-
- // Record CPU time up to this point, and start timing. Note: this
- // must happen at the end of this method, otherwise the timing will
- // include noise.
- mStart = SystemClock.uptimeMillis();
- mPreCpuTime = Process.getElapsedCpuTime();
+ mPerformanceCollector.beginSnapshot(null);
}
}
public void endPerformanceSnapshot() {
if (!isProfiling()) {
- // Stop the timing. This must be done first before any other counting is stopped.
- long cpuTime = Process.getElapsedCpuTime();
- long duration = SystemClock.uptimeMillis();
-
- stopAllocCounting();
-
- long nativeMax = Debug.getNativeHeapSize() / 1024;
- long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
- long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
-
- Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
- Debug.getMemoryInfo(memInfo);
-
- Runtime runtime = Runtime.getRuntime();
-
- long dalvikMax = runtime.totalMemory() / 1024;
- long dalvikFree = runtime.freeMemory() / 1024;
- long dalvikAllocated = dalvikMax - dalvikFree;
-
- // Add final binder counts
- Bundle binderCounts = getBinderCounts();
- for (String key: binderCounts.keySet()) {
- addPerfMetricLong(key, binderCounts.getLong(key));
- }
-
- // Add alloc counts
- Bundle allocCounts = getAllocCounts();
- for (String key: allocCounts.keySet()) {
- addPerfMetricLong(key, allocCounts.getLong(key));
- }
-
- addPerfMetricLong("execution_time", duration - mStart);
- addPerfMetricLong("pre_cpu_time", mPreCpuTime);
- addPerfMetricLong("cpu_time", cpuTime - mPreCpuTime);
-
- addPerfMetricLong("native_size", nativeMax);
- addPerfMetricLong("native_allocated", nativeAllocated);
- addPerfMetricLong("native_free", nativeFree);
- addPerfMetricInt("native_pss", memInfo.nativePss);
- addPerfMetricInt("native_private_dirty", memInfo.nativePrivateDirty);
- addPerfMetricInt("native_shared_dirty", memInfo.nativeSharedDirty);
-
- addPerfMetricLong("java_size", dalvikMax);
- addPerfMetricLong("java_allocated", dalvikAllocated);
- addPerfMetricLong("java_free", dalvikFree);
- addPerfMetricInt("java_pss", memInfo.dalvikPss);
- addPerfMetricInt("java_private_dirty", memInfo.dalvikPrivateDirty);
- addPerfMetricInt("java_shared_dirty", memInfo.dalvikSharedDirty);
-
- addPerfMetricInt("other_pss", memInfo.otherPss);
- addPerfMetricInt("other_private_dirty", memInfo.otherPrivateDirty);
- addPerfMetricInt("other_shared_dirty", memInfo.otherSharedDirty);
-
+ mPerfMetrics = mPerformanceCollector.endSnapshot();
}
}
- private void addPerfMetricLong(String key, long value) {
- mPerfMetrics.putLong("performance." + key, value);
- }
-
- private void addPerfMetricInt(String key, int value) {
- mPerfMetrics.putInt("performance." + key, value);
- }
-
/**
* Called when the instrumented application is stopping, after all of the
* normal application cleanup has occurred.
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index f474f06..75e4669 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1137,6 +1137,11 @@
String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
Intent intent = createIntent(action, null, null, query, null,
actionKey, actionMsg);
+ // Allow GlobalSearch to log and create shortcut for searches launched by
+ // the search button, enter key or an action key.
+ if (mGlobalSearchMode) {
+ mSuggestionsAdapter.reportSearch(query);
+ }
launchIntent(intent);
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 267d86a..3a14f6f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1350,6 +1350,14 @@
* When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
*/
public final static int THRESH_HIT = 3;
+
+ /**
+ * When a search is started without using a suggestion.
+ */
+ public final static int SEARCH = 4;
+ public final static String SEARCH_SEND_MAX_DISPLAY_POS
+ = "DialogCursorProtocol.SEARCH.sendDisplayPosition";
+ public final static String SEARCH_SEND_QUERY = "DialogCursorProtocol.SEARCH.query";
}
/**
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 90f8c50..8730288 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -290,7 +290,7 @@
*/
void callCursorOnClick(Cursor cursor, int position) {
if (!mGlobalSearchMode) return;
- final Bundle request = new Bundle(1);
+ final Bundle request = new Bundle(3);
request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
@@ -301,6 +301,23 @@
}
/**
+ * Tell the cursor that a search was started without using a suggestion.
+ *
+ * @param query The search query.
+ */
+ void reportSearch(String query) {
+ if (!mGlobalSearchMode) return;
+ Cursor cursor = getCursor();
+ if (cursor == null) return;
+ final Bundle request = new Bundle(3);
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.SEARCH);
+ request.putString(DialogCursorProtocol.SEARCH_SEND_QUERY, query);
+ request.putInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+ // the response is always empty
+ cursor.respond(request);
+ }
+
+ /**
* Tags the view with cached child view look-ups.
*/
@Override
diff --git a/core/java/android/os/PerformanceCollector.java b/core/java/android/os/PerformanceCollector.java
new file mode 100644
index 0000000..4ca1f32
--- /dev/null
+++ b/core/java/android/os/PerformanceCollector.java
@@ -0,0 +1,524 @@
+/*
+ * 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.os;
+
+
+import java.util.ArrayList;
+
+/**
+ * Collects performance data between two function calls in Bundle objects and
+ * outputs the results using writer of type {@link PerformanceResultsWriter}.
+ * <p>
+ * {@link #beginSnapshot(String)} and {@link #endSnapshot()} functions collect
+ * memory usage information and measure runtime between calls to begin and end.
+ * These functions logically wrap around an entire test, and should be called
+ * with name of test as the label, e.g. EmailPerformanceTest.
+ * <p>
+ * {@link #startTiming(String)} and {@link #stopTiming(String)} functions
+ * measure runtime between calls to start and stop. These functions logically
+ * wrap around a single test case or a small block of code, and should be called
+ * with the name of test case as the label, e.g. testSimpleSendMailSequence.
+ * <p>
+ * {@link #addIteration(String)} inserts intermediate measurement point which
+ * can be labeled with a String, e.g. Launch email app, compose, send, etc.
+ * <p>
+ * Snapshot and timing functions do not interfere with each other, and thus can
+ * be called in any order. The intended structure is to wrap begin/endSnapshot
+ * around calls to start/stopTiming, for example:
+ * <p>
+ * <code>beginSnapshot("EmailPerformanceTest");
+ * startTiming("testSimpleSendSequence");
+ * addIteration("Launch email app");
+ * addIteration("Compose");
+ * stopTiming("Send");
+ * startTiming("testComplexSendSequence");
+ * stopTiming("");
+ * startTiming("testAddLabel");
+ * stopTiming("");
+ * endSnapshot();</code>
+ * <p>
+ * Structure of results output is up to implementor of
+ * {@link PerformanceResultsWriter }.
+ *
+ * {@hide} Pending approval for public API.
+ */
+public class PerformanceCollector {
+
+ /**
+ * Interface for reporting performance data.
+ */
+ public interface PerformanceResultsWriter {
+
+ /**
+ * Callback invoked as first action in
+ * PerformanceCollector#beginSnapshot(String) for reporting the start of
+ * a performance snapshot.
+ *
+ * @param label description of code block between beginSnapshot and
+ * PerformanceCollector#endSnapshot()
+ * @see PerformanceCollector#beginSnapshot(String)
+ */
+ public void writeBeginSnapshot(String label);
+
+ /**
+ * Callback invoked as last action in PerformanceCollector#endSnapshot()
+ * for reporting performance data collected in the snapshot.
+ *
+ * @param results memory and runtime metrics stored as key/value pairs,
+ * in the same structure as returned by
+ * PerformanceCollector#endSnapshot()
+ * @see PerformanceCollector#endSnapshot()
+ */
+ public void writeEndSnapshot(Bundle results);
+
+ /**
+ * Callback invoked as first action in
+ * PerformanceCollector#startTiming(String) for reporting the start of
+ * a timing measurement.
+ *
+ * @param label description of code block between startTiming and
+ * PerformanceCollector#stopTiming(String)
+ * @see PerformanceCollector#startTiming(String)
+ */
+ public void writeStartTiming(String label);
+
+ /**
+ * Callback invoked as last action in
+ * {@link PerformanceCollector#stopTiming(String)} for reporting the
+ * sequence of timings measured.
+ *
+ * @param results runtime metrics of code block between calls to
+ * startTiming and stopTiming, in the same structure as
+ * returned by PerformanceCollector#stopTiming(String)
+ * @see PerformanceCollector#stopTiming(String)
+ */
+ public void writeStopTiming(Bundle results);
+ }
+
+ /**
+ * In a results Bundle, this key references a List of iteration Bundles.
+ */
+ public static final String METRIC_KEY_ITERATIONS = "iterations";
+ /**
+ * In an iteration Bundle, this key describes the iteration.
+ */
+ public static final String METRIC_KEY_LABEL = "label";
+ /**
+ * In a results Bundle, this key reports the cpu time of the code block
+ * under measurement.
+ */
+ public static final String METRIC_KEY_CPU_TIME = "cpu_time";
+ /**
+ * In a results Bundle, this key reports the execution time of the code
+ * block under measurement.
+ */
+ public static final String METRIC_KEY_EXECUTION_TIME = "execution_time";
+ /**
+ * In a snapshot Bundle, this key reports the number of received
+ * transactions from the binder driver before collection started.
+ */
+ public static final String METRIC_KEY_PRE_RECEIVED_TRANSACTIONS = "pre_received_transactions";
+ /**
+ * In a snapshot Bundle, this key reports the number of transactions sent by
+ * the running program before collection started.
+ */
+ public static final String METRIC_KEY_PRE_SENT_TRANSACTIONS = "pre_sent_transactions";
+ /**
+ * In a snapshot Bundle, this key reports the number of received
+ * transactions from the binder driver.
+ */
+ public static final String METRIC_KEY_RECEIVED_TRANSACTIONS = "received_transactions";
+ /**
+ * In a snapshot Bundle, this key reports the number of transactions sent by
+ * the running program.
+ */
+ public static final String METRIC_KEY_SENT_TRANSACTIONS = "sent_transactions";
+ /**
+ * In a snapshot Bundle, this key reports the number of garbage collection
+ * invocations.
+ */
+ public static final String METRIC_KEY_GC_INVOCATION_COUNT = "gc_invocation_count";
+ /**
+ * In a snapshot Bundle, this key reports the amount of allocated memory
+ * used by the running program.
+ */
+ public static final String METRIC_KEY_JAVA_ALLOCATED = "java_allocated";
+ /**
+ * In a snapshot Bundle, this key reports the amount of free memory
+ * available to the running program.
+ */
+ public static final String METRIC_KEY_JAVA_FREE = "java_free";
+ /**
+ * In a snapshot Bundle, this key reports the number of private dirty pages
+ * used by dalvik.
+ */
+ public static final String METRIC_KEY_JAVA_PRIVATE_DIRTY = "java_private_dirty";
+ /**
+ * In a snapshot Bundle, this key reports the proportional set size for
+ * dalvik.
+ */
+ public static final String METRIC_KEY_JAVA_PSS = "java_pss";
+ /**
+ * In a snapshot Bundle, this key reports the number of shared dirty pages
+ * used by dalvik.
+ */
+ public static final String METRIC_KEY_JAVA_SHARED_DIRTY = "java_shared_dirty";
+ /**
+ * In a snapshot Bundle, this key reports the total amount of memory
+ * available to the running program.
+ */
+ public static final String METRIC_KEY_JAVA_SIZE = "java_size";
+ /**
+ * In a snapshot Bundle, this key reports the amount of allocated memory in
+ * the native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_ALLOCATED = "native_allocated";
+ /**
+ * In a snapshot Bundle, this key reports the amount of free memory in the
+ * native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_FREE = "native_free";
+ /**
+ * In a snapshot Bundle, this key reports the number of private dirty pages
+ * used by the native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_PRIVATE_DIRTY = "native_private_dirty";
+ /**
+ * In a snapshot Bundle, this key reports the proportional set size for the
+ * native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_PSS = "native_pss";
+ /**
+ * In a snapshot Bundle, this key reports the number of shared dirty pages
+ * used by the native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_SHARED_DIRTY = "native_shared_dirty";
+ /**
+ * In a snapshot Bundle, this key reports the size of the native heap.
+ */
+ public static final String METRIC_KEY_NATIVE_SIZE = "native_size";
+ /**
+ * In a snapshot Bundle, this key reports the number of objects allocated
+ * globally.
+ */
+ public static final String METRIC_KEY_GLOBAL_ALLOC_COUNT = "global_alloc_count";
+ /**
+ * In a snapshot Bundle, this key reports the size of all objects allocated
+ * globally.
+ */
+ public static final String METRIC_KEY_GLOBAL_ALLOC_SIZE = "global_alloc_size";
+ /**
+ * In a snapshot Bundle, this key reports the number of objects freed
+ * globally.
+ */
+ public static final String METRIC_KEY_GLOBAL_FREED_COUNT = "global_freed_count";
+ /**
+ * In a snapshot Bundle, this key reports the size of all objects freed
+ * globally.
+ */
+ public static final String METRIC_KEY_GLOBAL_FREED_SIZE = "global_freed_size";
+ /**
+ * In a snapshot Bundle, this key reports the number of private dirty pages
+ * used by everything else.
+ */
+ public static final String METRIC_KEY_OTHER_PRIVATE_DIRTY = "other_private_dirty";
+ /**
+ * In a snapshot Bundle, this key reports the proportional set size for
+ * everything else.
+ */
+ public static final String METRIC_KEY_OTHER_PSS = "other_pss";
+ /**
+ * In a snapshot Bundle, this key reports the number of shared dirty pages
+ * used by everything else.
+ */
+ public static final String METRIC_KEY_OTHER_SHARED_DIRTY = "other_shared_dirty";
+
+ private PerformanceResultsWriter mPerfWriter;
+ private Bundle mPerfSnapshot;
+ private Bundle mPerfMeasurement;
+ private long mSnapshotCpuTime;
+ private long mSnapshotExecTime;
+ private long mCpuTime;
+ private long mExecTime;
+
+ public PerformanceCollector() {
+ }
+
+ public PerformanceCollector(PerformanceResultsWriter writer) {
+ setPerformanceResultsWriter(writer);
+ }
+
+ public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
+ mPerfWriter = writer;
+ }
+
+ /**
+ * Begin collection of memory usage information.
+ *
+ * @param label description of code block between beginSnapshot and
+ * endSnapshot, used to label output
+ */
+ public void beginSnapshot(String label) {
+ if (mPerfWriter != null)
+ mPerfWriter.writeBeginSnapshot(label);
+ startPerformanceSnapshot();
+ }
+
+ /**
+ * End collection of memory usage information. Returns collected data in a
+ * Bundle object.
+ *
+ * @return Memory and runtime metrics stored as key/value pairs. Values are
+ * of type long, and keys include:
+ * <ul>
+ * <li>{@link #METRIC_KEY_CPU_TIME cpu_time}
+ * <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time}
+ * <li>{@link #METRIC_KEY_PRE_RECEIVED_TRANSACTIONS
+ * pre_received_transactions}
+ * <li>{@link #METRIC_KEY_PRE_SENT_TRANSACTIONS
+ * pre_sent_transactions}
+ * <li>{@link #METRIC_KEY_RECEIVED_TRANSACTIONS
+ * received_transactions}
+ * <li>{@link #METRIC_KEY_SENT_TRANSACTIONS sent_transactions}
+ * <li>{@link #METRIC_KEY_GC_INVOCATION_COUNT gc_invocation_count}
+ * <li>{@link #METRIC_KEY_JAVA_ALLOCATED java_allocated}
+ * <li>{@link #METRIC_KEY_JAVA_FREE java_free}
+ * <li>{@link #METRIC_KEY_JAVA_PRIVATE_DIRTY java_private_dirty}
+ * <li>{@link #METRIC_KEY_JAVA_PSS java_pss}
+ * <li>{@link #METRIC_KEY_JAVA_SHARED_DIRTY java_shared_dirty}
+ * <li>{@link #METRIC_KEY_JAVA_SIZE java_size}
+ * <li>{@link #METRIC_KEY_NATIVE_ALLOCATED native_allocated}
+ * <li>{@link #METRIC_KEY_NATIVE_FREE native_free}
+ * <li>{@link #METRIC_KEY_NATIVE_PRIVATE_DIRTY native_private_dirty}
+ * <li>{@link #METRIC_KEY_NATIVE_PSS native_pss}
+ * <li>{@link #METRIC_KEY_NATIVE_SHARED_DIRTY native_shared_dirty}
+ * <li>{@link #METRIC_KEY_NATIVE_SIZE native_size}
+ * <li>{@link #METRIC_KEY_GLOBAL_ALLOC_COUNT global_alloc_count}
+ * <li>{@link #METRIC_KEY_GLOBAL_ALLOC_SIZE global_alloc_size}
+ * <li>{@link #METRIC_KEY_GLOBAL_FREED_COUNT global_freed_count}
+ * <li>{@link #METRIC_KEY_GLOBAL_FREED_SIZE global_freed_size}
+ * <li>{@link #METRIC_KEY_OTHER_PRIVATE_DIRTY other_private_dirty}
+ * <li>{@link #METRIC_KEY_OTHER_PSS other_pss}
+ * <li>{@link #METRIC_KEY_OTHER_SHARED_DIRTY other_shared_dirty}
+ * </ul>
+ */
+ public Bundle endSnapshot() {
+ endPerformanceSnapshot();
+ if (mPerfWriter != null)
+ mPerfWriter.writeEndSnapshot(mPerfSnapshot);
+ return mPerfSnapshot;
+ }
+
+ /**
+ * Start measurement of user and cpu time.
+ *
+ * @param label description of code block between startTiming and
+ * stopTiming, used to label output
+ */
+ public void startTiming(String label) {
+ if (mPerfWriter != null)
+ mPerfWriter.writeStartTiming(label);
+ mPerfMeasurement = new Bundle();
+ mPerfMeasurement.putParcelableArrayList(
+ METRIC_KEY_ITERATIONS, new ArrayList<Parcelable>());
+ mExecTime = SystemClock.uptimeMillis();
+ mCpuTime = Process.getElapsedCpuTime();
+ }
+
+ /**
+ * Add a measured segment, and start measuring the next segment. Returns
+ * collected data in a Bundle object.
+ *
+ * @param label description of code block between startTiming and
+ * addIteration, and between two calls to addIteration, used
+ * to label output
+ * @return Runtime metrics stored as key/value pairs. Values are of type
+ * long, and keys include:
+ * <ul>
+ * <li>{@link #METRIC_KEY_LABEL label}
+ * <li>{@link #METRIC_KEY_CPU_TIME cpu_time}
+ * <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time}
+ * </ul>
+ */
+ public Bundle addIteration(String label) {
+ mCpuTime = Process.getElapsedCpuTime() - mCpuTime;
+ mExecTime = SystemClock.uptimeMillis() - mExecTime;
+
+ Bundle iteration = new Bundle();
+ iteration.putString(METRIC_KEY_LABEL, label);
+ iteration.putLong(METRIC_KEY_EXECUTION_TIME, mExecTime);
+ iteration.putLong(METRIC_KEY_CPU_TIME, mCpuTime);
+ mPerfMeasurement.getParcelableArrayList(METRIC_KEY_ITERATIONS).add(iteration);
+
+ mExecTime = SystemClock.uptimeMillis();
+ mCpuTime = Process.getElapsedCpuTime();
+ return iteration;
+ }
+
+ /**
+ * Stop measurement of user and cpu time.
+ *
+ * @param label description of code block between addIteration or
+ * startTiming and stopTiming, used to label output
+ * @return Runtime metrics stored in a bundle, including all iterations
+ * between calls to startTiming and stopTiming. List of iterations
+ * is keyed by {@link #METRIC_KEY_ITERATIONS iterations}.
+ */
+ public Bundle stopTiming(String label) {
+ addIteration(label);
+ if (mPerfWriter != null)
+ mPerfWriter.writeStopTiming(mPerfMeasurement);
+ return mPerfMeasurement;
+ }
+
+ /*
+ * Starts tracking memory usage, binder transactions, and real & cpu timing.
+ */
+ private void startPerformanceSnapshot() {
+ // Create new snapshot
+ mPerfSnapshot = new Bundle();
+
+ // Add initial binder counts
+ Bundle binderCounts = getBinderCounts();
+ for (String key : binderCounts.keySet()) {
+ mPerfSnapshot.putLong("pre_" + key, binderCounts.getLong(key));
+ }
+
+ // Force a GC and zero out the performance counters. Do this
+ // before reading initial CPU/wall-clock times so we don't include
+ // the cost of this setup in our final metrics.
+ startAllocCounting();
+
+ // Record CPU time up to this point, and start timing. Note: this
+ // must happen at the end of this method, otherwise the timing will
+ // include noise.
+ mSnapshotExecTime = SystemClock.uptimeMillis();
+ mSnapshotCpuTime = Process.getElapsedCpuTime();
+ }
+
+ /*
+ * Stops tracking memory usage, binder transactions, and real & cpu timing.
+ * Stores collected data as type long into Bundle object for reporting.
+ */
+ private void endPerformanceSnapshot() {
+ // Stop the timing. This must be done first before any other counting is
+ // stopped.
+ mSnapshotCpuTime = Process.getElapsedCpuTime() - mSnapshotCpuTime;
+ mSnapshotExecTime = SystemClock.uptimeMillis() - mSnapshotExecTime;
+
+ stopAllocCounting();
+
+ long nativeMax = Debug.getNativeHeapSize() / 1024;
+ long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
+ long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
+
+ Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
+ Debug.getMemoryInfo(memInfo);
+
+ Runtime runtime = Runtime.getRuntime();
+
+ long dalvikMax = runtime.totalMemory() / 1024;
+ long dalvikFree = runtime.freeMemory() / 1024;
+ long dalvikAllocated = dalvikMax - dalvikFree;
+
+ // Add final binder counts
+ Bundle binderCounts = getBinderCounts();
+ for (String key : binderCounts.keySet()) {
+ mPerfSnapshot.putLong(key, binderCounts.getLong(key));
+ }
+
+ // Add alloc counts
+ Bundle allocCounts = getAllocCounts();
+ for (String key : allocCounts.keySet()) {
+ mPerfSnapshot.putLong(key, allocCounts.getLong(key));
+ }
+
+ mPerfSnapshot.putLong(METRIC_KEY_EXECUTION_TIME, mSnapshotExecTime);
+ mPerfSnapshot.putLong(METRIC_KEY_CPU_TIME, mSnapshotCpuTime);
+
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax);
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated);
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree);
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PSS, memInfo.nativePss);
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PRIVATE_DIRTY, memInfo.nativePrivateDirty);
+ mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SHARED_DIRTY, memInfo.nativeSharedDirty);
+
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_SIZE, dalvikMax);
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_ALLOCATED, dalvikAllocated);
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_FREE, dalvikFree);
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_PSS, memInfo.dalvikPss);
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_PRIVATE_DIRTY, memInfo.dalvikPrivateDirty);
+ mPerfSnapshot.putLong(METRIC_KEY_JAVA_SHARED_DIRTY, memInfo.dalvikSharedDirty);
+
+ mPerfSnapshot.putLong(METRIC_KEY_OTHER_PSS, memInfo.otherPss);
+ mPerfSnapshot.putLong(METRIC_KEY_OTHER_PRIVATE_DIRTY, memInfo.otherPrivateDirty);
+ mPerfSnapshot.putLong(METRIC_KEY_OTHER_SHARED_DIRTY, memInfo.otherSharedDirty);
+ }
+
+ /*
+ * Starts allocation counting. This triggers a gc and resets the counts.
+ */
+ private static void startAllocCounting() {
+ // Before we start trigger a GC and reset the debug counts. Run the
+ // finalizers and another GC before starting and stopping the alloc
+ // counts. This will free up any objects that were just sitting around
+ // waiting for their finalizers to be run.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+
+ Debug.resetAllCounts();
+
+ // start the counts
+ Debug.startAllocCounting();
+ }
+
+ /*
+ * Stops allocation counting.
+ */
+ private static void stopAllocCounting() {
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ Debug.stopAllocCounting();
+ }
+
+ /*
+ * Returns a bundle with the current results from the allocation counting.
+ */
+ private static Bundle getAllocCounts() {
+ Bundle results = new Bundle();
+ results.putLong(METRIC_KEY_GLOBAL_ALLOC_COUNT, Debug.getGlobalAllocCount());
+ results.putLong(METRIC_KEY_GLOBAL_ALLOC_SIZE, Debug.getGlobalAllocSize());
+ results.putLong(METRIC_KEY_GLOBAL_FREED_COUNT, Debug.getGlobalFreedCount());
+ results.putLong(METRIC_KEY_GLOBAL_FREED_SIZE, Debug.getGlobalFreedSize());
+ results.putLong(METRIC_KEY_GC_INVOCATION_COUNT, Debug.getGlobalGcInvocationCount());
+ return results;
+ }
+
+ /*
+ * Returns a bundle with the counts for various binder counts for this
+ * process. Currently the only two that are reported are the number of send
+ * and the number of received transactions.
+ */
+ private static Bundle getBinderCounts() {
+ Bundle results = new Bundle();
+ results.putLong(METRIC_KEY_SENT_TRANSACTIONS, Debug.getBinderSentTransactions());
+ results.putLong(METRIC_KEY_RECEIVED_TRANSACTIONS, Debug.getBinderReceivedTransactions());
+ return results;
+ }
+}
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
index f126c4d..d5cc2207 100644
--- a/core/java/android/provider/Im.java
+++ b/core/java/android/provider/Im.java
@@ -27,7 +27,7 @@
import java.util.HashMap;
/**
- * The IM provider stores all information about roster contacts, chat messages, presence, etc.
+ * The GTalk provider stores all information about roster contacts, chat messages, presence, etc.
*
* @hide
*/
@@ -38,7 +38,7 @@
private Im() {}
/**
- * The Columns for IM providers (i.e. AIM, Y!, GTalk)
+ * The Columns for IM providers
*/
public interface ProviderColumns {
/**
@@ -146,20 +146,20 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/providers");
+ Uri.parse("content://com.google.android.providers.talk/providers");
public static final Uri CONTENT_URI_WITH_ACCOUNT =
- Uri.parse("content://im/providers/account");
+ Uri.parse("content://com.google.android.providers.talk/providers/account");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-providers";
+ "vnd.android.cursor.dir/gtalk-providers";
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-providers";
+ "vnd.android.cursor.item/gtalk-providers";
/**
* The default sort order for this table
@@ -253,21 +253,21 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/accounts");
+ Uri.parse("content://com.google.android.providers.talk/accounts");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* account.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-accounts";
+ "vnd.android.cursor.dir/gtalk-accounts";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* account.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-accounts";
+ "vnd.android.cursor.item/gtalk-accounts";
/**
* The default sort order for this table
@@ -326,19 +326,19 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/accountStatus");
+ Uri.parse("content://com.google.android.providers.talk/accountStatus");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of account status.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-account-status";
+ "vnd.android.cursor.dir/gtalk-account-status";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single account status.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-account-status";
+ "vnd.android.cursor.item/gtalk-account-status";
/**
* The default sort order for this table
@@ -522,83 +522,83 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/contacts");
+ Uri.parse("content://com.google.android.providers.talk/contacts");
/**
* The content:// style URL for contacts joined with presence
*/
public static final Uri CONTENT_URI_WITH_PRESENCE =
- Uri.parse("content://im/contactsWithPresence");
+ Uri.parse("content://com.google.android.providers.talk/contactsWithPresence");
/**
* The content:// style URL for barebone contacts, not joined with any other table
*/
public static final Uri CONTENT_URI_CONTACTS_BAREBONE =
- Uri.parse("content://im/contactsBarebone");
+ Uri.parse("content://com.google.android.providers.talk/contactsBarebone");
/**
* The content:// style URL for contacts who have an open chat session
*/
public static final Uri CONTENT_URI_CHAT_CONTACTS =
- Uri.parse("content://im/contacts/chatting");
+ Uri.parse("content://com.google.android.providers.talk/contacts/chatting");
/**
* The content:// style URL for contacts who have been blocked
*/
public static final Uri CONTENT_URI_BLOCKED_CONTACTS =
- Uri.parse("content://im/contacts/blocked");
+ Uri.parse("content://com.google.android.providers.talk/contacts/blocked");
/**
* The content:// style URL for contacts by provider and account
*/
public static final Uri CONTENT_URI_CONTACTS_BY =
- Uri.parse("content://im/contacts");
+ Uri.parse("content://com.google.android.providers.talk/contacts");
/**
* The content:// style URL for contacts by provider and account,
* and who have an open chat session
*/
public static final Uri CONTENT_URI_CHAT_CONTACTS_BY =
- Uri.parse("content://im/contacts/chatting");
+ Uri.parse("content://com.google.android.providers.talk/contacts/chatting");
/**
* The content:// style URL for contacts by provider and account,
* and who are online
*/
public static final Uri CONTENT_URI_ONLINE_CONTACTS_BY =
- Uri.parse("content://im/contacts/online");
+ Uri.parse("content://com.google.android.providers.talk/contacts/online");
/**
* The content:// style URL for contacts by provider and account,
* and who are offline
*/
public static final Uri CONTENT_URI_OFFLINE_CONTACTS_BY =
- Uri.parse("content://im/contacts/offline");
+ Uri.parse("content://com.google.android.providers.talk/contacts/offline");
/**
* The content:// style URL for operations on bulk contacts
*/
public static final Uri BULK_CONTENT_URI =
- Uri.parse("content://im/bulk_contacts");
+ Uri.parse("content://com.google.android.providers.talk/bulk_contacts");
/**
* The content:// style URL for the count of online contacts in each
* contact list by provider and account.
*/
public static final Uri CONTENT_URI_ONLINE_COUNT =
- Uri.parse("content://im/contacts/onlineCount");
+ Uri.parse("content://com.google.android.providers.talk/contacts/onlineCount");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-contacts";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-contacts";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-contacts";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/gtalk-contacts";
/**
* The default sort order for this table
@@ -634,21 +634,21 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/contactLists");
+ Uri.parse("content://com.google.android.providers.talk/contactLists");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-contactLists";
+ "vnd.android.cursor.dir/gtalk-contactLists";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-contactLists";
+ "vnd.android.cursor.item/gtalk-contactLists";
/**
* The default sort order for this table
@@ -699,21 +699,21 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/blockedList");
+ Uri.parse("content://com.google.android.providers.talk/blockedList");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-blockedList";
+ "vnd.android.cursor.dir/gtalk-blockedList";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-blockedList";
+ "vnd.android.cursor.item/gtalk-blockedList";
/**
* The default sort order for this table
@@ -822,21 +822,21 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/contactsEtag");
+ Uri.parse("content://com.google.android.providers.talk/contactsEtag");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-contactsEtag";
+ "vnd.android.cursor.dir/gtalk-contactsEtag";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-contactsEtag";
+ "vnd.android.cursor.item/gtalk-contactsEtag";
}
/**
@@ -1057,75 +1057,75 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/messages");
+ Uri.parse("content://com.google.android.providers.talk/messages");
/**
* The content:// style URL for messages by thread id
*/
public static final Uri CONTENT_URI_MESSAGES_BY_THREAD_ID =
- Uri.parse("content://im/messagesByThreadId");
+ Uri.parse("content://com.google.android.providers.talk/messagesByThreadId");
/**
* The content:// style URL for messages by account and contact
*/
public static final Uri CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT =
- Uri.parse("content://im/messagesByAcctAndContact");
+ Uri.parse("content://com.google.android.providers.talk/messagesByAcctAndContact");
/**
* The content:// style URL for messages by provider
*/
public static final Uri CONTENT_URI_MESSAGES_BY_PROVIDER =
- Uri.parse("content://im/messagesByProvider");
+ Uri.parse("content://com.google.android.providers.talk/messagesByProvider");
/**
* The content:// style URL for messages by account
*/
public static final Uri CONTENT_URI_BY_ACCOUNT =
- Uri.parse("content://im/messagesByAccount");
+ Uri.parse("content://com.google.android.providers.talk/messagesByAccount");
/**
* The content:// style url for off the record messages
*/
public static final Uri OTR_MESSAGES_CONTENT_URI =
- Uri.parse("content://im/otrMessages");
+ Uri.parse("content://com.google.android.providers.talk/otrMessages");
/**
* The content:// style url for off the record messages by thread id
*/
public static final Uri OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID =
- Uri.parse("content://im/otrMessagesByThreadId");
+ Uri.parse("content://com.google.android.providers.talk/otrMessagesByThreadId");
/**
* The content:// style url for off the record messages by account and contact
*/
public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT =
- Uri.parse("content://im/otrMessagesByAcctAndContact");
+ Uri.parse("content://com.google.android.providers.talk/otrMessagesByAcctAndContact");
/**
* The content:// style URL for off the record messages by provider
*/
public static final Uri OTR_MESSAGES_CONTENT_URI_BY_PROVIDER =
- Uri.parse("content://im/otrMessagesByProvider");
+ Uri.parse("content://com.google.android.providers.talk/otrMessagesByProvider");
/**
* The content:// style URL for off the record messages by account
*/
public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT =
- Uri.parse("content://im/otrMessagesByAccount");
+ Uri.parse("content://com.google.android.providers.talk/otrMessagesByAccount");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-messages";
+ "vnd.android.cursor.dir/gtalk-messages";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-messages";
+ "vnd.android.cursor.item/gtalk-messages";
/**
* The default sort order for this table
@@ -1166,21 +1166,21 @@
private GroupMembers(){}
public static final Uri CONTENT_URI =
- Uri.parse("content://im/groupMembers");
+ Uri.parse("content://com.google.android.providers.talk/groupMembers");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* group members.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-groupMembers";
+ "vnd.android.cursor.dir/gtalk-groupMembers";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* group member.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-groupMembers";
+ "vnd.android.cursor.item/gtalk-groupMembers";
}
/**
@@ -1246,21 +1246,21 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/invitations");
+ Uri.parse("content://com.google.android.providers.talk/invitations");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* invitations.
*/
public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-invitations";
+ "vnd.android.cursor.dir/gtalk-invitations";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* invitation.
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-invitations";
+ "vnd.android.cursor.item/gtalk-invitations";
}
/**
@@ -1302,24 +1302,25 @@
/**
* The content:// style URL for this table
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/avatars");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/avatars");
/**
* The content:// style URL for avatars by provider, account and contact
*/
public static final Uri CONTENT_URI_AVATARS_BY =
- Uri.parse("content://im/avatarsBy");
+ Uri.parse("content://com.google.android.providers.talk/avatarsBy");
/**
* The MIME type of {@link #CONTENT_URI} providing the avatars
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-avatars";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-avatars";
/**
* The MIME type of a {@link #CONTENT_URI}
*/
public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-avatars";
+ "vnd.android.cursor.item/gtalk-avatars";
/**
* The default sort order for this table
@@ -1397,28 +1398,31 @@
/**
* The content:// style URL for this table
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/presence");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/presence");
/**
- * The content URL for IM presences for an account
+ * The content URL for Talk presences for an account
*/
- public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/presence/account");
+ public static final Uri CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://com.google.android.providers.talk/presence/account");
/**
* The content:// style URL for operations on bulk contacts
*/
- public static final Uri BULK_CONTENT_URI = Uri.parse("content://im/bulk_presence");
+ public static final Uri BULK_CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/bulk_presence");
/**
* The content:// style URL for seeding presences for a given account id.
*/
public static final Uri SEED_PRESENCE_BY_ACCOUNT_CONTENT_URI =
- Uri.parse("content://im/seed_presence/account");
+ Uri.parse("content://com.google.android.providers.talk/seed_presence/account");
/**
* The MIME type of a {@link #CONTENT_URI} providing a directory of presence
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-presence";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-presence";
/**
* The default sort order for this table
@@ -1491,22 +1495,23 @@
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/chats");
+ Uri.parse("content://com.google.android.providers.talk/chats");
/**
* The content URL for all chats that belong to the account
*/
- public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/chats/account");
+ public static final Uri CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://com.google.android.providers.talk/chats/account");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of chats.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-chats";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/gtalk-chats";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single chat.
*/
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-chats";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/gtalk-chats";
/**
* The default sort order for this table
@@ -1534,19 +1539,20 @@
/**
* The content:// style URI for this table
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/sessionCookies");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/sessionCookies");
/**
* The content:// style URL for session cookies by provider and account
*/
public static final Uri CONTENT_URI_SESSION_COOKIES_BY =
- Uri.parse("content://im/sessionCookiesBy");
+ Uri.parse("content://com.google.android.providers.talk/sessionCookiesBy");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
- public static final String CONTENT_TYPE = "vnd.android-dir/im-sessionCookies";
+ public static final String CONTENT_TYPE = "vnd.android-dir/gtalk-sessionCookies";
}
/**
@@ -1581,12 +1587,12 @@
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI =
- Uri.parse("content://im/providerSettings");
+ Uri.parse("content://com.google.android.providers.talk/providerSettings");
/**
* The MIME type of {@link #CONTENT_URI} providing provider settings
*/
- public static final String CONTENT_TYPE = "vnd.android-dir/im-providerSettings";
+ public static final String CONTENT_TYPE = "vnd.android-dir/gtalk-providerSettings";
/**
* A boolean value to indicate whether this provider should show the offline contacts
@@ -1596,13 +1602,13 @@
/** controls whether or not the GTalk service automatically connect to server. */
public static final String SETTING_AUTOMATICALLY_CONNECT_GTALK = "gtalk_auto_connect";
- /** controls whether or not the IM service will be automatically started after boot */
+ /** controls whether or not the GTalk service will be automatically started after boot */
public static final String SETTING_AUTOMATICALLY_START_SERVICE = "auto_start_service";
/** controls whether or not the offline contacts will be hided */
public static final String SETTING_HIDE_OFFLINE_CONTACTS = "hide_offline_contacts";
- /** controls whether or not enable the IM notification */
+ /** controls whether or not enable the GTalk notification */
public static final String SETTING_ENABLE_NOTIFICATION = "enable_notification";
/** specifies whether or not to vibrate */
@@ -1794,10 +1800,10 @@
}
/**
- * A convenience method to set whether or not enable the IM notification.
+ * A convenience method to set whether or not enable the GTalk notification.
*
* @param contentResolver The ContentResolver to use to access the setting table.
- * @param enable Whether enable the IM notification
+ * @param enable Whether enable the GTalk notification
*/
public static void setEnableNotification(ContentResolver contentResolver, long providerId,
boolean enable) {
@@ -1935,18 +1941,18 @@
}
/**
- * Set whether or not enable the IM notification.
+ * Set whether or not enable the GTalk notification.
*
- * @param enable Whether or not enable the IM notification.
+ * @param enable Whether or not enable the GTalk notification.
*/
public void setEnableNotification(boolean enable) {
ProviderSettings.setEnableNotification(mContentResolver, mProviderId, enable);
}
/**
- * Check if the IM notification is enabled.
+ * Check if the GTalk notification is enabled.
*
- * @return Whether or not enable the IM notification.
+ * @return Whether or not enable the GTalk notification.
*/
public boolean getEnableNotification() {
return getBoolean(SETTING_ENABLE_NOTIFICATION,
@@ -1954,7 +1960,7 @@
}
/**
- * Set whether or not to vibrate on IM notification.
+ * Set whether or not to vibrate on GTalk notification.
*
* @param vibrate Whether or not to vibrate.
*/
@@ -1963,7 +1969,7 @@
}
/**
- * Gets whether or not to vibrate on IM notification.
+ * Gets whether or not to vibrate on GTalk notification.
*
* @return Whether or not to vibrate.
*/
@@ -2138,8 +2144,8 @@
/**
- * Columns for IM branding resource map cache table. This table caches the result of
- * loading the branding resources to speed up IM landing page start.
+ * Columns for GTalk branding resource map cache table. This table caches the result of
+ * loading the branding resources to speed up GTalk landing page start.
*/
public interface BrandingResourceMapCacheColumns {
/**
@@ -2160,14 +2166,15 @@
}
/**
- * The table for caching the result of loading IM branding resources.
+ * The table for caching the result of loading GTalk branding resources.
*/
public static final class BrandingResourceMapCache
implements BaseColumns, BrandingResourceMapCacheColumns {
/**
* The content:// style URL for this table.
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/brandingResMapCache");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/brandingResMapCache");
}
@@ -2229,13 +2236,14 @@
/**
* The content:// style URL for this table.
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/outgoingRmqMessages");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/outgoingRmqMessages");
/**
* The content:// style URL for the highest rmq id for the outgoing rmq messages
*/
public static final Uri CONTENT_URI_FOR_HIGHEST_RMQ_ID =
- Uri.parse("content://im/outgoingHighestRmqId");
+ Uri.parse("content://com.google.android.providers.talk/outgoingHighestRmqId");
/**
* The default sort order for this table.
@@ -2309,7 +2317,8 @@
/**
* The content:// style URL for this table.
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/lastRmqId");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/lastRmqId");
}
/**
@@ -2327,7 +2336,8 @@
/**
* The content:// style URL for this table.
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/s2dids");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://com.google.android.providers.talk/s2dids");
}
}
diff --git a/core/java/android/test/TimedTest.java b/core/java/android/test/TimedTest.java
new file mode 100644
index 0000000..3a60a25
--- /dev/null
+++ b/core/java/android/test/TimedTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation can be used on an {@link junit.framework.TestCase}'s test
+ * methods. When the annotation is present, the test method is timed and the
+ * results written through instrumentation output. It can also be used on the
+ * class itself, which is equivalent to tagging all test methods with this
+ * annotation.
+ *
+ * {@hide} Pending approval for public API.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TimedTest { }
\ No newline at end of file
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index d61e888..ce25c47 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -208,7 +208,7 @@
if ((mask & WEB_URLS) != 0) {
gatherLinks(links, text, Regex.WEB_URL_PATTERN,
- new String[] { "http://", "https://" },
+ new String[] { "http://", "https://", "rtsp://" },
sUrlMatchFilter, null);
}
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
index a349b82..a6844a4 100644
--- a/core/java/android/text/util/Regex.java
+++ b/core/java/android/text/util/Regex.java
@@ -65,7 +65,7 @@
*/
public static final Pattern WEB_URL_PATTERN
= Pattern.compile(
- "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+" // named host
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8446475..0f178e9 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -458,8 +458,7 @@
private static final int SWITCH_TO_LONGPRESS = 4;
private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
- private static final int SWITCH_TO_CLICK = 7;
- private static final int RESUME_WEBCORE_UPDATE = 8;
+ private static final int RESUME_WEBCORE_UPDATE = 7;
//! arg1=x, arg2=y
static final int SCROLL_TO_MSG_ID = 10;
@@ -2049,12 +2048,9 @@
protected int computeHorizontalScrollRange() {
if (mDrawHistory) {
return mHistoryWidth;
- } else if (mLastWidthSent == mContentWidth) {
- // special case to avoid rounding error. Otherwise we may get a
- // faked scrollbar sometimes.
- return getViewWidth();
} else {
- return contentToViewDimension(mContentWidth);
+ // to avoid rounding error caused unnecessary scrollbar, use floor
+ return (int) Math.floor(mContentWidth * mActualScale);
}
}
@@ -2066,18 +2062,8 @@
if (mDrawHistory) {
return mHistoryHeight;
} else {
- int height;
- // special case to avoid rounding error. Otherwise we may get a
- // faked scrollbar sometimes.
- if (mLastHeightSent == mContentHeight) {
- height = getViewHeight();
- } else {
- height = contentToViewDimension(mContentHeight);
- }
- if (mFindIsUp) {
- height += FIND_HEIGHT;
- }
- return height;
+ // to avoid rounding error caused unnecessary scrollbar, use floor
+ return (int) Math.floor(mContentHeight * mActualScale);
}
}
@@ -3677,16 +3663,27 @@
if (mShiftIsPressed) {
return false;
}
- if (getSettings().supportZoom()
- && mTouchMode == TOUCH_DOUBLECLICK_MODE) {
- zoomScrollOut();
- } else {
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(SWITCH_TO_CLICK), TAP_TIMEOUT);
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "TOUCH_DOUBLECLICK_MODE");
- }
- mTouchMode = TOUCH_DOUBLECLICK_MODE;
+
+ // perform the single click
+ Rect visibleRect = sendOurVisibleRect();
+ // Note that sendOurVisibleRect calls viewToContent, so the
+ // coordinates should be in content coordinates.
+ if (!nativeCursorIntersects(visibleRect)) {
+ return false;
+ }
+ nativeSetFollowedLink(true);
+ nativeUpdatePluginReceivesEvents();
+ WebViewCore.CursorData data = cursorData();
+ mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
+ playSoundEffect(SoundEffectConstants.CLICK);
+ boolean isTextInput = nativeCursorIsTextInput();
+ if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
+ nativeCursorText())) {
+ mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
+ nativeCursorNodePointer());
+ }
+ if (isTextInput) {
+ rebuildWebTextView();
}
return true;
}
@@ -4334,7 +4331,6 @@
return true;
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mPrivateHandler.removeMessages(SWITCH_TO_CLICK);
mTrackballDown = true;
if (mNativeClass == 0) {
return false;
@@ -4582,9 +4578,8 @@
}
private int computeMaxScrollY() {
- int maxContentH = contentToViewDimension(mContentHeight)
- + getTitleHeight();
- return Math.max(maxContentH - getHeight(), 0);
+ int maxContentH = computeVerticalScrollRange() + getTitleHeight();
+ return Math.max(maxContentH - getHeight(), getTitleHeight());
}
public void flingScroll(int vx, int vy) {
@@ -4890,6 +4885,9 @@
}
int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
+ // In case the soft keyboard has been dismissed, bring it back up.
+ InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
+ 0);
nativeTextInputMotionUp(x, y);
}
@@ -5023,8 +5021,8 @@
int measuredWidth = widthSize;
// Grab the content size from WebViewCore.
- int contentHeight = Math.round(mContentHeight * mActualScale);
- int contentWidth = Math.round(mContentWidth * mActualScale);
+ int contentHeight = contentToViewDimension(mContentHeight);
+ int contentWidth = contentToViewDimension(mContentWidth);
// Log.d(LOGTAG, "------- measure " + heightMode);
@@ -5198,32 +5196,6 @@
}
break;
}
- case SWITCH_TO_CLICK:
- // The user clicked with the trackball, and did not click a
- // second time, so perform the action of a trackball single
- // click
- mTouchMode = TOUCH_DONE_MODE;
- Rect visibleRect = sendOurVisibleRect();
- // Note that sendOurVisibleRect calls viewToContent, so the
- // coordinates should be in content coordinates.
- if (!nativeCursorIntersects(visibleRect)) {
- break;
- }
- nativeSetFollowedLink(true);
- nativeUpdatePluginReceivesEvents();
- WebViewCore.CursorData data = cursorData();
- mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
- playSoundEffect(SoundEffectConstants.CLICK);
- boolean isTextInput = nativeCursorIsTextInput();
- if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
- nativeCursorText())) {
- mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
- nativeCursorNodePointer());
- }
- if (isTextInput) {
- rebuildWebTextView();
- }
- break;
case SCROLL_BY_MSG_ID:
setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
break;
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 4e76254..6e10811 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -39,7 +39,7 @@
// log tag
protected static final String LOGTAG = "webviewdatabase";
- private static final int DATABASE_VERSION = 9;
+ private static final int DATABASE_VERSION = 10;
// 2 -> 3 Modified Cache table to allow cache of redirects
// 3 -> 4 Added Oma-Downloads table
// 4 -> 5 Modified Cache table to support persistent contentLength
@@ -48,6 +48,7 @@
// 6 -> 7 Change cache localPath from int to String
// 7 -> 8 Move cache to its own db
// 8 -> 9 Store both scheme and host when storing passwords
+ // 9 -> 10 Update httpauth table UNIQUE
private static final int CACHE_DATABASE_VERSION = 3;
// 1 -> 2 Add expires String
// 2 -> 3 Add content-disposition
@@ -256,6 +257,20 @@
+ DATABASE_VERSION + ", which will destroy old data");
}
boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
+ boolean justAuth = 9 == oldVersion && 10 == DATABASE_VERSION;
+ if (justAuth) {
+ mDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_HTTPAUTH_ID]);
+ mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
+ return;
+ }
+
if (!justPasswords) {
mDatabase.execSQL("DROP TABLE IF EXISTS "
+ mTableNames[TABLE_COOKIES_ID]);
@@ -302,8 +317,8 @@
+ HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL + ", "
- + HTTPAUTH_USERNAME_COL + ") ON CONFLICT REPLACE);");
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
}
// passwords
mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index 44bcd16..51d9570 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -11,7 +11,6 @@
import android.util.Log;
import android.os.*;
-import android.net.Uri;
/**
* Integrates the framework with Dalvik's sampling profiler.
@@ -60,14 +59,25 @@
public static void writeSnapshot(final String name) {
if (!enabled) return;
+ /*
+ * If we're already writing a snapshot, don't bother enqueing another
+ * request right now. This will reduce the number of individual
+ * snapshots and in turn the total amount of memory consumed (one big
+ * snapshot is smaller than N subset snapshots).
+ */
if (!pending) {
pending = true;
snapshotWriter.execute(new Runnable() {
public void run() {
String dir = "/sdcard/snapshots";
if (!dirMade) {
- makeDirectory(dir);
- dirMade = true;
+ new File(dir).mkdirs();
+ if (new File(dir).isDirectory()) {
+ dirMade = true;
+ } else {
+ Log.w(TAG, "Creation of " + dir + " failed.");
+ return;
+ }
}
try {
writeSnapshot(dir, name);
@@ -86,7 +96,7 @@
if (!enabled) return;
String dir = "/data/zygote/snapshots";
- makeDirectory(dir);
+ new File(dir).mkdirs();
writeSnapshot(dir, "zygote");
}
@@ -102,7 +112,7 @@
* we capture two snapshots in rapid succession.
*/
long start = System.currentTimeMillis();
- String path = dir + "/" + name.replace(':', '.') + "-"
+ String path = dir + "/" + name.replace(':', '.') + "-" +
+ System.currentTimeMillis() + ".snapshot";
try {
// Try to open the file a few times. The SD card may not be mounted.
@@ -117,7 +127,7 @@
Log.e(TAG, "Could not open " + path + ".");
return;
}
-
+
// Sleep for a bit and then try again.
try {
Thread.sleep(2500);
@@ -137,8 +147,4 @@
Log.e(TAG, "Error writing snapshot.", e);
}
}
-
- private static void makeDirectory(String dir) {
- new File(dir).mkdirs();
- }
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 568ed92..d1cb0bd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2843,7 +2843,9 @@
is also used as an icon to the left of the search box and you cannot modify this
behavior, so including the icon attribute is unecessary and this may be
deprecated in the future.
- <i>Optional attribute.</i> -->
+ <i>Optional attribute.</i>
+ {@deprecated This will create a non-standard UI appearance, because the search bar UI
+ now puts the activity or application icon beside the search box.} -->
<attr name="icon" />
<!-- This is the user-displayed name of the searchable activity. <i>Required
attribute.</i> -->
@@ -2868,7 +2870,10 @@
<flag name="showSearchLabelAsBadge" value="0x04" />
<!-- If set, this flag enables the display of the search target (icon) within the
search bar. (Note, overrides showSearchLabel) If neither bad mode is selected,
- no badge will be shown.-->
+ no badge will be shown.
+ {@deprecated This will create a non-standard UI appearance, because the search bar UI
+ now puts the activity or application icon beside the search box.}
+ -->
<flag name="showSearchIconAsBadge" value="0x08" />
<!-- If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA to
be considered as the text for suggestion query rewriting. This should only
diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java
index a706c89..b47ae12 100644
--- a/keystore/java/android/security/Keystore.java
+++ b/keystore/java/android/security/Keystore.java
@@ -60,7 +60,7 @@
@Override
public int lock() {
- Reply result = mServiceCommand.execute(ServiceCommand.LOCK, null);
+ Reply result = mServiceCommand.execute(ServiceCommand.LOCK);
return (result != null) ? result.returnCode : -1;
}
@@ -73,15 +73,14 @@
@Override
public int getState() {
- Reply result = mServiceCommand.execute(ServiceCommand.GET_STATE,
- null);
+ Reply result = mServiceCommand.execute(ServiceCommand.GET_STATE);
return (result != null) ? result.returnCode : -1;
}
@Override
public int changePassword(String oldPassword, String newPassword) {
Reply result = mServiceCommand.execute(ServiceCommand.PASSWD,
- oldPassword + "\0" + newPassword + "\0");
+ oldPassword, newPassword);
return (result != null) ? result.returnCode : -1;
}
@@ -106,14 +105,14 @@
@Override
public int put(String namespace, String keyname, String value) {
Reply result = mServiceCommand.execute(ServiceCommand.PUT_KEY,
- namespace + "\0" + keyname + "\0" + value);
+ namespace, keyname, value);
return (result != null) ? result.returnCode : -1;
}
@Override
public String get(String namespace, String keyname) {
Reply result = mServiceCommand.execute(ServiceCommand.GET_KEY,
- namespace + "\0" + keyname + "\0");
+ namespace, keyname);
return (result != null) ? ((result.returnCode != 0) ? null :
new String(result.data, 0, result.len)) : null;
}
@@ -121,13 +120,13 @@
@Override
public int remove(String namespace, String keyname) {
Reply result = mServiceCommand.execute(ServiceCommand.REMOVE_KEY,
- namespace + "\0" + keyname + "\0");
+ namespace, keyname);
return (result != null) ? result.returnCode : -1;
}
@Override
public int reset() {
- Reply result = mServiceCommand.execute(ServiceCommand.RESET, null);
+ Reply result = mServiceCommand.execute(ServiceCommand.RESET);
return (result != null) ? result.returnCode : -1;
}
}
diff --git a/keystore/java/android/security/ServiceCommand.java b/keystore/java/android/security/ServiceCommand.java
index cefae40..ee80014 100644
--- a/keystore/java/android/security/ServiceCommand.java
+++ b/keystore/java/android/security/ServiceCommand.java
@@ -141,10 +141,18 @@
return reply;
}
- private boolean writeCommand(int cmd, String _data) {
+ private byte[] convert(String... data) {
+ StringBuilder sb = new StringBuilder();
+ if (data.length >=1) sb.append(data[0]).append("\0");
+ if (data.length >=2) sb.append(data[1]).append("\0");
+ if (data.length >=3) sb.append(data[2]);
+ return sb.toString().getBytes();
+ }
+
+ private boolean writeCommand(int cmd, String... data) {
byte buf[] = new byte[8];
- byte[] data = (_data == null) ? new byte[0] : _data.getBytes();
- int len = data.length;
+ byte[] dataBytes = convert(data);
+ int len = dataBytes.length;
// the length of data
buf[0] = (byte) ((len >> 24) & 0xff);
buf[1] = (byte) ((len >> 16) & 0xff);
@@ -157,7 +165,7 @@
buf[7] = (byte) (cmd & 0xff);
try {
mOut.write(buf, 0, 8);
- mOut.write(data, 0, len);
+ mOut.write(dataBytes, 0, len);
} catch (IOException ex) {
Log.e(mTag,"write error", ex);
disconnect();
@@ -166,7 +174,7 @@
return true;
}
- private Reply executeCommand(int cmd, String data) {
+ private Reply executeCommand(int cmd, String... data) {
if (!writeCommand(cmd, data)) {
/* If service died and restarted in the background
* (unlikely but possible) we'll fail on the next
@@ -181,7 +189,7 @@
return readReply();
}
- public synchronized Reply execute(int cmd, String data) {
+ public synchronized Reply execute(int cmd, String... data) {
Reply result;
if (!connect()) {
Log.e(mTag, "connection failed");
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index e2b6b51..790a655 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2014,6 +2014,7 @@
: RefBase(),
mThread(thread),
mClient(client),
+ mCblk(0),
mFrameCount(0),
mState(IDLE),
mClientTid(-1),
@@ -2162,21 +2163,23 @@
: TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
{
- sp<ThreadBase> baseThread = thread.promote();
- if (baseThread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
- mName = playbackThread->getTrackName_l();
+ if (mCblk != NULL) {
+ sp<ThreadBase> baseThread = thread.promote();
+ if (baseThread != 0) {
+ PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
+ mName = playbackThread->getTrackName_l();
+ }
+ LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+ if (mName < 0) {
+ LOGE("no more track names available");
+ }
+ mVolume[0] = 1.0f;
+ mVolume[1] = 1.0f;
+ mStreamType = streamType;
+ // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
+ // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
+ mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
}
- LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
- if (mName < 0) {
- LOGE("no more track names available");
- }
- mVolume[0] = 1.0f;
- mVolume[1] = 1.0f;
- mStreamType = streamType;
- // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
- // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
- mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
}
AudioFlinger::PlaybackThread::Track::~Track()
@@ -2390,14 +2393,16 @@
channelCount, frameCount, flags, 0),
mOverflow(false)
{
- LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
- if (format == AudioSystem::PCM_16_BIT) {
- mCblk->frameSize = channelCount * sizeof(int16_t);
- } else if (format == AudioSystem::PCM_8_BIT) {
- mCblk->frameSize = channelCount * sizeof(int8_t);
- } else {
- mCblk->frameSize = sizeof(int8_t);
- }
+ if (mCblk != NULL) {
+ LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
+ if (format == AudioSystem::PCM_16_BIT) {
+ mCblk->frameSize = channelCount * sizeof(int16_t);
+ } else if (format == AudioSystem::PCM_8_BIT) {
+ mCblk->frameSize = channelCount * sizeof(int8_t);
+ } else {
+ mCblk->frameSize = sizeof(int8_t);
+ }
+ }
}
AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 3fbd8c7..436d793 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -246,10 +246,30 @@
int surface, int num)
: SharedBufferBase(sharedClient, surface, num), tail(0)
{
+ SharedBufferStack& stack( *mSharedStack );
+ int32_t avail;
+ int32_t head;
+ // we need to make sure we read available and head coherently,
+ // w.r.t RetireUpdate.
+ do {
+ avail = stack.available;
+ head = stack.head;
+ } while (stack.available != avail);
+ tail = head - avail + 1;
+ if (tail < 0) {
+ tail += num;
+ }
}
ssize_t SharedBufferClient::dequeue()
{
+ SharedBufferStack& stack( *mSharedStack );
+
+ if (stack.head == tail && stack.available == 2) {
+ LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
+ tail, stack.head, stack.available, stack.queued);
+ }
+
//LOGD("[%d] about to dequeue a buffer",
// mSharedStack->identity);
DequeueCondition condition(this);
@@ -257,8 +277,6 @@
if (err != NO_ERROR)
return ssize_t(err);
-
- SharedBufferStack& stack( *mSharedStack );
// NOTE: 'stack.available' is part of the conditions, however
// decrementing it, never changes any conditions, so we don't need
// to do this as part of an update.
@@ -270,6 +288,7 @@
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
dequeued, tail, dump("").string());
+
return dequeued;
}
@@ -326,7 +345,7 @@
{
RetireUpdate update(this, mNumBuffers);
ssize_t buf = updateCondition( update );
- LOGD_IF(DEBUG_ATOMICS, "retire=%d, %s", int(buf), dump("").string());
+ LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string());
return buf;
}
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index fc39a46..5089157 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -83,6 +83,7 @@
status_t *status)
{
Parcel data, reply;
+ sp<IAudioTrack> track;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeInt32(streamType);
@@ -96,12 +97,14 @@
status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("createTrack error: %s", strerror(-lStatus));
+ } else {
+ lStatus = reply.readInt32();
+ track = interface_cast<IAudioTrack>(reply.readStrongBinder());
}
- lStatus = reply.readInt32();
if (status) {
*status = lStatus;
}
- return interface_cast<IAudioTrack>(reply.readStrongBinder());
+ return track;
}
virtual sp<IAudioRecord> openRecord(
@@ -115,6 +118,7 @@
status_t *status)
{
Parcel data, reply;
+ sp<IAudioRecord> record;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeInt32(input);
@@ -123,12 +127,17 @@
data.writeInt32(channelCount);
data.writeInt32(frameCount);
data.writeInt32(flags);
- remote()->transact(OPEN_RECORD, data, &reply);
- status_t lStatus = reply.readInt32();
+ status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
+ if (lStatus != NO_ERROR) {
+ LOGE("openRecord error: %s", strerror(-lStatus));
+ } else {
+ lStatus = reply.readInt32();
+ record = interface_cast<IAudioRecord>(reply.readStrongBinder());
+ }
if (status) {
*status = lStatus;
}
- return interface_cast<IAudioRecord>(reply.readStrongBinder());
+ return record;
}
virtual uint32_t sampleRate(int output) const
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index 8fb5d3d..dacf75a 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -56,9 +56,13 @@
virtual sp<IMemory> getCblk() const
{
Parcel data, reply;
+ sp<IMemory> cblk;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
- remote()->transact(GET_CBLK, data, &reply);
- return interface_cast<IMemory>(reply.readStrongBinder());
+ status_t status = remote()->transact(GET_CBLK, data, &reply);
+ if (status == NO_ERROR) {
+ cblk = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ return cblk;
}
};
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 75b861b..7f43347 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -81,9 +81,13 @@
virtual sp<IMemory> getCblk() const
{
Parcel data, reply;
+ sp<IMemory> cblk;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
- remote()->transact(GET_CBLK, data, &reply);
- return interface_cast<IMemory>(reply.readStrongBinder());
+ status_t status = remote()->transact(GET_CBLK, data, &reply);
+ if (status == NO_ERROR) {
+ cblk = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ return cblk;
}
};
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index a964d17..d905619 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -232,6 +232,16 @@
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
+ if (!strncmp(componentName, "OMX.TI.", 7)) {
+ // Apparently I must not use OMX_UseBuffer on either input or
+ // output ports on any of the TI components or quote:
+ // "(I) may have unexpected problem (sic) which can be timing related
+ // and hard to reproduce."
+
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ }
+
sp<OMXCodec> codec = new OMXCodec(
omx, node, quirks, createEncoder, mime, componentName,
source);
@@ -840,8 +850,8 @@
mNode, portIndex, mem, &buffer);
} else if (portIndex == kPortIndexOutput
&& (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
- err = mOMX->allocate_buffer(
- mNode, portIndex, def.nBufferSize, &buffer);
+ err = mOMX->allocate_buffer_with_backup(
+ mNode, portIndex, mem, &buffer);
} else {
err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 45a5e53..a86ef8f9 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -415,7 +415,7 @@
null, null, "231180", "1", null},
{"/sdcard/media_api/metaDataTestMedias/M4A/Jaws Of Life_ver1.m4a", "1/8", "Suspended Animation",
"John Petrucci", null, null, "20070510T125223.000Z",
- "13", "Jaws Of Life", "2005", "19815424", "1", "m4a composer"},
+ "13", "Jaws Of Life", "2005", "449329", "1", "m4a composer"},
{"/sdcard/media_api/metaDataTestMedias/M4V/sample_iPod.m4v", null, null,
null, null, null, "20051220T202015.000Z",
null, null, null, "85500", "2", null},
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index 5e213d7..3667fae 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -97,6 +97,7 @@
int video_duration = MediaNames.VIDEO_H263_AAC_DURATION;
int random_play_time = 0;
int random_seek_time = 0;
+ int random_no_of_seek = 0;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
try {
@@ -106,8 +107,13 @@
mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
mp.prepare();
mp.start();
+ random_no_of_seek = generator.nextInt(10);
+ // make sure the seek at least run once.
+ if (random_no_of_seek == 0) {
+ random_no_of_seek = 1;
+ }
// Random seek and play
- for (int j = 0; j < generator.nextInt(10); j++) {
+ for (int j = 0; j < random_no_of_seek; j++) {
random_play_time =
generator.nextInt(video_duration / 2);
Log.v(TAG, "Play time = " + random_play_time);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 38df47b..ba65f01 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -63,7 +63,7 @@
import java.util.Observer;
class PowerManagerService extends IPowerManager.Stub
- implements LocalPowerManager,Watchdog.Monitor, SensorEventListener {
+ implements LocalPowerManager, Watchdog.Monitor, SensorEventListener {
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
@@ -1848,7 +1848,17 @@
}
public void setKeyboardVisibility(boolean visible) {
- mKeyboardVisible = visible;
+ synchronized (mLocks) {
+ if (mSpew) {
+ Log.d(TAG, "setKeyboardVisibility: " + visible);
+ }
+ mKeyboardVisible = visible;
+ // don't signal user activity when closing keyboard if the screen is off.
+ // otherwise, we want to make sure the backlights are adjusted.
+ if (visible || (mPowerState & SCREEN_ON_BIT) != 0) {
+ userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
+ }
+ }
}
/**
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 6e6f66f..53ff78e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -374,13 +374,6 @@
}
setWifiEnabledState(eventualWifiState, uid);
- /*
- * Initialize the number of allowed radio channels if Wi-Fi is being turned on.
- */
- if (enable) {
- mWifiStateTracker.setNumAllowedChannels();
- }
-
return true;
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index ece708a..8d2785a 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -100,7 +100,6 @@
public static final int EVENT_CLEAN_UP_CONNECTION = 34;
protected static final int EVENT_CDMA_OTA_PROVISION = 35;
protected static final int EVENT_RESTART_RADIO = 36;
- private static final int EVENT_ENABLE_APN_REQUEST = 37;
/***** Constants *****/
@@ -126,6 +125,10 @@
+ "5000,10000,20000,40000,80000:5000,160000:5000,"
+ "320000:5000,640000:5000,1280000:5000,1800000:5000";
+ /** Retry configuration for secondary networks: 4 tries in 20 sec */
+ protected static final String SECONDARY_DATA_RETRY_CONFIG =
+ "max_retries=3; 5000, 5000, 5000";
+
/** Slow poll when attempting connection recovery. */
protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
/** Default ping deadline, in seconds. */
@@ -171,7 +174,7 @@
protected boolean netStatPollEnabled = false;
/** Manage the behavior of data retry after failure */
- protected final RetryManager mRetryMgr = new RetryManager();
+ protected RetryManager mRetryMgr = new RetryManager();
// wifi connection status will be updated by sticky intent
protected boolean mIsWifiConnected = false;
@@ -266,33 +269,8 @@
public void handleMessage (Message msg) {
switch (msg.what) {
- case EVENT_ENABLE_APN_REQUEST:
- int apnId = msg.arg1;
- synchronized (this) {
- if (DBG) {
- Log.d(LOG_TAG, "got EVENT_ENABLE_APN_REQUEST with apnType = " + apnId +
- " and enable = " + msg.arg2);
- Log.d(LOG_TAG, "dataEnabled[apnId] = " + dataEnabled[apnId] +
- ", enabledCount = " + enabledCount);
- }
- if (msg.arg2 == APN_ENABLED) {
- // enable
- if (!dataEnabled[apnId]) {
- dataEnabled[apnId] = true;
- enabledCount++;
- }
- onTrySetupData(null);
- } else {
- // disable
- if (dataEnabled[apnId]) {
- dataEnabled[apnId] = false;
- enabledCount--;
- if (enabledCount == 0) {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
- }
- }
- }
- }
+ case EVENT_ENABLE_NEW_APN:
+ onEnableApn(msg.arg1, msg.arg2);
break;
case EVENT_TRY_SETUP_DATA:
@@ -392,6 +370,24 @@
}
}
+ protected String apnIdToType(int id) {
+ switch (id) {
+ case APN_DEFAULT_ID:
+ return Phone.APN_TYPE_DEFAULT;
+ case APN_MMS_ID:
+ return Phone.APN_TYPE_MMS;
+ case APN_SUPL_ID:
+ return Phone.APN_TYPE_SUPL;
+ case APN_DUN_ID:
+ return Phone.APN_TYPE_DUN;
+ case APN_HIPRI_ID:
+ return Phone.APN_TYPE_HIPRI;
+ default:
+ Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType");
+ return Phone.APN_TYPE_DEFAULT;
+ }
+ }
+
protected abstract boolean isApnTypeActive(String type);
protected abstract boolean isApnTypeAvailable(String type);
@@ -449,8 +445,6 @@
}
setEnabled(id, true);
- mRequestedApnType = type;
- sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
return Phone.APN_REQUEST_STARTED;
}
@@ -471,7 +465,6 @@
if (isEnabled(id)) {
setEnabled(id, false);
if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
- mRequestedApnType = Phone.APN_TYPE_DEFAULT;
if (dataEnabled[APN_DEFAULT_ID]) {
return Phone.APN_ALREADY_ACTIVE;
} else {
@@ -485,16 +478,56 @@
}
}
- protected void setEnabled(int id, boolean enable) {
+ private void setEnabled(int id, boolean enable) {
if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " +
dataEnabled[id] + " and enabledCount = " + enabledCount);
- Message msg = obtainMessage(EVENT_ENABLE_APN_REQUEST);
+ Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
msg.arg1 = id;
msg.arg2 = (enable ? APN_ENABLED : APN_DISABLED);
sendMessage(msg);
}
+ protected synchronized void onEnableApn(int apnId, int enabled) {
+ if (DBG) {
+ Log.d(LOG_TAG, "got EVENT_APN_ENABLE_REQUEST with apnType = " + apnId +
+ " and enable = " + enabled);
+ Log.d(LOG_TAG, "dataEnabled[apnId] = " + dataEnabled[apnId] +
+ ", enabledCount = " + enabledCount);
+ }
+ if (enabled == APN_ENABLED) {
+ if (!dataEnabled[apnId]) {
+ mRequestedApnType = apnIdToType(apnId);
+ onEnableNewApn();
+
+ dataEnabled[apnId] = true;
+ enabledCount++;
+ }
+ onTrySetupData(null);
+ } else {
+ // disable
+ if (dataEnabled[apnId]) {
+ dataEnabled[apnId] = false;
+ enabledCount--;
+ if (enabledCount == 0) {
+ onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ } else if (dataEnabled[APN_DEFAULT_ID] == true) {
+ mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+ onEnableNewApn();
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when we switch APNs.
+ *
+ * mRequestedApnType is set prior to call
+ * To be overridden.
+ */
+ protected void onEnableNewApn() {
+ }
+
/**
* Prevent mobile data connections from being established,
* or once again allow mobile data connections. If the state
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 5203d3f..f32837f 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -154,6 +154,7 @@
static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached";
static final String REASON_APN_CHANGED = "apnChanged";
static final String REASON_APN_SWITCHED = "apnSwitched";
+ static final String REASON_APN_FAILED = "apnFailed";
static final String REASON_RESTORE_DEFAULT_APN = "restoreDefaultApn";
static final String REASON_RADIO_TURNED_OFF = "radioTurnedOff";
static final String REASON_PDP_RESET = "pdpReset";
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 0215ab2..b063e0a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -150,6 +150,11 @@
static final String APN_ID = "apn_id";
private boolean canSetPreferApn = false;
+ // for tracking retrys on the default APN
+ private RetryManager mDefaultRetryManager;
+ // for tracking retrys on a secondary APN
+ private RetryManager mSecondaryRetryManager;
+
BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
{
@Override
@@ -253,6 +258,19 @@
mRetryMgr.configure(20, 2000, 1000);
}
}
+
+ mDefaultRetryManager = mRetryMgr;
+ mSecondaryRetryManager = new RetryManager();
+
+ if (!mSecondaryRetryManager.configure(SystemProperties.get(
+ "ro.gsm.2nd_data_retry_config"))) {
+ if (!mSecondaryRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple sequence.
+ Log.e(LOG_TAG, "Could note configure using SECONDARY_DATA_RETRY_CONFIG="
+ + SECONDARY_DATA_RETRY_CONFIG);
+ mSecondaryRetryManager.configure("max_retries=3, 333, 333, 333");
+ }
+ }
}
public void dispose() {
@@ -1019,6 +1037,12 @@
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
if (!mRetryMgr.isRetryNeeded()) {
+ if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+ // if no more retries on a secondary APN attempt, tell the world and revert.
+ phone.notifyDataConnection(Phone.REASON_APN_FAILED);
+ onEnableApn(apnTypeToId(mRequestedApnType), APN_DISABLED);
+ return;
+ }
if (mReregisterOnReconnectFailure) {
// We've re-registerd once now just retry forever.
mRetryMgr.retryForeverUsingLastTimeout();
@@ -1069,7 +1093,16 @@
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
}
+ @Override
protected void onEnableNewApn() {
+ // change our retry manager to use the appropriate numbers for the new APN
+ if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+ mRetryMgr = mDefaultRetryManager;
+ } else {
+ mRetryMgr = mSecondaryRetryManager;
+ }
+ mRetryMgr.resetRetryCount();
+
// TODO: To support simultaneous PDP contexts, this should really only call
// cleanUpConnection if it needs to free up a PdpConnection.
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
@@ -1189,6 +1222,10 @@
// No try for permanent failure
if (cause.isPermanentFail()) {
notifyNoData(cause);
+ if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+ phone.notifyDataConnection(Phone.REASON_APN_FAILED);
+ onEnableApn(apnTypeToId(mRequestedApnType), APN_DISABLED);
+ }
return;
}
@@ -1381,9 +1418,7 @@
private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
notifyNoData(cause);
- if (mRequestedApnType == Phone.APN_TYPE_DEFAULT) {
- reconnectAfterFail(cause, reason);
- }
+ reconnectAfterFail(cause, reason);
}
private void setPreferredApn(int pos) {
@@ -1442,10 +1477,6 @@
onRecordsLoaded();
break;
- case EVENT_ENABLE_NEW_APN:
- onEnableNewApn();
- break;
-
case EVENT_GPRS_DETACHED:
onGprsDetached();
break;
diff --git a/test-runner/android/test/AndroidTestRunner.java b/test-runner/android/test/AndroidTestRunner.java
index 358b7e9..0f1599a 100644
--- a/test-runner/android/test/AndroidTestRunner.java
+++ b/test-runner/android/test/AndroidTestRunner.java
@@ -18,6 +18,8 @@
import android.app.Instrumentation;
import android.content.Context;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
+
import com.google.android.collect.Lists;
import junit.framework.Test;
import junit.framework.TestCase;
@@ -39,6 +41,7 @@
private List<TestListener> mTestListeners = Lists.newArrayList();
private Instrumentation mInstrumentation;
+ private PerformanceResultsWriter mPerfWriter;
@SuppressWarnings("unchecked")
public void setTestClassName(String testClassName, String testMethodName) {
@@ -162,6 +165,7 @@
for (TestCase testCase : mTestCases) {
setContextIfAndroidTestCase(testCase, mContext, testContext);
setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation);
+ setPerformanceWriterIfPerformanceTestCase(testCase, mPerfWriter);
testCase.run(mTestResult);
}
}
@@ -184,6 +188,13 @@
}
}
+ private void setPerformanceWriterIfPerformanceTestCase(
+ Test test, PerformanceResultsWriter writer) {
+ if (PerformanceTestBase.class.isAssignableFrom(test.getClass())) {
+ ((PerformanceTestBase) test).setPerformanceResultsWriter(writer);
+ }
+ }
+
public void setInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
}
@@ -197,6 +208,13 @@
setInstrumentation(instrumentation);
}
+ /**
+ * {@hide} Pending approval for public API.
+ */
+ public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
+ mPerfWriter = writer;
+ }
+
@Override
protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
return mContext.getClassLoader().loadClass(suiteClassName);
diff --git a/test-runner/android/test/InstrumentationTestRunner.java b/test-runner/android/test/InstrumentationTestRunner.java
index 23f0ed4..b9978d6 100644
--- a/test-runner/android/test/InstrumentationTestRunner.java
+++ b/test-runner/android/test/InstrumentationTestRunner.java
@@ -17,17 +17,31 @@
package android.test;
import static android.test.suitebuilder.TestPredicates.REJECT_PERFORMANCE;
+
+import com.android.internal.util.Predicate;
+
import android.app.Activity;
import android.app.Instrumentation;
import android.os.Bundle;
import android.os.Debug;
import android.os.Looper;
+import android.os.Parcelable;
+import android.os.PerformanceCollector;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
import android.test.suitebuilder.TestMethod;
import android.test.suitebuilder.TestPredicates;
import android.test.suitebuilder.TestSuiteBuilder;
import android.util.Log;
-import com.android.internal.util.Predicate;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
@@ -38,22 +52,13 @@
import junit.runner.BaseTestRunner;
import junit.textui.ResultPrinter;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-
/**
* An {@link Instrumentation} that runs various types of {@link junit.framework.TestCase}s against
* an Android package (application). Typical usage:
* <ol>
* <li>Write {@link junit.framework.TestCase}s that perform unit, functional, or performance tests
* against the classes in your package. Typically these are subclassed from:
- * <ul><li>{@link android.test.ActivityInstrumentationTestCase}</li>
+ * <ul><li>{@link android.test.ActivityInstrumentationTestCase2}</li>
* <li>{@link android.test.ActivityUnitTestCase}</li>
* <li>{@link android.test.AndroidTestCase}</li>
* <li>{@link android.test.ApplicationTestCase}</li>
@@ -111,13 +116,13 @@
* <p/>
* <b>To run in 'log only' mode</b>
* -e log true
- * This option will load and iterate through all test classes and methods, but will bypass actual
- * test execution. Useful for quickly obtaining info on the tests to be executed by an
+ * This option will load and iterate through all test classes and methods, but will bypass actual
+ * test execution. Useful for quickly obtaining info on the tests to be executed by an
* instrumentation command.
* <p/>
* <b>To generate EMMA code coverage:</b>
* -e coverage true
- * Note: this requires an emma instrumented build. By default, the code coverage results file
+ * Note: this requires an emma instrumented build. By default, the code coverage results file
* will be saved in a /data/<app>/coverage.ec file, unless overridden by coverageFile flag (see
* below)
* <p/>
@@ -129,11 +134,10 @@
/* (not JavaDoc)
* Although not necessary in most case, another way to use this class is to extend it and have the
- * derived class return
- * the desired test suite from the {@link #getTestSuite()} method. The test suite returned from this
- * method will be used if no target class is defined in the meta-data or command line argument
- * parameters. If a derived class is used it needs to be added as an instrumentation to the
- * AndroidManifest.xml and the command to run it would look like:
+ * derived class return the desired test suite from the {@link #getTestSuite()} method. The test
+ * suite returned from this method will be used if no target class is defined in the meta-data or
+ * command line argument parameters. If a derived class is used it needs to be added as an
+ * instrumentation to the AndroidManifest.xml and the command to run it would look like:
* <p/>
* adb shell am instrument -w com.android.foo/<i>com.android.FooInstrumentationTestRunner</i>
* <p/>
@@ -155,66 +159,65 @@
public static final String ARGUMENT_DELAY_MSEC = "delay_msec";
private static final String SMALL_SUITE = "small";
- private static final String MEDIUM_SUITE = "medium";
+ private static final String MEDIUM_SUITE = "medium";
private static final String LARGE_SUITE = "large";
-
+
private static final String ARGUMENT_LOG_ONLY = "log";
-
/**
- * This constant defines the maximum allowed runtime (in ms) for a test included in the "small" suite.
- * It is used to make an educated guess at what suite an unlabeled test belongs.
+ * This constant defines the maximum allowed runtime (in ms) for a test included in the "small"
+ * suite. It is used to make an educated guess at what suite an unlabeled test belongs.
*/
private static final float SMALL_SUITE_MAX_RUNTIME = 100;
-
+
/**
- * This constant defines the maximum allowed runtime (in ms) for a test included in the "medium" suite.
- * It is used to make an educated guess at what suite an unlabeled test belongs.
+ * This constant defines the maximum allowed runtime (in ms) for a test included in the
+ * "medium" suite. It is used to make an educated guess at what suite an unlabeled test belongs.
*/
private static final float MEDIUM_SUITE_MAX_RUNTIME = 1000;
-
+
/**
- * The following keys are used in the status bundle to provide structured reports to
- * an IInstrumentationWatcher.
+ * The following keys are used in the status bundle to provide structured reports to
+ * an IInstrumentationWatcher.
*/
/**
- * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
+ * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER},
* identifies InstrumentationTestRunner as the source of the report. This is sent with all
* status messages.
*/
public static final String REPORT_VALUE_ID = "InstrumentationTestRunner";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the total number of tests that are being run. This is sent with all status
* messages.
*/
public static final String REPORT_KEY_NUM_TOTAL = "numtests";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the sequence number of the current test. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NUM_CURRENT = "current";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the name of the current test class. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NAME_CLASS = "class";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* identifies the name of the current test. This is sent with any status message
* describing a specific test being started or completed.
*/
public static final String REPORT_KEY_NAME_TEST = "test";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* reports the run time in seconds of the current test.
*/
private static final String REPORT_KEY_RUN_TIME = "runtime";
/**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
* reports the guessed suite assignment for the current test.
*/
private static final String REPORT_KEY_SUITE_ASSIGNMENT = "suiteassignment";
@@ -224,6 +227,19 @@
*/
private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath";
/**
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * reports the cpu time in milliseconds of the current test.
+ */
+ private static final String REPORT_KEY_PERF_CPU_TIME =
+ "performance." + PerformanceCollector.METRIC_KEY_CPU_TIME;
+ /**
+ * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
+ * reports the run time in milliseconds of the current test.
+ */
+ private static final String REPORT_KEY_PERF_EXECUTION_TIME =
+ "performance." + PerformanceCollector.METRIC_KEY_EXECUTION_TIME;
+
+ /**
* The test is starting.
*/
public static final int REPORT_VALUE_RESULT_START = 1;
@@ -240,15 +256,15 @@
*/
public static final int REPORT_VALUE_RESULT_FAILURE = -2;
/**
- * If included in the status bundle sent to an IInstrumentationWatcher, this key
- * identifies a stack trace describing an error or failure. This is sent with any status
+ * If included in the status bundle sent to an IInstrumentationWatcher, this key
+ * identifies a stack trace describing an error or failure. This is sent with any status
* message describing a specific test being completed.
*/
public static final String REPORT_KEY_STACK = "stack";
// Default file name for code coverage
private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec";
-
+
private static final String LOG_TAG = "InstrumentationTestRunner";
private final Bundle mResults = new Bundle();
@@ -316,7 +332,7 @@
if (testSuite != null) {
testSuiteBuilder.addTestSuite(testSuite);
} else {
- // no package or class bundle arguments were supplied, and no test suite
+ // no package or class bundle arguments were supplied, and no test suite
// provided so add all tests in application
testSuiteBuilder.includePackages("");
}
@@ -324,7 +340,7 @@
} else {
parseTestClasses(testClassesArg, testSuiteBuilder);
}
-
+
testSuiteBuilder.addRequirements(getBuilderRequirements());
mTestRunner = getAndroidTestRunner();
@@ -336,8 +352,10 @@
if (mSuiteAssignmentMode) {
mTestRunner.addTestListener(new SuiteAssignmentPrinter());
} else {
+ WatcherResultPrinter resultPrinter = new WatcherResultPrinter(mTestCount);
mTestRunner.addTestListener(new TestPrinter("TestRunner", false));
- mTestRunner.addTestListener(new WatcherResultPrinter(mTestCount));
+ mTestRunner.addTestListener(resultPrinter);
+ mTestRunner.setPerformanceResultsWriter(resultPrinter);
}
start();
}
@@ -347,7 +365,8 @@
}
/**
- * Parses and loads the specified set of test classes
+ * Parses and loads the specified set of test classes
+ *
* @param testClassArg - comma-separated list of test classes and methods
* @param testSuiteBuilder - builder to add tests to
*/
@@ -360,8 +379,9 @@
/**
* Parse and load the given test class and, optionally, method
- * @param testClassName - full package name of test class and optionally method to add. Expected
- * format: com.android.TestClass#testMethod
+ *
+ * @param testClassName - full package name of test class and optionally method to add.
+ * Expected format: com.android.TestClass#testMethod
* @param testSuiteBuilder - builder to add tests to
*/
private void parseTestClass(String testClassName, TestSuiteBuilder testSuiteBuilder) {
@@ -372,8 +392,7 @@
testMethodName = testClassName.substring(methodSeparatorIndex + 1);
testClassName = testClassName.substring(0, methodSeparatorIndex);
}
- testSuiteBuilder.addTestClassByName(testClassName, testMethodName,
- getTargetContext());
+ testSuiteBuilder.addTestClassByName(testClassName, testMethodName, getTargetContext());
}
protected AndroidTestRunner getAndroidTestRunner() {
@@ -384,12 +403,12 @@
String tagString = arguments.getString(tag);
return tagString != null && Boolean.parseBoolean(tagString);
}
-
+
/*
* Returns the size predicate object, corresponding to the "size" argument value.
*/
private Predicate<TestMethod> getSizePredicateFromArg(String sizeArg) {
-
+
if (SMALL_SUITE.equals(sizeArg)) {
return TestPredicates.SELECT_SMALL;
} else if (MEDIUM_SUITE.equals(sizeArg)) {
@@ -400,11 +419,11 @@
return null;
}
}
-
+
@Override
public void onStart() {
Looper.prepare();
-
+
if (mJustCount) {
mResults.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
mResults.putInt(REPORT_KEY_NUM_TOTAL, mTestCount);
@@ -413,30 +432,30 @@
if (mDebug) {
Debug.waitForDebugger();
}
-
+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream writer = new PrintStream(byteArrayOutputStream);
try {
StringResultPrinter resultPrinter = new StringResultPrinter(writer);
-
+
mTestRunner.addTestListener(resultPrinter);
-
+
long startTime = System.currentTimeMillis();
mTestRunner.runTest();
long runTime = System.currentTimeMillis() - startTime;
-
+
resultPrinter.print(mTestRunner.getTestResult(), runTime);
} finally {
- mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nTest results for %s=%s",
- mTestRunner.getTestClassName(),
+ mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nTest results for %s=%s",
+ mTestRunner.getTestClassName(),
byteArrayOutputStream.toString()));
if (mCoverage) {
generateCoverageReport();
}
writer.close();
-
+
finish(Activity.RESULT_OK, mResults);
}
}
@@ -459,7 +478,7 @@
public ClassLoader getLoader() {
return null;
}
-
+
private void generateCoverageReport() {
// use reflection to call emma dump coverage method, to avoid
// always statically compiling against emma jar
@@ -467,9 +486,9 @@
java.io.File coverageFile = new java.io.File(coverageFilePath);
try {
Class emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
- Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
+ Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
coverageFile.getClass(), boolean.class, boolean.class);
-
+
dumpCoverageMethod.invoke(null, coverageFile, false, false);
// output path to generated coverage file so it can be parsed by a test harness if
// needed
@@ -495,15 +514,14 @@
private String getCoverageFilePath() {
if (mCoverageFilePath == null) {
return getTargetContext().getFilesDir().getAbsolutePath() + File.separator +
- DEFAULT_COVERAGE_FILE_NAME;
- }
- else {
+ DEFAULT_COVERAGE_FILE_NAME;
+ } else {
return mCoverageFilePath;
}
}
private void reportEmmaError(Exception e) {
- reportEmmaError("", e);
+ reportEmmaError("", e);
}
private void reportEmmaError(String hint, Exception e) {
@@ -524,30 +542,29 @@
printFooter(result);
}
}
-
+
/**
- * This class sends status reports back to the IInstrumentationWatcher about
+ * This class sends status reports back to the IInstrumentationWatcher about
* which suite each test belongs.
*/
- private class SuiteAssignmentPrinter implements TestListener
- {
-
+ private class SuiteAssignmentPrinter implements TestListener {
+
private Bundle mTestResult;
private long mStartTime;
private long mEndTime;
private boolean mTimingValid;
-
+
public SuiteAssignmentPrinter() {
}
-
+
/**
* send a status for the start of a each test, so long tests can be seen as "running"
*/
public void startTest(Test test) {
mTimingValid = true;
- mStartTime = System.currentTimeMillis();
+ mStartTime = System.currentTimeMillis();
}
-
+
/**
* @see junit.framework.TestListener#addError(Test, Throwable)
*/
@@ -576,7 +593,7 @@
runTime = -1;
} else {
runTime = mEndTime - mStartTime;
- if (runTime < SMALL_SUITE_MAX_RUNTIME
+ if (runTime < SMALL_SUITE_MAX_RUNTIME
&& !InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
assignmentSuite = SMALL_SUITE;
} else if (runTime < MEDIUM_SUITE_MAX_RUNTIME) {
@@ -588,8 +605,8 @@
// Clear mStartTime so that we can verify that it gets set next time.
mStartTime = -1;
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- test.getClass().getName() + "#" + ((TestCase) test).getName()
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ test.getClass().getName() + "#" + ((TestCase) test).getName()
+ "\nin " + assignmentSuite + " suite\nrunTime: "
+ String.valueOf(runTime) + "\n");
mTestResult.putFloat(REPORT_KEY_RUN_TIME, runTime);
@@ -598,36 +615,40 @@
sendStatus(0, mTestResult);
}
}
-
+
/**
* This class sends status reports back to the IInstrumentationWatcher
*/
- private class WatcherResultPrinter implements TestListener
- {
+ private class WatcherResultPrinter implements TestListener, PerformanceResultsWriter {
private final Bundle mResultTemplate;
Bundle mTestResult;
int mTestNum = 0;
int mTestResultCode = 0;
String mTestClass = null;
-
+ boolean mIsTimedTest = false;
+ long mCpuTime = 0;
+ long mExecTime = 0;
+
public WatcherResultPrinter(int numTests) {
mResultTemplate = new Bundle();
mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
}
-
+
/**
- * send a status for the start of a each test, so long tests can be seen as "running"
+ * send a status for the start of a each test, so long tests can be seen
+ * as "running"
*/
public void startTest(Test test) {
String testClass = test.getClass().getName();
+ String testName = ((TestCase)test).getName();
mTestResult = new Bundle(mResultTemplate);
mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
- mTestResult.putString(REPORT_KEY_NAME_TEST, ((TestCase) test).getName());
+ mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum);
// pretty printing
if (testClass != null && !testClass.equals(mTestClass)) {
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
String.format("\n%s:", testClass));
mTestClass = testClass;
} else {
@@ -635,9 +656,9 @@
}
// The delay_msec parameter is normally used to provide buffers of idle time
- // for power measurement purposes. To make sure there is a delay before and after
+ // for power measurement purposes. To make sure there is a delay before and after
// every test in a suite, we delay *after* every test (see endTest below) and also
- // delay *before* the first test. So, delay test1 delay test2 delay.
+ // delay *before* the first test. So, delay test1 delay test2 delay.
try {
if (mTestNum == 1) Thread.sleep(mDelayMsec);
@@ -647,8 +668,25 @@
sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
mTestResultCode = 0;
+
+ mIsTimedTest = false;
+ try {
+ // Look for TimedTest annotation on both test class and test
+ // method
+ mIsTimedTest = test.getClass().isAnnotationPresent(TimedTest.class) ||
+ test.getClass().getMethod(testName).isAnnotationPresent(TimedTest.class);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ }
+
+ if (mIsTimedTest) {
+ mExecTime = SystemClock.uptimeMillis();
+ mCpuTime = Process.getElapsedCpuTime();
+ }
}
-
+
/**
* @see junit.framework.TestListener#addError(Test, Throwable)
*/
@@ -656,9 +694,9 @@
mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
mTestResultCode = REPORT_VALUE_RESULT_ERROR;
// pretty printing
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nError in %s:\n%s",
- ((TestCase) test).getName(), BaseTestRunner.getFilteredTrace(t)));
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nError in %s:\n%s",
+ ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
}
/**
@@ -668,28 +706,68 @@
mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t));
mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
// pretty printing
- mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- String.format("\nFailure in %s:\n%s",
- ((TestCase) test).getName(), BaseTestRunner.getFilteredTrace(t)));
+ mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
+ String.format("\nFailure in %s:\n%s",
+ ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t)));
}
/**
* @see junit.framework.TestListener#endTest(Test)
*/
public void endTest(Test test) {
+ if (mIsTimedTest) {
+ mCpuTime = Process.getElapsedCpuTime() - mCpuTime;
+ mExecTime = SystemClock.uptimeMillis() - mExecTime;
+ mTestResult.putLong(REPORT_KEY_PERF_CPU_TIME, mCpuTime);
+ mTestResult.putLong(REPORT_KEY_PERF_EXECUTION_TIME, mExecTime);
+ }
+
if (mTestResultCode == 0) {
mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
}
sendStatus(mTestResultCode, mTestResult);
- try { // Sleep after every test, if specified
+ try { // Sleep after every test, if specified
Thread.sleep(mDelayMsec);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
+ public void writeBeginSnapshot(String label) {
+ // Do nothing
+ }
+
+ public void writeEndSnapshot(Bundle results) {
+ // Copy all snapshot data fields as type long into mResults, which
+ // is outputted via Instrumentation.finish
+ for (String key : results.keySet()) {
+ mResults.putLong(key, results.getLong(key));
+ }
+ }
+
+ public void writeStartTiming(String label) {
+ // Do nothing
+ }
+
+ public void writeStopTiming(Bundle results) {
+ // Copy results into mTestResult by flattening list of iterations,
+ // which is outputted via WatcherResultPrinter.endTest
+ int i = 0;
+ for (Parcelable p :
+ results.getParcelableArrayList(PerformanceCollector.METRIC_KEY_ITERATIONS)) {
+ Bundle iteration = (Bundle)p;
+ String index = "performance.iteration" + i + ".";
+ mTestResult.putString(index + PerformanceCollector.METRIC_KEY_LABEL,
+ iteration.getString(PerformanceCollector.METRIC_KEY_LABEL));
+ mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_CPU_TIME,
+ iteration.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME));
+ mTestResult.putLong(index + PerformanceCollector.METRIC_KEY_EXECUTION_TIME,
+ iteration.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
+ i++;
+ }
+ }
+
// TODO report the end of the cycle
- // TODO report runtime for each test
}
}
diff --git a/test-runner/android/test/PerformanceTestBase.java b/test-runner/android/test/PerformanceTestBase.java
index 93ac90c..572a9b8 100644
--- a/test-runner/android/test/PerformanceTestBase.java
+++ b/test-runner/android/test/PerformanceTestBase.java
@@ -16,13 +16,95 @@
package android.test;
-import android.test.PerformanceTestCase;
-import junit.framework.TestCase;
+import android.os.Bundle;
+import android.os.PerformanceCollector;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
+
+import java.lang.reflect.Method;
/**
- * {@hide} Not needed for SDK.
+ * Provides hooks and wrappers to automatically and manually collect and report
+ * performance data in tests.
+ *
+ * {@hide} Pending approval for public API.
*/
-public abstract class PerformanceTestBase extends TestCase implements PerformanceTestCase {
+public class PerformanceTestBase extends InstrumentationTestCase implements PerformanceTestCase {
+
+ private static PerformanceCollector sPerfCollector = new PerformanceCollector();
+ private static int sNumTestMethods = 0;
+ private static int sNumTestMethodsLeft = 0;
+
+ // Count number of tests, used to emulate beforeClass and afterClass from JUnit4
+ public PerformanceTestBase() {
+ if (sNumTestMethods == 0) {
+ Method methods[] = getClass().getMethods();
+ for (Method m : methods) {
+ if (m.getName().startsWith("test")) {
+ sNumTestMethods ++;
+ sNumTestMethodsLeft ++;
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // @beforeClass
+ // Will skew timing measured by TestRunner, but not by PerformanceCollector
+ if (sNumTestMethodsLeft == sNumTestMethods) {
+ sPerfCollector.beginSnapshot(this.getClass().getName());
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // @afterClass
+ // Will skew timing measured by TestRunner, but not by PerformanceCollector
+ if (--sNumTestMethodsLeft == 0) {
+ sPerfCollector.endSnapshot();
+ }
+ super.tearDown();
+ }
+
+ public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
+ sPerfCollector.setPerformanceResultsWriter(writer);
+ }
+
+ /**
+ * @see PerformanceCollector#beginSnapshot(String)
+ */
+ protected void beginSnapshot(String label) {
+ sPerfCollector.beginSnapshot(label);
+ }
+
+ /**
+ * @see PerformanceCollector#endSnapshot()
+ */
+ protected Bundle endSnapshot() {
+ return sPerfCollector.endSnapshot();
+ }
+
+ /**
+ * @see PerformanceCollector#startTiming(String)
+ */
+ protected void startTiming(String label) {
+ sPerfCollector.startTiming(label);
+ }
+
+ /**
+ * @see PerformanceCollector#addIteration(String)
+ */
+ protected Bundle addIteration(String label) {
+ return sPerfCollector.addIteration(label);
+ }
+
+ /**
+ * @see PerformanceCollector#stopTiming(String)
+ */
+ protected Bundle stopTiming(String label) {
+ return sPerfCollector.stopTiming(label);
+ }
public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
return 0;
@@ -31,12 +113,4 @@
public boolean isPerformanceOnly() {
return true;
}
-
- /*
- * Temporary hack to get some things working again.
- */
- public void testRun() {
- throw new RuntimeException("test implementation not provided");
- }
}
-
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java
new file mode 100644
index 0000000..1a0c2d1
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java
@@ -0,0 +1,441 @@
+/*
+ * 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 com.android.unit_tests.os;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.PerformanceCollector;
+import android.os.PerformanceCollector.PerformanceResultsWriter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class PerformanceCollectorTest extends TestCase {
+
+ private PerformanceCollector mPerfCollector;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPerfCollector = new PerformanceCollector();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mPerfCollector = null;
+ }
+
+ public void testBeginSnapshotNoWriter() throws Exception {
+ mPerfCollector.beginSnapshot("testBeginSnapshotNoWriter");
+
+ assertTrue((Long)readPrivateField("mSnapshotCpuTime", mPerfCollector) > 0);
+ assertTrue((Long)readPrivateField("mSnapshotExecTime", mPerfCollector) > 0);
+ Bundle snapshot = (Bundle)readPrivateField("mPerfSnapshot", mPerfCollector);
+ assertNotNull(snapshot);
+ assertEquals(2, snapshot.size());
+ }
+
+ @LargeTest
+ public void testEndSnapshotNoWriter() throws Exception {
+ mPerfCollector.beginSnapshot("testEndSnapshotNoWriter");
+ sleepForRandomLongPeriod();
+ Bundle snapshot = mPerfCollector.endSnapshot();
+
+ verifySnapshotBundle(snapshot);
+ }
+
+ public void testStartTimingNoWriter() throws Exception {
+ mPerfCollector.startTiming("testStartTimingNoWriter");
+
+ assertTrue((Long)readPrivateField("mCpuTime", mPerfCollector) > 0);
+ assertTrue((Long)readPrivateField("mExecTime", mPerfCollector) > 0);
+ Bundle measurement = (Bundle)readPrivateField("mPerfMeasurement", mPerfCollector);
+ assertNotNull(measurement);
+ verifyTimingBundle(measurement, new ArrayList<String>());
+ }
+
+ public void testAddIterationNoWriter() throws Exception {
+ mPerfCollector.startTiming("testAddIterationNoWriter");
+ sleepForRandomTinyPeriod();
+ Bundle iteration = mPerfCollector.addIteration("timing1");
+
+ verifyIterationBundle(iteration, "timing1");
+ }
+
+ public void testStopTimingNoWriter() throws Exception {
+ mPerfCollector.startTiming("testStopTimingNoWriter");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("timing2");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("timing3");
+ sleepForRandomShortPeriod();
+ Bundle timing = mPerfCollector.stopTiming("timing4");
+
+ ArrayList<String> labels = new ArrayList<String>();
+ labels.add("timing2");
+ labels.add("timing3");
+ labels.add("timing4");
+ verifyTimingBundle(timing, labels);
+ }
+
+ public void testBeginSnapshot() throws Exception {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.beginSnapshot("testBeginSnapshot");
+
+ assertEquals("testBeginSnapshot", writer.snapshotLabel);
+ assertTrue((Long)readPrivateField("mSnapshotCpuTime", mPerfCollector) > 0);
+ assertTrue((Long)readPrivateField("mSnapshotExecTime", mPerfCollector) > 0);
+ Bundle snapshot = (Bundle)readPrivateField("mPerfSnapshot", mPerfCollector);
+ assertNotNull(snapshot);
+ assertEquals(2, snapshot.size());
+ }
+
+ @LargeTest
+ public void testEndSnapshot() throws Exception {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.beginSnapshot("testEndSnapshot");
+ sleepForRandomLongPeriod();
+ Bundle snapshot1 = mPerfCollector.endSnapshot();
+ Bundle snapshot2 = writer.snapshotResults;
+
+ assertTrue(snapshot1.equals(snapshot2));
+ verifySnapshotBundle(snapshot1);
+ }
+
+ public void testStartTiming() throws Exception {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.startTiming("testStartTiming");
+
+ assertEquals("testStartTiming", writer.timingLabel);
+ assertTrue((Long)readPrivateField("mCpuTime", mPerfCollector) > 0);
+ assertTrue((Long)readPrivateField("mExecTime", mPerfCollector) > 0);
+ Bundle measurement = (Bundle)readPrivateField("mPerfMeasurement", mPerfCollector);
+ assertNotNull(measurement);
+ verifyTimingBundle(measurement, new ArrayList<String>());
+ }
+
+ public void testAddIteration() throws Exception {
+ mPerfCollector.startTiming("testAddIteration");
+ sleepForRandomTinyPeriod();
+ Bundle iteration = mPerfCollector.addIteration("timing5");
+
+ verifyIterationBundle(iteration, "timing5");
+ }
+
+ public void testStopTiming() throws Exception {
+ mPerfCollector.startTiming("testStopTiming");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("timing6");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("timing7");
+ sleepForRandomShortPeriod();
+ Bundle timing = mPerfCollector.stopTiming("timing8");
+
+ ArrayList<String> labels = new ArrayList<String>();
+ labels.add("timing6");
+ labels.add("timing7");
+ labels.add("timing8");
+ verifyTimingBundle(timing, labels);
+ }
+
+ @LargeTest
+ public void testSimpleSequence() throws Exception {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.beginSnapshot("testSimpleSequence");
+ mPerfCollector.startTiming("testSimpleSequenceTiming");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration1");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration2");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration3");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration4");
+ sleepForRandomShortPeriod();
+ Bundle timing = mPerfCollector.stopTiming("iteration5");
+ sleepForRandomLongPeriod();
+ Bundle snapshot1 = mPerfCollector.endSnapshot();
+ Bundle snapshot2 = writer.snapshotResults;
+
+ assertTrue(snapshot1.equals(snapshot2));
+ verifySnapshotBundle(snapshot1);
+
+ ArrayList<String> labels = new ArrayList<String>();
+ labels.add("iteration1");
+ labels.add("iteration2");
+ labels.add("iteration3");
+ labels.add("iteration4");
+ labels.add("iteration5");
+ verifyTimingBundle(timing, labels);
+ }
+
+ @LargeTest
+ public void testLongSequence() throws Exception {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.beginSnapshot("testLongSequence");
+ mPerfCollector.startTiming("testLongSequenceTiming1");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration1");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration2");
+ sleepForRandomShortPeriod();
+ Bundle timing1 = mPerfCollector.stopTiming("iteration3");
+ sleepForRandomLongPeriod();
+
+ mPerfCollector.startTiming("testLongSequenceTiming2");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration4");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration5");
+ sleepForRandomShortPeriod();
+ Bundle timing2 = mPerfCollector.stopTiming("iteration6");
+ sleepForRandomLongPeriod();
+
+ mPerfCollector.startTiming("testLongSequenceTiming3");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration7");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration8");
+ sleepForRandomShortPeriod();
+ Bundle timing3 = mPerfCollector.stopTiming("iteration9");
+ sleepForRandomLongPeriod();
+
+ mPerfCollector.startTiming("testLongSequenceTiming4");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration10");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration11");
+ sleepForRandomShortPeriod();
+ Bundle timing4 = mPerfCollector.stopTiming("iteration12");
+ sleepForRandomLongPeriod();
+
+ mPerfCollector.startTiming("testLongSequenceTiming5");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration13");
+ sleepForRandomTinyPeriod();
+ mPerfCollector.addIteration("iteration14");
+ sleepForRandomShortPeriod();
+ Bundle timing5 = mPerfCollector.stopTiming("iteration15");
+ sleepForRandomLongPeriod();
+ Bundle snapshot1 = mPerfCollector.endSnapshot();
+ Bundle snapshot2 = writer.snapshotResults;
+
+ assertTrue(snapshot1.equals(snapshot2));
+ verifySnapshotBundle(snapshot1);
+
+ ArrayList<String> labels1 = new ArrayList<String>();
+ labels1.add("iteration1");
+ labels1.add("iteration2");
+ labels1.add("iteration3");
+ verifyTimingBundle(timing1, labels1);
+ ArrayList<String> labels2 = new ArrayList<String>();
+ labels2.add("iteration4");
+ labels2.add("iteration5");
+ labels2.add("iteration6");
+ verifyTimingBundle(timing2, labels2);
+ ArrayList<String> labels3 = new ArrayList<String>();
+ labels3.add("iteration7");
+ labels3.add("iteration8");
+ labels3.add("iteration9");
+ verifyTimingBundle(timing3, labels3);
+ ArrayList<String> labels4 = new ArrayList<String>();
+ labels4.add("iteration10");
+ labels4.add("iteration11");
+ labels4.add("iteration12");
+ verifyTimingBundle(timing4, labels4);
+ ArrayList<String> labels5 = new ArrayList<String>();
+ labels5.add("iteration13");
+ labels5.add("iteration14");
+ labels5.add("iteration15");
+ verifyTimingBundle(timing5, labels5);
+ }
+
+ /*
+ * Verify that snapshotting and timing do not interfere w/ each other,
+ * by staggering calls to snapshot and timing functions.
+ */
+ @LargeTest
+ public void testOutOfOrderSequence() {
+ MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
+ mPerfCollector.setPerformanceResultsWriter(writer);
+ mPerfCollector.startTiming("testOutOfOrderSequenceTiming");
+ sleepForRandomShortPeriod();
+ mPerfCollector.beginSnapshot("testOutOfOrderSequenceSnapshot");
+ sleepForRandomShortPeriod();
+ Bundle timing1 = mPerfCollector.stopTiming("timing1");
+ sleepForRandomShortPeriod();
+ Bundle snapshot1 = mPerfCollector.endSnapshot();
+
+ Bundle timing2 = writer.timingResults;
+ Bundle snapshot2 = writer.snapshotResults;
+
+ assertTrue(snapshot1.equals(snapshot2));
+ verifySnapshotBundle(snapshot1);
+
+ assertTrue(timing1.equals(timing2));
+ ArrayList<String> labels = new ArrayList<String>();
+ labels.add("timing1");
+ verifyTimingBundle(timing1, labels);
+ }
+
+ private void sleepForRandomPeriod(int minDuration, int maxDuration) {
+ Random random = new Random();
+ int period = minDuration + random.nextInt(maxDuration - minDuration);
+ int slept = 0;
+ // Generate random positive amount of work, so cpu time is measurable in
+ // milliseconds
+ while (slept < period) {
+ int step = random.nextInt(minDuration/5);
+ try {
+ Thread.sleep(step);
+ } catch (InterruptedException e ) {
+ // eat the exception
+ }
+ slept += step;
+ }
+ }
+
+ private void sleepForRandomTinyPeriod() {
+ sleepForRandomPeriod(25, 50);
+ }
+
+ private void sleepForRandomShortPeriod() {
+ sleepForRandomPeriod(100, 250);
+ }
+
+ private void sleepForRandomLongPeriod() {
+ sleepForRandomPeriod(500, 1000);
+ }
+
+ private void verifySnapshotBundle(Bundle snapshot) {
+ assertTrue("At least 26 metrics collected", 26 <= snapshot.size());
+
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_CPU_TIME));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME) > 0);
+
+ assertTrue(snapshot.containsKey(
+ PerformanceCollector.METRIC_KEY_PRE_RECEIVED_TRANSACTIONS));
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_PRE_SENT_TRANSACTIONS));
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_RECEIVED_TRANSACTIONS));
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_SENT_TRANSACTIONS));
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_GC_INVOCATION_COUNT));
+
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_ALLOCATED));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_ALLOCATED) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_FREE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_FREE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_PRIVATE_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_PRIVATE_DIRTY) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_PSS));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_PSS) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_SHARED_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_SHARED_DIRTY) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_JAVA_SIZE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_JAVA_SIZE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_ALLOCATED));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_ALLOCATED) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_FREE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_FREE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_PRIVATE_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_PRIVATE_DIRTY) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_PSS));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_PSS) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_SHARED_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_SHARED_DIRTY) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_NATIVE_SIZE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_NATIVE_SIZE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_GLOBAL_ALLOC_COUNT));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_GLOBAL_ALLOC_COUNT) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_GLOBAL_ALLOC_SIZE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_GLOBAL_ALLOC_SIZE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_GLOBAL_FREED_COUNT));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_GLOBAL_FREED_COUNT) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_GLOBAL_FREED_SIZE));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_GLOBAL_FREED_SIZE) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_OTHER_PRIVATE_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_OTHER_PRIVATE_DIRTY) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_OTHER_PSS));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_OTHER_PSS) > 0);
+ assertTrue(snapshot.containsKey(PerformanceCollector.METRIC_KEY_OTHER_SHARED_DIRTY));
+ assertTrue(snapshot.getLong(PerformanceCollector.METRIC_KEY_OTHER_SHARED_DIRTY) > 0);
+ }
+
+ private void verifyIterationBundle(Bundle iteration, String label) {
+ assertEquals(3, iteration.size());
+ assertTrue(iteration.containsKey(PerformanceCollector.METRIC_KEY_LABEL));
+ assertEquals(label, iteration.getString(PerformanceCollector.METRIC_KEY_LABEL));
+ assertTrue(iteration.containsKey(PerformanceCollector.METRIC_KEY_CPU_TIME));
+ assertTrue(iteration.getLong(PerformanceCollector.METRIC_KEY_CPU_TIME) > 0);
+ assertTrue(iteration.containsKey(PerformanceCollector.METRIC_KEY_EXECUTION_TIME));
+ assertTrue(iteration.getLong(PerformanceCollector.METRIC_KEY_EXECUTION_TIME) > 0);
+ }
+
+ private void verifyTimingBundle(Bundle timing, ArrayList<String> labels) {
+ assertEquals(1, timing.size());
+ assertTrue(timing.containsKey(PerformanceCollector.METRIC_KEY_ITERATIONS));
+ ArrayList<Parcelable> iterations = timing.getParcelableArrayList(
+ PerformanceCollector.METRIC_KEY_ITERATIONS);
+ assertNotNull(iterations);
+ assertEquals(labels.size(), iterations.size());
+ for (int i = 0; i < labels.size(); i ++) {
+ Bundle iteration = (Bundle)iterations.get(i);
+ verifyIterationBundle(iteration, labels.get(i));
+ }
+ }
+
+ private Object readPrivateField(String fieldName, Object object) throws Exception {
+ Field f = object.getClass().getDeclaredField(fieldName);
+ f.setAccessible(true);
+ return f.get(object);
+ }
+
+ private class MockPerformanceResultsWriter implements PerformanceResultsWriter {
+
+ public String snapshotLabel;
+ public Bundle snapshotResults = new Bundle();
+ public String timingLabel;
+ public Bundle timingResults = new Bundle();
+
+ public void writeBeginSnapshot(String label) {
+ snapshotLabel = label;
+ }
+
+ public void writeEndSnapshot(Bundle results) {
+ snapshotResults = results;
+ }
+
+ public void writeStartTiming(String label) {
+ timingLabel = label;
+ }
+
+ public void writeStopTiming(Bundle results) {
+ timingResults = results;
+ }
+ }
+}
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 2325047..4a68d72 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -59,8 +59,18 @@
run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix
(adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
- if adb_output.find('INSTRUMENTATION_FAILED') != -1 or \
- adb_output.find('Process crashed.') != -1:
+ fail_flag = False
+ for line in adb_output.splitlines():
+ line = line.strip()
+ if line.find('INSTRUMENTATION_CODE') == 0:
+ if not line[22:] == '-1':
+ fail_flag = True
+ break
+ if (line.find('INSTRUMENTATION_FAILED') != -1 or
+ line.find('Process crashed.') != -1):
+ fail_flag = True
+ break
+ if fail_flag:
logging.error("Error happened : " + adb_output)
sys.exit(1)
@@ -80,7 +90,6 @@
shell_cmd_str = adb_cmd + " pull " + result_file + " " + results_dir
adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
logging.info(adb_output)
-
logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n")
if '__main__' == __name__:
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
index c562650..4dbcfdc 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
@@ -88,7 +88,7 @@
* @param projectCallback The {@link IProjectCallback} object to get information from
* the project.
* @param logger the object responsible for displaying warning/errors to the user.
- * @return an {@link ILayoutResult} object that contains the result of the layout.
+ * @return a new {@link ILayoutResult} object that contains the result of the layout.
* @since 4
*/
ILayoutResult computeLayout(IXmlPullParser layoutDescription,
@@ -123,7 +123,7 @@
* @param projectCallback The {@link IProjectCallback} object to get information from
* the project.
* @param logger the object responsible for displaying warning/errors to the user.
- * @return an {@link ILayoutResult} object that contains the result of the layout.
+ * @return a new {@link ILayoutResult} object that contains the result of the layout.
* @since 3
*/
@Deprecated
@@ -155,7 +155,7 @@
* @param projectCallback The {@link IProjectCallback} object to get information from
* the project.
* @param logger the object responsible for displaying warning/errors to the user.
- * @return an {@link ILayoutResult} object that contains the result of the layout.
+ * @return a new {@link ILayoutResult} object that contains the result of the layout.
* @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
* @since 2
*/
@@ -187,7 +187,7 @@
* @param projectCallback The {@link IProjectCallback} object to get information from
* the project.
* @param logger the object responsible for displaying warning/errors to the user.
- * @return an {@link ILayoutResult} object that contains the result of the layout.
+ * @return a new {@link ILayoutResult} object that contains the result of the layout.
* @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
* @since 1
*/
@@ -205,7 +205,7 @@
* until this method is called.
* <p/>The cache is not configuration dependent and should only be cleared when a
* resource changes (at this time only bitmaps and 9 patches go into the cache).
- * @param objectKey the key for the project.
+ * @param projectKey the key for the project.
* @since 1
*/
void clearCaches(Object projectKey);
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
index 5a06349..2d8a210 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
@@ -23,13 +23,17 @@
* {@link ILayoutLibBridge#computeLayout(IXmlPullParser, int, int, String, java.util.Map, java.util.Map, java.util.Map, IFontLoader, ILayoutLibLog, ICustomViewLoader)}
*/
public interface ILayoutResult {
- /** Sucess return code */
+ /**
+ * Success return code
+ */
final static int SUCCESS = 0;
- /** Error return code.
- * <p/>See {@link #getErrorMessage()}
- */
+
+ /**
+ * Error return code, in which case an error message is guaranteed to be defined.
+ * @See {@link #getErrorMessage()}
+ */
final static int ERROR = 1;
-
+
/**
* Returns the result code.
* @see #SUCCESS
@@ -62,18 +66,18 @@
* Returns the list of children views.
*/
ILayoutViewInfo[] getChildren();
-
+
/**
* Returns the key associated with the node.
* @see IXmlPullParser#getViewKey()
*/
Object getViewKey();
-
+
/**
* Returns the name of the view.
*/
String getName();
-
+
/**
* Returns the left of the view bounds.
*/
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index fa24a98..9a11404 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -784,6 +784,9 @@
mBluetoothA2dp = new BluetoothA2dp(mContext);
}
checkIsBluetoothPlaying();
+
+ // initialize this after the supplicant is alive
+ setNumAllowedChannels();
break;
case EVENT_SUPPLICANT_DISCONNECT: